전체화면 캡쳐에 이어서 포커스가 있는 윈도우의 캡쳐하는 소스에 대해서 보도록 하겠습니다. 이번에는 핫키를 이용해서 해당 핫키를 눌렀을때 지금 포커스가 있는 윈도우를 캡쳐하게 하는 소스입니다. 우선 전체 화면 캡쳐와는 많은 차이가 없으므로 바로 소스와 약간의 분석을 하도록 하겠습니다.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HBITMAP ScreenCapture(HWND);
HINSTANCE g_hInst;
LPCTSTR lpszClass=TEXT("ScreenCapturTest");
HBITMAP hBit = NULL;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst = hInstance;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc;
WndClass.lpszClassName = lpszClass;
WndClass.lpszMenuName = NULL;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
while(GetMessage(&Message, NULL, 0, 0))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HDC hScrDC, hMemDC;
HBITMAP hOldBitmap;
BITMAP bmp;
switch(iMessage)
{
case WM_CREATE:
RegisterHotKey(hWnd, 0, MOD_CONTROL, VK_F4);
break;
case WM_HOTKEY:
hBit = ScreenCapture(hWnd);
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
if(hBit != NULL)
{
hMemDC = CreateCompatibleDC(hdc);
SelectObject(hMemDC, hBit);
GetObject(hBit, sizeof(BITMAP), &bmp);
BitBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
}
else
{
}
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
if(hBit != NULL)
{
DeleteObject(hBit);
}
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
HBITMAP ScreenCapture(HWND hWnd)
{
HDC hScrDC, hMemDC;
HBITMAP hBitmap;
RECT rt;
GetWindowRect(GetForegroundWindow(), &rt);
rt.left = max(0, rt.left);
rt.right = min(rt.right, GetSystemMetrics(SM_CXSCREEN));
rt.top = max(0, rt.top);
rt.bottom = min(rt.bottom, GetSystemMetrics(SM_CYSCREEN));
hScrDC=CreateDC("DISPLAY",NULL,NULL,NULL);
hMemDC = CreateCompatibleDC(hScrDC);
hBitmap = CreateCompatibleBitmap(hScrDC, rt.right-rt.left, rt.bottom-rt.top);
SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, rt.right-rt.left, rt.bottom-rt.top, hScrDC, rt.left, rt.top, SRCCOPY);
DeleteDC(hMemDC);
DeleteDC(hScrDC);
InvalidateRect(hWnd, NULL, TRUE);
return hBitmap;
}
소스는 위와 같은데요 우선 전반적인 부분과 특히 화면캡쳐를 하는 ScreenCapture 함수에 전반적인 코드에는 많은 변화는 없습니다. 단지 현재 포커스가 가있는 윈도우의 위치와 크기를 구해서 그 윈도우의 크기만큼만 비트맵으로 복사를 하게 하는 것이지요.
도우창이 만들어질 때 핫키를 등록하도록 하였습니다. 혹시 핫키가 무엇인지 모르는분들을 위해 설명하자면 우리가 윈도우에서 작업을 할때 단축키를 많이 쓰게 될것입니다. 핫키가 바로 그 단축키를 말하는 것입니다. 뭐 대단한걸 소개하는것 처럼 되버리긴 했지만 핫키를 알아두면 할 수 있는게 참 많아지겠죠 ^^ 핫키를 등록하는 방법은 RegisterHotKey()함수를 사용해서 등록하게 되는데요. 첫번째 인자는 윈도우 핸들러를 가저오게 되고 두번째 인자는 키의 아이디 값입니다. 세번째 인자는 특수키의 값, 네번째는 일반키를 나타내게 됩니다. 현재는 컨트롤 F$를 누르면 이벤트가 일어나게 되어 있습니다.
그리고 핫키가 눌렸을 때 WM_HOTKEY 메시지 루틴이 실행되게 됩니다. 이때 저는 ScreenCapture 함수를 호출해서 실제로 캡쳐를 하게 되는 것이죠.
그럼 화면 캡쳐 하는 부분에서 수정된 부분만 보도록 하겠습니다. RECT 라는 구조체를 가져와 포커스를 가진 윈도우의 정보를 채울 준비를 하고요. GetWindowRect 함수를 이용해 해당 윈도우의 위치, 크기 정보를 가져오게 합니다. GetForegroundWindow() 함수로 해당 포커스가 있는 윈도우를 알아내고 그 정보를 rt에 리턴해주는 것입니다. rt의 4가지 크기의 수정은 해당 윈도우 밖의 영역이 캡쳐 되지 않도록 수정해 주는 것이고요. 그밖에 부분은 캡쳐 크기만 틀려지게 해놓았다는 것을 제외하고는 다 똑같은 것을 볼 수가 있지요.
해당 화면은 프로그램을 실행시키고 MSDN에 포커스를 두고 컨트롤+F4를 눌렀을때의 화면입니다. 캡쳐가 잘 되는 것을 볼수가 있지요 ^^
보시는 것과 같이 약간의 API 함수의 변경으로도 이렇게 다른 효과를 줄수가 있습니다. 그럼 다음에는 마우스 영역을 캡쳐하는것을 보도록 하지요 ^^
감사합니다.
P.S 혹시 전체 화면 캡쳐에 대해 보고싶은 분이 있을지 몰라 바로 링크 넣어드립니다 ^^
http://darkangelus.tistory.com/entry/API로-구현한-전체화면-캡쳐-소스
출처 : api 정복
'API' 카테고리의 다른 글
1초에 한번씩 캡쳐 화면 파일로 저장하기 (0) | 2010.03.27 |
---|---|
디렉토리 생성 (0) | 2010.03.27 |
Win API Timer (0) | 2010.03.21 |
캡쳐 화면 BMP로 저장하기 (0) | 2010.03.14 |
메뉴의 단축키, 액셀러레이터 생성 (0) | 2010.03.12 |
메뉴 만들기 (1) | 2010.03.11 |
API로 구현한 전체화면 캡쳐 소스 (0) | 2010.03.09 |
DC 구조체에 관해.... (1) | 2010.03.09 |
버튼 생성 (0) | 2010.03.06 |
API의 첫 시작 (0) | 2010.03.05 |