聲明:
本人最近也在看孫老師的視頻,為了加強(qiáng)理解,所以想一些讀書(shū)筆記。但是在CSDN上一搜索,發(fā)現(xiàn)已經(jīng)有朋友做了相關(guān)筆記。根據(jù)面向?qū)ο蟮摹袄^承”觀點(diǎn),為了解決勞動(dòng)力,所以我打算在他們的基礎(chǔ)上添加、修改。應(yīng)該不涉及著作權(quán)什么的東東吧?!
我在BLOG.CSDN.NET/LEWISLAU上搜索了下 ,有兩位朋寫了相關(guān)筆記(而且都是一樣的)。不知道誰(shuí)才是原作者,所以列出兩位BLOG地址:
http://blog.csdn.net/hhitjsj021 http://blog.csdn.net/d007879
以后我會(huì)在前輩的基礎(chǔ)上修改、發(fā)文!呵呵!繼承嘛!
windows程序設(shè)計(jì)是種事件驅(qū)動(dòng)方式的程序設(shè)計(jì),主要基于消息的。當(dāng)用戶需要完成某種功能時(shí),需要調(diào)用OS某種支持,然后OS將用戶的需要包裝成消息,并投入到消息隊(duì)列中,最后應(yīng)用程序從消息隊(duì)列中取走消息并進(jìn)行響應(yīng)。
MSG Structure
--------------------------------------------------------------------------------
The MSG structure contains message information from a thread's message queue.
Syntax
typedef struct {
HWND hwnd; //指示一個(gè)窗口的句柄,改消息和那個(gè)窗口相關(guān)聯(lián)。
UINT message; //具體的消息,用無(wú)符號(hào)整形表示
WPARAM wParam; //關(guān)于消息的附加參數(shù)
LPARAM lParam; //同上
DWORD time; //32位整數(shù),表示消息被投遞出去的時(shí)間
POINT pt; //表示光標(biāo)位置
} MSG, *PMSG;
句柄,資源的標(biāo)識(shí),操作系統(tǒng)通過(guò)句柄指到資源。常見(jiàn)的句柄有圖標(biāo)句柄(HICON),光標(biāo)句柄(HCURSOR),窗口句柄(HWND),應(yīng)用程序句柄(HINSTANCE)
例如:當(dāng)按下按鍵會(huì)發(fā)送出WM_CHAR消息 通過(guò)消息的附加參數(shù),保存對(duì)應(yīng)的ASCII碼,即可知道按下的是那個(gè)鍵。
消息隊(duì)列:
每個(gè)應(yīng)用程序OS都為它建立一個(gè)消息隊(duì)列,消息隊(duì)列是個(gè)先進(jìn)先出的緩沖區(qū),其中每個(gè)元素都是一個(gè)消息,OS將生成的每個(gè)消息按先后順序放進(jìn)消息隊(duì)列中,應(yīng)用程序總是取走當(dāng)前消息隊(duì)列中的第一條消息,應(yīng)用程序取走消息后便知道用戶的操作和程序的狀態(tài),然后對(duì)其處理即消息響應(yīng),消息響應(yīng)通過(guò)編碼實(shí)現(xiàn)。
使用VC編程除了良好的C基礎(chǔ)外還需要掌握兩方面:
一,消息本身。不同消息所代表的用戶操作和應(yīng)用程序的狀態(tài)。
二,對(duì)于某個(gè)特定的消息來(lái)說(shuō),要讓OS執(zhí)行某個(gè)特定的功能去響應(yīng)消息。
Window程序入口:
int WINAPI WinMain(
HINSTANCE hInstance, // 當(dāng)前事例句柄。
HINSTANCE hPrevInstance, // 先前事例句柄。
LPSTR lpCmdLine, // 命令行指針
int nCmdShow // (窗口)顯示的狀態(tài)
);
說(shuō)明:WinMain函數(shù)是Windows程序入口點(diǎn)函數(shù),由OS調(diào)用,當(dāng)OS啟動(dòng)應(yīng)用程序的時(shí)候,winmain函數(shù)的參數(shù)由OS傳遞的。
創(chuàng)建一個(gè)完整的窗口需要經(jīng)過(guò)下面四個(gè)操作步驟:
一,設(shè)計(jì)一個(gè)窗口類;如:WNDCLASS wndcls;
二,注冊(cè)窗口類; 如:RegisterClass(&wndcls);
三,創(chuàng)建窗口; 如:CreateWindow(),CreateWindowEX();
四,顯示及更新窗口。如:ShowWindow(),UpdateWindow();
說(shuō)明:創(chuàng)建窗口的時(shí)候一定要基于已經(jīng)注冊(cè)的窗口類.
Windows提供的窗口類:
typedef struct WNDCLASS {
UINT style; //窗口的類型
WNDPROC lpfnWndProc; //窗口過(guò)程函數(shù)指針(回調(diào)函數(shù))
int cbClsExtra; //窗口類附加字節(jié),為該類窗口所共享。通常0。
int cbWndExtra; //窗口附加字節(jié)。通常設(shè)為0。
HANDLE hInstance; //當(dāng)前應(yīng)用程序事例句柄。
HICON hIcon; //圖標(biāo)句柄 LoadIcon();
HCURSOR hCursor; //光標(biāo)句柄 LoadCursor();
HBRUSH hbrBackground; //畫(huà)刷句柄 (HBRUSH)GetStockObject();
LPCTSTR lpszMenuName; //菜單名字
LPCTSTR lpszClassName; //類的名字
} WNDCLASS,*PWNDCLASS;
窗口類型style為一個(gè)變量,該變量每一位對(duì)應(yīng)著一種特性。對(duì)應(yīng)為1時(shí),有該種特性;對(duì)應(yīng)為0時(shí),無(wú)該種特性。為了方便記憶,用一些宏對(duì)應(yīng)一些特征,通過(guò)取反(~)和相與(&)可以取消一些特性。 通常設(shè)置為"CS_HREDRAW | CS_VREDRAW"表示垂直重繪和水平重繪。
HICON可以由LoadIcon 賦值(它有兩個(gè)參數(shù)HINSTANCE和LPCTSTR,通常第一個(gè)參數(shù)為空,只對(duì)第二個(gè)參數(shù)賦值,即圖標(biāo)的ID)
HCURSOR同HICON
HBRUSH 使用GetStockObject函數(shù),它可以用來(lái)獲取筆、畫(huà)刷、字符、調(diào)試板的畫(huà)刷。使用時(shí)要用HBRUSH做一直強(qiáng)制轉(zhuǎn)化。因?yàn)镚etStockObject返回值和HBRUSH不同。
窗口類注冊(cè):
ATOM RegisterClass(
CONST WNDCLASS *lpWndClass // address of structure with class
// data
);
//注意,是使用地址符
創(chuàng)建窗口:
HWND CreateWindow(
LPCTSTR lpClassName, //注冊(cè)窗口類名,用引號(hào)
LPCTSTR lpWindowName, //窗口標(biāo)題,用引號(hào)
DWORD dwStyle, //窗口類型(風(fēng)格)通常為(WS_OVERLAPPEDWINDOW)
int x, // 窗口X坐標(biāo)
int y, // 窗口X坐標(biāo)
int nWidth, // 寬度
int nHeight, // 高度
HWND hWndParent, // 指向父窗口的句柄
HMENU hMenu, // 菜單句柄
HANDLE hInstance, // 當(dāng)前實(shí)例的句柄,由WINMAIN傳遞
LPVOID lpParam // WM_CREATE附加參數(shù)傳入指針
);
創(chuàng)建窗口的時(shí)候會(huì)發(fā)送WM_CREATE消息
顯示和更新窗口窗口:
BOOL ShowWindow(
HWND hWnd, // handle to window
int nCmdShow // show state of window
);
BOOL UpdateWindow(
HWND hWnd // handle of window 送出WM_PAINT消息
);
消息循環(huán)
MSG msg;
while(GetMessage(&msg,...)) //從消息隊(duì)列中取出一條消息
{
TranslateMessage(&msg); //進(jìn)行消息(如鍵盤消息)轉(zhuǎn)化。轉(zhuǎn)化過(guò)程不會(huì)影響原消息,只會(huì)創(chuàng)建新的消息。
DispatchMessage(&msg); //分派消息到窗口的回調(diào)函數(shù)處理,(OS調(diào)用窗口回調(diào)函數(shù)進(jìn)行處理)。
}
BOOL GetMessage(
LPMSG lpMsg, // 消息結(jié)構(gòu)體變量
HWND hWnd, // 句柄,那個(gè)一個(gè)窗口?為NULL則為所有窗口句柄
UINT wMsgFilterMin, // 最小消息值,為0時(shí)返回所有消息
UINT wMsgFilterMax // 最大消息值
);
回調(diào)原理:當(dāng)應(yīng)用程序受到給某個(gè)窗口的消息時(shí),就應(yīng)調(diào)用某一函數(shù)來(lái)處理這條消息。這一消息有操作系統(tǒng)自動(dòng)完成。
注:函數(shù)名可以用以表示函數(shù)代碼的首地址(函數(shù)指針),額外數(shù)據(jù)通常為0。
窗口過(guò)程函數(shù)(回調(diào)函數(shù))原型:
LRESULT CALLBACK WindowProc( //這里WindowProc是個(gè)代號(hào)名字。
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
說(shuō)明:兩種函數(shù)調(diào)用約定(__stdcall 和 __cdecl):
#define CALLBACK __stdcall
//__stdcall 標(biāo)準(zhǔn)調(diào)用預(yù)定,是PASCAL 調(diào)用約定,象DELPHI使用的就是標(biāo)準(zhǔn)調(diào)用約定
#define WINAPIV __cdecl
// __cdecl 是C 語(yǔ)言形式的調(diào)用約定。
主要區(qū)別:函數(shù)參數(shù)傳遞順序 和 對(duì)堆棧的清除上。
問(wèn)題:除了那些可變參數(shù)的函數(shù)調(diào)用外,其余的一般都是__stdcall約定。但 C/C++編譯默然的是__cdecl約定。所以如果在VC等環(huán)境中調(diào)用__stdcall約定的函數(shù),必須要在函數(shù)聲明的時(shí)加上 __stdcall 修飾符,以便對(duì)這個(gè)函數(shù)的調(diào)用是使用__stdcall約定(如使用DELPHI編寫的DLL時(shí)候)。
(VC中可通過(guò)這途徑修改:project|settings..|c/c++|...)
在窗口過(guò)程函數(shù)中通過(guò)一組switch語(yǔ)句來(lái)對(duì)消息進(jìn)行處理:
如:
LRESULT CALLBACK WindowProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch(uMsg)
{
case WM_PAINT:
...
break;
case ...
break;
case WM_CLOSE:
//DestroyWindow(hwnd);
//銷毀窗口,并發(fā)送WM_DESTROY消息。
break;
case WM_DESTROY:
//PostQuitMessage(0);
//發(fā)送WM_QUIT消息到消息隊(duì)列中,請(qǐng)求終止。
//GetMessage()取到WM_QUIT消息后,返回0,退出消息循 // 環(huán),從而終止應(yīng)用程序。
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
//用缺省的窗口過(guò)程處理我們不感興趣的消息(其它消息)。
//這是必須的。
}//switch
return 0;
}//WindowProc
響應(yīng)WM_DESTROY,調(diào)用PostQuitMessage(int)結(jié)束進(jìn)程。它會(huì)投遞一個(gè)WM_QUIT消息對(duì)消息隊(duì)列中。當(dāng)消息循環(huán)的GetMessage取到WM_QUIT消息,則返回0,程序結(jié)束。
另外對(duì)于不感興趣的消息要景象缺省的處理,使用DefWindowProc()內(nèi)為窗口的參數(shù)。
關(guān)于DC句柄獲取:
a)使用BeginPaint(),EndPaint()對(duì)。注意只能在響應(yīng)WM_PAINT消息時(shí)使用。
b)使用GetDc(),ReleaseDC()對(duì)。注意他們不能在響應(yīng)WM_PAINT中使用