使用MASM寫Windows程序,其實(shí)就是和Windows API打交道,而一個(gè)人是不可能記住所有的API用法的,所以API參考手冊是必不可少的,API的參考手冊中函數(shù)原型是按匈牙利表示法表示的,下面這個(gè)表就是API原型中那些前綴的詳細(xì)解釋
資料來源: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ū)砟鼙灰浦驳狡渌N類的計(jì)算機(jī)平臺上或適應(yīng)Windows將來的新版本的變化。例如,本教程目前使用16位API(Application Program Interface),現(xiàn)在Windows的版本使用32位API,只要將HANDLE等句柄類型定義為32位長,然后重新編譯程序,就可以很方便地將一個(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)識符:

類型 說明 
MSG 消息結(jié)構(gòu) 
WNDCLASS 窗口的類的結(jié)構(gòu) 
PAINTSTRUCT 繪圖結(jié)構(gòu) 
POINT 點(diǎn)的坐標(biāo)的結(jié)構(gòu) 
RECT 矩形結(jié)構(gòu) 


       我們在這里以類型MSG為例來說明類型的定義方法,對于其它類型,在以后用到時(shí)再作詳細(xì)地說明。類型MSG是一個(gè)消息結(jié)構(gòu),它的定義方式及其各域的含義如下:

  typedef struct tagMSG {
     HWND     hWnd;  // 窗口對象的標(biāo)識符,該條消息傳遞到它所標(biāo)識的窗口上
     UINT    message;  // 消息標(biāo)識符,標(biāo)識某個(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中說明的大部分指針類型都采用這里介紹的方法進(jìn)行說明,例如,LPRECT,它表示一個(gè)RECT類型的遠(yuǎn)指針。
  在Windows.h中說明的大部分指針類型使用了C/C++的關(guān)鍵字const,如果一個(gè)指針類型的名字前綴為LPC、NPC或PC,則其中的字母C表示這種類型的指針變量所指向的變量不能通過該指針變量來修改,這種指針類型一般采用下述方法進(jìn)行說明:

  typedef const POINT FAR * LPCPOINT;
  typedef const REC  FAR * LPCRECT;


  一個(gè)使用const修飾的指針(稱其為const指針)可以指向沒有使用const修飾的變量,但沒有使用const修飾的指針不能指向const修飾的變量,例如:

  const POINT pt;
  LPCPOINT lpPoint = &pt;
   // 正確
  LPPOINT  lpPoint = &pt;   // 錯(cuò)誤

  當(dāng)向函數(shù)傳遞參數(shù)時(shí),必須特別注意這個(gè)問題,例如:

  void fun(LPPOINT lppt) ;
  ......
  LPCPOINT lpPoint ;
  fun(lpPoint) ;


  編譯器將指示這個(gè)函數(shù)調(diào)用語句是錯(cuò)誤的。所以,在一個(gè)函數(shù)不修改一個(gè)指針參數(shù)所指向的變量的情況下,最好將該參數(shù)說明為const指針,使const類型的指針也能用于該函數(shù)的參數(shù)。Windows.h中說明的大部分函數(shù)使用了const指針參數(shù)。
  在Windows.h中,大多數(shù)語句是用于定義一個(gè)常量,例如:

  #denfine WM_QUIT 0X0012

  該語句用標(biāo)識符WM_QUIT來表示編號為0X0012的消息。每個(gè)常量由一個(gè)前綴和表示其含義的單詞組成的標(biāo)識符組成,兩者之間用下畫線隔開。前綴表明這些常量所屬的一般范疇。下面是一些前綴和它們所屬的范疇的說明。

類型 說明 
CS 窗口類的風(fēng)格(Class Style) 
IDI 預(yù)定義的圖標(biāo)對象的標(biāo)識符(IDentity of Icon) 
IDC 預(yù)定義的光標(biāo)對象的標(biāo)識符(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ù)類型:

類型 說明 
b BOOL,布爾類型 
by BYTE類型 
c char類型 
dw DWORD類型 
fn 函數(shù)類型 
i 整型 
l LONG類型 
lp 遠(yuǎn)(長)指針(
long pointer) 
n 短整型 
np 近(短)指針(near pointer) 
p 指針 
s 字符串 
sz 以
'\0'結(jié)尾的字符串 
w WORD類型 
short,用于表示X坐標(biāo)時(shí) 
short,用于表示Y坐標(biāo)時(shí) 



        Windows程序員也可以根據(jù)上述思想和使用目的,發(fā)明一些其他的前綴,但要注意,對這些前綴的使用必須保持前后一致。在Windows中,所有的函數(shù)根據(jù)其用途來命名,它們一般由2到3個(gè)英文單詞組成,每個(gè)單詞的第一個(gè)字母大寫,例如,函數(shù)CreateWindow(),由該函數(shù)的名字可以知道它的用途是創(chuàng)建一個(gè)窗口。

比如說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è)指向字符串的長指針(在MASM中則是偏移地址),x、y表示需傳遞整數(shù)值,nWidth與nHeight表示傳遞短整數(shù),hWndParent表示需要一個(gè)窗口句柄,hMenu表示傳遞一個(gè)菜單句柄,hInstance表示傳遞的是程序?qū)嵗浔?lpParam表示可以傳遞長指針(地址)。
注意看前綴時(shí)請不要看前面的類型說明符,而是要看詞的前綴,如DWORD dwExStyle,只需要看dwExStyle就知道傳遞的是雙字?jǐn)?shù)。
另外還有其它的組合,只要稍注意就能行,比如說lpfn表示指向函數(shù)的長指針,在MASM中則是一個(gè)函數(shù)的地址,,還有像lpSecurityAttributes之類的,則是指向SECURITY_ATTRIBUTES結(jié)構(gòu)的長指針(地址),lpvBuffer表示傳遞一個(gè)緩存(Buffer)長指針(lp)或者為空(void),還有一些沒有前綴的則是這個(gè)詞已經(jīng)足夠說明它的意思了。等等,熟悉這些前綴的含義可以讓你在學(xué)習(xí)API的時(shí)候進(jìn)行快速的掌握。并能排除一些錯(cuò)誤。

