'타이머'에 해당되는 글 8건

  1. 2010.07.18 WinApi 타이머2 [SendMessage]
  2. 2010.07.18 WinApi 타이머
posted by nsakura 2010. 7. 18. 18:39

바로 전 타이머 포스팅을 보면 약간의 문제가 있다.

프로그램이 실행되면 바로 약간 갭이 있는후에 시계가 뜬다

이유가 뭘까?

WM_PAINT가 문제일까 WM_TIMER가 문제일까?

자세히 살펴보자

WM_PAINT는 단지 화면에 글씨를 출력시켜주는 일밖에 안한다.

그러니 문제가 없다고 본다.

그렇다면 WM_TIMER에서 문제일까?

그렇다 WM_TIMER의문제 인데. 이유는 간단!

WM_TIMER에서 현 시간을 조사하는데 걸리는 시간이 1초라는것이다.

간단하게 말하면 WM_TIMER가 프로그램이 실행되고 1초후라는거다.

그러니 1초라는 갭이있는데 이 갭을 없애고 싶다는것이다.

그러기 위해서 사용하는 함수가 SendMessage함수이다.

원형을 보자.

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

즉 이 함수는 강제적으로 메시지가 발생한 것처럼 만들어주는 함수라고 보면 된다.

첫 번째 인수 윈도우를 말하는것

두 번째 인수 보내고자하는 메세지

세 번째 네 번째 인수는 메세지의 추가 정보인 wParam,lParam이며 보내는 메세지에따라 달라진다.

wParam은 타이머 Id를 보내도록 되어있다.

타이머 포스트의 소스의 일부를

 case WM_CREATE:
  SetTimer(hWnd,1,1000,NULL);
  SendMessage(hWnd,WM_TIMER,1,0);
  return 0;

이렇게 추가하자.

본인이 프로그램을 짤때는 문제는 없으니 책을 보니 두번째 문제가 있다고 하는데.

바로 시간을 갱신할때 화면이 껌뻑거릴수있다고 하는데. 이것에 대한 문재는.

InvalidateRect(hWnd,NULL,true);

두번째 인자가 null이다 즉 전체 화면에 대해 다시 그린다 인데 이게 문제가되어서 화면이 깜빡거릴수있다고 한다.

두번째 인자는 앞 포스팅에서 말했듯 다시그릴 영역 즉 범위를 설정한다고 했다.

코드 전체를 보면

#include <windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

HINSTANCE g_Inst;
LPCTSTR wndname=TEXT("GFP TIME");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nShowCmd){
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_Inst=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=wndname;
 WndClass.lpszMenuName=NULL;
 WndClass.style=CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd=CreateWindow(wndname,wndname,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);

 ShowWindow(hWnd,nShowCmd);

 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;
 SYSTEMTIME st;
 
 static RECT table={100,100,400,120};

 static TCHAR sTime[128];

 switch(iMessage){
 case WM_DESTROY:
  KillTimer(hWnd,1);
  PostQuitMessage(0);
  return 0;
 case WM_CREATE:
  SetTimer(hWnd,1,1000,NULL);
  SendMessage(hWnd,WM_TIMER,1,0);
  return 0;
 case WM_TIMER:
  GetLocalTime(&st);
  wsprintf(sTime,TEXT("%d : %d: %d"),st.wHour,st.wMinute,st.wSecond);
  InvalidateRect(hWnd,&table,true);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  TextOut(hdc,100,100,sTime,lstrlen(sTime));
  EndPaint(hWnd,&ps);
  return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));


}


이런식이 되겠다.


'Computer > Win API' 카테고리의 다른 글

WinApi 두개의 타이머  (0) 2010.07.18
WinApi 타이머 확장 문제.  (0) 2010.07.18
WinApi 타이머  (0) 2010.07.18
WinApi 마우스 입력.  (0) 2010.07.18
WinApi WM_KEYDOWN  (0) 2010.07.18
posted by nsakura 2010. 7. 18. 17:49

메세지는 프로그램 실행중에 사용자로부터 입력 된다.

메세지는 이렇게 사용자에 의해 대부분 유발되지만  사용자의 동작과 상관없이 발생하는 메세지도 있는데

대표적으로 WM_TIMER가있다.

자 WM_TIMER를 이용해 프로그램을 하나 짜보자.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

HINSTANCE g_Inst;
LPCTSTR wndname=TEXT("GFP TIME");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nShowCmd){
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_Inst=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=wndname;
 WndClass.lpszMenuName=NULL;
 WndClass.style=CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd=CreateWindow(wndname,wndname,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);

 ShowWindow(hWnd,nShowCmd);

 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;
 SYSTEMTIME st;
 static TCHAR sTime[128];

 switch(iMessage){
 case WM_DESTROY:
  KillTimer(hWnd,1);
  PostQuitMessage(0);
  return 0;
 case WM_CREATE:
  SetTimer(hWnd,1,1000,NULL);
  return 0;
 case WM_TIMER:
  GetLocalTime(&st);
  wsprintf(sTime,TEXT("%d : %d: %d"),st.wHour,st.wMinute,st.wSecond);
  InvalidateRect(hWnd,NULL,true);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  TextOut(hdc,100,100,sTime,lstrlen(sTime));
  EndPaint(hWnd,&ps);
  return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

여기서 새로운 구조체와 몇개의 함수가 등장하는데.

SYSTEMTIME 구조체와  GetLocalTimer이라는 함수는  일단 차후에 자세히 다루게 될 것이다.

WM_CREATE메세지는 윈도우가 처음 생설될 때 발생한다.

WM_CREATE가 발생하면

SetTimer 함수가 호출되는데.. 함수 원형은

UINT SetTimer(HWND hWnd, UINT nlDEvent, UINT uElapse, TIMERPROC ipTimerFunc);

첫 번째 인수 타이머 메세지를 받을 윈도우

두 번째  타이머의 번호를 지정하며 이 번호 WM_TIMER 메시지에서 타이머를 구분하기 위한 표식을 사용

세 번째 타이머의 주기를 설정하는데 단위는 1/1000초이다.

네 번째 타이머 메세지가 발생할 때마다 호출되는 함수를 지정하는데 사용하지 않을 경우 NULL로 지정한다.

WM_TIMER 메세지는 wParam으로 타이머 ID를 전달 받으면 lParam으로 타이머 메세지를 발생시 호출될 함수의 번지를 전달한다.

WM_TIMER 메세지가 발생하면 GetLocalTime함수로 시간을 조사한 후 출력을 위해 sTimer 문자열로 변환해 둔다. 시간이 바뀔때마다.

갱신 InvalidateRect함수로 통해 WM_PAINT를 발생.

그리고 윈도우가 꺼질때.

WM_DESTROY메세지가 발생 되는데...

KillTimer함수는 설치된 타이머를 없애는 함수 이다.


'Computer > Win API' 카테고리의 다른 글

WinApi 타이머 확장 문제.  (0) 2010.07.18
WinApi 타이머2 [SendMessage]  (0) 2010.07.18
WinApi 마우스 입력.  (0) 2010.07.18
WinApi WM_KEYDOWN  (0) 2010.07.18
WinApi input WM_CHAR  (0) 2010.07.17