240 likes | 449 Views
2. Windows 와 메시지. 1. 첫번째 API 프로그램. #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("HelloWin") ; HWND hwnd ;
E N D
2. Windows 와 메시지
1. 첫번째 API프로그램 #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("HelloWin") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; • wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; • wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; • wndclass.lpszMenuName = NULL ; • wndclass.lpszClassName = szAppName ; • if (!RegisterClass (&wndclass)) • { • MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName, • MB_ICONERROR) ; • return 0 ; • }
hwnd = CreateWindow (szAppName, // window class name "The Hello Program", // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; }
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps ; RECT rect ; switch (message) { case WM_CREATE: PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME |SND_ASYNC) ; return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, "Hello, Windows 98!", -1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }
2. 첫 번째 API프로그램 분석 • 헝거리언 표기법 • MS사의 전설적인 프로그래머 Charles Simonyi를 기리는 뜻으로 붙여진 이름) • char szAddress[50]; 해당 변수의 데이터 타입을 나타내는 접두어 표기
2. 첫 번째 API프로그램 분석 • 접두어
2. 첫 번째 API프로그램 분석 • 새로운 데이터 형식들
2. 첫 번째 API프로그램 분석 • 새로운 데이터 형식들 • 윈도우 클래스 등록하기 • 윈도우는 항상 윈도우 클래스를 기반으로 하여 생성된다. • 모든 Button윈도우는 동일한 윈도우 클래스를 기반으로 하여 생성된다. • 윈도우 클래스는 윈도우의 특성들을 정의한다. • 응용 프로그램은 윈도우를 생성하기 전에 반드시 RegisterClass를 호출하여 윈도우 클래스를 등록해야 한다.
2. 첫 번째 API프로그램 분석 typedef struct { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; } WNDCLASS, * PWNDCLASS,NEAR * NPWNDCLASSA, FAR * LPWNDCLASSA; • wndclass.style=CS_HREDRAW|CS_VREDRAW; • 수평 또는 수직윈도우가 변경될 때마다 완전히 새로 클래스의 Brush로 다시 칠하게 된다. • winuser.h에 정의되어 있다.
2. 첫 번째 API프로그램 분석 /* Class styles */ #define CS_VREDRAW 0x0001 #define CS_HREDRAW 0x0002 #define CS_DBLCLKS 0x0008 #define CS_OWNDC 0x0020 #define CS_CLASSDC 0x0040 #define CS_PARENTDC 0x0080 #define CS_NOCLOSE 0x0200 #define CS_SAVEBITS 0x0800 #define CS_BYTEALIGNCLIENT 0x1000 #define CS_BYTEALIGNWINDOW 0x2000 #define CS_GLOBALCLASS 0x4000 #define CS_IME 0x00010000 • wndclass.lpfnWndProc = WndProc ; • 윈도우와 연결되는 윈도우 함수를 연결한다. • wndclass.cbClsExtra = 0; • wndclass.cbWndExtra = 0; • 윈도우 클래스에 여유공간을 두거나, 윈도우에 여유공간을 예약하는데 사용
2. 첫 번째 API프로그램 분석 • cbClsExtra • 윈도우 클래스에서 사용하고자 하는 여분의 메모리 양 • 바이트 수로 지정한다. • 운영체제는 윈도우 클래스를 등록할 때 이 멤버가 지정하는 만큼의 메모리를 추가로 할당해 준다 • SetClassLong, GetClassLong함수로 이 메모리를 사용한다. • cbWndExtra • 개별 윈도우에서 사용하고자 하는 여분의 메모리 양을 지정한다. • 운영체제는 개별 윈도우가 만들어질 때마다 이 멤버가 지정하는 만큼의 메모리를 추가로 할당해 준다. • GetWindowLong,SetWindowLong함수로 이 메모리를 사용한다.
2. 첫 번째 API프로그램 분석 • wndclass.hInstance = hInstance • 프로그램의 인스턴스 핸들 • wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION) • 이 윈도우 클래스를 기반으로 하여 생성된 모든 윈도우에 대한 아이콘을 설정한다. • 프로그램이 실행될 때 아이콘은 Windows작업 표시줄에 나타난다. • 프로그램에 있는 ICON을 지정하려면 NULL에 hInstance를 넣는다. • wndclass.hCursor = LoadCursor(NULL,IDI_APPLICATION) • 윈도우에서 사용하는 커서를 지정한다. • wndcalss.hbrBackground = GetStocObject(WHITE_BRUSH) ; • Window의 배경색을 지정한다. • Windows에는 여러 가지의 표준 혹은 ‘stock’브러쉬가 있다. • wndclass.hMenu = NULL; • 윈도우의 메뉴를 지정한다. • wndclass.lpszClassName=szAppName; • 클래스는 반드시 이름을 부여 받아야 한다. • RegisterClass를 호출하여 윈도우 클래스를 등록
2. 첫 번째 API프로그램 분석 if (!RegisterClass(&wndclass)) { MessageBox(NULL,TEXT(“This program requires Windows NT!”, szAppName,MB_ICONERROR); return 0; }
2. 첫 번째 API프로그램 분석 • 윈도우 생성하기 hwnd = CreateWindow ( szAppName, // window class name "The Hello Program", // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters • CreateWindow를 호출하여 윈도우 생성 • CreateWindow시에는 윈도우의 개별적인 특징을 지정한다. • 윈도우의 크기, 윈도우의 위치,…
2. 첫 번째 API프로그램 분석 • WS_OVERLAPPENDWINDOW • 제목표시줄,시스템메뉴,두꺼운 윈도우 크기 변경 경계, 제목표시줄의 최소화,최대화,닫기 단추 • (WINUSER.H에서 확인) #define WS_OVERLAPPEDWINDOW ( WS_OVERLAPPED | WS_CAPTION | \ WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | \ WS_MAXIMIZEBOX) • 부모 윈도우 핸들 • 부모 윈도우를 만드는 경우는 NULL • 자식 윈도우를 만드는 경우는 부모 윈도우의 핸들값 • 윈도우 메뉴 핸들 • 윈도우 클래스에서 지정한 메뉴를 사용하려면 NULL • 윈도우 클래스에서 지정한 메뉴를 사용하지 않으려면 메뉴의 핸들을 지정한다. • 프로그램 인스턴스 핸들 • WinMain의 매개변수로 프로그램에 전달되는 인스턴스의 핸들을 지정한다. • Return값 • 생성된 윈도우의 핸들
2. 첫 번째 API프로그램 분석 • CreateWindow()후에는 윈도우가 내부적으로 생성되어 있다. • 화면에는 보이지 않는 상태 • 화면에 출력하려면 • ShowWindow(hwnd,iCmdShow) • hwnd : CreateWindow()의 리턴 값. • iCmdShow : 초기에 화면에 윈도우가 어떻게 표시되는 지를 나타낸다. • 윈도우를 화면에 나타내며 지정된 브러쉬로 윈도우의 Client영역을 칠한다.
2. 첫 번째 API프로그램 분석 • 메시지 루프 • 메시지 루프는 세 개의 함수 호출로 이루어져 있으며 전체 루프는 while문으로 싸여져 있어 무한히 반복되는 구조를 가지고 있다. • 이벤트가 발생하면 Windows는 이벤트를 메시지로 변환하여 프로그램의 메시지 큐에 저장한다. • GetMessage( &msg,NULL,0,0) • 메시지 큐로부터 메시지를 읽어 온다. • 읽어들인 메시지는 첫 번째 인수가 지정하는 MSG 구조체에 저장된다. • WM_QUIT 메시지인 경우 0을 Return한다. 그 이외의 메시지이면 TRUE를 리턴한다. • 나머지 세 개의 인수는 읽어 들일 메시지의 범위를 지정한다. 잘 사용하지 않는다.
2. 첫 번째 API프로그램 분석 while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } typedef struct tagMSG { HWND hwnd; UINT message;//어떤 종류의 메시지인가를 나타낸다. WPARAM wParam; // 전달된 메시지의 부가적인 정보 LPARAM lParam; // DWORD time; // 메시지가 메시지 큐에 저장된 시간 POINT pt; //메시지 큐에 저장된 시간의 마우스 좌표 } MSG , * PMSG typedef struct tagPOINT { LONG x; LONG y; } POINT, * PPOINT;
2. 첫 번째 API프로그램 분석 • TranslateMessage(&msg); • 키보드 번역 • DisplatchMessage(&msg); • 메시지 큐에서 꺼낸 메시지를 윈도우 프로시저로 전달한다. • 윈도우 프로시저 LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam, LPARAM lParam) • 윈도우 프로시저는 항상 RegisterClass를 호출하여 등록한 특정한 윈도우 클래스와 연결되어 있다. • SendMessage라는 함수를 통해서 자신의 윈도우 프로시저를 간접적으로 호출한다. • Message는 WINUSER.H에 define되어 있다. • 윈도우 프로시저가 메시지를 처리할 때에 반드시 윈도우 프로시저로부터 0이 반환되어야 한다. • 윈도우 프로시저가 처리하지 않는 모든 메시지들은 반드시 DefWindowProc라는 이름의 Windows함수에 전달되어야 한다.
2. 첫 번째 API프로그램 분석 • WM_PAINT 메시지 • 윈도우 클라이언트 영역의 일부가 무효화 영역이 되면 발생한다. • 윈도우가 다시 그려져야 함을 알린다. • CS_HREDRAW,CS_VREDRAW는 윈도우의 크기가 변경될 때WM_PAINT를 발생시킨다. • WM_PAINT는 항상 hdc=BeginPaint(hwnd,&ps) • EndPaint( hwnd, &ps)를 이용하여 처리한다. • BeginPaint는 dc의 handle를 반환한다. • BeginPaint호출중에 Windows는 클라이언트 영역의 배경을 윈도우 클래스에 지정한 브러쉬로 지운다. • GetClientRect(hwnd,&rect)는 클라이언트의 크기를 Return한다. • DrawText (hdc, "Hello, Windows 98!",-1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; • 텍스트를 그려준다. • 세 번째 인자 –1은 문자열이 NULL로 종료됨을 의미
2. 첫 번째 API프로그램 분석 • DC란 • 출력에 필요한 모든 정보를 가지는 데이터 구조체이다. • 어떤 폰트를 사용할 것이지, 선의 색상과 굵기, 채움 무늬와 색상, 출력방법 과 같은 정보를 담고 있다. • 모든 출력은 윈도우를 기준으로 하며 이러한 원점에 대한 정보도 DC에 있다. • 현재 상황에서 어떤 영역이 출력이 허가된 영역인가를 보고 허가된 영역에만 출력을 내 보낸다. • GDI모듈에 의해 관리된다. • DrawText(HDC uDC, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat);
2. 첫 번째 API프로그램 분석 • int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) • hWnd : 메시지 박스의 오너 윈도우 핸들
2. 첫 번째 API프로그램 분석 • WM_DESTROY메시지 • 윈도우가 종료되고 있음을 나타낸다. • 사용자가 종료단추를 클릭하거나 시스템 메뉴의 종료 메뉴를 선택하면 WM_DESTOROY를 발생시킨다. • PostQuitMessage(0); • 메시지큐에 WM_QUIT를 삽입한다. • GetMessage()는 메시지가 WM_QUIT면 0을 리턴한다. • 종료 버튼 클릭시 종료순서 • => WM_SYSCOMMAND • => WM_CLOSE • => DestoryWindow() • => WM_DESTORY • => PostQuitMessage()를 call • => 메시지큐에 WM_QUIT를 넣는다.
2. 첫 번째 API프로그램 분석 • 큐에 저장되는 메시지와 큐에 저장되지 않는 메시지 • 큐에 저장되는 메시지 • 키 스트로크 메시지 • WM_KEYDOWN,WM_KEYUP,WM_CHAR • 마우스 메시지 • WM_LBUTTONDOWN,WM_RBUTTONDOWN,WM_MOUSEMOVE • 타이머 메시지 : WM_TIMER • 다시 그리기 메시지 : WM_PAINT • 종료 메시지 : WM_QUIT • 큐에 저장되지 않는 메시지 • 특정한 Window함수 호출의 결과이다. • CreateWindow() : WM_CREATE • ShowWindow() : WM_SIZE,WM_SHOWWINDOW • UpdateWindow() : WM_PAINT메시지를 윈도우 프로시저에 보낸다. • WM_COMMAND • 메시지 큐와 윈도우 프로시저는 동시에 수행되지 않는다. • DispatchMessage()는 윈도우 프로시저가 Window에게 컨트롤을 넘기기 전까지는 반환되지 않는다.