WindowsSDK入门系列(2) Timer的使用
现在是4点,距离下班还有一个小时时间,准备再复习一下SDK。
由于MFC使用了很长时间,总是有想返回去好好研究一下SDK的冲动。无奈时间有限,只能复习个一鳞半爪。
通过本文能够了解到:
Timer的使用
第一部分:工程做成
在VC 6.0下面新建--Win32 Application ,在项目名处填写testTimer,点击OK,在下一页选择中间的选项,点击完成。一个空空如也的项目建立完毕。
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
return 0;
}
第二部分:添加骨肉
可以将SDK骨架简单记忆成:InitApp,InitInstance,Message循环,再加上一个WinProc四部分就可以了。雏形就不多说了。内容如下:
testTimer.cpp
BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName);
BOOL InitInstance(HINSTANCE hInst, LPCSTR szClassName, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
MSG msg;
char szClassName[] = " timer " ;
if ( ! hPrevInstance)
{
if ( ! InitApp(hInstance, szClassName))
return FALSE;
}
if ( ! InitInstance(hInstance, szClassName, nCmdShow))
{
return FALSE;
}
while (GetMessage( & msg, NULL, 0 , 0 ))
{
TranslateMessage( & msg);
DispatchMessage( & msg);
}
return msg.wParam;
}
// Windows register == MFC's PreCreateWindow
BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc; // Window Proc's Name
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
wc.hInstance = hInst; // Instance
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = " TIMERMENU " ; // Menu
wc.lpszClassName = (LPCSTR)szClassName;
return (RegisterClass( & wc));
}
// Create Windows
BOOL InitInstance(HINSTANCE hInst, LPCSTR szClassName, int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindow(szClassName,
" Timer " , // Disp in Title bar
WS_OVERLAPPEDWINDOW, // Window's kind
CW_USEDEFAULT, // X
CW_USEDEFAULT, // Y
CW_USEDEFAULT, // Width
CW_USEDEFAULT, // Hight
NULL, // Parent's handle
NULL, // menu's handle
hInst, // instanse 's handle
NULL);
if ( ! hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
// WndProc
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_COMMAND: // Click Menu
switch (LOWORD(wp))
{
case IDM_END: // Menu's “Exit” Clicked
SendMessage(hWnd, WM_CLOSE, 0 , 0L );
break ;
default :
break ;
}
break ;
case WM_DESTROY:
PostQuitMessage( 0 );
break ;
default : // calls the default window procedure
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0L ;
}
追加的File
myresource.h
#define IDM_END 1000
testTimer.rc
/////////////////////////////////////////////////////////////////////////// //
//
// Menu
//
TIMERMENU MENU DISCARDABLE
BEGIN
MENUITEM " Exit " , IDM_END
END
框架做好了。编译一下,是不是可以生成一个最基本的程序框架了?
此框架啥都没做,点击一下Exit。程序退出。
第三部分:Timer的使用
好多人估计还不熟悉SDK框架,以后有时间我会补一个框架介绍,并暂定今天的标题为WindowsSDK入门系列,同时说明我的复习的内容均Copy自网上,如有雷同,概不负责。
我想使用的Timer很简单,就是在程序界面上面,每一秒更新一次时间。就跟Windows右下角的那个钟表一样。
先看一下SetTimer的原型
UINT_PTR SetTimer( HWND hWnd, // 接受Timer消息的窗口句柄
UINT_PTR nIDEvent, // timerID
UINT uElapse, // 经过时间,毫秒为单位
TIMERPROC lpTimerFunc // Timer的回调函数
);
这个设定一开始,Windows就会按时(根据uElapse)向程序发送WM_TIMER消息了。如果将回调函数设置为NULL,那么该消息能就在WndProc中获得。
要想停止Timer,只需要调用函数
BOOL KillTimer( HWND hWnd,
UINT_PTR uIDEvent
);
传入Window 句柄,跟TimerID即可关闭timer。
主要函数说完了,先看代码,然后再说说需要注意的细节。
#include < time.h >
#include < stdio.h >
#include " myresource.h "
BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName);
BOOL InitInstance(HINSTANCE hInst, LPCSTR szClassName, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
int GetTimeStr( void );
char time_str[ 256 ];
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{ MSG msg;
char szClassName[] = " timer " ;
if ( ! hPrevInstance)
{
if ( ! InitApp(hInstance, szClassName))
return FALSE;
}
if ( ! InitInstance(hInstance, szClassName, nCmdShow))
{
return FALSE;
}
while (GetMessage( & msg, NULL, 0 , 0 ))
{
TranslateMessage( & msg);
DispatchMessage( & msg);
}
return msg.wParam;
}
// Windows register == MFC's PreCreateWindow
BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc; // Window Proc's Name
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
wc.hInstance = hInst; // Instance
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = " TIMERMENU " ; // Menu
wc.lpszClassName = (LPCSTR)szClassName;
return (RegisterClass( & wc));
}
// Create Windows
BOOL InitInstance(HINSTANCE hInst, LPCSTR szClassName, int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindow(szClassName,
" Timer " , // Disp in Title bar
WS_OVERLAPPEDWINDOW, // Window's kind
CW_USEDEFAULT, // 倃
CW_USEDEFAULT, // 倄
320 , // Width
100 , // Hight
NULL, // Parent's handle
NULL, // menu's handle
hInst, // instanse 's handle
NULL);
if ( ! hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
// WndProc
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
PAINTSTRUCT ps;
HDC hdc;
int id;
switch (msg) {
case WM_CREATE:
if (SetTimer(hWnd, ID_MYTIMER, 1000 , NULL) == 0 )
{
MessageBox(hWnd,(LPCSTR) " Fail " ,(LPCSTR) " Fail " , MB_OK | MB_ICONEXCLAMATION);
}
break ;
case WM_TIMER:
GetTimeStr();
InvalidateRect(hWnd, NULL, TRUE);
break ;
case WM_PAINT:
hdc = BeginPaint(hWnd, & ps);
TextOut(hdc, 50 , 15 , (LPCSTR)time_str, strlen(time_str));
EndPaint(hWnd, & ps);
break ;
case WM_COMMAND: // Click Menu
switch (LOWORD(wp))
{
case IDM_END: // Menu's 乬Exit乭 Clicked
SendMessage(hWnd, WM_CLOSE, 0 , 0L );
break ;
default :
break ;
}
break ;
case WM_CLOSE:
id = MessageBox(hWnd,
(LPCSTR) " Really Quit? " ,
(LPCSTR) " Quit " ,
MB_YESNO | MB_ICONQUESTION);
if (id == IDYES) {
if (KillTimer(hWnd, ID_MYTIMER) == TRUE) {
/*
MessageBox(hWnd,
(LPCSTR)"timer was killed",
(LPCSTR)"kill timer success",
MB_OK | MB_ICONEXCLAMATION); */
}
DestroyWindow(hWnd);
}
break ;
case WM_DESTROY:
PostQuitMessage( 0 );
break ;
default : // calls the default window procedure
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0L ;
}
int GetTimeStr( void )
{
char * str_org = " %2d年%d月%2d日 %2d时%2d分%2d秒 " ;
SYSTEMTIME stSystemTime;
::GetLocalTime( & stSystemTime);
sprintf(time_str, str_org,
stSystemTime.wYear,stSystemTime.wMonth , stSystemTime.wDay,
stSystemTime.wHour,stSystemTime.wMinute, stSystemTime.wSecond
);
return 0 ;
}
咳咳,现在说一下“要点”,其实也算不上什么要点。就是一些细节而已。把细节掌握多了,对程序也就会更加了解。
1. 我们将SetTimer放在WM_CREATE消息中执行,这个消息是在CreateWindow执行,创建了hWnd句柄后,我们才能将hWnd传入SetTimer的以一个参数不是。
2. KillTimer可以放到WM_DESTROY中执行,如果你想要在停止前还做到什么其他动作。比如我想在停止前弹一个消息框,就可以在WM_CLOSE中添加,注意因为你可以调用Hook这个消息,但是一定要将他要做的事情也顺带做好了。WM_CLOSE自己要做什么?DestroyWindow(hWnd)。DestroyWindow将会发送WM_DESTROY消息。
3. Menu消息是通过WM_COMMAND来获得的。
4. WM_PAINT在这个消息中一般用BeginPaint,EndPaint搭对使用,来获得和销毁句柄。
如果在其他地方,使用GetDC(),ReleaseDC 。MFC中,直接用那个dc(this)就可以了。
5. GetTimeStr使用GetLocalTime来获取系统当前时间。
6. 关于屏幕刷新InvalidateRect BOOL InvalidateRect(
HWND hWnd,
const RECT* lpRect,
BOOL bErase
hWnd为要刷新句柄,lpRect为刷新区域,指定NULL为刷新整个区域。bErase为FASLE是不刷新背景。
End。