现在是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
#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 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
#include "myresource.h"
/////////////////////////////////////////////////////////////////////////////
//
// 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 "stdafx.h"
#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。