C語言Windows程序設計->第四天->詳解我的窗口(中)


對窗口創建的詳細解釋

============

 

·窗口的注冊

  一個窗口的風格, 總是要根據窗口類來決定的, 同時, 窗口類決定了處理窗口消息所使用的函數(窗口過程)。 當定義好窗口類對象並完成對象屬性后, 如果想要建立這個窗口必須調用函數RegisterClass來注冊窗口類, RegisterClass的函數原型如下:

ATOM RegisterClass(CONST WNDCLASS *lpWndClass);

  該函數只有一個參數, 一個指向一個WNDCLASS結構的指針, 現在, 我們再來看一下WNDCLASS窗口類的結構, 下面是等效定義, 和WINUSER.H中的WNDCLASS效果相同, 但WINUSER.H中是通過定義tagWNDCLASSA(ASCII版本)和tagWNDCLASSW(Unicode版本), 然后進行 :

#ifdef UNICODE
typedef WNDCLASSW WNDCLASS;
typedef PWNDCLASSW PWNDCLASS;
typedef NPWNDCLASSW NPWNDCLASS;
typedef LPWNDCLASSW LPWNDCLASS;
#else
typedef WNDCLASSA WNDCLASS;
typedef PWNDCLASSA PWNDCLASS;
typedef NPWNDCLASSA NPWNDCLASS;
typedef LPWNDCLASSA LPWNDCLASS;
#endif // UNICODE

來實現 WNDCLASS的定義, 在效果上和以下定義是相同的:

typedef struct tagWNDCLASS {
    UINT        style;                 //窗口樣式
    WNDPROC     lpfnWndProc;          //回調函數
    int         cbClsExtra;            //窗口類擴展
    int         cbWndExtra;            //窗口實例擴展
    HINSTANCE   hInstance;             //窗口實例句柄
    HICON       hIcon;                 //窗口最小化圖標
    HCURSOR     hCursor;               //窗口采用鼠標指針樣式
    HBRUSH      hbrBackground;         //窗口背景顏色
    LPCWSTR     lpszMenuName;          //窗口菜單
    LPCWSTR     lpszClassName;         //窗口類名
} WNDCLASS, *PWNDCLASS;

 

在WinMain主函數中, 我們使用WNDCLASS創建了一個窗口類對象:wndclass, 並且對wndclass的屬性做了如下設置:

wndclass.style = CS_HREDRAW | CS_VREDRAW ;                         //窗口樣式
wndclass.lpszClassName = szAppName ;                               //窗口類名
wndclass.lpszMenuName = NULL ;                                     //窗口菜單:無
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;    //窗口背景顏色
wndclass.lpfnWndProc = WndProc ;                                   //窗口消息處理函數
wndclass.cbWndExtra = 0 ;                                          //窗口實例擴展:無
wndclass.cbClsExtra = 0 ;                                          //窗口類擴展:無
wndclass.hInstance = hInstance ;                                   //窗口實例句柄
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;               //窗口最小化圖標:使用缺省圖標
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;                 //窗口采用箭頭光標

下面我們來詳細看下WNDCLASS的這些成員:

  1>. wndclass.style = CS_HREDRAW | CS_VREDRAW ; 

  style屬性決定着窗口的風格, 可以通過C語言的或運算組合出不同風格類型的窗口, 在WINUSER.H頭文件中定義着這些標識符以及其值, 所有的前綴為CS_的標識符如下:

/*
 * Class styles
 */
#define CS_VREDRAW          0x0001
#define CS_HREDRAW          0x0002
#define CS_DBLCLKS          0x0008
#define CS_OWNDC            0x0020
#define CS_CLASSDC          0x0040
#define CS_PARENTDC         0x0080
#define CS_NOCLOSE          0x0200
#define CS_SAVEBITS         0x0800
#define CS_BYTEALIGNCLIENT  0x1000
#define CS_BYTEALIGNWINDOW  0x2000
#define CS_GLOBALCLASS      0x4000
#define CS_IME              0x00010000

 

  2>. wndclass.lpszClassName = szAppName ;

  賦予窗口一個名稱, 可以使用ASCII版本的字符串也可以使用Unicode版本的字符串, 需要注意的是, 這里的窗口名稱並不是指窗口標題。

 

  3>. wndclass.lpszMenuName = NULL ; 

  指定窗口類的菜單, 由於我們這個窗口沒有使用菜單, 所以為NULL, 具體的用法以后肯定會學習到;

 

  4>. wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;

  窗口的背景顏色, 這里使用的是以白色作為填充, 填充白色這是常見的做法, 如果你願意, 也可以填充為其他的一些樣式, 這里是一些樣式的標識符:

 

