Windows SDK編程初探

第一章 Windows程序的框架

要點:程序的主函數,消息處理函數

      Windows程序具有相對穩定的結構,也就是說Windows程序是有一定的框架的,程序員要做的事情就是用特定的內容來填充這個框架。

      Windows程序的主函數:這個函數就像我們學習C語言時程序的主函數main()的功能是一樣的,他代表了程序的入口。但是這個函數看上去比main()似乎繁的多,如果是第一次看見這個函數肯定會感覺一頭霧水,但是不要緊我們來看看這個函數各個參數的意義,(其實開始的時候完全可以不理會他們的意義)hInstance是本實例的句柄,句柄可以理解爲操作系統管理使用我們的應用程序的別名,它跟指針類似但又不同於指針,它的意義只有操作系統知道,也就是說操作系統通過hInstance就可以找到我們現在的這個程序。hPrevInstance是前一個實例的句柄。szCmdLine:是命令行參數,iCmdShow是窗口的顯示方式。現在我們沒有必要清除每個參數的具體意義,在接下來的學習中我們用的最多的就是hInstance這個參數,但也不多,而且我們使用vc++時,無論有哪種程序生成方式這個函數一般都會自動生成。

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)

      主函數是windows程序框架的主要部分,由於windows程序是基於消息處理的,所以消息處理函數也算作是程序框架的一部分。說到消息,我覺得從基本的c編程轉到windows編程最難的一點可能就是理解windows消息機制,雖然說是機制但不必覺得高深莫測,其實很簡單,舉個例子來說吧:在一個應用程序中有一個按鈕,當按鈕被按下時,我們已經習慣的程序會產生一個動作,在這樣一個簡單的過程中大部分事情是操作系統替我們完成了,檢測按鈕的動作,並將這個動作表現出來:按鈕的按下、起來;按鈕被按下時它會向他所在的程序發送一個消息“我被按下了”,程序中有一個消息處理函數,捕捉到這個消息,接着轉而處理它:也就是調用相關的函數。

      那麼我們就接着看一下消息處理函數,消息處理函數其實是一個消息循環,是一個回調函數,什麼是回調函數暫不管它,只管理解爲,函數由你定義而不歸你調用,是由操作系統來調用的。下面來看一下,消息處理函數的原型及其結構:

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)

{

   switch(message)

      {

         case...

         case...//這些分支語句用來分別處理不同的消息

      }

return DefWindowProc(hwnd,message,wParam,lParam);

/*這個函數是系統默認的消息處理函數,也就是說,我們的窗口程序的消息處理函數處理的只是我們感興趣的消息,即上面的case語句,對於其他的消息我們還是使用系統默認的消息處理函數。我們的消息處理函數是要在我們的窗口主程序中登記的,登記爲我們自定義的消息處理函數之後,系統的消息就有它來處理了。所以,在本函數的最後要使用該默認函數,否則其他的消息,本程序就無法處理了。*/

}

   瞭解了消息處理函數,我們繼續來看程序的主函數,它是程序的容器,程序的主窗體要在其中建立,程序的消息處理函數也要在其中設置。在主體函數中我們要做的就是兩件事,一件是註冊窗口類,另外一件是建立窗口。所謂註冊窗口類就是通過填寫一個WNDCLASS結構,我們的窗口就算基本成型,然後要向系統註冊(註冊過程系統也提供了相應的函數,當然技術差不多了以後也可以自己寫註冊過程)。窗口註冊完畢,接下來的任務就是真正的來建立這個窗口,建立的時候前面註冊的窗口類的名稱作爲參數傳入,當然該窗口有自定義的消息處理函數的話,這時也要將這個函數傳入。

         這樣,我們就瞭解了Windows程序的框架,現在我再給出一個比較經典的Windows SDK程序的例子來看看我們的框架。

//example.cpp

#include //一定要包含該頭文件

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//消息處理函數的聲明,定義放在主函數後面

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)

{

   static TCHAR szAppName[]=TEXT("Hello");//註冊的窗口類的名稱,此處爲"Hello"

   WNDCLASS wndclass;//定義了一個窗口類

   wndclass.style=CS_HREDRAW|CS_VREDRAW;

   wndclass.lpfnWndProc=WndProc;//此處關聯了定義的消息處理函數

   wndclass.cbClsExtra=0;

   wndclass.cbWndExtra=0;

   wndclass.hInstance=hInstance;//實例句柄

   wndclass.hIcon=NULL;//窗口的圖標,我們這裏不設置

   wndclass.hCursor=LoadCursor(NULL,IDC_ARROR);//設置光標

   wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//畫刷

   wndclass.lpszMenuName=NULL;

   wndclass.lpszClassName=szAppName;//類名稱

   if(!RegisterClass(&wndclass))//註冊窗口

      {

         MessageBox(NULL,TEXT("窗口註冊失敗"),szAppName,MB_ICONERROR);

         return 0;

      }

   //下面開始建立窗口

   HWND hwnd;

   hwnd=CreateWindow(szAppName,TEXT("The Hello Program"),

                                       CW_OVERLAPPEDWINDOW,

                                       CW_USEDEFAULT,

                                        CW_USEDEFAULT,

                                       CW_USEDEFAULT,

                                       CW_USEDEFAULT,

                                       NULL,

                                       hInstance,

                                       NULL);

   ShowWindow(hwnd,iCmdShow);

   UpdateWindow(hwnd);

   //接下來是消息循環,程序不斷的從消息隊列中取消息,讓消息處理函數處理

   while(GetMessage(&msg,NULL,0,0))

   {

      TranslateMessage(&msg);

      DispatchMessage(&msg);

   }

   return msg.wParam;

}

//消息處理函數定義

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM)//此例子中我們只是處理簡單的消息

{

   switch(message)

   {

      case WM_DESTROY:

            PostQuitMessage(0);

            return 0;

   }

   return ::DefWindowProc(hwnd,message,wParam,lParam);

}

to be continued...

發佈了27 篇原創文章 · 獲贊 2 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章