2011년 3월 15일 화요일

GetDC(0) 으로 캡쳐되지 않는 윈도우

Transparent 나 AlphaBlend 가 먹힌 윈도우는 GetDC(0) 으로 캡쳐되지 않음.
(AlphaBlendValue 가 254 라도 안됨)
결론: Window Styles 의 Extended Styles 에 WS_EX_LAYERED가 있다면 일반적 GetDC(0) 으로는 화면이 가져와지지 않음.
하지만 특정 윈도우의 핸들을 통해 GetDC(HWND) 로 받아오면 그려지는 걸로 봐서는
(하지만 Transparent, AlphaBlend 는 사라진 상태로)
WS_EX_LAYERED 가 먹힌 윈도우의 화면은 바탕화면의 DC에서 관장하지 않는 듯함.
아래는 원격제어 중 화면전송에서 저게 필요해서 부린 꽁수.
그냥 최상위 윈도우는 따로 받아와서 GetDC(0) 으로 그려놓은 비트맵에 덧그리기임.
별로 느리지 않아서 다행.
// 매개변수로 받은 비트맵에 최상위 윈도우의 화면을 덧그려줌.
// 매개변수로 받은 비트맵이 무조건 전체화면의 그림이라는 전제이므로 안전장치 같은 건 없음...
procedureDrawTopMostWnd(aBitmap: TBitmap);
var
aHWND: HWND;
aDC: HDC;
cRect, wRect: TRect;
X, Y: Integer;
BorderThick: Integer;
btm: TBitmap;

begin
// 최상위 윈도우의 핸들을 가져옴
aHWND:=GetForegroundWindow;
// 그런거 없다면 그냥 관둠...
ifaHWND=0thenExit;
// 최상위 윈도우의 ClientRect, WindowRect 가져옴
Windows.GetClientRect(aHWND, cRect);
Windows.GetWindowRect(aHWND, wRect);

btm:=TBitmap.Create;
try
// 비트맵 크기 맞춤 btm.Width:=cRect.Right;
btm.Height:=cRect.Bottom;
// 최상위 윈도우의 DC를 가져옴
aDC:=GetDC(aHWND);
// 일단 그려주고
Bitblt(btm.Canvas.Handle,0,0,btm.Width,btm.Height,aDC,0,0,SRCCOPY);
// 테두리 영역의 크기를 구하고 전체화면에서 클라이언트 영역의 위치계산 (좀 더 스마트한 방법은 없을까...)
BorderThick:=(wRect.Right-wRect.Left-cRect.Right) div2;
X:=wRect.Left+BorderThick;
Y:=wRect.Top+((wRect.Bottom-wRect.Top-cRect.Bottom))-BorderThick;
// 전체화면에 최상위 윈도우의 화면을 덧그려줌
Bitblt(aBitmap.Canvas.Handle,X,Y,btm.Width,btm.Height,btm.Canvas.Handle,0,0,SRCCOPY);
finally
FreeAndNil(btm);
ReleaseDC(aHWND, aDC);
CloseHandle(aHWND);
end;
end;
// 위의 함수를 이용해 최상위 윈도우가 WS_EX_LAYERED 라도 포함시켜 화면캡쳐 해주는 예제
procedureTForm1.Button1Click(Sender: TObject);
var
btm: TBitmap;

begin
btm:=TBitmap.Create;
try
btm.Width:=Screen.Width;
btm.Height:=Screen.Height;
Bitblt(btm.Canvas.Handle,0,0,btm.Width,btm.Height,GetDC(0),0,0,SRCCOPY);
DrawTopMostWnd(btm);
Image1.Picture.Assign(btm);
Image1.Refresh;
finally FreeAndNil(btm);
end;
end;

댓글 없음:

댓글 쓰기