現在是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。