自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

網(wǎng)絡(luò)安全編程:Windows消息機(jī)制實(shí)例

安全
那么窗口接收到消息后的一系列行為是如何發(fā)生的?下面通過熟悉Windows的消息機(jī)制來理解消息處理背后的秘密。

[[376643]]

 SendMessage()將指定的消息發(fā)送給指定的窗口,窗口接收到消息也有相應(yīng)的行為發(fā)生。那么窗口接收到消息后的一系列行為是如何發(fā)生的?下面通過熟悉Windows的消息機(jī)制來理解消息處理背后的秘密。

01 DOS程序與Windows程序執(zhí)行流程對(duì)比

Windows下的窗口應(yīng)用程序都是基于消息機(jī)制的,操作系統(tǒng)與應(yīng)用程序之間、應(yīng)用程序與應(yīng)用程序之間,大部分都是通過消息機(jī)制進(jìn)行通信、交互的。要真正掌握Windows應(yīng)用程序內(nèi)部對(duì)消息的處理,必須分析實(shí)際的源代碼。在編寫一個(gè)基于消息的Windows應(yīng)用程序前,先來比較DOS程序和Windows程序在執(zhí)行時(shí)的流程。

1. DOS程序執(zhí)行流程

在DOS下將編寫完的程序進(jìn)行執(zhí)行,在執(zhí)行時(shí)有較為清晰的流程。比如用C語言編寫程序后,程序執(zhí)行時(shí)的大致流程如圖1所示。

圖1  傳統(tǒng)DOS程序執(zhí)行流程

在圖1中可以看出,DOS程序的流程是按照代碼的順序(這里的順序并不是指程序控制結(jié)構(gòu)中的順序、分支和循環(huán)的意思,而是指程序運(yùn)行的邏輯有明顯的流程)和流程依次執(zhí)行。大致步驟為:DOS程序從main()主函數(shù)開始執(zhí)行(其實(shí)程序真正的入口并不是main()函數(shù));執(zhí)行的過程中按照代碼編寫流程依次調(diào)用各個(gè)子程序;在執(zhí)行的過程中會(huì)等待用戶的輸入等操作;當(dāng)各個(gè)子程序執(zhí)行完成后,最終會(huì)返回main()主函數(shù),執(zhí)行main()主函數(shù)的return語句后,程序退出(其實(shí)程序真正的出口也并不是main()函數(shù)的return語句)。

2. Windows程序執(zhí)行流程

DOS程序的執(zhí)行流程比較簡(jiǎn)單,但是Windows應(yīng)用程序的執(zhí)行流程就比較復(fù)雜了。DOS是單任務(wù)的操作系統(tǒng)。在DOS中,通過輸入命令,DOS操作系統(tǒng)會(huì)將控制權(quán)由Command.com轉(zhuǎn)交給DOS程序從而執(zhí)行。而Windows是多任務(wù)的操作系統(tǒng),在Windows下同時(shí)會(huì)運(yùn)行若干個(gè)應(yīng)用程序,那么Windows就無法把控制權(quán)完全交給一個(gè)應(yīng)用程序。Windows下的應(yīng)用程序是如何工作的?首先看一下Windows應(yīng)用程序內(nèi)部的大致結(jié)構(gòu)圖,如圖2所示。

圖2  Windows應(yīng)用程序執(zhí)行原理圖

圖2可能看起來比較復(fù)雜,其實(shí)Windows應(yīng)用程序的內(nèi)部結(jié)構(gòu)比該示意圖更復(fù)雜。在實(shí)際開發(fā)Windows應(yīng)用程序時(shí),需要關(guān)注的部分主要是“主程序”和“窗口過程”兩部分。但是從圖2來看,主程序和窗口過程沒有直接的調(diào)用關(guān)系,而在主程序和窗口過程之間有一個(gè)“系統(tǒng)程序模塊”。“主程序”的功能是用來注冊(cè)窗口類、獲取消息和分發(fā)消息。而“窗口過程”中定義了需要處理的消息,“窗口過程”會(huì)根據(jù)不同的消息執(zhí)行不同的動(dòng)作,而不需要程序處理的消息則會(huì)交給默認(rèn)的系統(tǒng)過程進(jìn)行處理。

