“Windows編程就像去見牙科醫生:雖然明明知道最自己是有益處的,可還是沒人喜歡總是找牙醫。”記得很早的時候,看了一下MFC,還根本不知道窗口啊,按鈕啊,菜單啊,現在讀這一章才看到的Windows的真面目了。
1. 傳說中的“匈牙利符號表示法”,早有耳聞此法,但未曾一見啊,最是頭痛的就屬看幫助文檔的,尤其是MSDN了,不過要想閱讀Microsoft的一些代碼,還真的懂此法呀。
* 匈牙利符號表示法前綴代碼
前綴 |
數據類型(基礎類型) |
c |
Char字符 |
by |
BYTE字節(無符號字符) |
n |
Short短整數和整數(表示一個數) |
i |
int整數 |
x,y |
Short短整數(通常用于x和y坐標) |
cx,cy |
short短整數(通常用于x和y的長度;c表示計數) |
b |
BOOL(整數) |
w |
UINT(無符號數)和WORD(無符號字) |
l |
LONG(長整數) |
dw |
DWORD(無符號長整數) |
fn |
函數指針 |
s |
字符串 |
sz,str |
以一個字節的0(空值)終止的字符串 |
lp |
32位指針 |
h |
編號(常用于表示Windows對象) |
msg |
消息 |
*變量的命名
變量的命名應用匈牙利符號表示法,變量可用上表中的前綴代碼表示。另外,變量由一個或幾個子名構成時,每一個子名都要大寫字母開頭。
例如: char *szFileName; // a null terminated string
int *lpiData; //a 32-bit pointer to a int
還有一點就是,全局變量以g_或g開頭。
*函數命名
函數命名和變量命名規則相同,但是沒有前綴。也就是說,只需要子名的第一個字母要大寫。
而且函數名中使用下劃線是非法的。例如,下面的函數名表示是無效的匈牙利符號表示法:
int Get_Pixel(int ix,int iy);
*類型和常量的命名
所有的類型和常量都是大寫的字母,但名字中可以允許使用下劃線。
*類的命名
所有c++的類必須使用大寫的C為前綴。類名字的每一個子名的第一個字母要大寫。
*參數的命名
函數的參數命名和標準變量命名約定相同。
2.怎樣創建一個完全實用的Windows程序,也就是那個我們經常見面的那個窗口。你只需要下面幾步:
1.創建一個Windows類。
2.創建一個事件句柄或WinProc。
3.用Windows注冊Windows類。
4.用前面創建的Windows類創建一個窗口。
5.創建一個能夠從事件句柄獲得或向事件句柄傳遞Windows信息的主事件循環。
2.1 Windows類
“ Windows中的每一個窗口、控件、列表框、對話框和小部件等等實際上都是一個窗口。區別它們的就是定義它們的類。一個Windows類就是Windows能夠操作的一個窗口類型的描述。”
“控制Windows類信息的數據結構有兩個:WNDCLASS和WNDCLASSEX。WNDCLASS是比較古老的一個,可能不久將廢棄,因此我們應當使用新的擴展版WNDCLASSEX。”
typedef struct _WNDCLASSEX
{
UNIT cbsize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HANDLE hInstance;
HICON hIcon;
HCURSON hCoursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
}WNDCLASSEX;
創建一個這樣的結構,然后就是填寫里面所有的成員變量:WNDCLASSEX winclass;
2.2事件句柄
這里所說的句柄(exent handler)就是當事件發生時Windows從主事件循環調用的回調
函數。對于創建的任何一個Windows類,都有一個獨立的事件句柄,我們稱呼它為WinProc,當用戶
和Windows運行任務時,你的窗口和/或其他的應用程序窗口產生事件和消息。所有的消息都進入一
個隊列,而你的窗口的消息發送你的窗口專用隊列中。然后主事件循環檢索這些消息,并且將它們發
送到你的窗口的WinProc中來處理。
WinProc原型:
LRESULT CALLBACK WindowProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam );
2.3注冊Windows類
Windows類已經定義并且存放在Windsclass中,必須將新的類通知Windows。該功能通過
RegisterClassEx()函數實現,使用一個指向新類定義的指針來實現。如下:
RegisterClassEx(&winclass);
2.4創建窗口
創建窗口使用CreateWindow()或CreateWindowEx()函數。
2.5主事件循環
while(TRUE)
{
// test if there is a message in queue, if so get it
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit
if (msg.message == WM_QUIT)
break;
// translate any accelerator keys
TranslateMessage(&msg);
// send the message to the window proc
DispatchMessage(&msg);
} // end if
// main game processing goes here
Game_Main();
} // end while