본문 바로가기
코스웨어/15년 스마트컨트롤러

2015-11-13 Win32 API 개인 업무일지 - 천정호

by 알 수 없는 사용자 2015. 11. 16.
728x90
반응형

배경색, 커서, 창 타이틀의 변경은 모두 WNDCLASS  구조체에서 변경이 가능하다.


배경색 변경

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

구조체의 hbrBackground 멤버로 변경이 가능하며 변경방법은 (HBRUSH)GetStockObject(WHITE_BRUSH); GetStockObject 함수의 인자로 변경할 색상을 넘겨주고 그 값을 WNDCLASS 구조체의 hbrBaclground 멤버의 값으로 넣어주면 그 값이 해당 색상으로 반영이 된다.


커서 변경

WndClass.hCursor = LoadCursor(NULL, IDC_IBEAM);

LoadCursor(NULLIDC_IBEAM); LoadCursor 함수의 첫 번째 인자는 Windows가 제공하는 기본 커서를 사용할지 말지를 경절하는 인자이며 첫 번째 인자에 NULL을 넣게 되면 Windows가 제공하는 기본 커서를 사용한다. 두 번째 인자는 Windows가 제공하는 커서중 어떤 커서를 사용할 것인지를 결정하는 인자이다.

밑의 표는 Windows가 제공하는 기본 커서의 인자값과 각 인자들의 설명이다.

설명
IDC_ARROW화살표 모양
IDC_CROSS십자 모양
IDC_IBEAMI자 모양
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(hWndhoc);와 같이 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_NOUPDATACPCP를 사용하지 않고 지정한 좌표를 사용하며 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_ABORTRETRYIGNOREAbort, Retry, Ignore 세 개의 버튼이 나타난다.
MB_OKOK버튼 하나만 나타난다.
MB_OKCANCELOK, Cancel 두 개의 버튼이 나타난다.
MB_RETRYCANCELRetry, Cancel 두 개의 버튼이 나타난다.
MB_YESNOYes, No 두 개의 버튼이 나타난다.
MB_YESNOCANCELYes, 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(hWndNULLFALSE); 함수를 이용하여 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_BACK08Backspace
VK_TAB09Tab
VK_RETURN0DEnter
VK_SHIFT10Shift
VK_CONTROL11Ctrl
VK_MENU12Alt
VK_PAUSE13Pause
VK_CAPITAL14Caps Lock
VK_ESCAPE1BEsc
VK_SPACE20스페이스
VK_PRIOR21PgUp
VK_NEXT22PgDn
VK_END23End
VK_HOME24Home
VK_LEFT25좌측 커서 이동키
VK_UP26위쪽 커서 이동키
이하생략 이하생략


Translate Message

Windows 운영체제와 같은 RTOS는 운영체제에서 보내는 모든 메세지를 모두 다 처리하며 GetMessage에 0이 오면 루프를 탈출하고 종료한다. 그러면서 창이 닫힌다.

while (GetMessage(&Message, 0, 0, 0)) {

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return Message.wParam;

TranslateMessage 함수는 키보드를 감시하는 함수이고 DispatchMessage Windows가 처리하고 남은 메세지를 DispatchMessage함수에 넘겨서 DispatchMessage함수가 처리한다.











728x90