배경색, 커서, 창 타이틀의 변경은 모두 WNDCLASS 구조체에서 변경이 가능하다.
배경색 변경
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
구조체의 hbrBackground 멤버로 변경이 가능하며 변경방법은 (HBRUSH)GetStockObject(WHITE_BRUSH); GetStockObject 함수의 인자로 변경할 색상을 넘겨주고 그 값을 WNDCLASS 구조체의 hbrBaclground 멤버의 값으로 넣어주면 그 값이 해당 색상으로 반영이 된다.
커서 변경
WndClass.hCursor = LoadCursor(NULL, IDC_IBEAM);
LoadCursor(NULL, IDC_IBEAM); LoadCursor 함수의 첫 번째 인자는 Windows가 제공하는 기본 커서를 사용할지 말지를 경절하는 인자이며 첫 번째 인자에 NULL을 넣게 되면 Windows가 제공하는 기본 커서를 사용한다. 두 번째 인자는 Windows가 제공하는 커서중 어떤 커서를 사용할 것인지를 결정하는 인자이다.
밑의 표는 Windows가 제공하는 기본 커서의 인자값과 각 인자들의 설명이다.
값 | 설명 |
IDC_ARROW | 화살표 모양 |
IDC_CROSS | 십자 모양 |
IDC_IBEAM | I자 모양 |
IDC_NO | 원안에 빗금이 쳐진 모양 |
IDC-WAIT | 모래시계 모양 |
Window 타이틀 변경, Window 크기 변경, Window 스타일
CreateWindow(lpszClass,
L"Windows API",
WS_OVERLAPPEDWINDOW,
100,
100,
500,
400,
NULL,
(HMENU)NULL,
hInstance,
NULL);
Window 타이틀을 설정하기 위해서는 두 번째 인자를 설정하고 싶은 문자열로 지정하면 된다. Window 크기의 변경은 네 번째 인자부터 일곱 번째까지 인자를 설정하면 된다. 네 번째 인자는 창의 시작을 설정하는 X좌표 다섯 번째 인자는 창의 시작을 설정하는 Y좌표 그리고 여섯 번째 인자는 X좌표부터 창의 가로길이 일곱 번째 인자는 Y좌표부터 창의 세로길이를 의미한다. 이렇게 네 번째부터 일곱 번째 인자까지 사용자의 용도에 맞게 설정하면된다. Window 스타일은 세 번째 인자를 설정하면 되는데 인자값은 복수로 지정이 가능하다. 복수로 지정방식은 각각의 설정 값 사이에 | 기호를 넣어서 설정 하거나 #define으로 설정내용을 모아서 한 번에 설정하여 Define명으로 값을 설정하면 된다.
각각의 설정값은 다음과 같다.
값 | 설명 |
WS_CAPTION | 타이틀 바를 가진다. |
WS_HSCROLL | 수평 스크롤 바를 가진다. |
WS_VSCROLL | 수직 스크롤 바를 가진다. |
WS_MAXIMIZEBOX | 최대화 버튼을 가진다. |
WS_MINIMIZEBOX | 최소화 버튼을 가진다. |
WS_SYSMENU | 시스템 메뉴를 가진다. |
WS_THICKFRAME | 크기를 조절할 수 있는 경계선을 가진다. |
DC의 필요성
DC란 Device Context를 줄인말이며 출력에 필요한 모든 정보를 가지는 데이터 구조체이며 GDI 모듈에 의해 관리된다. 어떤 폰트를 사용할 것인가, 선의 색상, 굵기, 채움 무늬와 색상, 출력 방법등을 출력에 관련된 모든 정보들에 필요한 정보들이다.
선 하나를 긋기 위해서 복잡한 방법을 사용할 것인가 아니면 DC에 저장된 정보를 통하여 쉽고 편리하게 사용할 것인가를 생각해보면 DC의 필요성을 느끼게 될 것이다.
문자열 출력
문자열의 출력, 줄긋기 색상 등의 설정은 WinMain에서의 설정이 아니다. 이런 모든 설정과 이벤트를 담당하는 함수는 WinProc 함수이므로 WinProc함수에서 설정한다.
case WM_RBUTTONDOWN:
hdc = GetDC(hWnd);
TextOut(hdc, 50, 50, L"안녕하세요", 5);
ReleaseDC(hWnd, hdc);
return 0;
WM_RBUTTONDOWN는 마우스 오른쪽 버튼을 눌리면 발생하는 이벤트를 설정한다.
가장 먼저 GetDC 함수의 인자를 WinProc 함수의 첫번째 인자인 Window Handler 값을 넣어 DC 정보를 설정한다.
그 후 문자열을 화면에 출력하기위해서 TextOut 함수를 사용하여 (Handler DC, 문자열을 표시할 X, Y의 좌표 출력할 문자열, 문자열의 문자 개수)를 넣어 문자열을 출력한다.
마지막으로 ReleaseDC(hWnd, hoc);와 같이 ReleaseDC 함수를 통하여 DC 기능을 해제하여준다. 인자값은 Window Handler, Handler Dc의 값을 넣어서 DC를 해제한다.
WM_PRINT 메세지
Windows는 하나의 창에 다른 창을 겹치게 올렸다가 분리를 시키면 두 개의 창이 겹쳐졌던 부분이 지워지게 되는데 우리가 보기에는 원래의 모양이 유지되는것처럼 보인다. 하지만 Windows는 이를 유지하는것이 아니라 그 겹쳐진 부분을 다시 그리는 방식을 이용하는데 이렇게 지워졌던 부분을 다시 그리게 해주는 메세지를 WM_PRINT라고하며 사용이 된다.
PAINTSTRUCT ps;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 100, 100, "A", 1);
EndPaint(hWnd, &ps);
return 0;
WM_PRINT는 BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); 함수가 하나가 되어서 WM_PRINT 메세지 기능을 이루는데 BeginPaint 함수에 Window Handler와 Pant 구조체 변수를 넣어서 WM_PRINT 시작을 설정하고 EndPaint 함수에 같은 인자를 넣어서 WM_PRINT 끝을 설정하면된다. 여기서 시작과 끝 사이에 다시 그릴 이벤트를 지정해놓으면 된다.
TextOut
SetTextAlign(hdc, TA_CENTER);
TextOut(hdc, 100, 100, L"Win32 API 문자열 출력", 16);
문자열의 출력에서 출력할 문자열의 위치를 지정하는 기능이 존재하는데 SetTextAlign(hdc, TA_CENTER); 이와 같은 방식으로 사용이 가능하다. SetTextAlign 함수에 Handler DC의 값을 지정하고 문자열의 위치를 지정해주면 지정한 위치에 문자열이 출력이 된다.
문자열 출력 위치에 대한 설정 값과 설명은 아래의 표를 참고한다.
값 | 설명 |
TA_TOP | 지정한 좌표가 상단좌표가 된다. |
TA_BOTTOM | 지정한 좌표가 하단 좌표가 된다. |
TA_CENTER | 지정한 좌표가 수평 중앙 좌표가 된다. |
TA_LEFT | 지정한 좌표가 수평 왼쪽 좌표가 된다. |
TA_RIGHT | 지정한 좌표가 수평 오른쪽 좌표가 된다. |
TA_UPDATECP | 지정한 좌표대신 CP를 사용하며 문자열 출력후에 CP를 변경한다. |
TA_NOUPDATACP | CP를 사용하지 않고 지정한 좌표를 사용하며 CP를 변경하지 않는다. |
DrawText
TextOut 함수의 기능보다 문자열을 출력하는데 더 많은 기능을 가진 함수는 DrawText이다.
RECT rt = { 100, 100, 400, 300 };
RECT 구조체는 사각형을 그릴때, 어떤 내용을 출력할때 출력할 영역을 설정하여 변수 값으로 지정할 수 있게 해주는 구조체이다.
WCHAR str[] = { ("님은 갔습니다. 아아 사랑하는 나의 님은 갔습니다. 푸른 산빛을 ") };
DrawText(hdc, str, -1, &rt, DT_CENTER | DT_WORDBREAK); DrawText 함수의 사용 예로 첫 번째는 Handler DC의 값을 두 번째 인자는 출력할 문자열의 주소, 세 번째는 세번째 인수는 출력할 문자열의 길이이되 이 값이 -1이면 널 종료 문자열로 간주, 네 번째 인자는 위에서 설정한 문자열을 출력할 영역을, 다섯 번째 인자는 문자열을 출력할 방법을 설정한다.
아래의 표는 문자열을 출력할 방법에 해당하는 표이다.
값 | 설명 |
DT_LEFT | 수평 왼쪽 정렬한다. |
DT_RIGHT | 수평 오른쪽 정렬한다. |
DT_CENTER | 수평 중앙 정렬한다. |
DT_BOTTOM | 사각 영역의 바닥에 문자열을 출력한다. |
DT_VCENTER | 사각 영역의 수직 중앙에 문자열을 출력한다. |
DT_WORDBREAK | 사각영역의 오른쪽 끝에서 자동 개행되도록 한다. |
DT_SINGLELINE | 한줄로 출력한다. |
DT_NOCLIP | 사각 영역의 경계를 벗어나도 문자열을 자르지 않고 그대로 출력한다. |
그래픽 출력
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
MoveToEx(hdc, 150, 150, NULL);
LineTo(hdc, 180, 200);
Rectangle(hdc, 200, 100, 250, 180);
Ellipse(hdc, 200, 200, 250, 280);
EndPaint(hWnd, &ps);
return 0;
선을 긋기 위해서는 MoveToEx, LineTo 함수가 필요하며 처음 인자는 모두 DC값을 가진다. 그리고 두번째 좌표는 선을 그릴 X, Y축을 각 각 지정한다. MoveToEx 함수의 마지막 인자는 CP의 좌표를 lpPoint에 대입하기 위해서 사용하는데 CP 값이 필요하지 않는 경우에는 NULL을 넘겨주면된다.
Rectangle 함수는 사각형을 그려주기 위한 함수로 DC값, 사각형을 그릴 좌표와 가로 세로의 크기를 인자로 넣어주면 된다.
Ellipse 함수는 원을 그리는 함수로 인자는 Rectangle 함수와 동일하며 원이 그려지는 방식은 사각형 각변의 가운데 점을 내접하며 원이 그려진다.
메세지 박스
case WM_LBUTTONDOWN:
MessageBox(hWnd, L"마우스 왼쪽 버튼을 눌렀습니다", L"메시지 박스", MB_OK);
return 0;
메세지 박스는 어떠한 이벤트 발생시에 생성되는 창을 말하여 메세지 박스 함수의 활용법은 MessageBox 함수에 Window Handler, 메세지 박스의 내용, 메세지 바스 창 내용, 메세지 박스의 버튼 종류를 인자로 넘겨서 사용하면 된다.
아래는 메세지 박스의 각 버튼에 해당하는 값과 설명이다.
값 | 설명 |
MB_ABORTRETRYIGNORE | Abort, Retry, Ignore 세 개의 버튼이 나타난다. |
MB_OK | OK버튼 하나만 나타난다. |
MB_OKCANCEL | OK, Cancel 두 개의 버튼이 나타난다. |
MB_RETRYCANCEL | Retry, Cancel 두 개의 버튼이 나타난다. |
MB_YESNO | Yes, No 두 개의 버튼이 나타난다. |
MB_YESNOCANCEL | Yes, No, Cancel 세 개의 버튼이 나타난다. |
그리고 메세지 박스에는 아이콘도 함께 표시가 가능한데 아이콘의 표시는 메세지 박스의 버튼을 설정하는 마지막 인자에 아이콘에 해당하는 값을 | 연산으로 설정하여 넣으면 된다.
아래는 메세지 박스에서 사용가능한 아이콘의 값과 아이콘 모양
값 | 아이콘 |
MB_ICONEXCLAMATION MB_ICONWARNING | ![]() |
MB_ICONINFORMATION MB_ICONASTERISK | ![]() |
MB_ICONQUESTION | ![]() |
MB_ICONSTOP MB_ICONERROR MB_ICONHAND | ![]() |
WM_CHAR 메세지
키보드로부터 입력 이벤트가 발생하면 Windows가 보내는 메세지이다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
case WM_CHAR:
len = lstrlen(str);
str[len] = (TCHAR)wParam;
str[len + 1] = 0;
if ((TCHAR)wParam == 32) {
str[0] = 0;
}
else {
len = lstrlen(str);
str[len] = (TCHAR)wParam;
str[len + 1] = 0;
}
InvalidateRect(hWnd, NULL, FALSE);
return 0;
}
키보드로부터 문자를 읽으면 Windows는 WndProc 함수로 WM_CHAR 메세지를 보내게 되며 키보드로부터 읽어들인 문자는 Window Proc 함수의 세 번째 인자인 wParam에 입력한 값이 들어가게 된다.
WM_CHAR 메세지를 통하여 WM_CHAR 메세지 아래에 있는 내용을 수행하면서 해당 기능이 활성화 되며 WM_CHAR 메세지는 이벤트 발생시 해당 내용만 처리하게 되며 입력받은 문자를 화면에 출력하기 위해서는 InvalidateRect(hWnd, NULL, FALSE); 함수를 이용하여 WM_PAINT 메세지를 호출하여 화면에 출력하게 된다.
키보드가 눌러렸을때 사용되는 비트로 어떤 키가 눌러졌는지 일반키인지 특수키인지 구별하는 것을 그려놓은 그림이다.
키보드 입력시 내용을 문자열에 넣게되면 문자열의 끝에는 항상 NULL을 자동으로 넣어서 문자열을 완성시킨다.
무효화 영역
WM_PAINT에 대하여 설명할때 하나의 창위에 다른 창이 겹쳐져있다 분리되는 과정에서 겹쳤던 부분을 이야기 했었는데 이 부분을 무효화 영역이라고 부른다.
Windows에서 이런 무효화 영역을 WM_PAINT를 호출하여 다시 그리는 방식을 사용한다.
InvalidateRect(hWnd, NULL, FALSE); 무효화 영역 복구를 위하여 사용되는 함수로써 첫 번째 인자는 Windows Handler 값을 이용하여 적업 영역을 무효화시켜 Windows가 WM_PAINT 메세지를 호출하게 한다.
두 번째 인자는 무효화 되는 영역을 써주는데 부분 영역을 지정하려면 위의 RECT 구조체 변수를 이용하여 위치를 지정하고 화면전체를 무효화 시키려면 NULL을 넣으면 된다.
세 번째 인자는 무효화되기 전에 배경을 모두 지우고 그릴것인지 배경을 지우지 않고 그릴지에 대한 값을 넣는다.
WM_KEYDOWN
case WM_KEYDOWN:
switch (wParam) {
case VK_LEFT:
if (x == 0) {
x = 0;
break;
}
else if (x > 0) {
x = x - 8;
break;
}
case VK_RIGHT:
x = x + 8;
break;
case VK_UP:
if (y == 0) {
y = 0;
break;
}
else if (y > 0) {
y = y - 8;
break;
}
case VK_DOWN:
y = y + 8;
break;
}
InvalidateRect(hWnd, NULL, FALSE);
return 0;
WM_KEYDOWN 메시지는 wParam에 문자 코드가 아닌 가상 키코드라는 것을 전달해 준다.
WM_KEYDOWN를 받고 각 특수키별 이벤트를 담당하는 메세지들은 아래를 참고하기 바란다.
가상키 코드 | 값 | 키 |
VK_BACK | 08 | Backspace |
VK_TAB | 09 | Tab |
VK_RETURN | 0D | Enter |
VK_SHIFT | 10 | Shift |
VK_CONTROL | 11 | Ctrl |
VK_MENU | 12 | Alt |
VK_PAUSE | 13 | Pause |
VK_CAPITAL | 14 | Caps Lock |
VK_ESCAPE | 1B | Esc |
VK_SPACE | 20 | 스페이스 |
VK_PRIOR | 21 | PgUp |
VK_NEXT | 22 | PgDn |
VK_END | 23 | End |
VK_HOME | 24 | Home |
VK_LEFT | 25 | 좌측 커서 이동키 |
VK_UP | 26 | 위쪽 커서 이동키 |
이하생략 | 이하생략 |
Translate Message
Windows 운영체제와 같은 RTOS는 운영체제에서 보내는 모든 메세지를 모두 다 처리하며 GetMessage에 0이 오면 루프를 탈출하고 종료한다. 그러면서 창이 닫힌다.
while (GetMessage(&Message, 0, 0, 0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
TranslateMessage 함수는 키보드를 감시하는 함수이고 DispatchMessage Windows가 처리하고 남은 메세지를 DispatchMessage함수에 넘겨서 DispatchMessage함수가 처리한다.
'코스웨어 > 15년 스마트컨트롤러' 카테고리의 다른 글
2015.11.16 -권오민- WinAPI-3일차 (3) | 2015.11.16 |
---|---|
20151116 22번 업무일지 우대희 API (3) | 2015.11.16 |
20151116 임현수 업무일지 WIN32API #3 (2) | 2015.11.16 |
20151113 22번 업무일지 우대희 API (5) | 2015.11.16 |
20151113_안향진_API_02 (5) | 2015.11.15 |
20151113 - 주재민 API 개인 업무일지 2일차 (4) | 2015.11.15 |
20151113 - 강동조 API 개인 업무일지 2일차 (5) | 2015.11.13 |
20151113 WinAPI / 11번 남수진 (5) | 2015.11.13 |