為了更好的了解WINDOWS編程,這里我必須介紹幾個(gè)基本的概念:
1,句柄:它是WINDOWS編程的基礎(chǔ)。一個(gè)句柄是指WINDOWS在內(nèi)存中使用的一個(gè)唯一的整數(shù)質(zhì),是一個(gè)4個(gè)字節(jié)長的數(shù)值,用于標(biāo)識應(yīng)用程序中不同對象和相同對象的不同實(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消息來與其它的WINDOWS應(yīng)用程序及WINDOWS系統(tǒng)進(jìn)行消息交換。所以消息是一個(gè)十分重要的對象它的結(jié)構(gòu)如下。

typedef struct{
  HWND hwnd;     //檢索消息的窗口句柄
  UN99v message;  //代表一個(gè)消息的消息質(zhì)
  WPARAM wParam; //消息附加信息的字參數(shù)
  LPARAM lParam; //消息附加信息的長字參數(shù)
  DWORD time;    //消息入隊(duì)時(shí)間
  POINT pt;      //消息發(fā)送時(shí)鼠標(biāo)的位置 point.x;point.y;
} tagMSG;

2,消息:VC++中消息都用前綴標(biāo)示消息所屬的分類,下面我來介紹一下這些前綴

BM表示按鈕控制消息
CB表示組合框控制消息
DM表示默認(rèn)下壓式按鈕控制消息
EM表示編輯控制消息
LB表示列表框控制消息
SBM表示滾動(dòng)條控制消息
WM表示窗口消息

現(xiàn)在我來對系統(tǒng)常用的一些消息進(jìn)行說明:
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ǔ)入門知識,我們就可以簡單的了解一下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,注冊窗口類,建立窗口及執(zhí)行其他必要的初始化工作
2,進(jìn)入消息循環(huán),根據(jù)從應(yīng)用程序消息隊(duì)列接受的消息,調(diào)用相應(yīng)的處理過程。
3,當(dāng)消息循環(huán)檢索到WM_QU99v消息時(shí)中止程序運(yùn)行
WinMain函數(shù)有三個(gè)基本組成部分:函數(shù)說明、初始化和消息循環(huán)。

(1)函數(shù)說明

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)初始化
初始化包括窗口類的定義、注冊、創(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)過程處理。

它的基本寫法如下:

MSG Meg;//定義消息
//(...)省略了一些內(nèi)容
while (GetMessage(&Meg,NULL,0,0)
{
  TranslanteMessage(&Meg);
  DispatchMessage(&Meg);
}