일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- directx
- 수광 소자
- Visual Micro
- LineTracer
- 아두이노 컴파일러
- Algorithm
- Array
- map
- Arduino
- c++
- 컴퓨터 그래픽스
- Deque
- html
- 통계학
- 자료구조
- stl
- priority_queue
- Stack
- list
- WinAPI
- vector
- set
- C언어
- 아두이노 소스
- 아두이노
- arduino compiler
- 시스템프로그래밍
- 라인트레이서
- queue
- 운영체제
- Today
- Total
Kim's Programming
WinApi - 분석(2/2) 본문
윈도우 프로시저
메세지 처리 함수란 메세지가 발생할 때 프로그램의 반응을 처리하는 일을 하며 WinMain함수와는 별도로 WndProc이라는 이름으로 존재합니다. 윈도우 프로시저(Window Procedure)라는 뜻이지만 통상적으로 읽을 때는 윈드 프록으로 읽습니다. WndProc은 WinMain에서 호출하는 것이 아니라 운영체제에 의해 호출됩니다. WinMain내의 메시지 루프는 메세지 루프는 메세지를 메세지 처리 함수로 보내기만 할 뿐이며 WndProc은 메세지가 입력되면 운영체제에 의해 호출되어 메세지를 처리합니다. 이렇게 운영체제에 의해 호출되는 응용 프로그램 내의 콜백(Callback)함수라고 합니다. 콜백 함수라는 용어는 나중에 따로 하겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 | switch(iMessage) { case Msg1: 처리1; return 0; 처리2; return 0; 처리3; return 0; default: return DefWindowProc(...); } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 | LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { switch (iMessage) { case WM_DESTROY: PostQuitMessage(0); return 0; break; } return(DefWindowProc(hWnd, iMessage, wParam, lParam)); } | cs |
원래 만든 프로젝트의 배결색은 흰색이었습니다. 배경색이 흰색인 이유는 WndClss의 멤버 중 배경 색상을 지정하는 hbrBackground가 흰색 브러시로 지정되어 있기 떄문입니다.
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
여기서 사용된 GetStockObject 함수는 윈도우즈가 기본적으로 제공하는 브러시, 펜 등의 핸들을 구하는 함수인데 이 함수의 인수로 WHITE_BRUSH를 지정했기 떄문에 배경색을 칠하는 데 흰색 브러시가 사용되었습니다. 이 값을 BLACK_BRUSH로 변경하면 검정색이 배경색으로 사용되며 LTGRAY_BRUSH로 변경하면 옅은 회색 배경으로 만들어집니다.
LTGRAY_BRUSH로 하였을 경우 다음과 같이 나옵니다.
적접 해보면 나올 것입니다. 하지만 RED나 YELLO는 되지 않습니다. 왜냐하면 윈도우즈의 기본 브러시는 흰색, 검정색, 회색 뿐이며 원색 브러시는 제공되지 않기 떄문입니다. 윈도우즈가 제공하는 브러시 이외의 브러시를 사용하려면 다른 방법을 사용해야 하는데 소개만 하겠습니다. 다음 코드는 파란색 배경을 가지는 윈도우를 만듭니다.
WndClass.hbrBackground = CreateSolidBrush(RGB(0, 0, 255));
다음 코드는 빨간색의 기울어진 바둑판 배경을 그립니다.
WndClass.hbrBackground = CreateHatchBrush(HS_DIAGCROSS, RGB(255, 0, 0));
원하는 색상과 무늬의 브러시를 만들어 배경 브러시로 지정하기만 하면 됩니다. 원칙대로 하자면 파괴도 해야하는데 실습이므로 생략했습니다. 특정 색상을 지정하는 것보다 COLOR_WINDOW+1 시스템 색상을 지정하여 사용자가 제어판에서 설정한 윈도우 배경색을 쓰는 것이 가장 좋습니다.
커서 바꾸기
위의 윈도우 위에 마우스 커서를 위치시키면 화살표 모양의 표준 커서가 나타납니다. 이 커서가 사용되는 이유는 WndClass에서 커서를 지정하는 멤버가 다음과 같이 정의 되어있기 때문입니다.
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
hCursor 멤버는 윈도우가 기본적으로 사용할 커서를 지정하며 LoadCursor함수는 커서를 읽어오는 함수입니다.
HCURSOR LoadCursor(HINSTANCE hInstance, LPCTSTR lpCursorName);
첫 번째 인수 hInstance는 커서를 가지고 있는 프로그램의 인스턴스 핸들이되 윈도우즈가 제공하는 표준 커서를 사용하려면 이 인수를 NULL로 지정합니다. 두 번쨰 인수 lpCursorName은 사용하고자 하는 커서의 이름을 지정합니다. 윈도우즈가 디폴트로 제공하는 커서에는 다음과 같은 종류가 있습니다.
값 |
모양 |
IDC_ARROW |
화살표 모양(보통 사용하는 모양) |
IDC_CROSS |
십자 모양 |
IDC_IBEAM |
I 모양 |
IDC_NO |
금지표시, 원안에 빗금 |
IDC_WAIT |
모래시계 모양(윈도우 비스타 부터는 원형) |
윈도우즈가 제공하는 표준 커서외에 자신이 직접 커서를 디자인해서 사용하는 방법도 있는데 이 방법은 뒤에서 알아보겠습니다. 커서를 바꿀 수 있는 것 처럼 타이틀 바의 좌 상단에 표시되는 프로그램의 아이콘도 바꿀 수 있습니다.
값 |
모양 |
IDI_ASTERISK |
|
IDI_ERROR |
|
IDI_EXCLAMATION |
|
IDI_QUESTION |
타이틀 바의 아이콘이 지정한 모양으로 바뀝니다.(바뀐걸 캡쳐해 붙였습니다) 물론 아이콘도 운영체제가 제공하는 것이 아닌 원하는 모양으로 디자인해서 사용할 수 있습니다. 여기서 볼 수 있듯 WndClass의 멤버들을 변경하면 생성되는 윈도우의 여러 가지 속성을 원하는 대로 설정할 수 있습니다.
윈도우의 타이틀 바꾸기
위 소스를 컴파일 했을 때 타이틀 바에 "첫예제"라는 문자열이 나타내는데 이 값은 우리가 CreateWindow 함수의 두 번째 인수로 지정한 lpszClass 문자열이며 이는 또한 윈도우 클래스의 이름이기도 합니다. 타이틀 바에 나타나는 윈도우의 이름을 변경하려면 CreateWindow함수의 두 번째 인수를 원하는 문자열로 변경하면 됩니다. 진한색 부분을 변경하면 타이틀이 바뀌게 됩니다.
hWnd = CreateWindow(lpszClass, TEXT("타이틀은여기에"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);
앞에서 설명 했듯 문자열 상수를 쓸 때는 항상 TEXT()매크로로 둘러싸야 유니코드로 쉽게 이식할 수 있습니다. 타이틀 바에 첫 예제라는 이름 말고 지정한 이름으로 표시되는 것을 확인 할 수 있습니다. 문자열이기 떄문에 한글 기호 한자 전부다 가능합니다.
실행중에 타이틀 바의 문자열을 변경하고 싶다면 wsprintf 등의 서식 조립 함수로 조립하여 사용하면 됩니다. 윈도우의 위치와 크기를 지정하는 값은 CreateWIndow의 4번째~7번째 인수 까지 이며 첫번째 이 소스에서는 나머지는 CW_USERDEFAULT를 사용하여 윈도우즈가 정해주는대로의 크기와 위치를 사용했습니다. 이값을 다음과같이 상수로 변경하면 크기와 위치를 원하는대로 정해줄 수 있습니다.
hWnd = CreateWindow(lpszClass,lpszClass, WS_OVERLAPPEDWINDOW, 300, 400, 300, 200, NULL, (HMENU)NULL, hInstance, NULL);
위의 소스에서는 300,400의 위치에 폭 300 너비 200의 창을 만든다는 의미 입니다. (진한부분) 꼭 틍정위치에 정해진 크기대로 윈도우를 만들어야한다면 이 인수들을 사용하여 윈도우를 만들 때 크기와 위치를 고정시킬 수 있되 그렇게 하는 경우는 드뭅니다. 왜냐하면 윈도우는 사용자가 언제든지 타이틀 바를 드래그하여 이동시킬 수 있으므로 운영체제가 화면 해상도에 맞게 적당한 위치에 표시하는 것이 더 자연스럽기 떄문입니다.
윈도우의 스타일
CreateWindow함수의 세 번째 인수 dwStyle은 윈도우의 모양과 동작 방식을 결정하는 여러 가지 속성을 지정합니다. 여러 가지 스타일값을 가지는 32비트 정수값이며 이 값을 변경함에 따라 다양한 모양의 윈도우를 만들 수 있다. 일단 dwStyle에 사용될 수 있는 값들을 보겠습니다. 이 값들을 OR연산자로 연결하여 여러 가지 속성을 지정할 수 있습니다.
값 |
의미 |
WS_CAPTION |
타이틀 바를 가집니다. |
WS_HSCROLL |
수평 스크롤 바를 가집니다. |
WS_VSCROLL |
수직 스크롤 바를 가집니다. |
WS_MAXIMIZEBOX |
최대화 버튼을 가집니다. |
WS_MINIMIZEBOX |
최소화 버튼을 가집니다. |
WS_SYSMENU |
시스템 메뉴를 가집니다. |
WS_THICKFRAME |
크기를 조정할 수 있는 경계선을 가집니다. |
이 외에도 더 많은 속성값들이 있지만 이 값만 사용하여 변경해 보겠습니다. 우선 위에서 사용했던 WS_OVERLAPPEDWINDOW는 다음과 같이 정의 되어 있습니다.
1 | #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | W_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) | cs |
여기서 WS_OVERLAPPED는 실제로 0이므로 아무런 의미가 없으며 타이틀 바, 시스템 메뉴, 크기 조절이 가능한 경계선, 최소, 최대 버튼 등의 스타일이 한꺼번에 정의되어 있습니다. 즉 WS_OVERLAPPEDWINDOW 스타일을 사용하면 가장 평범한 모양의 윈도우가 만들어집니다. CreatWindow의 dwStyle인수를 다음과 같이 변경합니다.
1 | WS_CAPTION | W_SYSMENU | cs |
두개의 스타일만 남기고 나머지 스타일을 사용하면 다음과 같은 윈도우가 만들어집니다.
타이틀 바와 시스템 메뉴만 있을 뿐 최대, 최소화 버튼이 없습니다. 또한 윈도우 크기조정 경계선도 없어서 크기 변경도 되지 않습니다. 여기서 WS_MAXIMIZEBOX, WS_MINIMIZEBOX 스타일을 차례대로 추가 지정하면 타이틀 바에 최대화 버튼, 최소화 버튼이 생깁니다.
또 다른 걸로 바꿔서 보겠습니다.
1 | WS_OVERLAPPEDWINDOW | WS_VSCROLL | cs |
이렇게 변경한후 다시 프로그램을 실행하게되면 다음과 같이 수직 스크롤 바가 달린 윈도우가 만들어집니다. 수평 스크롤을 달고 싶으면 WS_HSCROLL을 추가로 주면 됩니다.
다음은 윈도우를 마우스로 왼쪽 클릭했을때 소리가 나게 하는 것입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { switch (iMessage) { case WM_DESTROY: PostQuitMessage(0); return 0; break; case WM_LBUTTONDOWN: MessageBeep(0); return 0; } return(DefWindowProc(hWnd, iMessage, wParam, lParam)); } | cs |
다음 포스팅부터는 이와 같은 출력에 대해서 작성하겠습니다.
'Programming > Windows API' 카테고리의 다른 글
WinApi - 출력(2/2) (0) | 2015.08.29 |
---|---|
WinApi - 출력(1/2) (0) | 2015.08.27 |
WinApi - 분석(1/2) (1) | 2015.08.26 |
WinAPI - 첫번째 시작 - 프로젝트 만들기 (0) | 2015.08.25 |
WinAPI - 시작하기전에 알고 갑시다. (0) | 2015.08.24 |