<Win32_1>深入淺出windows訊息機制[轉自crocodile_]

Simmy.臥龍先生發表於2013-11-15

上學期學習了Java ,感覺Java寫一個視窗真心簡單,很易上手,也就難怪很多開發人員選擇Java作為自己的開發程式語言。但是由於自身對windows的熱愛,讓我覺得c、c++語言才是我親睞的程式語言,雖然難度大些,但是這才能體現能力所在。其實之前一直想自學一下win32,但是由於時間的顯示和種種原因而耽擱了,於是今年暑假決心深入學習win32。

 

在學習過程中呢,我會在此留下自己的學習心得,當做自己的筆記。初學者可以借鑑,高手可以多多指教,呵呵……

 

好了,今天開始做第一課的筆記吧:

學習Win32最好是對windows作業系統有較為深入的理解,這樣才能學得深入、紮實。因此學習Win32的第一步就是了解windows

作業系統的訊息機制,這個可是重中之重

 

首先上一張自己親手繪製的圖,能很清晰地表示windows訊息機制的工作原理

 

也許你初次看到這張圖,感覺密密麻麻的,不是很懂,別擔心,我將逐步講解:

(1)   數字1箭頭:  表示windows(os)將訊息傳遞到應用程式的訊息佇列中

(2)   數字2箭頭:  表示應用程式通過訊息迴圈在訊息佇列中讀取訊息

(3)   數字3箭頭:  表示應用程式的訊息迴圈將讀取到的訊息告訴給windows(os)

(4)   數字4箭頭:  表示windows(os)通過應用程式傳遞的訊息來呼叫應用程式繫結的回撥函式(WndProc) , 根據回撥函式 , 來確定是否做出響應

 

到這裡,想必你能從本質上了解到windows的訊息機制了吧

 

