API(7) - realtime 방식과 button ,setTimer
이번에는 realtime 방식과 button ,setTimer을 해보겠습니다.
들어가기에 앞서
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, // 응용 프로그램의 고유 아이디 중요!!
_In_opt_ HINSTANCE hPrevInstance, //
_In_ LPWSTR lpCmdLine, //
_In_ int nCmdShow) // 윈도우의 초기 상태 지정
WinMain의 인수에 대한 것입니다.
마지막 인수 nCmdShow 를 보시면
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
밑에 코드에 이것이 있습니다. nCmdShow 는 그냥 초기상태 값이라고 보면되는데
howWindow(hWnd, SW_SHOWDEFAULT); //SW_SHOWDEFAULT 이것도 디버깅 하면 10 -> 즉 ncmdSHow는 default값
UpdateWindow(hWnd); //WM_PAINT를 띄워주는 역할 invalidate()(큐안에들어감)하고 비슷한데 updatewindow는
//큐안에 안들어감 while문 안에 들어가기전에 로딩화면 초기화 해주는 역할
SHOWDEFAULT 값과 같습니다. (SHOWDEFULT값 -10)
그리고 UpdataeWindow는 전시간에 배운 InvalidateRect()와 비슷하게 WM_PAINT를 발생시켜주는 함수입니다.
하지만 UpdataeWindow은 큐에 들어가지 않아서 메세지 처리를 안하기 때문에 while문에 접근 하기 전에 초기화해주는 함수라고 보면 될 것같습니다.
그리고 realtime방식입니다.
bool done = FALSE;
while (!done)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) //noneblocking 메세지 큐에 메세지전달
{
if (msg.message == WM_QUIT) //메세지가 종료였다면 true로 while문 빠져나감
done = TRUE;
else {
TranslateMessage(&msg); //
DispatchMessage(&msg);
}
}
else {
//변수 갱신만 전문적으로 하는 함수
//그리기와 관련된 함수 rendering 함수 ---> InvalidateRect() 함수
}
}
realtime방식은 blocking 즉 멈추는경우 없이 동작하는 경우입니다.
즉 메세지가 들어오면 메세지 처리를 하고 아니면 else로 보내서 다른 처리를 하게 됩니다.
이런경우 변수 갱신이나 , rendering 함수를 많이 else부분에 넣습니다.
이제 버튼 만드는 방식을 보겠습니다.
WndPoc에 WM_CREATE 케이스를 만들어서 버튼을 넣어보겠습니다.
HWND hBtn1; //전역함수로
case WM_CREATE:
{
//MessageBox(0, TEXT("WM_CREATE"), TEXT("WMCREATE"), MB_OK);
hBtn1 = CreateWindowW(
TEXT("BUTTON"), //예약어 COMBOBOX, EDIT 등의 종류
TEXT("호랑이1"),
WS_VISIBLE | WS_CHILD | WS_BORDER, // BS_DEFPUSHBUTTON, --> 윈도우의 스타일 설정
0, 0, //윈도우 위치
100, 50, //모양 크기
hWnd, //부모
(HMENU)1000, //어떤걸 눌렀는지 식별해주는 번호 --> wParam
hInst, //인스턴스 전달
NULL); //
}
이렇게 뜨게 됩니다. 중요한건 (HMENU)1000부분에서 식별해주는 것이 디버깅을 하면 wParam으로 가는 것을 알 수있습니다. 그러면 버튼을 클릭했을 경우 어떠한 발생을 일으킬 수 있다는 것을 알 수 있습니다 .
그리고 버튼 클릭했을 경우 WM_COMMAND에 함수 작성을 해줍니다.
버튼 3개만들어주시고
case WM_CREATE:
{
//MessageBox(0, TEXT("WM_CREATE"), TEXT("WMCREATE"), MB_OK);
hBtn1 = CreateWindowW(
TEXT("BUTTON"), //예약어 COMBOBOX, EDIT 등의 종류
TEXT("호랑이1"),
WS_VISIBLE | WS_CHILD | WS_BORDER, // BS_DEFPUSHBUTTON, --> 윈도우의 스타일 설정
0, 0, //윈도우 위치
100, 50, //모양 크기
hWnd, //부모
(HMENU)1000, //어떤걸 눌렀는지 식별해주는 번호 --> wParam
hInst, //인스턴스 전달
NULL); //
hBtn2 = CreateWindowW(
TEXT("BUTTON"), TEXT("호랑이2"),
WS_VISIBLE | WS_CHILD | WS_BORDER,
0, 50, 100, 50,
hWnd,
(HMENU)2000,
hInst, NULL);
hBtn3 = CreateWindowW(
TEXT("BUTTON"), TEXT("호랑이3"),
WS_VISIBLE | WS_CHILD | WS_BORDER,
0, 100, 100, 50,
hWnd,
(HMENU)3000,
hInst, NULL);
}
case WM_COMMAND:
{
switch (wParam)
{
case 1000:
{
//ShowWindow(hBtn3, false);
//EnableWindow(hBtn3, false);
//SetWindowText(hBtn3, TEXT("고양이"));
//MessageBox(hWnd, TEXT("id :1000 "), TEXT("h"), MB_OK);
}
break;
case 2000:
{
//ShowWindow(hBtn3, true);
//EnableWindow(hBtn3, true);
//SetWindowText(hBtn3, TEXT("독수리"));
//MessageBox(hWnd, TEXT("id: 2000 "), TEXT("h"), MB_OK);
}
break;
showWindow ,EnableWindow ,SetWindowText 등을 나타낼 수 있습니다.
showWindow는 hBtn3을 true -나타내준다. false - 없애준다.
SetWindowText는 Text를 써주는 것입니다.
EnEnableWindow -hBtn3을 true - 사용가능 false - 사용불가능
이번에는 SetTimer를 알아보겠습니다.
HANDLE hTimer = (HANDLE)SetTimer(hWnd, 123, 1000, NULL); //1초는 1000ms -> WM_TIMER을 발생시킴
SetTimer(주체, ID, 시간 간격 ,null)
그리고 1000->1초입니다.
SetTimer는 WM_TIMER을 발생시키므로 WM_TIMER을 설정해주어야 합니다.
case WM_TIMER :
{
switch (wParam) {
case 123:
{
WCHAR Str[32];
static int ct = 0;
wsprintf(Str, TEXT("fisrt Timer: %d\n"), rand()%100);
OutputDebugString(Str);
}
break;
case 456:
{
WCHAR Str[32];
static int ct = 0;
wsprintf(Str, TEXT("second Timer: %d\n"), ct++);
OutputDebugString(Str);
}
아까 설정해준 id 또한 wParam으로 가기 때문에 위 코드와 같이 나누어 주면 됩니다.
KillTimer(hWnd, 123);
그리고 SetTimer을 했으면 반드시 꺼주어야 합니다.