본문 바로가기

공부/윈도우api

[윈도우 api] 입력

반응형

키보드 입력

 

키보드 입력이 발생하는 시점과 문자열을 출력해야 할 시점이 분리되어 있음

문자열을 계속 모아 두었다가 필요할 때 출력을 WM_PAINT에서 처리함

 

무효영역

: 윈도우의 일부분이 가려졌다가 나타나거나 최소화되었다가 복구시 무효영역이 발생

  그때마다 운영체제가 WM_PAINT메세지를 발생시킴

 

강제로 윈도우의 작업영역을 무효화

BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase);

1. hWnd

무효화의 대상이 되는 윈도우 나타냄

2. *lpRect

무효화할 사각영역을 지정

이 값이 NULL이면 윈도우의 전 영역이 무효화

화면이 깜빡거리지 않고 보기 좋게 하기위해서는 무효화할 사각영역을 정확하게 지정할 것

3.bErase

무효화되기 전에 배경을 모두 지운 후 다시 그릴 것인지 아니면 배경을 지우지 않고 그릴 것인지를 지정

이 값이 TRUE이면 배경을 지운 후 다시 그리고 FALSE이면 배경을 지우지 않은 채로 다시 그림

 

소스

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("Key");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst = hInstance;

 WndClass.cbClsExtra = 0;
 WndClass.cbWndExtra = 0;
 WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
 WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 WndClass.hInstance = hInstance;
 WndClass.lpfnWndProc = WndProc;
 WndClass.lpszClassName = lpszClass;
 WndClass.lpszMenuName = NULL;
 WndClass.style = CS_HREDRAW | CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);
 ShowWindow(hWnd, nCmdShow);

 while(GetMessage(&Message, NULL, 0, 0)) {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }
 return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 static TCHAR str[256];
 int len;

 switch(iMessage) {
  case WM_CHAR:
   if ((TCHAR)wParam == ' '){
    str[0] = 0;
   } else {
    len = lstrlen(str);
    str[len] = (TCHAR)wParam;
    str[len+1] = 0;
   }
   //InvalidateRect(hWnd, NULL, FALSE);
   return 0;
   //len = lstrlen(str);
   //str[len] = (TCHAR)wParam;
   //str[len+1] = 0;
   //InvalidateRect(hWnd, NULL, FALSE);
   //return 0;
  case WM_PAINT:
   hdc = BeginPaint(hWnd, &ps);
   TextOut(hdc, 100, 100, str, lstrlen(str));
   EndPaint(hWnd, &ps);
   return 0;
  case WM_DESTROY:
   PostQuitMessage(0);
   return 0;
 }
 return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

 

키보드 입력 메세지

문자키가 눌렸을 때 = WM_CHAR

몇 가지를 제외한 모든 키에 대해 키가 눌릴 때 = WM_KEYDOWN

키가 떨어질 때 = WM_KEYUP

wParam에 가상키코드가 전달됨

 

TranslateMessage(&Message)함수에서 WM_CHAR메세지 발생

발생조건 = WM_KEY DOWN + 문자키 입력

아래와 같이 어떤 키가 눌렸는지 조사

 

 

WM_SYSKEYDOWN, WM_SYSKEYUP, WM_SYSCHAR = Alt키와 함께 눌러지는 키보드 메세지

 

마우스 입력

 

메세지

 버튼

 누름

놓음 

더블클릭 

좌측

우측

중앙

WM_LBUTTONDOWN

WM_RBUTTONDOWN

WM_MBUTTONDOWN

WM_LBUTTONUP

WM_RBUTTONUP

  WM_MBUTTONUP 

WM_LBUTTONDBLCLK

WM_RBUTTONDBLCLK

WM_MBUTTONDBLCLK

 

lParam => 마우스 버튼이 눌러진 좌표가 상위 워드에 y좌표, 하위 워드에 x좌표

 

좌표 값 검출 매크로 함수

LOWORD(lParam), HIWORD(lParam)

       = x                       = y

 

wParam = 마우스 버튼 상태와 키보드 조합키(shift, ctrl)의 상태전달

 

WM_LBUTTONDWON = 누르고 있으면 계속 발생하는 게 아니라 눌렀을 때의 순간에만 메세지가 한번만 발생

