이번에는 지금까지 공부했던 함수들을 모아모아 1초에 한번씩 화면을 캡쳐해서 그 화면을 파일로 해당 폴더에 저장해주는 프로그램을 만들어 보았습니다. 뭐 지금까지 공부했던 걸 그냥 모아서 만든 프로그램이라 그렇게 어려운 부분은 없었던거 같습니다. 이번에는 유니코드를 다 지원해주고 하느라 좀 골치가 아팠었는데요. 덕분에 유니코드에 대해서 좀 많이 알수 있었던 것 같습니다~
혹시 위 함수들에 대해서 잘 모르겠다 싶으신분들은 이전 포스트들에 적혀져 있는 것을 보시면 자세히 알수 있을 것입니다~
#include <windows.h>
#include <shlwapi.h>
#include "Resource.h"
#pragma comment(lib, "shlwapi")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void CALLBACK TimeProc(HWND, UINT, UINT, DWORD);
void SaveBitmap(HBITMAP, LPCTSTR);
BOOL CreateDirectoryFunc(LPCTSTR);
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("ScreenCapturForTimer");
HBITMAP FullScreenCapture(HWND);
HBITMAP g_hBit;
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 = MAKEINTRESOURCE(IDR_MENU1);
WndClass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd=CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 200, 100, NULL, (HMENU)NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
HACCEL hAccel;
hAccel=LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
while(GetMessage(&Message, 0, 0, 0))
{
if(!TranslateAccelerator(hWnd, hAccel, &Message))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}
return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HMENU hMenu = GetMenu(hWnd);
TCHAR szPath[] = TEXT("D:\\CaptureTest1\\test\\test\\"); //파일을 저장할 폴더
switch(iMessage)
{
case WM_CREATE:
CreateDirectoryFunc(szPath); //폴더 생성 함수
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_MENU_CAPTURESTART:
SetTimer(hWnd, 1, 1000, TimeProc); //1초에 한번씩 TimeProc를 호출
EnableMenuItem(hMenu, ID_MENU_CAPTUREEND, MF_ENABLED);
EnableMenuItem(hMenu, ID_MENU_CAPTURESTART, MF_GRAYED);
break;
case ID_MENU_CAPTUREEND:
EnableMenuItem(hMenu, ID_MENU_CAPTURESTART, MF_ENABLED);
EnableMenuItem(hMenu, ID_MENU_CAPTUREEND, MF_GRAYED);
KillTimer(hWnd, 1); //타이머를 없앰..
break;
case ID_MENU_EXIT:
DestroyWindow(hWnd);
break;
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
// 초당 화면캡쳐 함수와 파일 저장함수를 호출해주는 콜백 함수
void CALLBACK TimeProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
SYSTEMTIME st;
GetLocalTime(&st);
TCHAR str[MAX_PATH];
wsprintf(str, TEXT("D:\\CaptureTest1\\test\\test\\%d%d%d%d%d%d.BMP"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
g_hBit = FullScreenCapture(hWnd);
SaveBitmap(g_hBit , str);
}
// 폴더를 생성하는 함수
// 경로로 지정한 모든 폴더를 생성함
BOOL CreateDirectoryFunc(LPCTSTR path)
{
TCHAR szPathBuffer[MAX_PATH];
UINT len = lstrlen(path);
for(UINT i = 0; i < len; i++)
{
szPathBuffer[i] = *(path + i);
if(szPathBuffer[i] == TEXT('\\') || szPathBuffer[i] == TEXT('/'))
{
szPathBuffer[i + 1] = NULL;
if(!PathFileExists(szPathBuffer))
{
if(!CreateDirectory(szPathBuffer, NULL))
{
if(GetLastError() != ERROR_ALREADY_EXISTS)
return FALSE;
}
}
}
}
return TRUE;
}
// 캡쳐한 화면을 BITMAP 파일로 저장함
void SaveBitmap(HBITMAP hBit, LPCTSTR path)
{
BITMAPFILEHEADER bFile;
BITMAPINFOHEADER bInfo;
BITMAP bit;
BITMAPINFO *pih;
int PalSize;
HANDLE hFile;
DWORD dwWritten,Size;
HDC hdc;
hdc = GetDC(NULL);
GetObject(hBit, sizeof(BITMAP), &bit);
bInfo.biSize=sizeof(BITMAPINFOHEADER);
bInfo.biWidth=bit.bmWidth;
bInfo.biHeight=bit.bmHeight;
bInfo.biPlanes=1;
bInfo.biBitCount=bit.bmPlanes*bit.bmBitsPixel;
if(bInfo.biBitCount>8) bInfo.biBitCount=24;
bInfo.biCompression=BI_RGB;
bInfo.biSizeImage=0;
bInfo.biXPelsPerMeter=0;
bInfo.biYPelsPerMeter=0;
bInfo.biClrUsed=0;
bInfo.biClrImportant=0;
PalSize=(bInfo.biBitCount==24?0:1 << bInfo.biBitCount)*sizeof(RGBQUAD);
pih=(BITMAPINFO *)malloc(bInfo.biSize+PalSize);
pih->bmiHeader=bInfo;
GetDIBits(hdc,hBit,0,bit.bmHeight, NULL,pih,DIB_RGB_COLORS);
bInfo=pih->bmiHeader;
if(bInfo.biSizeImage==0)
{
bInfo.biSizeImage=((((bInfo.biWidth*bInfo.biBitCount) +31 ) & ~31) >> 3) * bInfo.biHeight;
}
Size = bInfo.biSize+PalSize+bInfo.biSizeImage;
pih=(BITMAPINFO *)realloc(pih,Size);
GetDIBits(hdc,hBit,0,bit.bmHeight,(PBYTE)pih+bInfo.biSize+PalSize,pih,DIB_RGB_COLORS);
bFile.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+PalSize;
bFile.bfReserved1=0;
bFile.bfReserved2=0;
bFile.bfSize=Size+sizeof(BITMAPFILEHEADER);
bFile.bfType=0x4d42;
hFile=CreateFile(path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
WriteFile(hFile,&bFile,sizeof(bFile),&dwWritten,NULL);
WriteFile(hFile,pih,Size,&dwWritten,NULL);
ReleaseDC(NULL,hdc);
CloseHandle(hFile);
}
//전체 화면을 캡쳐해 주는 함수
HBITMAP FullScreenCapture(HWND hWnd)
{
int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
HDC hScrDC, hMemDC;
HBITMAP hBitmap;
hScrDC=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
hMemDC=CreateCompatibleDC(hScrDC);
hBitmap=CreateCompatibleBitmap(hScrDC, ScreenWidth, ScreenHeight);
SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC,0,0,ScreenWidth,ScreenHeight,hScrDC,0,0,SRCCOPY);
DeleteDC(hMemDC);
DeleteDC(hScrDC);
return hBitmap;
}
Resource.h 파일의 내용입니다
#define IDR_MENU1 101
#define IDR_ACCELERATOR1 102
#define ID_MENU_CAPTURESTART 40001
#define ID_MENU_CAPTUREEND 40002
#define ID_MENU_EXIT 40003
메뉴는 캡쳐시작과 캡쳐 끝내기, 프로그램 끝내기 메뉴로 구성되고 액셀러레이터는 저 3 메뉴에 대해서 다 걸려 있습니다
이프로그램을 실행시켜보면 다음과 같이 나올꺼에요...
참 허접한 내용이지만 끝까지 봐주셔서 감사하고요. 혹시 문제 되는 점이나 이해가 안가는 부분은 덧글 남겨주시면 또 열심히 알아보고 답변해드리겠습니다~
감사합니다`~^^
'API' 카테고리의 다른 글
디렉토리 생성 (0) | 2010.03.27 |
---|---|
Win API Timer (0) | 2010.03.21 |
캡쳐 화면 BMP로 저장하기 (0) | 2010.03.14 |
메뉴의 단축키, 액셀러레이터 생성 (0) | 2010.03.12 |
메뉴 만들기 (1) | 2010.03.11 |
포커스가 있는 윈도우 캡쳐 (0) | 2010.03.10 |
API로 구현한 전체화면 캡쳐 소스 (0) | 2010.03.09 |
DC 구조체에 관해.... (1) | 2010.03.09 |
버튼 생성 (0) | 2010.03.06 |
API의 첫 시작 (0) | 2010.03.05 |