#define WHITE_BRUSH         0
#define LTGRAY_BRUSH        1
#define GRAY_BRUSH          2
#define DKGRAY_BRUSH        3
#define BLACK_BRUSH         4
#define NULL_BRUSH          5
#define HOLLOW_BRUSH        NULL_BRUSH
#define WHITE_PEN           6
#define BLACK_PEN           7
#define NULL_PEN            8
#define OEM_FIXED_FONT      10
#define ANSI_FIXED_FONT     11
#define ANSI_VAR_FONT       12
#define SYSTEM_FONT         13
#define DEVICE_DEFAULT_FONT 14
#define DEFAULT_PALETTE     15
#define SYSTEM_FIXED_FONT   16

 

 

  5>. wndclass.lpfnWndProc = WndProc ; 

  將窗口的消息處理函數設置為我們自定義的WndProc函數。

 

  6>. wndclass.cbWndExtra = 0 ; 

  7>. wndclass.cbClsExtra = 0 ;

  這兩個屬性用來維護結構中預留的一些額外空間, 程序可以根據需要要使用這些額外空間, 通過匈牙利命名的cbClsExtra、cbWndExtra中的cb可以知道, 這些成員表示一個"字節數", 由於我們這個窗口沒有使用到額外空間, 所以將這個兩個屬性賦值為0;

 

  8>. wndclass.hInstance = hInstance ;

  表示應用程序的實例句柄,  hInstance的來源是WinMain的一個參數;

 

  9>. wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;

  加載一個位圖作為程序標題欄最左側的小圖標, 我們這里加載了一個系統的默認圖標, 后面的學習這將會學習到如何從磁盤加載我們自定義的圖標.

 

  10>. wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ; 

  與LoadIcon類似, 加載鼠標的指針位圖;

 

完成這是個窗口類成員屬性的初始化后, 我們就可以通過RegisterClass來注冊窗口了, 如果注冊成功, 將返回一個具有唯一標識已注冊的類的一個原子, 如果函數失敗,返回0。

 

 

 

 

·窗口的創建

  成功注冊窗口類后, 我們就可以呼叫CreateWindow函數對窗口進行創建了, CreateWindow函數的原型如下:

 

HWND CreateWindow(
  LPCTSTR lpClassName,               //窗口類名稱
  LPCTSTR lpWindowName,              //窗口標題
  DWORD dwStyle,                     //窗口樣式
  int x,                             //窗口初始x坐標
  int y,                             //窗口初始y坐標
  int nWidth,                        //窗口初始x方向尺寸
  int nHeight,                       //窗口初始y方向尺寸
  HWND hWndParent,                   //父窗口句柄
  HMENU hMenu,                       //窗口菜單句柄
  HANDLE hlnstance,                  //程序實例句柄
  LPVOID lpParam                     //創建參數
);

 

函數返回的是創建成功后的窗口的句柄。 需要說明的幾點:

  1>.參數一: LPCTSTR  lpClassName

  參數LPCTSTR lpClassName,為窗口的名稱, 我們需要傳入的參數就是剛才我們在窗口類注冊的窗口類名稱, 這樣使用CreateWindow建立的窗口就能與注冊的窗口進行關聯。

 

  2>. 參數三: DWORD dwStyle

  參數三為窗口的樣式, 示例中創建的是一個普通的層疊窗口樣式, WS_OVERLAPPEDWINDOW, 打開WINUSER.H頭文件, 對於WS_OVERLAPPEDWINDOW是這樣定義的:

#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     | \
                             WS_CAPTION        | \
                             WS_SYSMENU        | \
                             WS_THICKFRAME     | \
                             WS_MINIMIZEBOX    | \
                             WS_MAXIMIZEBOX)

可以看出, WS_OVERLAPPEDWINDOW樣式實際上是通過一些標識符通過或的組合, 此外我們還可以通過組合設計我們自己的樣式, 這些標識符在WINUSER.H的定義如下:

