4.25k likes | 4.5k Views
Win32 API. 강사 : 이준근 (egenie@korea.com). 1. 윈도우 프로그래밍의 이해. Application. MFC. VB. ATL/COM. owl. Delphi. DirectX OPEN/GL. API. Windows Kernel. HAL. HardWare. 1. API 의 Positioning. 2. Windows 의 구성. Windows 의 특징 32bit 선점형 멀티태스킹과 멀티스레딩을 지원하는 그래픽 운영체제이다 . 비선점형 :
E N D
Win32 API 강사 : 이준근 (egenie@korea.com)
1. 윈도우 프로그래밍의 이해
Application MFC VB ATL/COM owl Delphi DirectX OPEN/GL API Windows Kernel HAL HardWare 1. API의 Positioning
2. Windows의 구성 • Windows의 특징 • 32bit 선점형 멀티태스킹과 멀티스레딩을 지원하는 그래픽 운영체제이다. • 비선점형 : • 프로그램이 스스로 제어를 다른 프로그램에게 넘겨 주어야 한다. • GUI환경이다. • “GUI는 개인용 컴퓨터 산업의 가장 중요하고 유일한 ‘대중적 합의’라는 점은 이제 명백해 졌다.” - Charles Simonyi • GUI의 특징 • 1. 더 이상 컴퓨터나 새로운 프로그램의 사용법을 배우는데 많은 시간을 소비하지 않아도 된다. • 2. 일관된 사용자 인터페이스를 이용한다는 것은 메뉴와 대화상자를 구성할 때 Windows에 내장된 루틴을 이용한다는 것을 의미한다. • ‘동적 연결’이라는 개념을 중심으로 동작한다. • Windows에서 실행되는 프로그램은 ‘동적 연결 라이브러리’라고 하는 파일에 존재하는 루틴을 공유한다.
2. Windows의 구성 • 프로그램은 시스템에 연결되어 있는 장치의 종류를 몰라도 된다. • 화면 및 프린터와 같은 그래픽 디스플레이 장치의 하드웨어를 직접 사용하지 않는다.
3. 첫 번째 API프로그램 #include <windows.h> int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance, PSTR szCmdLine, int CmdShow) { MessageBox (NULL, "Hello, Windows 98!","HelloMsg", MB_OK) ; return 0 ; } • #include <windows.h> • 다른 Windows헤더 파일을 포함하는 마스터 include 파일이다. • WINDEF.H 기본형식 정의 • WINNT.H 유니코드지원을 위한 형식 정의 • WINBASE.H Kernel함수 • WINUSER.H 사용자 인터페이스 함수 • WINGDI.H 그래픽 장치 인터페이스 함수
4. 프로그램 진입점 int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance, PSTR szCmdLine, int CmdShow) • WINAPI windef.h에 정의되어 있다. • #define WINAPI __stdcall • Parameters • HINSTANCE hInstance : • 프로그램의 인스턴스 핸들 • HINSTANCE hPrevInstance : • 항상 NULL이다. • PSTR szCmdLine : • 프로그램을 실행할 때 사용된 명령줄 • int iCmdShow : • 최대화할 것인지 또는 아이콘화 하여 작업 표시줄에 표시할 것인지 지정 __stdcall은 함수를 호출하면 호출된 함수쪽에서 리턴하기 전에 스텍에 저장된 인자들을 정리하는 방식으로 16비트시절의 PASCAL호출규약과 동일하다.
4. 프로그램 진입점 • MessageBox : • 메시지 박스를 나타내는 함수
4. 사고의 전환을 위하여 • 도스 프로그래밍과 윈도우 프로그래밍의 차이점 • 도스 프로그램 : 절차적 (또는 순차적) • 프로그램의 실행 흐름이 프로그래머가 기술한 코드의 순서에 따라 진행한다. • 사용자의 키보드 조작이나 마우스의 움직임을 프로그래머가 일일이 알아서 직접 제어해야 한다. • 외부에서 무슨 일(이벤트)이 일어났는지 프로그래머가 알아내야 하고이에 따른 처리까지 맡아서 해야 한다. • 윈도우 프로그램 : • 이벤트 구동(Event-Driven)방식 또는 메시지 처리 방식 • 프로그램의 실행 흐름을 윈도우 시스템과 일을 분담하여 처리한다. • 외부에서 일어나는 일을 윈도우 시스템이 감지하여 해당 프로그램에 메시지를 전달하여 알려준다. • 프로그램은 이에 대한 처리만 한다. • 프로그래밍이 한결 수월해 진다. • Ex) Spy++ Test
5. 윈도우 프로그래밍과 친해지자 이벤트(Event)와 메시지(Message) 메시지 루프(Message Loop) 메시지 큐 (Queue) 핸들(Handle) 윈도우 프로시져 리소스(Resource) 인스턴스(Instance) 하드웨어 운용 방식
5. 윈도우 프로그래밍과 친해지자 • 이벤트(Event)와 메시지(Message) • 사용자가 키보드의 특정 키를 누르거나 마우스의 좌측 버튼을 클릭하는 등의 일을 할 때 이벤트가 발생한다. • 이벤트가 발생하면 윈도우 OS는 이름 감지하여 해당 프로그램으로 메시지를 전달한다. • 메시지에는 마우스의 좌측 버튼을 눌렀을 때 커서의 위치등과 같은 부가 정보가 함께 포함되어 있다. • WinUser.h [마우스에 관련된 Message들] #define WM_MOUSEMOVE 0x0200 #define WM_LBUTTONDOWN 0x0201 #define WM_LBUTTONUP 0x0202 #define WM_LBUTTONDBLCLK 0x0203 #define WM_RBUTTONDOWN 0x0204 #define WM_RBUTTONUP 0x0205 ( Winuser.h)
5. 윈도우 프로그래밍과 친해지자 typedef struct tagMSG { HWND hwnd; // 메시지를 받을 윈도우의 핸들 UINT message; //전달되는 메시지 유형 WPARAM wParam; //메시지와 관련된 부가적인 정보 LPARAM lParam; //메시지와 관련된 부가적인 정보 DWORD time; // 메시지가 전달된 시간 POINT pt; //메시지가 큐에 저장될 때의 마우스 위치 } MSG; typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; }MSG; WM_LBUTTONDOWN Key Flag LOWORD(lParam) HIWORD(lParam)
5. 윈도우 프로그래밍과 친해지자 • 메시지 큐(Message Queue) • 사용자의 컴퓨터 조작에 의해 발생한 이벤트는 메시지형태로 만들어져 윈도우 OS가 관리하는 “메시지 큐”에 저장된다. • 윈도우 시스템 전체를 관리하기 위한 [시스템 메시지 큐]와 응용 프로그램마다 별도 갖고 있는 [프로그램 메시지 큐]가 있다.
5. 윈도우 프로그래밍과 친해지자 시스템 메시지 큐 윈도우 OS 시스템 분배기 (RIT:Raw Input Thread) 프로그램 메시지 큐 프로그램 메시지 큐 프로그램 A 프로그램 B
5. 윈도우 프로그래밍과 친해지자 • 메시지 루프 • OS로부터 전달된 메시지를 보관하는 큐에 어떤 메시지가 들어왔는지를 지속적으로 감시하고 분석해주는 부분이 필요하다. While( GetMessage( &msg,NULL,0,0) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); }
5. 윈도우 프로그래밍과 친해지자 • 윈도우 프로시저(Window procedure) • 자신이 만든 함수이지만 자신이 직접 호출하지 않고 운영체제에서 호출하는 함수를 콜백함수라고 한다. • 함수 앞에 CALLBACK으로 선언 • 윈도우 프로시저는 콜백함수이다. • 모든 윈도우는 해당 윈도우 프로시저를 갖고 있다. • 메시지 루프에서 해석한 메시지를 구체적으로 처리하는 기능을 수행 • Call Back 함수는 윈도우에서 자동으로 불려지는 함수이다.그러므로 Language independent 해야 한다. • (호출형식을 통일해야 한다) • windef.h LRESULT CALLBACK WndProc( HWND hWnd, UNIT uMgs, WPARAM wParam,LPARAM lParam); #define CALLBACK __stdcall #define WINAPI __stdcall
5. 윈도우 프로그래밍과 친해지자 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (iMsg) { case WM_CREATE : PlaySound ("hellowin.wav", NULL, SND_FILENAME | SND_ASYNC) ; return 0 ; case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, "Hello, Windows 95!", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }
5. 윈도우 프로그래밍과 친해지자 • 핸들 (Handle) • 핸들은 프로그램에서 현재 사용중인 객체들을 식별하기 위해 윈도우 OS가 부여하는 고유 번호이다. • 그러면 왜 포인터를 이용하지 않고 핸들을 이용할까? Ex) HWND 윈도우에 대한 핸들 HCURSOR 커서에 대한 핸들 HICON 아이콘에 대한 핸들 HMENU 메뉴에 대한 핸들 총 메모리가 80KB라고 가정하자. 이때 30KB의 그림판, 40KB를 차지 하는 Visual C++을 실행시키면 그림판 (30KB) 비주얼 C++ (40KB) 여유공간 (10KB) 그림판을 종료하고 20KB를 필요로 하는 메모장을 실행시키면 메모장 (20KB) 여유공간 (10KB) 비주얼 C++ (40KB) 여유공간 (10KB)
5. 윈도우 프로그래밍과 친해지자 => 내부적으로 윈도우는 메모리 블록을 이리저리 이동시켜 필요 공간을 확보한다. (윈도우OS의 메모리 관리 기법) Ex) HGLOBAL GlobalAlloc( UINT uFlags, // allocation attributes DWORD dwBytes // number of bytes to allocate); GMEM_FIXED Allocates fixed memory. The return value is a pointer. GMEM_MOVEABLE Allocates movable memory. • 메모리 블록이 이리저리 이동되는 상황에서 도스에서처럼 포인터를 직접 활용한다면 OS가 할당된 메모리 블록을 함부로 이동시킬 수 없게 되고, 이동시킨다고 해도 프로그램쪽에서 이동되는 상황을 알 수 없기 때문에 엉뚱한 메모리 주소를 참조하게 될 것이다.
5. 윈도우 프로그래밍과 친해지자 • 인스턴스 • 프로그램은 명령들이 나열된 코드 영역(Code Segment)과 데이터를 보관하는 데이터 영역(Data Segment)으로 구분 • 동일한 프로그램에 코드 영역까지 별도의 메모리를 할당하면 메모리만 낭비하게 된다. • 실제 메모리 상에 할당된 객체를 인스턴스(Instance)라 한다. • 코드 영역에 대한 모듈 인스턴스(Module Instance) • 데이터 영역에 대한 데이터 인스턴스(Data Instance)두 개의 인스턴스가 있다. 코드영역 (모듈 인스턴스) 메모장1 메모장2 데이터 영역_1 (데이터 인스턴스) 데이터 영역_2 (데이터 인스턴스)
5. 윈도우 프로그래밍과 친해지자 • 리소스(Resource) • 메뉴,아이콘,커서,비트맵 등 사용자 인터페이스를 구성하는 자원들의 정적 데이터를 말한다. • 프로그램 실행 중 변경되지 않는 정형화된 데이터로 C나 C++같은 언어로 기술하지 않고 리소스 스크립트에 의해 정의된다. IDR_MAINFRAME MENU PRELOAD DISCARDABLE BEGIN POPUP "파일(&F)" BEGIN MENUITEM "새 파일(&N)\tCtrl+N", ID_FILE_NEW MENUITEM "열기(&O)...\tCtrl+O", ID_FILE_OPEN MENUITEM "저장(&S)\tCtrl+S", ID_FILE_SAVE MENUITEM "다른 이름으로 저장(&A)...", ID_FILE_SAVE_AS MENUITEM SEPARATOR MENUITEM "인쇄(&P)...\tCtrl+P", ID_FILE_PRINT MENUITEM "인쇄 미리 보기(&V)", ID_FILE_PRINT_PREVIEW MENUITEM "인쇄 설정(&R)...", ID_FILE_PRINT_SETUP MENUITEM SEPARATOR MENUITEM "최근 파일", ID_FILE_MRU_FILE1,GRAYED MENUITEM SEPARATOR MENUITEM "종료(&X)", ID_APP_EXIT END END
5. 윈도우 프로그래밍과 친해지자 • 리소스는 프로그램 코드와 분리하여 작성되며 자체 컴파일과정을 갖는다. • 리소스 스크립트 파일(.RC)은 리소스 컴파일러(RC.EXE)에 의해 이진화된 리소스 파일 (.RES)이 만들어 진다. • 리소스를 별도로 정의하는 이유는 메모리를 효율적으로 사용하기 위함이다. • 리소스에는 정적인 데이터가 있기 때문에 일반 변수와는 다른 메모리 관리를 한다. • 보통 리소스 데이터는 필요한 시점에 파일로부터 로딩이 되며 여러 개의 프로그램이 실행되어 메모리가 부족시 리소스 데이터가 할당된 메모리 블록을 이동(Moveable)기키거나 폐기(Discardable)한다.
5. 윈도우 프로그래밍과 친해지자 GUI 아이콘,커서,다이얼로그등 중복/증가로 파일크기가 커진다. 리소스를 프로그램과 분리, 필요 시에 Call 링크 시 소스코드와 리소스가 결합 리소스는 메모리 부족 시 폐기 가능(DISCARDABLE) 필요 시EXE나 DLL파일로부터 로딩 프로그램이 차지하는 메모리가 감소되어 메모리 효율성이 높아지고 소스 코드와 분리되어 작성되므로 프로그램 작성이 편리하다.
5. 윈도우 프로그래밍과 친해지자 • 하드웨어 운용 방식(장치 독립적인 그래픽 인터페이스) • 도스에서는 비디오 메모리나 프린터 포트 등을 직접 제어함으로써 특정한 하드웨어 장치에 종속된 프로그램을 작성하였다. • 장치 종속적 • 비디오 카드나 프린터 등과 같은 장치의 종류나 모델에 따라 출력방법이 달라진다. • 특정 장치에서만 제한적으로 실행되기 때문에 프로그램에서 지원하지 않는 장치는 사용할 수 없다. • 프로그램에서 필요한 디바이스 드라이버를 제공해야 한다. • 장치 독립적 • 장치의 종류와 모델에 상관없이 일관된 처리 방법으로 하드웨어 장치들을 다룰 수 있다. • 출력하고자 하는 출력장치의 종류에 상관없이 출력 방법이 동일하다. • 필요한 디바이스 드라이버를 윈도우 OS가 내장하고 있으면 어떤 하드웨어 장치건 상관없이 동일하게 작동되기 때문에 프로그래머는 중요한 기능에 보다 많은 시간을 투자할 수 있다. • 출력 장치에 대한 정보를 포함하는 구조체 디바이스 컨텍스트를 가지고 GDI함수를 호출하여 출력 작업을 수행
5. 윈도우 프로그래밍과 친해지자 case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, "Hello, Windows 95!", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; Display.drv GDI32.DLL Printer.drv Keyboard.drv USER32.DLL 윈도우 프로그램 Mouse.drv Sound.drv Timer H/W System.drv Comm.drv RS-232 Ms-Dos file I/O KERNEL32.DLL Memory Management
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를 넣는다.