在“主程序”中,RegisterClassEx()函數(shù)會(huì)注冊(cè)一個(gè)窗口類,窗口類中的字段中包含了“窗口過程”的地址信息,也就是把“窗口類”的信息(包括“窗口過程的地址信息”)告訴操作系統(tǒng)。然后“主程序”不斷通過調(diào)用GetMessage()函數(shù)獲取消息,再交由DispatchMessge()函數(shù)來分發(fā)消息。消息分發(fā)后并沒有直接調(diào)用“窗口過程”讓其處理消息,而是由系統(tǒng)模塊查找該窗口指定的窗口類,通過窗口類再找到窗口過程的地址,最后將消息送給該窗口過程,由窗口過程處理消息。

02 一個(gè)簡(jiǎn)單的Windows應(yīng)用程序

相對(duì)一個(gè)簡(jiǎn)單的DOS程序來說一個(gè)簡(jiǎn)單的Windows應(yīng)用程序要很長(zhǎng)。下面的例子中只實(shí)現(xiàn)了一個(gè)特別簡(jiǎn)單的Windows程序,這個(gè)程序在桌面上顯示一個(gè)簡(jiǎn)單的窗口,它沒有菜單欄、工具欄、狀態(tài)欄,只是在窗口中輸出一段簡(jiǎn)單的字符串。雖然程序如此簡(jiǎn)單,但是也要編寫100行左右的代碼??紤]到初學(xué)的朋友,這里將一部分一部分地逐步介紹代碼中的細(xì)節(jié),以減少代碼的長(zhǎng)度,從而方便初學(xué)者的學(xué)習(xí)。

1. Windows窗口應(yīng)用程序的主函數(shù)——WinMain()

在DOS時(shí)代,或編寫Windows下的命令行的程序,要使用C語言編寫代碼的時(shí)候都是從main()函數(shù)開始的。而在Windows下編寫有窗口的程序時(shí),要用C語言編寫窗口程序就不再?gòu)膍ain()函數(shù)開始了,取而代之的是WinMain()函數(shù)。

既然Windows應(yīng)用程序的主函數(shù)是WinMain(),那么就從了解WinMain()函數(shù)的定義開始學(xué)習(xí)Windows應(yīng)用程序的開發(fā)。WinMain()函數(shù)的定義如下: 

  1. int WINAPI WinMain(  
  2.  HINSTANCE hInstance,  
  3.  HINSTANCE hPrevInstance,  
  4.  LPSTR lpCmdLine,  
  5.  int nCmdShow  
  6. ); 

該函數(shù)的定義取自MSDN中,在看到WinMain()函數(shù)的定義后,很直觀地會(huì)發(fā)現(xiàn)WinMain函數(shù)的參數(shù)比main()函數(shù)的參數(shù)變多了。從參數(shù)個(gè)數(shù)上來說,WinMain()函數(shù)接收的信息更多了。下面來看每個(gè)參數(shù)的含義。

hInstance是應(yīng)用程序的實(shí)例句柄。保存在磁盤上的程序文件是靜態(tài)的,當(dāng)被加載到內(nèi)存中時(shí),被分配了CPU、內(nèi)存等進(jìn)程所需的資源后,一個(gè)靜態(tài)的程序就被實(shí)例化為一個(gè)有各種執(zhí)行資源的進(jìn)程了。句柄的概念隨上下文的不同而不同,句柄是操作某個(gè)資源的“把手”。當(dāng)需要對(duì)某個(gè)實(shí)例化進(jìn)程操作時(shí),需要借助該實(shí)例句柄進(jìn)行操作。這里的實(shí)例句柄是程序裝入內(nèi)存后的起始地址。實(shí)例句柄的值也可以通過GetModuleHandle()參數(shù)來獲得(注意系統(tǒng)中沒有GetInstanceHandle()函數(shù),不要誤以為是hInstance就會(huì)有GetInstance×××()類的函數(shù))。

