2012년 11월 10일 토요일

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


Delphi-GetDC0-으로-캡쳐되지-않는-윈도우 에서 갖어 왔습니다.

Transparent 나 AlphaBlend 가 먹힌 윈도우는 GetDC(0) 으로 캡쳐되지 않음.
(AlphaBlendValue 가 254 라도 안됨)

결론: Window Styles 의 Extended Styles 에 WS_EX_LAYERED 가 있다면 일반적 GetDC(0) 으로는 화면이 가져와지지 않음. 하지만 특정 윈도우의 핸들을 통해 GetDC(HWND) 로 받아오면 그려지는 걸로 봐서는 (하지만 Transparent, AlphaBlend 는 사라진 상태로) WS_EX_LAYERED 가 먹힌 윈도우의 화면은 바탕화면의 DC에서 관장하지 않는 듯함.

procedure DrawTopMostWnd(aBitmap: TBitmap);
 var
  aHWND: HWND;
  aDC: HDC;
  cRect, wRect: TRect;
  X, Y: Integer;
  BorderThick: Integer;
  btm: TBitmap;
begin
  // 최상위 윈도우의 핸들을 가져옴
  aHWND:=GetForegroundWindow;
  // 그런거 없다면 그냥 관둠...
  if aHWND=0 then Exit;
  // 최상위 윈도우의 ClientRect, WindowRect 가져옴
  WinAPI.Windows.GetClientRect(aHWND, cRect);
  Winapi.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) div 2;
    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;

procedure TForm1.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;

댓글 없음:

델파이 12.1이냐 11.3이냐?

 델파이가 12.1이 나왔습니다. 혹시 11.3버전의 커뮤니티버전이 필요하시는분이 있을 수 있을 것 같아 https://altd.embarcadero.com/.../RADStudio_11_3_esd_28... 와 이것 찾느랴 엄청고생함.