講程式終究和程式碼脫不了關係,下面我借用一下P先生(Charles Petzold)的第一個例子(HelloWin.c),不過裡面包含了我自己的東西,你一看就知道了:

  1. //windows程式的基礎程式碼  
  2. #include<windows.h>  
  3.   
  4. LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);//回撥函式宣告  
  5.   
  6. int WINAPI WinMain(HINSTANCE hInstance,     // 程式的當前例項控制程式碼  
  7.                    HINSTANCE hPrevInstance, // 程式的上一個例項控制程式碼 , 在win32程式中 , 它始終是NULL  
  8.                    PSTR szCmdLine,          // 命令列  
  9.                    int iCmdShow)            // 視窗顯示狀態  
  10. {  
  11.     static  TCHAR   szAppName[] = TEXT("HelloWin"); //以'\0'字元結尾的字串 , 這裡是程式的名稱(實際用作後面的視窗類的名字)  
  12.     HWND            hwnd;                           //視窗控制程式碼  
  13.     MSG             msg;                            //訊息結構體  
  14.     WNDCLASS        wndclass;                       //視窗類  
  15.       
  16.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;              //視窗類的風格  
  17.     wndclass.lpfnWndProc    = WndProc;                              //視窗類繫結的回撥函式(也稱為視窗過程)  
  18.     wndclass.cbClsExtra     = 0;                                    //視窗類額外引數(預設為0)  
  19.     wndclass.cbWndExtra     = 0;//視窗類額外引數(預設為0)   
  20.     wndclass.hInstance      = hInstance;                            //程式的當前例項控制程式碼 , 繫結到視窗類中  
  21.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);      //載入程式圖示  
  22.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);          //載入游標  
  23.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  //背景刷  
  24.     wndclass.lpszMenuName   = NULL;                                 //選單名指標  
  25.     wndclass.lpszClassName  = szAppName;                            //視窗類的名字  
  26.       
  27.     if(!RegisterClass(&wndclass))//註冊視窗類  
  28.     {  
  29.         MessageBox(NULL, TEXT("This program requires Windows NT!"),  
  30.             szAppName, MB_ICONERROR);  
  31.         return 0;  
  32.     }  
  33.       
  34.     //這裡建立的是一段記憶體 , 用於儲存建立視窗的資訊 , 同時返回該視窗的一個控制程式碼(視窗的標示)  
  35.     hwnd = CreateWindow(szAppName,                  //視窗類的名字  
  36.                         TEXT("The Hello Program"),  //視窗名稱(標題欄顯示的內容)  
  37.                         WS_OVERLAPPEDWINDOW,        //視窗的風格  
  38.                         CW_USEDEFAULT,              //視窗x座標  
  39.                         CW_USEDEFAULT,              //視窗y座標  
  40.                         CW_USEDEFAULT,              //視窗寬度  
  41.                         CW_USEDEFAULT,              //視窗長度  
  42.                         NULL,                       //父視窗控制程式碼  
  43.                         NULL,                       //選單控制程式碼  
  44.                         hInstance,                  //程式的當前例項  
  45.                         NULL);                      //視窗建立資料  
  46.   
  47.     /* 程式執行完CreateWindow , 還沒執行ShowWindow時 ,  
  48.     windows向視窗的WndProc傳送了第一條訊息: WM_Create */  
  49.   
  50.     ShowWindow(hwnd, iCmdShow); //顯示視窗  
  51.     UpdateWindow(hwnd);         //更新視窗  
  52.     /* 執行完UpdateWindow後 , windows向視窗的WndProc 
  53.     傳送了第二條訊息: WM_PAINT . 如果ShowWindow沒有呼叫或是呼叫失敗 , WM_PAINT訊息是不會傳送的*/  
  54.       
  55.     //訊息迴圈  
  56.     while(GetMessage(&msg, NULL, 0, 0))//這裡的NULL不能寫成hwnd , 否則程式不能正常執行  
  57.     {  
  58.         TranslateMessage(&msg);//轉換鍵盤訊息  
  59.         DispatchMessage(&msg);//將訊息傳送給windows(os) , 由windows來回撥  
  60.     }  
  61.       
  62.     return msg.wParam;//結束返回  
  63. }  
  64.   
  65. //視窗過程(回撥函式)  
  66. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  67. {  
  68.     HDC         hdc;    //裝置控制程式碼  
  69.     PAINTSTRUCT ps;     //包含視窗客戶區繪製的資訊  是一個結構體  
  70.     RECT        rect;   //矩形(兩個點)  
  71.       
  72.     //這裡是訊息處理  
  73.     switch(message)  
  74.     {  
  75.     //視窗建立訊息  
  76.     case WM_CREATE:  
  77.       //PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;//播音  
  78.       return 0 ;  
  79.   
  80.     //視窗客戶區重繪訊息  
  81.     case WM_PAINT:  
  82.         PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;//播音  
  83.         hdc = BeginPaint(hwnd, &ps);//獲取裝置控制程式碼 , 開始重繪  
  84.           
  85.         GetClientRect(hwnd, &rect);//獲取客戶區的大小  
  86.           
  87.         DrawText(hdc, TEXT("Hello, Windows 98!"), -1, &rect,  
  88.                  DT_SINGLELINE | DT_CENTER | DT_VCENTER);//繪製一個字串  
  89.   
  90.         EndPaint(hwnd, &ps);//結束重繪  
  91.         return 0;  
  92.   
  93.     //視窗退出訊息  
  94.     case WM_DESTROY:  
  95.         PostQuitMessage(0);//傳送退出訊息  
  96.         return 0;  
  97.     }  
  98.   
  99.     return DefWindowProc(hwnd, message, wParam, lParam);  
  100.     //windows對於訊息的預設處理  
  101.     //(注意: 第三個和第四個引數不能傳遞錯誤!!!)  
  102. }  

  

沒錯,我逐行註釋了,這樣我覺得很好,對於掌握和理解是很有幫助的,ni不放試試……

 

好了,今天到此為止吧,下次繼續了^_^

相關文章