句柄這個(gè)詞在開發(fā)Windows程序時(shí)是非常常見的一個(gè)詞。“句柄”一詞的含義隨上下文的不同而所有改變。比如,磁盤上的程序文件被加載到內(nèi)存中后,就創(chuàng)建了一個(gè)實(shí)例句柄,這個(gè)實(shí)例句柄是程序裝入內(nèi)存后的“起始地址”,或者說是“模塊的起始地址”。

拿SendMessage()函數(shù)舉例來說,句柄相當(dāng)于一個(gè)操作的面板,對(duì)句柄發(fā)送的消息相當(dāng)于面板上的各個(gè)開關(guān)按鍵,消息的附加數(shù)據(jù),相當(dāng)于給開關(guān)按鍵送的各種參數(shù),這些參數(shù)根據(jù)按鍵的不同而不同。

hPrevInstance是同一個(gè)文件創(chuàng)建的上一個(gè)實(shí)例的實(shí)例句柄。這個(gè)參數(shù)是Win16平臺(tái)下的遺留物,在Win32下已經(jīng)不再使用了。

lpCmdLine是主函數(shù)的參數(shù),用于在程序啟動(dòng)時(shí)給進(jìn)程傳遞參數(shù)。比如在“開始”菜單的“運(yùn)行”中輸入“notepad c:\boot.ini”,這樣就通過記事本打開了C盤下的boot.ini文件。C:\Boot.ini文件是通過WinMain()函數(shù)的lpCmdLine參數(shù)傳遞給notepad.exe程序的。

nCmdShow是進(jìn)程顯示的方式,可以是最大化顯示、最小化顯示,或者是隱藏等顯示方式(如果是啟動(dòng)木馬程序的話,啟動(dòng)方式當(dāng)然要由自己進(jìn)行控制)。

主函數(shù)的參數(shù)都介紹完了。編寫Windows的窗口程序,需要主函數(shù)中應(yīng)該完成哪些操作是下面要討論的內(nèi)容。

2. WinMain()函數(shù)中的流程

編寫Windows下的窗口程序,在WinMain()主函數(shù)中主要完成的任務(wù)是注冊(cè)一個(gè)窗口類,創(chuàng)建一個(gè)窗口并顯示創(chuàng)建的窗口,然后不停地獲取屬于自己的消息并分發(fā)給自己的窗口過程,直到收到WM_QUIT消息后退出消息循環(huán)結(jié)束進(jìn)程。這是主函數(shù)中程序的執(zhí)行脈絡(luò),程序中將注冊(cè)窗口類、創(chuàng)建窗口的操作封裝為自定義函數(shù)。

代碼如下: 

  1. int WINAPI WinMain(  
  2.  HINSTANCE hInstance,  
  3.  HINSTANCE hPrevInstance,  
  4.  LPSTR lpCmdLine,  
  5.  int nCmdShow)  
  6.  
  7.   MSG Msg;  
  8.   BOOL bRet;  
  9.   // 注冊(cè)窗口類  
  10.   MyRegisterClass(hInstance);  
  11.   // 創(chuàng)建窗口并顯示窗口  
  12.   if ( !InitInstance(hInstance, SW_SHOWNORMAL) )  
  13.   {  
  14.     return FALSE; 
  15.   }  
  16.   // 消息循環(huán)  
  17.   // 獲取屬于自己的消息并進(jìn)行分發(fā)  
  18.   while( (bRet = GetMessage(&Msg, NULL, 0, 0)) != 0 )  
  19.   {  
  20.     if ( bRet == -1 )  
  21.     {  
  22.       // handle the error and possibly exit  
  23.       break;  
  24.     }  
  25.     else  
  26.     {  
  27.       TranslateMessage(&Msg);  
  28.       DispatchMessage(&Msg);  
  29.     }  
  30.   }  
  31.   return Msg.wParam;  

在代碼中,MyRegisterClass()和InitInstance()是兩個(gè)自定義的函數(shù),分別用來注冊(cè)窗口類,創(chuàng)建窗口并顯示更新創(chuàng)建的窗口。后面的消息循環(huán)部分用來獲得消息并進(jìn)行消息分發(fā)。它的流程如圖2所示的“主程序”部分。

