現(xiàn)在是4點(diǎn),距離下班還有一個(gè)小時(shí)時(shí)間,準(zhǔn)備再?gòu)?fù)習(xí)一下SDK。
由于MFC使用了很長(zhǎng)時(shí)間,總是有想返回去好好研究一下SDK的沖動(dòng)。無(wú)奈時(shí)間有限,只能復(fù)習(xí)個(gè)一鱗半爪。
通過(guò)本文能夠了解到:
Timer的使用
第一部分:工程做成
在VC 6.0下面新建--Win32 Application ,在項(xiàng)目名處填寫(xiě)testTimer,點(diǎn)擊OK,在下一頁(yè)選擇中間的選項(xiàng),點(diǎn)擊完成。一個(gè)空空如也的項(xiàng)目建立完畢。
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
return 0;
}
第二部分:添加骨肉
可以將SDK骨架簡(jiǎn)單記憶成:InitApp,InitInstance,Message循環(huán),再加上一個(gè)WinProc四部分就可以了。雛形就不多說(shuō)了。內(nèi)容如下:
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
框架做好了。編譯一下,是不是可以生成一個(gè)最基本的程序框架了?
此框架啥都沒(méi)做,點(diǎn)擊一下Exit。程序退出。
第三部分:Timer的使用
好多人估計(jì)還不熟悉SDK框架,以后有時(shí)間我會(huì)補(bǔ)一個(gè)框架介紹,并暫定今天的標(biāo)題為WindowsSDK入門(mén)系列,同時(shí)說(shuō)明我的復(fù)習(xí)的內(nèi)容均Copy自網(wǎng)上,如有雷同,概不負(fù)責(zé)。
我想使用的Timer很簡(jiǎn)單,就是在程序界面上面,每一秒更新一次時(shí)間。就跟Windows右下角的那個(gè)鐘表一樣。
先看一下SetTimer的原型
UINT_PTR SetTimer( HWND hWnd, // 接受Timer消息的窗口句柄
UINT_PTR nIDEvent, // timerID
UINT uElapse, // 經(jīng)過(guò)時(shí)間,毫秒為單位
TIMERPROC lpTimerFunc // Timer的回調(diào)函數(shù)
);
這個(gè)設(shè)定一開(kāi)始,Windows就會(huì)按時(shí)(根據(jù)uElapse)向程序發(fā)送WM_TIMER消息了。如果將回調(diào)函數(shù)設(shè)置為NULL,那么該消息能就在WndProc中獲得。
要想停止Timer,只需要調(diào)用函數(shù)
BOOL KillTimer( HWND hWnd,
UINT_PTR uIDEvent
);
傳入Window 句柄,跟TimerID即可關(guān)閉timer。
主要函數(shù)說(shuō)完了,先看代碼,然后再說(shuō)說(shuō)需要注意的細(xì)節(jié)。
#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時(shí)%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;
}
咳咳,現(xiàn)在說(shuō)一下“要點(diǎn)”,其實(shí)也算不上什么要點(diǎn)。就是一些細(xì)節(jié)而已。把細(xì)節(jié)掌握多了,對(duì)程序也就會(huì)更加了解。
1. 我們將SetTimer放在WM_CREATE消息中執(zhí)行,這個(gè)消息是在CreateWindow執(zhí)行,創(chuàng)建了hWnd句柄后,我們才能將hWnd傳入SetTimer的以一個(gè)參數(shù)不是。
2. KillTimer可以放到WM_DESTROY中執(zhí)行,如果你想要在停止前還做到什么其他動(dòng)作。比如我想在停止前彈一個(gè)消息框,就可以在WM_CLOSE中添加,注意因?yàn)槟憧梢哉{(diào)用Hook這個(gè)消息,但是一定要將他要做的事情也順帶做好了。WM_CLOSE自己要做什么?DestroyWindow(hWnd)。DestroyWindow將會(huì)發(fā)送WM_DESTROY消息。
3. Menu消息是通過(guò)WM_COMMAND來(lái)獲得的。
4. WM_PAINT在這個(gè)消息中一般用BeginPaint,EndPaint搭對(duì)使用,來(lái)獲得和銷(xiāo)毀句柄。
如果在其他地方,使用GetDC(),ReleaseDC 。MFC中,直接用那個(gè)dc(this)就可以了。
5. GetTimeStr使用GetLocalTime來(lái)獲取系統(tǒng)當(dāng)前時(shí)間。
6. 關(guān)于屏幕刷新InvalidateRect BOOL InvalidateRect(
HWND hWnd,
const RECT* lpRect,
BOOL bErase
hWnd為要刷新句柄,lpRect為刷新區(qū)域,指定NULL為刷新整個(gè)區(qū)域。bErase為FASLE是不刷新背景。
End。