天天看點

Windows程式設計_Chap03_視窗與消息_學習筆記Windows程式設計_Chap03_視窗與消息_學習筆記

Windows程式設計_Chap03_視窗與消息_學習筆記

――By: Neicole(2013.06.07)

01. 開篇

    《Windows程式設計》的第3章,講述了在Windows程式設計中很基礎同時也是很重要的内容,第一個是Windows視窗是什麼,怎麼建立,第二個是Windows中的消息,Windows的消息機制。這次學習筆記,以視窗和Windows消息處理機制這兩個子產品進行展開。

02. Windows系統的視窗

02.01 概念

      視窗,位于螢幕中的一個矩形區域,用于接收使用者的輸入,然後以文本或圖形的形式顯示輸出。

      使用C#簡單地做了個界面,下圖形象簡單地說明了程式裡面可以有哪些視窗。

Windows程式設計_Chap03_視窗與消息_學習筆記Windows程式設計_Chap03_視窗與消息_學習筆記

02.02 使用WindowsAPI程式設計建立視窗

Windows程式設計_Chap03_視窗與消息_學習筆記Windows程式設計_Chap03_視窗與消息_學習筆記

      如上圖所示,使用WindowsAPI程式設計建立視窗汲及到五個基本步驟:

      一、建立視窗類WndClass,(視窗類允許多個視窗共享同一個視窗類)視窗類的風格決定了視窗的外觀和風格。所有的視窗都會屬于某一個視窗類。可以了解成是視窗的邏輯定義。

      二、注冊視窗類RegisterClass(...),我上網搜尋資料時,沒有找到統一的标準的答案,而我支援的一種說法是,注冊視窗,是為了共享資料,讓多個視窗可以使用同一個視窗類,同時,也相當于告訴系統存在這一個視窗類,避免重複。

      三、建立視窗CreateWindows(...),定義視窗在螢幕上顯示的基本資訊,标題,坐标,大小等,可以了解成是視窗的實作(顯示)定義。

      四、顯示、更新視窗。函數ShowWindow(...)和UpdateWindow(...),需要一提的是UpdateWindow(...)函數在《Windows程式設計》中描述是指它作用于視窗客戶區,通過向視窗過程發送一條WM_PAINT消息完成的。

      五、消息循環。從消息隊列中擷取消息,進入視窗過程函數進行處理。(Windows消息處理機制内容見後講述)

02.03 使用WindowsAPI程式設計經典執行個體

Windows程式設計_Chap03_視窗與消息_學習筆記Windows程式設計_Chap03_視窗與消息_學習筆記

    本執行個體是《Windows程式設計》上的執行個體,建立了主視窗,在打開程式時,會發出一聲響聲(實作方法可見程式中的WM_CREATE消息類型的處理),視窗标題為“The Hello Program”,包含最小化、最大化、關閉的這三個基本按鈕,在客戶區,白色背景,顯示“Hello,Windows98”的字樣。

/*------------------------------------------------------------
   HELLOWIN.C -- Displays "Hello, Windows 98!" in client area
                 (c) Charles Petzold, 1998
  ------------------------------------------------------------*/

#include <windows.h>
#pragma comment(lib,"winmm.lib")	// lib中含多媒體函數,PlaySound

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

// 主視窗
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("HelloWin") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;	// 視窗類

	 // 視窗類設計
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;	// 水準重繪,垂直重繪
     wndclass.lpfnWndProc   = WndProc ;					// 視窗過程
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;		// 視窗類名

	 // 注冊視窗類
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
  
	 // 建立視窗
     hwnd = CreateWindow (szAppName,                  // 與視窗類對應的視窗類名
                          TEXT ("The Hello Program"), // window caption
                          WS_OVERLAPPEDWINDOW,        // window style
                          CW_USEDEFAULT,              // initial x position
                          CW_USEDEFAULT,              // initial y position
                          CW_USEDEFAULT,              // initial x size
                          CW_USEDEFAULT,              // initial y size
                          NULL,                       // parent window handle
                          NULL,                       // window menu handle
                          hInstance,                  // program instance handle
                          NULL) ;                     // creation parameters
     
	 // 顯示、更新視窗
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
	 // 消息循環代碼塊
	 while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }

     return msg.wParam ;
}

// 視窗過程
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     HDC         hdc ;
     PAINTSTRUCT ps ;
     RECT        rect ;
     
     switch (message)	// 消息類型判斷
     {
     case WM_CREATE:
          PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
          return 0 ;
          
     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
          
          GetClientRect (hwnd, &rect) ;
          
          DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
                    DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
          
          EndPaint (hwnd, &ps) ;
          return 0 ;
          
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}
           

03. Windows消息處理機制

03.01 解析

       消息:Windows作業系統發給應用程式的一個通告,它告訴應用程式某個特定的事件發生了。

       Windows中有一個系統消息隊列,對于每一個正在執行的Windows應用程式,系統為其建立一個“消息隊列”,即應用程式隊列,用來存放該程式可能建立的各種視窗的消息。應用程式中含有一段稱作“消息循環”的代碼,用來從消息隊列中檢索這些消息并把它們分發到相應的視窗函數中。如下圖:

Windows程式設計_Chap03_視窗與消息_學習筆記Windows程式設計_Chap03_視窗與消息_學習筆記

03.02 隊列消息與非隊列消息

    隊列消息:由Windows放入程式的消息隊列中的消息。

              一般由使用者輸入産生。(按鍵、滑鼠、定時器、退出)

    非隊列消息:由Windows對視窗過程的直接調用而産生。

                一般調用特定的Windows函數引起。

03.03 與Windows消息處理相關的主要WindowsAPI函數

03.03.01 消息投遞相關

    SendMessage(...) [阻塞] 直接将消息發送給視窗過程,處理完再傳回。

    PostMessage(...) [非阻塞] 将消息放入消息隊列,立即傳回。

03.03.02 消息擷取相關

    GetMessage(...) [阻塞] 阻塞方式擷取消息,擷取消息後從隊列中删除消息。

    PeekMessage(...) [非阻塞] 以檢視方式擷取消息,擷取消息後不從隊列中删除消息,并立即傳回。

04. 參考資料

1. 《Windows程式設計》第五版 Charies Petzold 著

2. 《Windows消息機制》 http://wenku.it168.com/d_000712741.shtml

3. 《Windows消息機制的研究和應用》 http://www.docin.com/p-112396736.html

4. 《Windows 消息機制淺析》 http://blog.csdn.net/dandycheung/article/details/7304151

5. 《Windows消息機制要點》 http://neicole.blog.51cto.com/5621716/1210648

6. 《剖析Windows消息處理機制》 http://qiusuoge.com/8300.html

7. 《Windows精解:視窗類釋疑》 http://blog.csdn.net/xushiweizh/article/details/1376245

8. 《傳遞的HINSTANCE 有什麼用》 http://blog.sina.com.cn/s/blog_538457490100mhj8.html