代碼中主要是3個(gè)函數(shù),分別是GetMessage()、TranslateMessage()和DispatchMessage()。這3個(gè)函數(shù)是Windows提供的API函數(shù)。GetMessage()的定義如下: 

  1. BOOL GetMessage(  
  2.  LPMSG lpMsg,  
  3.  HWND hWnd,  
  4.  UINT wMsgFilterMin,  
  5.  UINT wMsgFilterMax  
  6. ); 

該函數(shù)用來獲取屬于自己的消息,并填充MSG結(jié)構(gòu)體。有一個(gè)類似于GetMessage()的函數(shù)是PeekMessage(),它可以判斷消息隊(duì)列中是否有消息,如果沒有消息,可以主動(dòng)讓出CPU時(shí)間給其他進(jìn)程。關(guān)于PeekMessage()函數(shù)的使用,請(qǐng)參考MSDN: 

  1. BOOL TranslateMessage(CONST MSG *lpMsg); 

該函數(shù)是用來處理鍵盤消息的。它將虛擬碼消息轉(zhuǎn)換為字符消息,也就是將WM_KEYDOWN消息和WM_KEYUP消息轉(zhuǎn)換為WM_CHAR消息,將WM_SYSKEYDOWN消息和WM_SYSKEYUP消息轉(zhuǎn)換為WM_SYSCHAR消息: 

  1. LRESULT DispatchMessage(CONST MSG *lpmsg); 

該函數(shù)是將消息分發(fā)到窗口過程中。

3. 注冊(cè)窗口類的自定義函數(shù)

在WinMain()函數(shù)中,首先調(diào)用了MyRegisterClass()這個(gè)自定義函數(shù),需要傳遞進(jìn)程的實(shí)例句柄hInstance作為參數(shù)。該函數(shù)完成窗口類的注冊(cè),分為兩步:第一步是填充WNDCLASSEX結(jié)構(gòu)體,第二步是調(diào)用RegisterClassEx()函數(shù)進(jìn)行注冊(cè)。該函數(shù)相對(duì)簡(jiǎn)單,但是,該函數(shù)中稍微復(fù)雜的是WNDCLASSEX結(jié)構(gòu)體的成員較多。

代碼如下: 

  1. ATOM MyRegisterClass(HINSTANCE hInstance)  
  2.  
  3.   WNDCLASSEX WndCls;  
  4.   // 填充結(jié)構(gòu)體為 0  
  5.   ZeroMemory(&WndCls, sizeof(WNDCLASSEX));  
  6.   // cbSize 是結(jié)構(gòu)體大小  
  7.   WndCls.cbSize = sizeof(WNDCLASSEX);  
  8.   // lpfnWndProc 是窗口過程地址  
  9.   WndCls.lpfnWndProc = WindowProc 
  10.   // hInstance 是實(shí)例句柄  
  11.   WndCls.hInstance = hInstance;  
  12.   // lpszClassName 是窗口類類名  
  13.   WndCls.lpszClassName = CLASSNAME 
  14.   // style 是窗口類風(fēng)格  
  15.   WndCls.style = CS_HREDRAW | CS_VREDRAW;  
  16.   // hbrBackground 是窗口類背景色  
  17.   WndCls.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME + 1;  
  18.   // hCursor 是鼠標(biāo)句柄  
  19.   WndCls.hCursor = LoadCursor(NULL, IDC_ARROW);  
  20.   // hIcon 是圖標(biāo)句柄  
  21.   WndCls.hIcon = LoadIcon(NULL, IDI_QUESTION);  
  22.   // 其他  
  23.   WndCls.cbClsExtra = 0 
  24.   WndCls.cbWndExtra = 0 
  25.   return RegisterClassEx(&WndCls);  

在代碼中,WNDCLASSEX結(jié)構(gòu)體的成員都介紹了。WNDCLASSEX中最重要的字段是lpfnWndProc,它將保存的是窗口過程的地址。窗口過程是對(duì)各種消息進(jìn)程處理的“匯集地”,也是編寫Windows應(yīng)用程序的重點(diǎn)部分。代碼中的函數(shù)都比較簡(jiǎn)單,主要涉及LoadCursor()、LoadIcon()和RegisterClassEx()這3個(gè)函數(shù)。由于這3個(gè)函數(shù)使用簡(jiǎn)單,通過代碼就可以進(jìn)行理解,這里不做過多介紹。