WM_MOUSEMOVE = 마우스가 이동할 때마다 발생, 마우스 이동이 멈춘 x, y 좌표값 전달

WM_MOUSEWHEEL

WM_LBUTTONDBLCLK = 더블클릭, 사용 원할 시 WndClass.style = CS_DBLCLKS; 추가할 것

 

타이머

타이머 메세지 WM_TIMER(wParam : 타이머ID, lParam : 타이머 발생시 호출될 함수)

UINT SetTimer(HWND hWnd, UINT nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc)

                     = 윈도우        = 타이머의 번호

UINT uElapse = 타이머의 주기 설정 값에 따라 그 주기에 맞게 타이머 메세지 전달

                    = 1 / 1000 * uElapse초

TIMERPROC lpTimerFunc = 타이머 메시지가 발생할 때마다 호출될 함수 지정

 

BOOL KillTimer(HWND hWnd, UINT uIDEvent);

                     = 윈도우         = 타이머의 번호

 

SendMessage

LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

                                    = 윈도우        = 메세지    = 메세지에 따라 추가 정보가 달라짐

 

타이머를 여러개 설정하여 필요한 용도에 사용 가능

 

백그라운드 작업

WinMain함수에 무한루프를 작성하면 안됨

Setimer()함수와 WM_TIMER메세지를 이용하여 계속 지속되어야 할 작업을 작게 나눠서 처리할 것

 

콜백함수

VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime);

hwnd = 타이머를 소유한 윈도우의 핸들

uMsg = WM_TIMER

idEvent = 타이머ID

dwTime = 윈도우즈가 실행된 후의 경과시간

 

콜백함수란(Callback Function)?

일반적으로 API함수들은 운영체제가 제공하며 프로그램에서는 이 함수들을 호출해서 운영체제의 서비스를 받는다

반면 콜백함수는 응용 프로그램이 제공하며 운영체제가 필요할 때 호출하는 함수

호출되는 방향이 거꾸로 되었기 때문에 콜백이라고 부름

 

 

일회용 타이머

Setimer()함수로 WM_TIMER메세지를 발생시키고

WndProc()함수 안에서 WM_TIMER에서 KillTimer()로 타이머를 한번만 사용하도록 함

 

윈도우 관리 메세지

생성 및 파괴

WinMain은 윈도우 생성 후, 파괴 후의 시점(프로그램 전역적인 초기/종료 처리)

WndProc은 윈도우 생성중, 파괴중(특정한 윈도우에 관련된 초기/종료 처리)

WM_CREATE(윈도우 생성)와 WM_DESTROY(윈도우 파괴)메세지

 

WM_DESTROY메세지 처리시 꼭 PostQuitMessage()함수를 호출해야 함

메인 윈도우는 응용프로그램이 처음 만드는 윈도우 자신이 파괴될 때 응용 프로그램을 종료해야 함

PostQuitMessage()함수는 WinMain()함수에 있는 메세지 루프를 종료시킴

 

작업영역

윈도우는 작업영역(Client Area)와 비작업영역(Non Client Area) 두 부분으로 구성됨

 

BOOL GetClientRect(HWND hWnd, LPRECT lpRect);

Client가 차지하고 있는 Rect를 얻기위한 함수

 

WM_SIZE

윈도우의 크기가 변경될 때마다 전달

lParam의 하위 워드에는 변경된 후의 윈도우 폭, 상위 워드에는 높이가 전달

wParam에서는 메세지가 발생한 이유를 나타내는 플래그를 전달 

플래그 

값 

 SIZE_MAXHIDE

다른 윈도우가 최대화되어 이 윈도우가 가려졌음 

 SIZE_MAXIMIZED

 최대화 되었음

 SIZE_MAXSHOW

 다른 윈도우가 원래 크기로 복구되어 이 윈도우가 드러남

 SIZE_MINIMIZED

 최소화되었음

 SIZE_RESTORED

 크기가 변경됨

 

WM_MOVE

윈도우의 위치가 변경될 때마다 보내짐

lParam의 하위 워드에 윈도우의 새 x좌표, 상위 워드에 윈도우의 새 y좌표가 전달

반응형