使用MASM寫Windows程序,其實(shí)就是和Windows API打交道,而一個(gè)人是不可能記住所有的API用法的,所以API參考手冊(cè)是必不可少的,API的參考手冊(cè)中函數(shù)原型是按匈牙利表示法表示的,下面這個(gè)表就是API原型中那些前綴的詳細(xì)解釋
資料來(lái)源:MicroSoft MSDN Platform SDK 參考
為便于開發(fā)Windows應(yīng)用程序,Windows的開發(fā)者新定義了一些數(shù)據(jù)類型。這些數(shù)據(jù)類型或是與C/C++中已有的數(shù)據(jù)類型同義,或是一些新的結(jié)構(gòu)數(shù)據(jù)類型。引入這些類型的主要目的是為便于程序員開發(fā)Windows應(yīng)用程序,同時(shí)也是為了增強(qiáng)程序的可讀性;另一個(gè)目的是為了便于程序?qū)?lái)能被移植到其它種類的計(jì)算機(jī)平臺(tái)上或適應(yīng)Windows將來(lái)的新版本的變化。例如,本教程目前使用16位API(Application Program Interface),現(xiàn)在Windows的版本使用32位API,只要將HANDLE等句柄類型定義為32位長(zhǎng),然后重新編譯程序,就可以很方便地將一個(gè)使用16位API的Windows應(yīng)用程序改為使用32位API的程序,使其能運(yùn)行在32位API Windows上。大部分的數(shù)據(jù)類型在Windows.h中定義,下面是在這個(gè)文件中定義的部分類型:
#define PASCAL pascal
#define NEAR near
#define FAR far
typedef unsigned char BYTE
typedef unsigned short WORD
typedef unsigned long DWORD
typedef long LONG
typedef char *PSTR
typedef char NEAR *NPSTR
typedef char FAR *LPSTR
typedef void VOID
typedef int *LPINT
typedef LONG (PASCAL FAR * FARPROC)(); 在Windows.h中,使用typedef還定義了一些新的結(jié)構(gòu)類型。這些結(jié)構(gòu)類型的名字也使用大寫形式的標(biāo)識(shí)符:
類型 說(shuō)明
MSG 消息結(jié)構(gòu)
WNDCLASS 窗口的類的結(jié)構(gòu)
PAINTSTRUCT 繪圖結(jié)構(gòu)
POINT 點(diǎn)的坐標(biāo)的結(jié)構(gòu)
RECT 矩形結(jié)構(gòu)
我們?cè)谶@里以類型MSG為例來(lái)說(shuō)明類型的定義方法,對(duì)于其它類型,在以后用到時(shí)再作詳細(xì)地說(shuō)明。類型MSG是一個(gè)消息結(jié)構(gòu),它的定義方式及其各域的含義如下:
typedef struct tagMSG { HWND hWnd; // 窗口對(duì)象的標(biāo)識(shí)符,該條消息傳遞到它所標(biāo)識(shí)的窗口上 UINT message; // 消息標(biāo)識(shí)符,標(biāo)識(shí)某個(gè)特定的消息 WPARAM wParam; // 隨同消息傳遞的16位參數(shù) LPARAM lParam; // 隨同消息傳遞的32位參數(shù) DWORD time; // 消息產(chǎn)生的時(shí)間 POINT pt; // 產(chǎn)生消息時(shí)光標(biāo)在屏幕上的坐標(biāo) } MSG;
typedef MSG FAR *LPMSG; 其中的POINT類型的定義是:
typedef struct tagPOINT { int x; /* X坐標(biāo) */ int y; /* Y坐標(biāo) */ } POINT;
typedef POINT FAR *LPPOINT; Windows.h在定義大部分類型的同時(shí),還定義了該類型的指針類型。例如,上例中的LPPOINT和LPMSG等,其中字母前綴LP表示遠(yuǎn)指針類型;若使用NP作為一個(gè)類型的前綴,則表示近指針類型;若使用P作為一個(gè)類型的前綴時(shí),則表示一般的指針類型,這時(shí)由編譯程序時(shí)所使用的內(nèi)存模塊決定這種指針是遠(yuǎn)指針或是近指針。在Windows.h中說(shuō)明的大部分指針類型都采用這里介紹的方法進(jìn)行說(shuō)明,例如,LPRECT,它表示一個(gè)RECT類型的遠(yuǎn)指針。
在Windows.h中說(shuō)明的大部分指針類型使用了C/C++的關(guān)鍵字const,如果一個(gè)指針類型的名字前綴為L(zhǎng)PC、NPC或PC,則其中的字母C表示這種類型的指針變量所指向的變量不能通過(guò)該指針變量來(lái)修改,這種指針類型一般采用下述方法進(jìn)行說(shuō)明:
typedef const POINT FAR * LPCPOINT;
typedef const REC FAR * LPCRECT; 一個(gè)使用const修飾的指針(稱其為const指針)可以指向沒(méi)有使用const修飾的變量,但沒(méi)有使用const修飾的指針不能指向const修飾的變量,例如:
const POINT pt;
LPCPOINT lpPoint = &pt; // 正確 LPPOINT lpPoint = &pt; // 錯(cuò)誤 當(dāng)向函數(shù)傳遞參數(shù)時(shí),必須特別注意這個(gè)問(wèn)題,例如:
void fun(LPPOINT lppt) ;
......
LPCPOINT lpPoint ;
fun(lpPoint) ; 編譯器將指示這個(gè)函數(shù)調(diào)用語(yǔ)句是錯(cuò)誤的。所以,在一個(gè)函數(shù)不修改一個(gè)指針參數(shù)所指向的變量的情況下,最好將該參數(shù)說(shuō)明為const指針,使const類型的指針也能用于該函數(shù)的參數(shù)。Windows.h中說(shuō)明的大部分函數(shù)使用了const指針參數(shù)。
在Windows.h中,大多數(shù)語(yǔ)句是用于定義一個(gè)常量,例如:
#denfine WM_QUIT 0X0012 該語(yǔ)句用標(biāo)識(shí)符WM_QUIT來(lái)表示編號(hào)為0X0012的消息。每個(gè)常量由一個(gè)前綴和表示其含義的單詞組成的標(biāo)識(shí)符組成,兩者之間用下畫線隔開。前綴表明這些常量所屬的一般范疇。下面是一些前綴和它們所屬的范疇的說(shuō)明。
類型 說(shuō)明
CS 窗口類的風(fēng)格(Class Style)
IDI 預(yù)定義的圖標(biāo)對(duì)象的標(biāo)識(shí)符(IDentity of Icon)
IDC 預(yù)定義的光標(biāo)對(duì)象的標(biāo)識(shí)符(IDentity of Cursor)
WS 窗口的風(fēng)格(Windows Style)
CW 創(chuàng)建窗口(Create Windows)
WM 窗口消息(Windows Message)
DT 繪制文本(Drawing Text)
在變量名的表示方法方面,Windows推薦使用一種稱為“匈牙利表示法”的方法。每個(gè)變量名用小寫字母或描述了變量的數(shù)據(jù)類型的字母作為前綴,變量的名字緊跟其后,且用大寫字母開始的單詞(一個(gè)或多個(gè)單詞)表示其含義,這樣每個(gè)變量都能附加上其數(shù)據(jù)類型的助記符。例如:
WORD wOffset ; /* w表示W(wǎng)ORD類型 */ DWORD dwValue ; /* dw表示DWORD類型 */ 下面是Windows中常使用的一些字母前綴和它們所代表的數(shù)據(jù)類型:
類型 說(shuō)明
b BOOL,布爾類型
by BYTE類型
c char類型
dw DWORD類型
fn 函數(shù)類型
i 整型
l LONG類型
lp 遠(yuǎn)(長(zhǎng))指針(long pointer)
n 短整型
np 近(短)指針(near pointer)
p 指針
s 字符串
sz 以'\0'結(jié)尾的字符串
w WORD類型
x short,用于表示X坐標(biāo)時(shí)
y short,用于表示Y坐標(biāo)時(shí)
Windows程序員也可以根據(jù)上述思想和使用目的,發(fā)明一些其他的前綴,但要注意,對(duì)這些前綴的使用必須保持前后一致。在Windows中,所有的函數(shù)根據(jù)其用途來(lái)命名,它們一般由2到3個(gè)英文單詞組成,每個(gè)單詞的第一個(gè)字母大寫,例如,函數(shù)CreateWindow(),由該函數(shù)的名字可以知道它的用途是創(chuàng)建一個(gè)窗口。
比如說(shuō)API函數(shù)CreateWindowsEx,API原型如下:
HWND CreateWindowEx(
DWORD dwExStyle, // extended window style
LPCTSTR lpClassName, // pointer to registered class name
LPCTSTR lpWindowName, // pointer to window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // handle to menu, or child-window identifier
HINSTANCE hInstance, // handle to application instance
LPVOID lpParam // pointer to window-creation data
);
那么根據(jù)上述前綴表可以得出,dwExStyle需要一個(gè)雙字值,lpClassName與lpWindowName需要一個(gè)指向字符串的長(zhǎng)指針(在MASM中則是偏移地址),x、y表示需傳遞整數(shù)值,nWidth與nHeight表示傳遞短整數(shù),hWndParent表示需要一個(gè)窗口句柄,hMenu表示傳遞一個(gè)菜單句柄,hInstance表示傳遞的是程序?qū)嵗浔?lpParam表示可以傳遞長(zhǎng)指針(地址)。
注意看前綴時(shí)請(qǐng)不要看前面的類型說(shuō)明符,而是要看詞的前綴,如DWORD dwExStyle,只需要看dwExStyle就知道傳遞的是雙字?jǐn)?shù)。
另外還有其它的組合,只要稍注意就能行,比如說(shuō)lpfn表示指向函數(shù)的長(zhǎng)指針,在MASM中則是一個(gè)函數(shù)的地址,,還有像lpSecurityAttributes之類的,則是指向SECURITY_ATTRIBUTES結(jié)構(gòu)的長(zhǎng)指針(地址),lpvBuffer表示傳遞一個(gè)緩存(Buffer)長(zhǎng)指針(lp)或者為空(void),還有一些沒(méi)有前綴的則是這個(gè)詞已經(jīng)足夠說(shuō)明它的意思了。等等,熟悉這些前綴的含義可以讓你在學(xué)習(xí)API的時(shí)候進(jìn)行快速的掌握。并能排除一些錯(cuò)誤。
為了更好的了解WINDOWS編程,這里我必須介紹幾個(gè)基本的概念:
1,句柄:它是WINDOWS編程的基礎(chǔ)。一個(gè)句柄是指WINDOWS在內(nèi)存中使用的一個(gè)唯一的整數(shù)質(zhì),是一個(gè)4個(gè)字節(jié)長(zhǎng)的數(shù)值,用于標(biāo)識(shí)應(yīng)用程序中不同對(duì)象和相同對(duì)象的不同實(shí)例。
這里我列出幾種WINDOWS常用的句柄:
HWND: 標(biāo)示窗口句柄
HINSTANCE:標(biāo)示當(dāng)前實(shí)例句柄
HCOURSOR:標(biāo)示光標(biāo)句柄
HFONT: 標(biāo)示字體句柄
HPEN:標(biāo)示畫筆句柄
HBRUSH:標(biāo)示畫刷句柄
HDC:標(biāo)示設(shè)備環(huán)境句柄
HB99vMP:標(biāo)示位圖句柄
HICON:標(biāo)示圖標(biāo)句柄
HMENU:標(biāo)示菜單句柄
HFILE:標(biāo)示文件句柄
由于WINDOWS應(yīng)用程序利用WINDOWS消息來(lái)與其它的WINDOWS應(yīng)用程序及WINDOWS系統(tǒng)進(jìn)行消息交換。所以消息是一個(gè)十分重要的對(duì)象它的結(jié)構(gòu)如下。
typedef struct{
HWND hwnd; //檢索消息的窗口句柄
UN99v message; //代表一個(gè)消息的消息質(zhì)
WPARAM wParam; //消息附加信息的字參數(shù)
LPARAM lParam; //消息附加信息的長(zhǎng)字參數(shù)
DWORD time; //消息入隊(duì)時(shí)間
POINT pt; //消息發(fā)送時(shí)鼠標(biāo)的位置 point.x;point.y;
} tagMSG;
2,消息:VC++中消息都用前綴標(biāo)示消息所屬的分類,下面我來(lái)介紹一下這些前綴
BM表示按鈕控制消息
CB表示組合框控制消息
DM表示默認(rèn)下壓式按鈕控制消息
EM表示編輯控制消息
LB表示列表框控制消息
SBM表示滾動(dòng)條控制消息
WM表示窗口消息
現(xiàn)在我來(lái)對(duì)系統(tǒng)常用的一些消息進(jìn)行說(shuō)明:
1,WM_LBUTTONDOWN: 單擊鼠標(biāo)左鍵時(shí)產(chǎn)生
2,WM_LBUTTONUP: 放開鼠標(biāo)左鍵時(shí)產(chǎn)生
3,WM_RBUTTONUP: 放開鼠標(biāo)右鍵時(shí)產(chǎn)生
4,WM_LBUTTONBLCLK: 雙擊鼠標(biāo)左鍵時(shí)產(chǎn)生
5,WM_RBUTTONBLCLK: 雙擊鼠標(biāo)右鍵時(shí)產(chǎn)生
6,WM_KEYDOWN: 按下了一個(gè)非系統(tǒng)鍵時(shí)產(chǎn)生的消息
7,WM_CHAR: 同上
8,WM_CREATE: 由CreateWindow函數(shù)發(fā)出的消息
9,WM_DESTROY: 消除窗口時(shí)發(fā)出的消息
10,WM_QU99v: 退出程序時(shí)發(fā)送的消息
11,WM_PAINT: 做任何移動(dòng)操作時(shí)發(fā)出的消息
介紹了以上的這些基礎(chǔ)入門知識(shí),我們就可以簡(jiǎn)單的了解一下WINDOWS API 程序的組成基本結(jié)構(gòu)。它是由入口函數(shù)WinMain和窗口函數(shù)基本框架,并包含各種數(shù)據(jù)類型、數(shù)據(jù)結(jié)構(gòu)與函數(shù)等應(yīng)用組建組成的。其中入口函數(shù)WinMain和窗口函數(shù)是WINDOWS應(yīng)用程序的主體。
一個(gè)基本的WinMain函數(shù)應(yīng)該具有以下的功能:
1,注冊(cè)窗口類,建立窗口及執(zhí)行其他必要的初始化工作
2,進(jìn)入消息循環(huán),根據(jù)從應(yīng)用程序消息隊(duì)列接受的消息,調(diào)用相應(yīng)的處理過(guò)程。
3,當(dāng)消息循環(huán)檢索到WM_QU99v消息時(shí)中止程序運(yùn)行
WinMain函數(shù)有三個(gè)基本組成部分:函數(shù)說(shuō)明、初始化和消息循環(huán)。
(1)函數(shù)說(shuō)明
int WINAPI WinMain
(
HINSTANCE hThisInst, //應(yīng)用程序當(dāng)前實(shí)例句柄
HINSTANCE hPrevInst, //應(yīng)用程序其它實(shí)例句柄
LPSTR lpszCmdLine, //指向程序命令行參數(shù)的指針
int nCmdShow //應(yīng)用程序開始執(zhí)行時(shí)窗口顯示方式的整數(shù)值標(biāo)示
)
(2)初始化
初始化包括窗口類的定義、注冊(cè)、創(chuàng)建窗口實(shí)例和顯示窗口四部分。(在以后的程序中我將詳細(xì)的介紹它們具體的實(shí)現(xiàn)方法)
(3)消息循環(huán)
WINDOWS應(yīng)用程序的運(yùn)行是以消息為核心的。WINDOWS將產(chǎn)生的消息放入應(yīng)用程序的消息隊(duì)列中,而應(yīng)用程序的WinMain函數(shù)從消息循環(huán)提取隊(duì)列中的消息,并將其傳遞給窗口函數(shù)的相應(yīng)過(guò)程處理。
它的基本寫法如下:
MSG Meg;//定義消息
//(...)省略了一些內(nèi)容
while (GetMessage(&Meg,NULL,0,0)
{
TranslanteMessage(&Meg);
DispatchMessage(&Meg);
}