注冊(cè)窗口類(提到窗口類,你是否想到了FindWindow()函數(shù)的第一個(gè)參數(shù)呢?)的重點(diǎn)是在后面的代碼中可以根據(jù)該窗口類創(chuàng)建該種類型的窗口。代碼中,在定義窗口類時(shí)指定了背景色、鼠標(biāo)指針、窗口圖標(biāo)等,那么使用該窗口類創(chuàng)建的窗口都具有相同的窗口類型。

4. 創(chuàng)建主窗口并顯示更新

注冊(cè)窗口類后,根據(jù)該窗口類創(chuàng)建具體的主窗口并顯示和更新窗口。

代碼如下: 

  1. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)  
  2.  
  3.   HWND hWnd = NULL 
  4.   // 創(chuàng)建窗口  
  5.   hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,  
  6.     CLASSNAME,  
  7.     "MyFirstWindow",  
  8.     WS_OVERLAPPEDWINDOW,  
  9.     CW_USEDEFAULT, CW_USEDEFAULT,  
  10.     CW_USEDEFAULT, CW_USEDEFAULT,  
  11.     NULL, NULL, hInstance, NULL);  
  12.   if ( NULL == hWnd )  
  13.   {  
  14.     return FALSE;  
  15.   }  
  16.   // 顯示窗口  
  17.   ShowWindow(hWnd, nCmdShow);  
  18.   // 更新窗口  
  19.   UpdateWindow(hWnd);  
  20.   return TRUE;  

在調(diào)用該函數(shù)時(shí),需要給該函數(shù)傳遞實(shí)例句柄和窗口顯示方式兩個(gè)參數(shù)。這兩個(gè)參數(shù)的第1個(gè)參數(shù)通過WinMain()函數(shù)的參數(shù)hInstance指定,第2個(gè)參數(shù)可以通過WinMain()函數(shù)的第3個(gè)參數(shù)指定,也可以進(jìn)行自定義指定。程序中的調(diào)用代碼如下: 

  1. InitInstance(hInstance, SW_SHOWNORMAL); 

在創(chuàng)建主窗口時(shí)調(diào)用了CreateWindowEx()函數(shù),先來看看它的函數(shù)原型: 

  1. HWND CreateWindowEx(  
  2.  DWORD dwExStyle,  
  3.  LPCTSTR lpClassName,  
  4.  LPCTSTR lpWindowName,  
  5.  DWORD dwStyle,  
  6.  int x,  
  7.  int y,  
  8.  int nWidth,  
  9.  int nHeight,  
  10.  HWND hWndParent,  
  11.  HMENU hMenu,  
  12.  HINSTANCE hInstance,  
  13.  LPVOID lpParam  
  14. ); 

CreateWindowEx()中的第2個(gè)參數(shù)是lpClassName,由注釋可以知道是已經(jīng)注冊(cè)的類名。這個(gè)已經(jīng)注冊(cè)的類名就是WNDCLASSEX結(jié)構(gòu)體的lpszClassName字段。

5. 處理消息的窗口過程

按照如圖2所示的流程,WinMain()主函數(shù)的部分已經(jīng)都實(shí)現(xiàn)完成了。接下來看程序中關(guān)鍵的部分——窗口過程。從WinMain()主函數(shù)中看出,在WinMain()主函數(shù)中沒有任何地方直接調(diào)用窗口過程,只是在注冊(cè)窗口類時(shí)指定了窗口過程的地址。那么窗口類是由誰進(jìn)行調(diào)用的呢?答案是由操作系統(tǒng)進(jìn)行調(diào)用的。原因有二,首先窗口過程的地址是由系統(tǒng)維護(hù)的,注冊(cè)窗口類時(shí)是將“窗口過程的地址”向操作系統(tǒng)進(jìn)行注冊(cè)。其次是除了應(yīng)用程序本身會(huì)調(diào)用自己的窗口過程外,其他應(yīng)用程序也會(huì)調(diào)用自己的窗口過程,比如前面的例子中調(diào)用SendMessage()函數(shù)發(fā)送消息后,需要系統(tǒng)調(diào)用目標(biāo)程序的窗口過程來完成相應(yīng)的動(dòng)作。如果窗口過程由自己調(diào)用,那么窗口就要自己維護(hù)窗口類的信息,進(jìn)程間消息的通信會(huì)非常繁瑣,也會(huì)無形中增加系統(tǒng)的開銷。

