天天看點

孫鑫VC++視訊學習筆記之1: Windows程式内部運作機制

  轉自: http://webbery.tianyablog.com 

   一、windows是事件驅動方式的程式設計

  windows程式設計是種事件驅動方式的程式設計,主要基于消息的。當使用者需要完成某種功能時,需要調用OS某種支援,然後OS将使用者的需要包裝成消息,并投入到消息隊列中,最後應用程式從消息隊列中取走消息并進行響應。

  

   二、消息隊列

   每個應用程式OS都為它建立一個消息隊列,消息隊列是個先進先出的緩沖區,其中每個元素都是一個消息,OS将生成的每個消息按先後順序放進消息隊列中, 應用程式總是取走目前消息隊列中的第一條消息,應用程式取走消息後便知道使用者的操作和程式的狀态,然後對其處理即消息響應,消息響應通過編碼實作。

  

   三、Window程式入口

  WinMain函數是Windows程式入口點函數,由OS調用,當OS啟動應用程式的時候,winmain函數的參數由OS傳遞的。

  

   四、建立一個完整的視窗需要經過下面四個操作步驟

  

  1, 設計一個視窗類。如:WNDCLASS wndcls。

  2, 注冊視窗類。如:RegisterClass(&wndcls)。

  3, 建立視窗。如:CreateWindow(),CreateWindowEX();

  4, 顯示及更新視窗。如:ShowWindow(),UpdateWindow();

  

  其他值得注意的地方

  

  1, 消息結構

  

  typedef struct tagMSG { // msg

   HWND hwnd; //接收消息的視窗句柄。和哪個視窗相關聯。

   UINT message; //消息辨別。消息本身是什麼。

   WPARAM wParam; //消息的附加資訊。具體取決于消息本身。

   LPARAM lParam;

   DWORD time; //消息投遞時間。

   POINT pt; //消息投遞時,光标在螢幕上的位置。

  } MSG;

  

  2, 掌握windows的消息機制

  

  需要掌握兩方面:(1)消息本身。不同消息所代表的使用者操作和應用程式的狀态。

  

  (2)對于某個特定的消息來說,要讓OS執行某個特定的功能去響應消息。

  

  3, Window入口函數說明

  

  int WINAPI WinMain(

   HINSTANCE hInstance, // 目前事例句柄。

   HINSTANCE hPrevInstance, // 先前事例句柄。32位系統中此值都為NULL

   LPSTR lpCmdLine, // 指令行指針

   int nCmdShow // (視窗)顯示的狀态

  );

  

  要帶參調用WinMain,類似于指令行的功能,在ProjectèsettingèDebug頁èProgram arguments項填寫參數

  

  4, Windows提供的視窗類詳解

  

  typedef struct _WNDCLASS {

   UINT style; //視窗的類型

   WNDPROC lpfnWndProc; //視窗過程函數指針(回調函數)

   int cbClsExtra; //視窗類附加位元組,為該類視窗所共享。通常0。

   int cbWndExtra; //視窗附加位元組。通常設為0。

   HANDLE hInstance; //目前應用程式事例句柄。

   HICON hIcon; //圖示句柄 LoadIcon();

   HCURSOR hCursor; //光标句柄 LoadCursor();

   HBRUSH hbrBackground; //畫刷句柄 (HBRUSH)GetStockObject();

   LPCTSTR lpszMenuName; //菜單名字

   LPCTSTR lpszClassName; //類的名字

  } WNDCLASS;

  

  5, 消息循環:

  

  MSG msg;

  while(GetMessage(&msg,...)) //從消息隊列中取出一條消息

  {

   TranslateMessage(&msg); //進行消息(如鍵盤消息)轉換

   DispatchMessage(&msg); //分派消息到視窗的回調函數處理,(OS調用視窗回調函數進行處理)。

  }

  

  6, 回調函數

  

  LRESULT CALLBACK WindowProc( //這裡WindowProc是個代号名字。

   HWND hwnd, // handle to window

   UINT uMsg, // message identifier

   WPARAM wParam, // first message parameter

   LPARAM lParam // second message parameter

  );

  

  說明:兩種函數調用約定(__stdcall 和 __cdecl):

  #define CALLBACK __stdcall

  //__stdcall 标準調用預定,是PASCAL 調用約定,象DELPHI使用的就是标準調用約定

  #define WINAPIV __cdecl

  // __cdecl 是C 語言形式的調用約定。

  

  主要差別:函數參數傳遞順序 和 對堆棧的清除上。

   問題:除了那些可變參數的函數調用外,其餘的一般都是__stdcall約定。但 C/C++編譯默然的是__cdecl約定。是以如果在VC等環境中調用__stdcall約定的函數,必須要在函數聲明的時加上 __stdcall 修飾符,以便對這個函數的調用是使用__stdcall約定(如使用DELPHI編寫的DLL時候)。

  (VC中可通過這途徑修改:projectèsettingsèc/c++ècategary選”Code Generation”,出現Call convention選項,修改之)

  

  7, DC句柄的使用

  

  (1)使用BeginPaint(),EndPaint()對。注意隻能在響應WM_PAINT消息時使用。

  (2)使用GetDc(),ReleaseDC()對。注意他們不能在響應WM_PAINT中使用。

  

  8, 其它

  

  (1)函數名代表函數的首位址。

  

  (2)建立視窗的時候一定要基于已經注冊的視窗類.