220 likes | 374 Views
Windows Programming 제대로 배우기. Chapter 1. Introduction to SDK Chapter 2. Structures of the SDK Windows Program. 윈도즈 프로그래밍. C 언어 + WIN32 SDK (Standard Developer Kit) 표준 개발 키드 윈도에서 프로그래밍할 경우 표준으로 사용해야 할 라이브러리 C++ 언어 + MFC (Microsoft Foundation Class) 목표 SDK 에서 제공하는 함수를 어떻게 사용하는가
E N D
Windows Programming제대로 배우기 Chapter 1. Introduction to SDK Chapter 2. Structures of the SDK Windows Program
윈도즈 프로그래밍 • C언어 + WIN32 SDK (Standard Developer Kit) • 표준 개발 키드 • 윈도에서 프로그래밍할 경우 표준으로 사용해야 할 라이브러리 • C++ 언어 + MFC (Microsoft Foundation Class) 목표 • SDK에서 제공하는 함수를 어떻게 사용하는가 • 프로그램 형식을 어떻게 하는가
윈도우 프로그래밍 기본 구조 (1) 윈도우 프로그래밍 • 초기화하는 부분 • 커널에게 허가를 받기 위한, 또는 커널이 점유하고 있는 시스템의 상황을 얻기 위한 커널과의 통신 부분 * 윈도우 프로그래밍에서는 모든 시스템 자원을 커널이 보유하고 있기 때문에 커널의 허가가 없이는 아무것도 할 수 없다.
윈도우 프로그래밍 기본 구조 (2) * 윈도우 프로그램은 다음과 같이 두 개의 함수가 필요 void Init() { //커널에 초기화 하는 부분 } void messagetranslation() { //메시지를 주고 받는 부분 }
윈도우 프로그래밍 기본 구조 (3) • 실제 프로그램에서도 위의 두 개의 형태로 구성 • 커널에초기화 하는 부분이 WinMain • 메시지를 처리하는 부분이 WndProc int WINAPI WinMain (......) { // 초기화 부분 } LRESULT CALLBACK WndProc (....) { // 메시지 처리 루틴 }
윈도우 프로그래밍 기본 구조 (4) . 실제로 프로그램은 메시지 처리루틴에서 작성 LRESULT CALLBACK WndProc (....) { switch(메시지) { case 키보드 눌렸음: 버퍼에 킷값을 저장함 break; case 화면출력해도 됨: 버퍼 내용을 화면에 출력한다. break; } }
윈도우 프로그래밍 기본 구조 (5) . 실제로 프로그램은 메시지 처리루틴에서 작성 LRESULT CALLBACK WndProc (....) { switch(메시지) { case 키보드 눌렸음: 버퍼에 킷값을 저장함 break; case 화면출력해도 됨: 버퍼 내용을 화면에 출력한다. break; } } * 커널에서 들어온 메시지에 의해서 필요한 부분들을 switch문을 이용하여 처리하여 주는 루틴이 됨. * 커널은 필요한 모든 메시지를 초기화한 윈도에 날려줌
윈도우 프로그래밍 기본 구조 (6) 이런 형태로 WndProc는 다음과 같이 변함 LRESULT CALLBACK WndProc (....) { //필요한 메시지만 처리하고 switch(메시지) { case 키보드 눌렸음: 버퍼에 킷값을 저장함 break; case 화면출력해도 됨: 버퍼 내용을 화면에 출력한다. break; } CallKernel(); //나머지는 커널에게 다시 의뢰를 한다. } * CallKernel이라는 함수가 있다는 것이 아니라 위와 같은 형식
WinMain 함수 - 윈도우 프로그래밍에서 초기화하는 부분을 WinMain • 리얼모드 프로그램에서 main()으로 시작하듯 윈도우에서는 WinMain으로 프로그램이 시작 (프로그램이 컴파일될 때 프로그램의 시작점을 바로 WinMain에서부터 찾기 때문) int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) - hInstance 란 프로그램 인스턴스라고 이야기 하는데 쉽게 보면 어플리케이션 프로그램의 ID - hPrevInstance는 같은 프로그램이 이전에 구동되었을 때 설정되는 인스턴이스인데 윈도우95이후부터는 사용을 하지 않으므로 그냥 써준다고 생각하고 무시 - szCmdLine는 프로그램과 함께 들어오는 인자들 - iCmdShow에는 윈도우가 처음 출력될 때 쓰는 값 (화면에 출력되는 형태가 어떤 형태가 좋은 지를 알려주는 값)
초기화 방법 (1) 초기화 방법 • 윈도우 클래스를 등록 • 메인 윈도우 만들기
초기화 방법 (2) 초기화 방법 • 커널에 초기화 할 때는 본 프로그램이 사용하는 클래스를 등록하는 것이 첫 번째 : 사용하는 함수가 RegisterClassEx • 두 번째로 메인 윈도우를 만들기 : CreateWindow int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { RegisterClassEx () ;//클래스를 등록하고 CreateWindow ()//윈도우를 만든다. }
초기화 방법 (3) 클래스가 두 개일경우에는 RegisterClassEx함수를 이용해서 또하나의 클래스를 등록 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { RegisterClassEx (메인윈도우스타일) ;//클래스를 등록하고 RegisterClassEx (차일드 윈도우 스타일) ;//클래스를 등록하고 CreateWindow ()//메인 윈도우를 만든다. }
프로시저 (1) - 윈도우는 Message Driven방식 : 모든 내용을 메시지를 이용하여 통신을 하는 것이 대부분인 프로그램방식 WinMain함수가 다음과 같은 형식으로 바꾸어져야 함 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { //메인 윈도우 클래스 RegisterClassEx (메인윈도우스타일,프로시저 -> WndProc) ; //차일드 윈도우 클래스 RegisterClassEx (차일드 윈도우 스타일,프로서저 -> ChildProc) ; CreateWindow ()//메인 윈도우를 만든다. }
프로시저 (2) LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch(iMsg) { 메뉴 메시지가 발생되었을 때 처리 } 나머지는 커널에 의뢰 } LRESULT CALLBACK ChildProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch(iMsg) { 키보드 입력이 있었을 때 처리 } 나머지는 커널에 의뢰 }
WinMain 분석 (1) int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { } ATOM RegisterClassEx( CONST WNDCLASSEX *lpwcx //윈도우 클래스 정보 ); lpwcx는 구조체 : RegisterClassEx를 수행하기 위해서는 WNDCLASSEX 구조체의 변수를 만들고 이 구조체의 맴버에 값을 넣어주고 이것을 RegisterClassEx 에 넘겨주어야 함.
WinMain 분석 (2) WNDCLASSEX 구조체 typedef struct _WNDCLASSEX { UINT cbSize; //본 구조체의 크기 UINT style; //출력 스타일 WNDPROC lpfnWndProc; //프로시저 함수 int cbClsExtra; //클래스 여분 메모리 int cbWndExtra; //윈도우 여분 메모리 HANDLE hInstance; //윈도우 인스턴스 HICON hIcon; //아이콘 HCURSOR hCursor; //커서 HBRUSH hbrBackground;//배경색 LPCTSTR lpszMenuName; // 메뉴이름 LPCTSTR lpszClassName; //클래스 이름 HICON hIconSm; //작은 아이콘 } WNDCLASSEX;
WinMain 분석 (3) 클래스를 하나 등록 WNDCLASSEX wndclass ; wndclass.cbSize = sizeof (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 ; wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ; RegisterClassEx (&wndclass) ;
WinMain 분석 (4) 메인 윈도우를 만드는 작업 hwnd = CreateWindow (szAppName, // 클래스 이름 "Exam02", // 윈도우 이름 WS_OVERLAPPEDWINDOW, // 윈도우 스타일 CW_USEDEFAULT, // 윈도우 출력 위치 x 값 CW_USEDEFAULT, // 윈도우 출력 위치 y 값 CW_USEDEFAULT, // 윈도우 출력 크기 x 값 CW_USEDEFAULT, // 윈도우 출력 크기 y 값 NULL, // 부모 윈도우 핸들 NULL, // 메뉴 이름 hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ;
WinMain 분석 (5) while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } 프로시저는 메시지를 처리할때마다 수행 프로시절를 호출하는 어떤 루프가 필요하고 이 루프가 바로 MainWnd에 설정 메인 윈도에 설정한 WndProc함수가 계속적으로 호출이 됨
Hello.c의 WndProc분석 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc ; PAINTSTRUCT ps ; switch (iMsg) { case WM_CREATE ://윈도우가 처음 만들어질때 return 0 ; case WM_PAINT ://화면이 출력될때 hdc = BeginPaint (hwnd, &ps) ; main(hdc); EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY ://윈도우가 사라질때 PostQuitMessage (0) ; return 0 ; } //나머지는 알아서 처리하도록.... return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }
Hello.c의 WndProc분석 • LRESULT : 결과 저장 32비트 변수 • CALLBACK : 콜백 함수 • iMsg : 들어오는 메시지 (여기서는 3개의 함수가 처리됨) • wParam, lParam : 메시지와 함께 설정되는 여러 정보를 보관하는 변수 • PostQuitMessage(0) : 메시지 큐에 종료 메시지 설정. 이때 Winmain의 • while루프의 GetMessage 함수는 • 0을 리턴하고 While루프 종료시 프로그램 종료. • <참고> • 윈도우 프로그래밍 : 핸들을 받아서 그 핸들을 사용하거나 핸들을 만들어서 • 설정하여 사용 • (예) 그릴 화면 핸들을 받고, 라인을 그릴 펜이라는 핸들을 만들고, • 펜이라는 핸들을 이용하여 그릴 화면 핸들에 라인을 그린다. • 윈도우 프로그래밍 -> 모든 것을 객체화 • 이 객체를 컨트롤하기 위해 핸들 사용 • (예) HWND (윈도우 핸들) • (예) HINSTANCE (인스턴스 핸들) • (예) HDC (디바이스 컨텍스트 핸들)
실습과제 • 교재 39와 41의 예제의 차이를 분석한다. • 이를 이용하여 이름, 학과, 학번을 출력하는 윈도우즈프로그램을 구현하시오. • CreateWindow함수를 이용하여, 초기 출력 위치를 바꾸고. • 처음 윈도우를 등록할때 아이콘, 커서, 배경색을 바꾸면서, 윈도우 등록 절차를 이해 • wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; • wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; • wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; • 출력예 홍길동 멀티미디어공학과 21003301