窗口過程的代碼如下: 

  1. LRESULT CALLBACK WindowProc(  
  2.     HWND hwnd,  
  3.     UINT uMsg,  
  4.     WPARAM wParam,  
  5.     LPARAM lParam)  
  6.  
  7.   PAINTSTRUCT ps;  
  8.   HDC hDC;  
  9.   RECT rt;  
  10.   char *pszDrawText = "Hello Windows Program." 
  11.   switch (uMsg)  
  12.   {  
  13.   case WM_PAINT:  
  14.     {  
  15.       hDC = BeginPaint(hwnd, &ps);  
  16.       GetClientRect(hwnd, &rt);  
  17.       DrawTextA(hDC,  
  18.         pszDrawText, strlen(pszDrawText),&rt,  
  19.         DT_CENTER | DT_VCENTER | DT_SINGLELINE);  
  20.       EndPaint(hwnd, &ps);  
  21.       break;  
  22.     }  
  23.   case WM_CLOSE:  
  24.     {  
  25.       if ( IDYES == MessageBox(hwnd,  
  26.         "是否退出程序", "MyFirstWin", MB_YESNO) )  
  27.       {  
  28.         DestroyWindow(hwnd);  
  29.         PostQuitMessage(0);  
  30.       }  
  31.       break;  
  32.     }  
  33.   default:  
  34.     {  
  35.       return DefWindowProc(hwnd, uMsg, wParam, lParam);  
  36.     }  
  37.   }  
  38.   return 0;  

在WinMain()函數(shù)中,通過調(diào)用RegisterClassEx()函數(shù)進(jìn)行了窗口類的注冊(cè),通過調(diào)用CreateWindowEx()函數(shù)創(chuàng)建了窗口,并且GetMessage()函數(shù)不停地獲取消息,但是在主函數(shù)中沒有對(duì)被創(chuàng)建的窗口做任何處理。那是因?yàn)檎嬲龑?duì)窗口行為的處理全部放在了窗口過程中。當(dāng)WinMain()函數(shù)中的消息循環(huán)得到消息以后,通過調(diào)用DispatchMessage()函數(shù)將消息派發(fā)(實(shí)際不是由DispatchMessage()函數(shù)直接派發(fā))給了窗口過程,從而由窗口過程對(duì)消息進(jìn)行處理。

窗口過程的定義是按照MSDN上給出的形式進(jìn)行定義的,MSDN上的定義形式如下: 

  1. LRESULT CALLBACK WindowProc(  
  2.  HWND hwnd,  
  3.  UINT uMsg,  
  4.  WPARAM wParam,  
  5.  LPARAM lParam  
  6. ); 

WindowProc是窗口過程的函數(shù)名,這個(gè)函數(shù)名可以隨意改變,但是該窗口過程的函數(shù)名必須與WNDCLASSEX結(jié)構(gòu)體中l(wèi)pfnWndProc的成員變量的值一致。函數(shù)的第1個(gè)參數(shù)hwnd是窗口的句柄,第2個(gè)參數(shù)uMsg是消息值,第3個(gè)和第4個(gè)參數(shù)是對(duì)于消息值的附加參數(shù)。這4個(gè)參數(shù)的類型與SendMessage()函數(shù)的參數(shù)相對(duì)應(yīng)。

上面WindowProc()窗口過程中只對(duì)兩個(gè)消息進(jìn)行了處理,分別是WM_PAINT和WM_CLOSE。這里為了演示因此只簡(jiǎn)單處理了兩個(gè)消息。Windows中有上千種消息,那么多的消息不可能全部都由程序員自己去處理,程序員只處理一些程序中需要的消息,其余的消息就交給了DefWindowProc()函數(shù)進(jìn)行處理。DefWindowProc()函數(shù)實(shí)際上是將消息傳遞給了操作系統(tǒng),由操作系統(tǒng)來處理程序中沒有處理的消息。比如,在調(diào)用CreateWindow()函數(shù)時(shí),系統(tǒng)會(huì)發(fā)送消息WM_CREATE給窗口過程,但是這個(gè)消息可能對(duì)程序的功能并不需要進(jìn)行特殊的處理,因此直接交由DefWindowProc()函數(shù)讓系統(tǒng)進(jìn)行處理。

