Windows Programming 제대로 배우기
description
Transcript of Windows Programming 제대로 배우기
1
Windows Programming
제대로 배우기Chapter 1. Introduction to SDKChapter 2. Structures of the SDK Windows Program
2
윈도즈 프로그래밍
1. C 언어 + WIN32 SDK (Standard Developer Kit)- 표준 개발 키드 - 윈도에서 프로그래밍할 경우 표준으로 사용해야 할 라이브러리
2. C++ 언어 + MFC (Microsoft Foundation Class)
목표 SDK 에서 제공하는 함수를 어떻게 사용하는가 프로그램 형식을 어떻게 하는가
3
윈도우 프로그래밍 기본 구조 (1)윈도우 프로그래밍
1. 초기화하는 부분2. 커널에게 허가를 받기 위한 , 또는 커널이 점유하고 있는 시스템의 상황을 얻기 위한 커널과의 통신 부분
* 윈도우 프로그래밍에서는 모든 시스템 자원을 커널이 보유하고 있기 때문에 커널의 허가가 없이는 아무것도 할 수 없다 .
4
윈도우 프로그래밍 기본 구조 (2)* 윈도우 프로그램은 다음과 같이 두 개의 함수가 필요
void Init() {
// 커널에 초기화 하는 부분 }
void messagetranslation() {
// 메시지를 주고 받는 부분 }
5
윈도우 프로그래밍 기본 구조 (3)
• 실제 프로그램에서도 위의 두 개의 형태로 구성• 커널에초기화 하는 부분이 WinMain• 메시지를 처리하는 부분이 WndProc
int WINAPI WinMain (......) {
// 초기화 부분 }
LRESULT CALLBACK WndProc (....) {
// 메시지 처리 루틴 }
6
윈도우 프로그래밍 기본 구조 (4). 실제로 프로그램은 메시지 처리루틴에서 작성
LRESULT CALLBACK WndProc (....) {
switch( 메시지 ) {
case 키보드 눌렸음 : 버퍼에 킷값을 저장함 break;
case 화면출력해도 됨 : 버퍼 내용을 화면에 출력한다 . break;
} }
7
윈도우 프로그래밍 기본 구조 (5). 실제로 프로그램은 메시지 처리루틴에서 작성
LRESULT CALLBACK WndProc (....) {
switch( 메시지 ) {
case 키보드 눌렸음 : 버퍼에 킷값을 저장함 break;
case 화면출력해도 됨 : 버퍼 내용을 화면에 출력한다 . break;
} }
* 커널에서 들어온 메시지에 의해서 필요한 부분들을 switch 문을 이용하여 처리하여 주는 루틴이 됨 .
* 커널은 필요한 모든 메시지를 초기화한 윈도에 날려줌
8
윈도우 프로그래밍 기본 구조 (6)이런 형태로 WndProc 는 다음과 같이 변함
LRESULT CALLBACK WndProc (....) {
// 필요한 메시지만 처리하고 switch( 메시지 ) {
case 키보드 눌렸음 : 버퍼에 킷값을 저장함 break;
case 화면출력해도 됨 : 버퍼 내용을 화면에 출력한다 . break;
} CallKernel(); // 나머지는 커널에게 다시 의뢰를 한다 .
}* CallKernel 이라는 함수가 있다는 것이 아니라 위와 같은 형식
9
WinMain 함수- 윈도우 프로그래밍에서 초기화하는 부분을 WinMain- 리얼모드 프로그램에서 main() 으로 시작하듯 윈도우에서는 WinMa
in 으로 프로그램이 시작 ( 프로그램이 컴파일될 때 프로그램의 시작점을 바로 WinMain 에서부터 찾기 때문 )
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
- hInstance 란 프로그램 인스턴스라고 이야기 하는데 쉽게 보면 어플리케이션 프로그램의 ID
- hPrevInstance 는 같은 프로그램이 이전에 구동되었을 때 설정되는 인스턴이스인데 윈도우 95 이후부터는 사용을 하지 않으므로 그냥 써준다고 생각하고 무시
- szCmdLine 는 프로그램과 함께 들어오는 인자들- iCmdShow 에는 윈도우가 처음 출력될 때 쓰는 값 ( 화면에 출력되는
형태가 어떤 형태가 좋은 지를 알려주는 값 )
10
초기화 방법 (1)초기화 방법1. 윈도우 클래스를 등록2. 메인 윈도우 만들기
11
초기화 방법 (2)초기화 방법1. 커널에 초기화 할 때는 본 프로그램이 사용하는 클래스를
등록하는 것이 첫 번째 : 사용하는 함수가 RegisterClassEx
2. 두 번째로 메인 윈도우를 만들기 : CreateWindow
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow) {
RegisterClassEx () ;// 클래스를 등록하고 CreateWindow ()// 윈도우를 만든다 .
}
12
초기화 방법 (3)
클래스가 두 개일경우에는 RegisterClassEx 함수를 이용해서 또하나의 클래스를 등록
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
RegisterClassEx ( 메인윈도우스타일 ) ;// 클래스를 등록하고 RegisterClassEx ( 차일드 윈도우 스타일 ) ;// 클래스를 등록하고 CreateWindow ()// 메인 윈도우를 만든다 .
}
13
프로시저 (1)- 윈도우는 Message Driven 방식 : 모든 내용을 메시지를 이용하여 통신을
하는 것이 대부분인 프로그램방식
WinMain 함수가 다음과 같은 형식으로 바꾸어져야 함
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
// 메인 윈도우 클래스 RegisterClassEx ( 메인윈도우스타일 , 프로시저 -> WndProc) ; // 차일드 윈도우 클래스 RegisterClassEx ( 차일드 윈도우 스타일 , 프로서저 -> ChildProc) ; CreateWindow ()// 메인 윈도우를 만든다 .
}
14
프로시저 (2)LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lPara
m) {
switch(iMsg) {
메뉴 메시지가 발생되었을 때 처리 } 나머지는 커널에 의뢰
}
LRESULT CALLBACK ChildProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{ switch(iMsg) { 키보드 입력이 있었을 때 처리 } 나머지는 커널에 의뢰
}
15
WinMain 분석 (1)int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { }
ATOM RegisterClassEx( CONST WNDCLASSEX *lpwcx // 윈도우 클래스 정보 );
lpwcx 는 구조체 : RegisterClassEx 를 수행하기 위해서는 WNDCLASSEX 구조체의 변수를 만들고 이 구조체의 맴버에 값을 넣어주고 이것을 RegisterClassEx 에 넘겨주어야 함 .
16
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;
17
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) ;
18
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) ;
19
WinMain 분석 (5)while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
프로시저는 메시지를 처리할때마다 수행
프로시절를 호출하는 어떤 루프가 필요하고 이 루프가 바로 MainWnd 에 설정
메인 윈도에 설정한 WndProc 함수가 계속적으로 호출이 됨
20
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) ;
}
21
Hello.c 의 WndProc 분석LRESULT : 결과 저장 32 비트 변수 CALLBACK : 콜백 함수 iMsg : 들어오는 메시지 ( 여기서는 3 개의 함수가 처리됨 )wParam, lParam : 메시지와 함께 설정되는 여러 정보를 보관하는 변수PostQuitMessage(0) : 메시지 큐에 종료 메시지 설정 . 이때 Winmain 의
while 루프의 GetMessage 함수는 0 을 리턴하고 While 루프 종료시 프로그램 종료 .
< 참고 > 윈도우 프로그래밍 : 핸들을 받아서 그 핸들을 사용하거나 핸들을 만들어서
설정하여 사용( 예 ) 그릴 화면 핸들을 받고 , 라인을 그릴 펜이라는 핸들을 만들고 ,
펜이라는 핸들을 이용하여 그릴 화면 핸들에 라인을 그린다 .
•윈도우 프로그래밍 -> 모든 것을 객체화 •이 객체를 컨트롤하기 위해 핸들 사용( 예 ) HWND ( 윈도우 핸들 )( 예 ) HINSTANCE ( 인스턴스 핸들 )( 예 ) HDC ( 디바이스 컨텍스트 핸들 )