- 윈도우 프로그램은 하나 이상의 윈도우(윈도우 단위로 구성)를 가지고 메세지 구동 방식으로 실행됩니다.
■ WinMain 함수 매개변수
- 윈도우 프로그램의 main 함수
int APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) |
hInstance : 현재 실행을 시작하는 프로그램의 인스턴스 핸들
hPrevInstance : 이전에 실행된 동일 프로그램의 인스턴스 핸들
lpCmdShow : main 함수의 argv와 같은 기능
nCmdShow : 프로그램의 윈도우가 어떤 모습으로 실행될 것인지 결정
옵션은 최소화 상태, 감춰진 상태, 보통 상태 등이 있음
※ 용어
인스턴스 : 프로그램이 실행되어 메모리에 로딩된 상태에 있을 때.
핸들 : 메모리에 로딩된 인스턴스 식별하기 위해 사용. 즉 윈도우 식별자
이외에도 윈도우 프로그래밍에서 '핸들'은 특정 메모리 블록을 식별하기 위한 포인터.
■ WinMain 함수의 구성
1. 프로그램을 초기화 한다.
2. 인스턴스를 초기화 한다.
3. 메세지 루프를 돈다.
#include <windows.h> int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 프로그램 초기화 if( !hPrevInstance ) // 인스턴스가 처음 생성되는 경우에만 실행 if( !InitApplication(hInstance) ) return FALSE ;
// 인스턴스 초기화 if( !hInitInstance(hInstance, nCmdShow ) ) return FALSE ;
// 메세지 루프 return Run() } |
프로그램 초기화 : 프로그램의 인스턴스가 메모리에 처음 로딩될 때 수행해야 하는 초기화 작업
인스턴스 초기화 : 각각의 인스턴스가 메모리에 로딩될 때마다 수행해야 하는 초기화 작업
즉, 프로그램이 이미 실행되어 메모리에 인스턴스가 존재하면 두 번째 인스턴스가 생성될 때 프로그램 초기화 작업은 하지 않아도 된다. 인스턴스 초기화 작업만 하면 된다.
□ 프로그램 초기화 : 윈도우 클래스 등록
- Edit 컨트롤, Combo Box 컨트롤, List Box 컨트롤 등의 윈도우는 운영체제에 이미 클래스가 등록되어 있다. => 파생클래스로 상속을 받아 조작
- 그러나 우리가 만드는 윈도우는 새로운 기능을 가진 윈도우므로 이 윈도우 클래스를 운영체제에 새로 등록해 주어야 한다.
1. WNDCLASS 구조체에 값을 채움
2. RegisterClass 함수를 호출하여 윈도우 클래스 등록
BOOL InitApplication( HINSTANCE hInstance ) { WNDCALSS wc ; wc.style = CS_HREDRAW | CS_VERDRAW ; wc.lpfnWndProc = WndProc ; // 함수 포인터 wc.hInstance = hInstance ; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ) wc.hCursor = LoadCursor( NULL, IDC_ARROW ) ; wc.hbrBackgroud = (HBRUSH)GetStockObject( WHITE_BRUSH ) ; wc.lpszMenuName = NULL ; wc.lpszClassName = "ExampleCalss" ; wc.cbClsExtra = 0 ; wc.cbWndExtra = 0 ;
reutnr RegisterClass( &wc ) ; } |
。WNDCLASS 구조체
typedef struct _WNDCLASS { UNIT style ; // 윈도우 스타일 WNDPROC lpfnWndProc ; // 윈도우 프로시저(메세지를 처리할 함수) int cbClsExtra ; // (사용하지 않음) 미래 확장을 위해 사용된 값 int cbWndExtra ; // (사용하지 않음) 미래 확장을 위해 예약된 값 HANDLE hInstance ; // 인스턴스 핸들 HICON hIcon ; // 윈도우가 최소화 되었을 때 표시될 아이콘의 핸들 HCURSOR hCursor ; // 윈도우 위로 마우스 커서가 올라갔을 때 보여질 커서의 핸들 HBRUSH hbrBackground ; // 배경을 지우는데 사용할 브러시의 핸들 LPCTSTR lpszMenuName ; // 이 윈도우가 소유할 메뉴 LPCTSTR lpszClassName ; // 윈도우 클래스의 이름 } WNDCLASS ; |
□ 인스턴스 초기화 : 윈도우 생성
1. 핸들 정의
2. 윈도우를 생성 값을 핸들에 넘김
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd ; if( !(hWnd = CreateWindow("ExampleClass", "C로 만든 프로그램", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ) ) ) return FALSE ;
ShowWindow( hWnd, nCmdShow ) ; // 메인 프레임 윈도우를 화면에 보이게 한다. UpdateWindow( hWnd ) ; // 메인 프레임 윈도우를 다시 그려준다. return TRUE ; } |
。CreateWindow 함수의 매개변수
매개변수 | 의미 |
lpClassNamae | 프로그램 초기화 부분에서 등록한 윈도우 클래스의 이름 |
lpWindowName | 윈도우 타이틀 바에 출력될 문자열 |
dwStyle | 윈도우 스타일 |
x, y, nWidth, nHeight | 윈도우의 위치와 가로 세로 길이 |
hWndParent | 부모 윈도우의 핸들 |
hMenu | 메뉴의 핸들 |
hInstance | 인스턴스의 핸들 |
lpParam | CREATESTRUCT 구조체로 지정되는 윈도우 생성에 필요한 추가 정보 |
□ 메세지 루프
- 프로그램에 어떤 이벤트가 발생하면 윈도우 운영체제가 이를 감지하여 프로그램의 메세지 큐에 적당한 메세지를 넣어준다.
1. 프로그램의 메세지 큐에서 메세지를 가져온다.
2. 이 메세지의 정보를 알려준다.
3. 메세지를 윈도우 프로시저에 전달한다.
int Run() { MSG msg ; while( GetMessage( &msg, NULL, NULL, NULL ) ) { TranslateMessage( &msg ) ; DispatchMessag( &msg ) ; } return (int)msg.wParam ; } |
GetMessage 함수는 프로그램의 메세지 큐에서 메세지를 가져오는 기능을 수행합니다.
이 함수는 프로그램을 종료하라는 WM_QUIT 메세지를 가져오면 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환한다. FALSE를 만나면 while문을 빠져나온다.
키보드가 눌리면 WM_KEYDOWN 메시지가, 키보드가 떼지면 WM_KEYUP 메세지가 발생한다. Translatemessage 함수는 이 메세지 조합을 이용하여 KEY_CHAR, KEY_DEADCHAR, KEY_SYSCHAR 등의 메세지를 발생하여 실제로 어떤 문자가 눌렸는지 정보를 알려준다.
DispatchMessage 함수는 이 메세지를 윈도우 프로시저에 전달한다.
□ 윈도우 프로시저 : 메세지 처리
- 윈도우 메세지를 처리하는 함수로 이 함수를 어떻게 만드냐에 따라 윈도우 기능이 결정된다.
LRESIT WINAPI WndProc(HANDLE hWnd, UNIT message, WPARAM wParam, LPARAM lParam) { switch( message ) { case WM_KEYDOWN : // 키보드가 눌렸을 때의 처리 break ; case WM_LBUTTONDOWN : // 마우스 왼쪽 버튼이 클릭되었을 때 break ; case WM_MOUSEMOVE : // 마우스가 움직였을 때 break ; } return DefWindowProc( hWnd, message, wParam, lParam ) ; } |
DefWindowProc 함수는 윈도우 운영체제가 미리 정해둔 윈도우의 기본 기능을 수행하도록 한다.
'개발지식창고 > Win32 API' 카테고리의 다른 글
리소스 풀어 헤치기 (0) | 2012.01.13 |
---|---|
특수 폴더 경로 알기 (SHGetSpecialFolderPath) (0) | 2012.01.12 |
64비트 기반 프로그래밍 (0) | 2011.03.20 |
작업관리자에서 프로세스 이름 감추기 (0) | 2010.08.22 |