该内核对象类似于计时器 。当然,它和用户模式下的计时器 是有区别的。
使用CreateWaitableTimer函数可以创建一个可等待计时器 内核对象。用SetWaitableTimer函数来对可等待计时器 内核对象进行设置。另外可等待计时器 内核对象还可以以异步(Asynchronous)方式调用函数( APC )。基本上都可以给它传递NULL。
我比较喜欢使用事件内核对象和可等待计时器 内核对象配合使用。否则前面学习的计时器 内核对象就白学了:-)。
下面给出没有任何注释的代码,因为代码很简单,很容易看懂,这是在Windows Live Writer中写的,所以没有代码模式:
#include <windows.h>
#include <tchar.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HWND g_hWnd;
HANDLE g_hTimer,g_hEvt;
DWORD WINAPI WTThreadWatch(PVOID pvParam)
{
static int yCur=0,nTimes=0;
HDC hdc;
TCHAR szBuf[1024]={0};
g_hEvt=CreateEvent(NULL,FALSE,FALSE,NULL);
while(TRUE)
{
WaitForSingleObject(g_hTimer,INFINITE);
SetEvent(g_hEvt);
hdc=GetDC(g_hWnd);
_stprintf_s(szBuf,_countof(szBuf),TEXT("This is the %d times WaitableTimer actived"),nTimes);
TextOut(hdc,250,0,szBuf,_tcslen(szBuf));
//yCur+=20;
nTimes++;
ReleaseDC(g_hWnd,hdc);
}
return 0;
}
DWORD WINAPI WTThreadActive(PVOID pvParam)
{
static BOOL bFlag=FALSE;
HDC hdc;
TCHAR szMsg[16]=TEXT("Actived");;
hdc=GetDC(g_hWnd);
while(1)
{
WaitForSingleObject(g_hEvt,INFINITE);
UpdateWindow(g_hWnd);
if(bFlag)
{
_tcsrev(szMsg);
TextOut(hdc,0,0,szMsg,_tcslen(szMsg));
bFlag=FALSE;
}
else
{
_tcsrev(szMsg);
TextOut(hdc,0,20,szMsg,_tcslen(szMsg));
bFlag=TRUE;
}
}
return 0;
}
int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE,PTSTR,int)
{
TCHAR szWndClass[]=TEXT("Waitable Timer");
WNDCLASSEX wc;
wc.cbClsExtra=0;
wc.cbSize=sizeof(wc);
wc.cbWndExtra=0;
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hIcon=LoadIcon(NULL,IDI_HAND);
wc.hIconSm=LoadIcon(NULL,IDI_HAND);
wc.lpszClassName=szWndClass;
wc.lpfnWndProc=WndProc;
wc.hInstance=hInstance;
wc.lpszMenuName=NULL;
wc.style=CS_HREDRAW|CS_VREDRAW;
if(!RegisterClassEx(&wc))
{
MessageBox(NULL,TEXT("Can not register class."),TEXT(""),MB_OK);
return -1;
}
g_hWnd=CreateWindowEx(0,szWndClass,TEXT("Waitable Timer Kernel Object"),WS_OVERLAPPED|WS_SYSMENU,CW_USEDEFAULT,CW_USEDEFAULT,500,800,NULL,NULL,hInstance,NULL);
if(!g_hWnd)
{
MessageBox(NULL,TEXT("Can not create window"),TEXT(""),MB_OK);
return -1;
}
ShowWindow(g_hWnd,SW_SHOWNORMAL);
UpdateWindow(g_hWnd);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
TEXTMETRIC tm;
static int cxChar=0,cyChar=0;
SYSTEMTIME st={0};
FILETIME ftLocal,ftUTC;
LARGE_INTEGER liTime;
switch(nMsg)
{
case WM_CREATE:
st.wYear=2009;
st.wMonth=9;
st.wDay=1;
st.wHour=20;
st.wMinute=6;
st.wSecond=0;
st.wMilliseconds=0;
SystemTimeToFileTime(&st,&ftLocal);
LocalFileTimeToFileTime(&ftLocal,&ftUTC);
liTime.HighPart=ftUTC.dwHighDateTime;
liTime.LowPart=ftUTC.dwLowDateTime;
hdc=GetDC(hWnd);
cxChar=GetTextMetrics(hdc,&tm);
cxChar=tm.tmAveCharWidth;
cyChar=tm.tmHeight+tm.tmExternalLeading;
g_hTimer=CreateWaitableTimer(NULL,FALSE,NULL);
SetWaitableTimer(g_hTimer,&liTime,(LONG)10*1000,NULL,NULL,FALSE);
return 0;
case WM_PAINT:
hdc=BeginPaint(hWnd,&ps);
EndPaint(hWnd,&ps);
return 0;
case WM_LBUTTONDOWN:
CreateThread(NULL,0,WTThreadWatch,NULL,0,NULL);
CreateThread(NULL,0,WTThreadActive,NULL,0,NULL);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,nMsg,wParam,lParam);
}