孙鑫01
1.消息和事件
用戶在操作系統(tǒng)中任何一個(gè)操作都是事件。比如鼠標(biāo)單擊了一個(gè)按鈕就是一個(gè)鼠標(biāo)事件。消息是操作系統(tǒng)將事件傳遞給用戶程序的數(shù)據(jù)格式,是一種數(shù)據(jù)通訊協(xié)議。操作系統(tǒng)將每個(gè)事件都包裝成一個(gè)稱為消息的結(jié)構(gòu)體MSG來傳遞給應(yīng)用程序。
MSG結(jié)構(gòu)定義如下:
- 句柄,資源的標(biāo)識(shí),操作系統(tǒng)要管理和操作這些資源,都是通過句柄來找到對(duì)應(yīng)的資源。句柄又可以分為圖標(biāo)句柄(HICON),光標(biāo)句柄(HCURSOR),窗口句柄(HWND),應(yīng)用程序?qū)嵗浔?#xff08;HINSTANCE)。操作系統(tǒng)給每一個(gè)窗口指定一個(gè)唯一的標(biāo)識(shí)號(hào)即窗口句柄。
- 消息,實(shí)質(zhì)是整數(shù),為了便于記憶采用了宏的形式,比如用WM_開頭的各種窗口消息。
- WParam LParam都是整型,表示消息的附加信息。比如WM_CHAR消息,WParam用來存放按鍵的ASCII碼,LParam比較復(fù)雜,MSDN說明如下:
The repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table.
Bits Meaning
0-15 The repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative.
16-23 The scan code. The value depends on the OEM.
24 Indicates whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
25-28 Reserved; do not use.
29 The context code. The value is 1 if the ALT key is held down while the key is pressed; otherwise, the value is 0.
30 The previous key state. The value is 1 if the key is down before the message is sent, or it is 0 if the key is up.
31 The transition state. The value is 1 if the key is being released, or it is 0 if the key is being pressed. - DWORD 記錄消息發(fā)送的時(shí)間
- POINT 記錄光標(biāo)的位置
2.windows的入口函數(shù)
int WINAPI WinMain {HINSTANCE hInstance, //handle to current instanceHINSTANCE hPreInstance, //handle to previous instanceLPSTR lpCmdLine, //command lineint nCmdShow //show state }- hPreInstance 比如有兩個(gè)一樣的程序,就有當(dāng)前和先前之分了。如果只有一個(gè)程序,那么hPreInstance應(yīng)該為空
- LPSTR 長指針,類似于char*。命令行參數(shù) 比如在windows運(yùn)行欄中輸入 notepad 1.txt 就能啟動(dòng)1.txt
這就是命令行參數(shù)。下圖是如何設(shè)定一個(gè)命令行參數(shù)。
- nCmdShow 顯示狀態(tài),比如窗口的最大化 最小化 隱藏顯示等
注意WinMain函數(shù)是由操作系統(tǒng)調(diào)用的。
2.創(chuàng)建一個(gè)完整窗口的步驟
- 設(shè)計(jì)一個(gè)窗口
- 注冊(cè)一個(gè)窗口
- 創(chuàng)建一個(gè)窗口
- 顯示及更新一個(gè)窗口
在我們的程序中,經(jīng)常要用到一類變量,這個(gè)變量的每一位,都對(duì)應(yīng)一種特性,當(dāng)該變量的某位為1時(shí),表示有該位對(duì)應(yīng)的那種特性,當(dāng)該位為0時(shí),即沒有該位所對(duì)應(yīng)的那種特性。當(dāng)變量中的某幾位同時(shí)為1時(shí),就表示同時(shí)具有幾種特性的組合。一個(gè)變量中的哪一位代表哪種意義不容易記憶,所以我們根據(jù)特征的英文拼寫的大寫去定義一些宏,我們可以用二進(jìn)制or|操作符將他們進(jìn)行或運(yùn)算相組合。如果要去掉某個(gè)特征,去反~之后再進(jìn)行&運(yùn)算就可以實(shí)現(xiàn)。例如style &~CS_NOCLOSE
窗口類
- WNDPROC lpfnWndProc回調(diào)函數(shù)指針?;卣{(diào)函數(shù)的原理是這樣的,當(dāng)應(yīng)用程序收到給某一個(gè)窗口的消息時(shí),就應(yīng)該調(diào)用某一函數(shù)來處理這條消息。這一調(diào)用過程不用應(yīng)用程序自己來實(shí)施,而由操作系統(tǒng)來完成,但是回調(diào)函數(shù)本身的代碼必須由應(yīng)用程序自己來完成。對(duì)于一條消息,操作系統(tǒng)到底調(diào)用應(yīng)用程序中的那個(gè)函數(shù)來處理呢,操作系統(tǒng)就調(diào)用接受消息的窗口所屬類型中的lpfnWndProc成員指定的函數(shù),每一種不同類型的窗口都有自己專用回調(diào)函數(shù),該函數(shù)就是通過lpfnWndProc成員指定
WNDCLASSEX wcex;
3.HWND和HINSTANCE的區(qū)別
hWnd,是指窗口句柄,通過該句柄可以操作窗口資源;hInstance是應(yīng)用程序句柄,是操作系統(tǒng)分配給實(shí)例的指針. 程序根據(jù)hInstance訪問其相應(yīng)的內(nèi)存空間。
應(yīng)用程序一定有hInstance,但不一定有hWnd.
4.注冊(cè)窗口
在用WNDCLASS設(shè)定好窗口的相關(guān)參數(shù)后,調(diào)用RegisterClass(&wndclass)就可以實(shí)現(xiàn)窗口類的注冊(cè)
5.創(chuàng)建窗口
先定義一個(gè)句柄
HWND hwnd; CreatWindow(LPCTSTR lpClassName //register calss name 即在wndclass注冊(cè)的類名,否則啟動(dòng)不了窗口LPCTSTR lpWindowName//window nameDWORD dwStyle //window styleint x //horizental position of windowint y //vertical position of windowint nWidth //window widthint nHeight //window heightHWND hWndParent //handle to parent or owner windowHINSTANCE hInstance //handle to application instanceLPVOID lpParam //window creation data);6.顯示窗口
ShowWindow(HWnd,int nCmdShow)
7.更新窗口
UpDateWindow(hwnd)
8.消息循環(huán)
MSG msg;
while(GetMessage(&MSG,NULL,0,0))
{
TranslateMessage(&MSG);
DispatchMessage(&MSG);
}
GetMessage是從消息隊(duì)列中獲取消息,
GetMessage{
LPMSG lpMsg //message information
HWND hwnd //handle to window
UINT wMsgFilterMin,//first message
UINT wMsgFilterMax //last message
}
HWND hwnd=NULL時(shí)表示調(diào)用線程的任何窗口的消息,也就是獲取所有的消息
wMsgFilterMin,wMsgFilterMax為NULL時(shí)表示接受所有的消息
返回值為bool,有返回值時(shí)即為真
- TranslateMessage(&MSG)
消息轉(zhuǎn)化,對(duì)取到的消息對(duì)轉(zhuǎn)化。比如keydown和keyup消息時(shí),能轉(zhuǎn)化到WM_char消息,并將轉(zhuǎn)換后的消息投放到消息隊(duì)列中,只會(huì)產(chǎn)生新消息,不會(huì)影響原來的消息 - DispatchMessage(&MSG)
將搜到的消息傳到窗口回調(diào)函數(shù)中處理。將消息路由到操作系統(tǒng),然后操作系統(tǒng)調(diào)用窗口的回調(diào)函數(shù)。
9.窗口過程的回調(diào)函數(shù)
LRESULT CALLBACK WindowProc
(
HWND hwnd,
MSG msg,
WParam wParam,
LParam lParam,
)
10.BeginPaint 和EndPaint
PAINTSTRUCT ps;
HDC hdc;
switch(umsg)
{
case WM_PAINT:
{
hdc=BeginPaint (hwnd,&ps);
EndPaint(hwnd,&ps);
break;
}
}
注意WM_PAINT中只能使用BeginPaint 和EndPaint,
GetDC和RRelaeaseDC不能再這里使用
11.關(guān)閉窗口消息WM_Close
case WM_Close:
if(IDYES==MessageBox(hend,“你是否要退出程序”,“維新”,MB_YESNO))
{
DestroyWindow(hwnd); //銷毀窗口,并發(fā)送WM_DESTROY消息,但不銷毀程序
}
break;
12.WM_DESTROY
case WM_DESTROY:
PostQuitMessage(0);
break;
通知系統(tǒng)線程請(qǐng)求終止,其形參是給出應(yīng)用程序退出的代碼,其值作為WM_QUIT消息的附加參數(shù),放到WParam中。發(fā)出的WM_QUIT消息發(fā)送到線程消息隊(duì)列中。PostQuitMessage()返回值為0,使GetMessage得到0值,退出程序。
13.缺省消息處理
default :
return DefWindowProc(hwnd,uMSG,WParam,LParam);
讓系統(tǒng)處理我們沒有定義的消息,注意此處不能缺省,不然無法正常啟動(dòng)程序
總結(jié)
- 上一篇: 直流单臂桥的使用注意事项:
- 下一篇: DO测量仪e+h溶解氧变送器维修COM2