#define WS_OVERLAPPED       0x00000000L            //產生一個層疊的窗口。一個層疊的窗口有一個標題條和一個邊框。與WS_TILED風格相同。 
#define WS_POPUP            0x80000000L            //創建一個彈出式窗口。該風格不能與WS_CHLD風格同時使用。 
#define WS_CHILD            0x40000000L            //創建一個子窗口。這個風格不能與WS_POPUP風格合用。 
#define WS_MINIMIZE         0x20000000L            //創建一個初始狀態為最小化的窗口。僅與WS_OVERLAPPED風格一起使用。
#define WS_VISIBLE          0x10000000L            //創建一個最初可見的窗口。
#define WS_DISABLED         0x08000000L            //創建一個初始狀態為禁止的窗口。
#define WS_CLIPSIBLINGS     0x04000000L            //排除子窗口之間的相對區域。
#define WS_CLIPCHILDREN     0x02000000L            //創建一個初始狀態為禁止的子窗口。一個禁止狀態的窗口不能接受來自用戶的輸入信息。 
#define WS_MAXIMIZE         0x01000000L            //創建一個初始狀態為最大化狀態的窗口。 
#define WS_CAPTION          0x00C00000L            //創建一個有標題框的窗口(包括WS_BODER風格)。 
#define WS_BORDER           0x00800000L            //創建一個單邊框的窗口。 
#define WS_DLGFRAME         0x00400000L            //創建一個帶對話框邊框風格的窗口。這種風格的窗口不能帶標題條。 
#define WS_VSCROLL          0x00200000L            //創建一個有垂直滾動條的窗口。 
#define WS_HSCROLL          0x00100000L            //創建一個有水平滾動條的窗口。 
#define WS_SYSMENU          0x00080000L            //創建一個在標題條上帶有窗口菜單的窗口,必須同時設定WS_CAPTION風格。 
#define WS_THICKFRAME       0x00040000L            //創建一個具有可調邊框的窗口,與WS_SIZEBOX風格相同。 
#define WS_GROUP            0x00020000L            //指定一組控制的第一個控制。
#define WS_TABSTOP          0x00010000L            //創建一個控制,這個控制在用戶按下Tab鍵時可以獲得鍵盤焦點。按下Tab鍵后使鍵盤焦點轉移到下一具有WS_TABSTOP風格的控制。 
#define WS_MINIMIZEBOX      0x00020000L            //創建一個具有最小化按鈕的窗口。
#define WS_MAXIMIZEBOX      0x00010000L            //創建一個具有最大化按鈕的窗口。
#define WS_TILED            WS_OVERLAPPED          //產生一個層疊的窗口。一個層疊的窗口有一個標題和一個邊框。與WS_OVERLAPPED風格相同。
#define WS_ICONIC           WS_MINIMIZE            //創建一個初始狀態為最小化的窗口。僅與WS_OVERLAPPED風格一起使用。
#define WS_SIZEBOX          WS_THICKFRAME          //創建一個具有厚邊框的窗口,可以通過厚邊框來改變窗口大小。
#define WS_TILEDWINDOW      WS_OVERLAPPEDWINDOW    //創建一個具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU,WS_THICKFRAME,WS_MINIMIZEBOX和WS_MAXIMIZEBOX風格的重疊式窗口。

關於這些樣式的詳細說明可以查閱MSDN Library(推薦)或到百科查詢。

 

 

·窗口的顯示

  使用CreateWindow函數成功創建好窗口后, 這個窗口就被在保存在一段內存中了, 但是此時窗口還不能顯示在屏幕上, 我們需要使用ShowWindow函數來將建立好的窗口顯示出來, ShowWindow函數的原型如下:

BOOL ShowWindow( HWND hWnd, int iCmdShow );

參數一為剛才通過CreateWindow函數窗口出的窗口句柄, 參數二為窗口的顯示方式, 由WinMain函數的int iCmdShow接收該值, 常用的顯示方式有:

SW_HIDE                        //隱藏窗口並激活其他窗口;
SW_MAXIMIZE                    //最大化;
SW_MINIMIZE                    //最小化指定的窗口並且激活在Z序中的下一個頂層窗口;
SW_RESTORE                     //激活並顯示窗口。如果窗口最小化或最大化,則系統將窗口恢復到原來的尺寸和位置;
SW_SHOW                        //在窗口原來的位置以原來的尺寸激活和顯示窗口;
SW_SHOWMAXIMIZED               //激活窗口並將其最大化;
SW_SHOWMINIMIZED               //激活窗口並將其最小化;
SW_SHOWMINNOACTIVE             //窗口最小化,激活窗口仍然維持激活狀態;
SW_SHOWNA
//以窗口原來的狀態顯示窗口。激活窗口仍然維持激活狀態; SW_SHOWNOACTIVATE //以窗口最近一次的大小和狀態顯示窗口。激活窗口仍然維持激活狀態;   SW_SHOWNORMAL //激活並顯示一個窗口。如果窗口被最小化或最大化,系統將其恢復到原來的尺寸和大小;

 

 

 

·窗口的更新

 

當窗口客戶區需要進行更新時, UpdateWindow函數就會被調用, 並繞過消息隊列直接發送一個WM_PAINT的消息給窗口過程函數WndProc進行相應處理, UpdateWindow函數的原型如下:

 

BOOL UpdateWindow( HWND hWnd  );

 

該函數只有一個參數, 參數為需要更新的窗口句柄; 函數調用成功返回值為非0, 調用失敗時返回值為0。

 

明天學習窗口過程WndProc是如何處理這些消息的。


--------------------

 

Wid, 2012.10.09

 

 上一篇: C語言Windows程序設計->第四天->詳解我的窗口(上)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM