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


對窗口創建的詳細解釋

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

  在昨天的學習中我們已經初步完成了一個窗口的創建雖然我們對於代碼中的許多語句可能還不理解但這暫時並不會影響到我們的學習再次來回顧昨天那個窗口的代碼部分:

Create myWindow - View Code
 1 #include <windows.h>
 2 
 3 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ;        //聲明用來處理消息的函數
 4 
 5 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
 6 {
 7     static TCHAR szAppName[] = TEXT("MyWindow") ;
 8     HWND hwnd ;
 9     MSG msg ;
10     WNDCLASS wndclass ;        //聲明一個窗口類對象
11 
12     //以下為窗口類對象wndclass的屬性
13     wndclass.style = CS_HREDRAW | CS_VREDRAW ;                         //窗口樣式
14     wndclass.lpszClassName = szAppName ;                               //窗口類名
15     wndclass.lpszMenuName = NULL ;                                     //窗口菜單:無
16     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;    //窗口背景顏色
17     wndclass.lpfnWndProc = WndProc ;                                   //窗口處理函數
18     wndclass.cbWndExtra = 0 ;                                          //窗口實例擴展:無
19     wndclass.cbClsExtra = 0 ;                                          //窗口類擴展:無
20     wndclass.hInstance = hInstance ;                                   //窗口實例句柄
21     wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;               //窗口最小化圖標:使用缺省圖標
22     wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;                 //窗口采用箭頭光標
23 
24     if( !RegisterClass( &wndclass ) )
25     {    //注冊窗口類, 如果注冊失敗彈出錯誤提示
26         MessageBox( NULL, TEXT("窗口注冊失敗!"), TEXT("錯誤"), MB_OK | MB_ICONERROR ) ;
27         return 0 ;
28     }
29 
30     hwnd = CreateWindow(                   //創建窗口
31                 szAppName,                 //窗口類名
32                 TEXT("我的窗口"),           //窗口標題
33                 WS_OVERLAPPEDWINDOW,       //窗口的風格
34                 CW_USEDEFAULT,             //窗口初始顯示位置x:使用缺省值
35                 CW_USEDEFAULT,             //窗口初始顯示位置y:使用缺省值
36                 CW_USEDEFAULT,             //窗口的寬度:使用缺省值
37                 CW_USEDEFAULT,             //窗口的高度:使用缺省值
38                 NULL,                      //父窗口:無
39                 NULL,                      //子菜單:無
40                 hInstance,                 //該窗口應用程序的實例句柄 
41                 NULL                       //
42             ) ;
43 
44     ShowWindow( hwnd, iCmdShow ) ;        //顯示窗口
45     UpdateWindow( &msg );                 //更新窗口
46 
47     while( GetMessage( &msg, NULL, 0, 0 ) )        //從消息隊列中獲取消息
48     {
49         TranslateMessage( &msg ) ;                 //將虛擬鍵消息轉換為字符消息
50         DispatchMessage( &msg ) ;                  //分發到回調函數(過程函數)
51     }
52     return msg.wParam ;
53 }
54 
55 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
56 {
57     HDC hdc ;                //設備環境句柄
58     PAINTSTRUCT ps ;         //繪制結構
59     RECT rect;               //矩形結構
60 
61     switch( message )        //處理得到的消息
62     {
63     case WM_CREATE:          //窗口創建完成時發來的消息
64         MessageBox( hwnd, TEXT("窗口已創建完成!"), TEXT("我的窗口"), MB_OK | MB_ICONINFORMATION ) ;
65         return 0;
66 
67     case WM_PAINT:           //處理窗口區域無效時發來的消息
68         hdc = BeginPaint( hwnd, &ps ) ;
69         GetClientRect( hwnd, &rect ) ;
70         DrawText( hdc, TEXT( "Hello, 這是我自己的窗口!" ), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ;
71         EndPaint( hwnd, &ps ) ;
72         return 0 ;
73 
74     case WM_LBUTTONDOWN:     //處理鼠標左鍵被按下的消息
75         MessageBox( hwnd, TEXT("鼠標左鍵被按下。"), TEXT("單擊"), MB_OK | MB_ICONINFORMATION ) ;
76         return 0;
77 
78     case WM_DESTROY:         //處理窗口關閉時的消息
79         MessageBox( hwnd, TEXT("關閉程序!"), TEXT("結束"), MB_OK | MB_ICONINFORMATION ) ;
80         PostQuitMessage( 0 ) ;
81         return 0;
82     }
83     return DefWindowProc( hwnd, message, wParam, lParam ) ;        //DefWindowProc處理我們自定義的消息處理函數沒有處理到的消息
84 }

 

·調用了哪些Windows API

  通過這段代碼我們完成了在客戶區(窗口的白色區域)中心顯示一段字符串此外我們還處理了系統發來的部分消息在這個過程中我們使用了Windows的諸多函數這些函數分別為:

 

函數名 函數描述

GetStockObject

獲取一個圖形對象

LoadIcon

為程序加載圖標

LoadCursor

為程序加載光標

RegisterClass

為程序窗口注冊一個窗口類

MessageBox

顯示消息對話框

CreateWindow

創建一個窗口

ShowWindow

在屏幕上將窗口顯示出來

UpdateWindow

重繪窗口客戶區

GetMessage

從消息隊列獲取消息

TranslateMessage

將虛擬鍵消息轉換為字符消息

DispatchMessage

將消息發送給消息處理函數

BeginPaint

准備對窗口進行繪圖

GetClientRect

獲取窗口客戶區尺寸

DrawText

繪制一個文本字符串

EndPaint

結束對窗口的繪圖

PostQuitMessage

向消息隊列插入"退出"消息 

DefWindowProc

執行系統默認的消息處理 

 

對於這些函數的詳細說明, 可以到百科查詢, 或者到MSDN Library文檔中查詢(推薦)。

 

 

·大寫標識符說明

  在上面的程序中出現了許多類似於XX_XXXX的大寫標識符:

 

CS_HREDRAW

CS_VREDRAW

IDI_APPLICATION

IDC_ARROW

MB_OK

MB_ICONERROR

WS_OVERLAPPEDWINDOW

CW_USEDEFAULT

DT_SINGLELINE

DT_CENTER

DT_VCENTER

WM_CREATE

WM_PAINT

WM_LBUTTONDOWN

WM_DESTROY

 

這些標識符均為數值常量WINUSER.H頭文件中有定義該程序中用到的一些標識符前綴含義為:

前綴

含義

CS_

類風格選項

CW_

創建窗口選項

DT_

文本繪制選項

IDI_

圖標的ID

IDC_

光標的ID

MB_

消息框選項

WM_

窗口消息

WS_

窗口風格

 

 

對於這些大寫標識符暫時沒必要強記下來只需要對其有個大致的印象即可不會影響到我們的學習。

 

 

·""數據類型

  在調用的函數中一些函數的參數類型是我們以往在C控制台編程中所沒有見到過的例如在代碼的第三行對回調函數的聲明中:

 

LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ; //聲明用來處理消息的函數

 

其中的"LRESULT""UINT""WPARAM""LPWARAM", 以及主函數WinMain中的"PSTR"之類的類型都是我們所沒有見過的這些""數據類型都是什么呢?

 

其實這些""數據類型是為了程序書寫時的簡便而使用typedef#defineC已有的數據類型重新定義的WINDEF.H/WINNT.H頭文件中有定義:

 

typedef unsigned int UINT; typedef char CHAR; typedef CHAR *LPSTR, *PSTR; typedef UINT WPARAM; typedef long LONG; typedef LONG LPARAM; typedef LONG LRESULT;

 

可以看出, UINT實際上就是unsigned int; PSTR就是一個char *, WPARAM被定義為UINT也就是unsigned int; LPARAMLRESULT被定義為long;

 

由此觀之, ""數據類型並不新。

 

在聲明消息處理函數WndProc在函數名前面我們還是使用了一個"CALLBACK"標識符這個標識符其實就是函數的調用規則WINDEF.H中有定義:

 

#define CALLBACK    __stdcall

 

在前些天的學習中我們還知道在WinMain主函數的前面有個WINAPI調用規則WINDEF.H中也被定義為 __stdcall

 

 

 

·結構類型

  結構體C語言的學習中我們已經對這種數據類型十分熟悉了在上述創建窗口的過程中我們使用了四種結構類型來創建結構體的對象這些結構體在WINUSER.H/WINDEF.H中有定義現在我們只需對其進行一下印象中的認識對於結構體的成員暫時不去討論這四種結構體分別為:

 

1>. MSG消息結構

 

MSGWINUSER.H中的定義:

 

typedef struct tagMSG {
    HWND        hwnd;
    UINT        message;
    WPARAM      wParam;
    LPARAM      lParam;
    DWORD       time;
    POINT       pt;
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

 

 

2>. WNDCLASS窗口類結構

WNDCLASSWINUSER.H中的定義:

 

typedef struct tagWNDCLASSW {
    UINT        style;
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCWSTR     lpszMenuName;
    LPCWSTR     lpszClassName;
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;
#ifdef UNICODE
typedef WNDCLASSW WNDCLASS;

 

 

3>. PAINTSTRUCT繪制結構

PAINTSTRUCTWINUSER.H中的定義:

 

typedef struct tagPAINTSTRUCT {
    HDC         hdc;
    BOOL        fErase;
    RECT        rcPaint;
    BOOL        fRestore;
    BOOL        fIncUpdate;
    BYTE        rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;

 

 

4>. RECT矩形結構

RECTWINDEF.H中的定義:

typedef struct tagRECT
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

 

 

 

·再談句柄

  不同類型的句柄有不同的標識符在我們嘗試創建窗口的代碼中用到的句柄有:

標識符

含義

HINSTANCE

實例句柄指程序本身

HWND

窗口句柄

HDC

設備環境句柄

HBRUSH

圖形畫刷句柄

 

  句柄是一個標識符,用來來標識對象, 一個句柄使用四個字節長的整數來存儲一個整數值這個具體的整數值實際上我們並不需要知道是多少我們要做的就是傳遞句柄, Windows會知道如果用過這個句柄找到並以引用相應的對象。

 

 

 

·匈牙利命名法

  匈牙利命名法是一種編程時的命名規范, 在一開始我們接觸的MessageBox對話框時我們就已經見到了匈牙利命名的變量:

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

這里的 hInstancehPrevInstanceszCmdLineiCmdShow的命名都遵循匈牙利命名法匈牙利命名法的目的和作用是使變量名非常清晰易懂,增強了代碼的可讀性,方便各程序員之間相互交流代碼, 減少代碼中因數據類型不匹配的錯誤

例如:

 

szCmdLine, 通過變量名我們就可以知道這是一個"0結束的字符串"; 

 

hInstance, h開頭代表一個句柄;

 

iCmdShow, i開頭代表一個int整形。

 

這樣就可以不用再去找到變量聲明的位置去看它的變量類型避免了在使用變量時由於數據類型不匹配引起的錯誤。

 

經常使用的匈牙利命名的前綴如下:

 

前綴

含義描述

p 指針
fn 函數
v  無效
h 句柄
l 長整形
b 布爾型
f 浮點型
dw 雙字
sz 字符串
n 短整型
d 雙精度浮點型
c 計數, 通常寫為cnt
ch 字符, 通常寫為c
i 整型
by 字節
w 字型
r 實型
u 無符號型
   
g_ 全局變量
c_ 常量
m_ 成員變量
s_ 靜態變量
   
Max 最大
Min 最小
Init 初始化
T 或 Temp 臨時變量
Src 源對象
Dest 目標對象

 

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

 


免責聲明!

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



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