DefWindowProc()函數(shù)的定義如下: 

  1. LRESULT DefWindowProc(  
  2.  HWND hWnd,  
  3.  UINT Msg,  
  4.  WPARAM wParam,  
  5.  LPARAM lParam  
  6. ); 

該函數(shù)的4個(gè)參數(shù)跟窗口過程的參數(shù)相同,只要將窗口過程的參數(shù)依次傳遞給DefWindowProc()函數(shù)就可以完成該函數(shù)的調(diào)用。在switch分支結(jié)構(gòu)中的default位置直接調(diào)用DefWindowProc()函數(shù)就可以了。

WM_CLOSE消息是關(guān)閉窗口時(shí)發(fā)出的消息,在這個(gè)消息中需要調(diào)用DestoryWindow()函數(shù)來銷毀窗口,并且調(diào)用PostQuitMessage()來退出消息循環(huán),使程序退出。對(duì)于WM_PAINT消息,這里不進(jìn)行介紹,涉及的幾個(gè)API函數(shù)可以參考MSDN進(jìn)行了解。

有的資料在介紹消息循環(huán)時(shí)會(huì)給出一個(gè)建議,就是把需要經(jīng)常處理的消息放到程序靠上的位置,而將不經(jīng)常處理的消息放到程序靠下的位置,從而提高程序的效率。其實(shí),在窗口過程中往往會(huì)使用switch結(jié)構(gòu)對(duì)消息進(jìn)行判斷(如果使用if和else結(jié)構(gòu)進(jìn)行消息的判斷,那么常用的消息是要放到前面),而switch結(jié)構(gòu)在編譯器進(jìn)行編譯后會(huì)進(jìn)行優(yōu)化處理,從而大大提高程序的運(yùn)行效率。 

 

責(zé)任編輯:龐桂玉 來源: 計(jì)算機(jī)與網(wǎng)絡(luò)安全
相關(guān)推薦

2021-05-24 11:55:55

網(wǎng)絡(luò)安全Windows鉤子函數(shù)

2021-04-26 10:32:38

網(wǎng)絡(luò)安全PE編程工具

2021-04-30 18:50:44

網(wǎng)絡(luò)安全PE編程添加節(jié)區(qū)

2021-04-28 14:35:48

網(wǎng)絡(luò)安全PE編程代碼

2021-04-25 21:25:09

網(wǎng)絡(luò)安全網(wǎng)絡(luò)安全編程PE編程

2021-03-03 12:20:42

網(wǎng)絡(luò)安全DLL編程

2021-02-19 09:30:52

網(wǎng)絡(luò)安全服務(wù)控制管理器代碼

2021-01-22 10:58:16

網(wǎng)絡(luò)安全進(jìn)程間碼如

2021-01-26 13:45:03

網(wǎng)絡(luò)安全Winsock編程

2021-03-05 13:46:56

網(wǎng)絡(luò)安全遠(yuǎn)程線程

2021-02-23 10:20:07

網(wǎng)絡(luò)安全進(jìn)程代碼

2011-05-20 14:23:59

WLANWEPWPA

2016-10-10 00:18:27

2021-02-21 18:19:43

網(wǎng)絡(luò)安全網(wǎng)絡(luò)安全編程創(chuàng)建進(jìn)程

2021-06-18 09:55:09

網(wǎng)絡(luò)安全目錄監(jiān)控

2010-09-26 08:46:08

802.1x

2021-03-15 13:50:24

網(wǎng)絡(luò)安全Android安全機(jī)制

2021-06-15 11:16:24

網(wǎng)絡(luò)安全U盤軟件

2021-04-19 10:26:41

網(wǎng)絡(luò)安全PE文件

2021-02-04 10:50:11

網(wǎng)絡(luò)安全非阻塞模Winsock編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)