使用MASM写Windows程序,其实就是和Windows API打交道,而一个人是不可能记住所有的API用法的,所以API参考手册是必不可少的,API的参考手册中函数原型是按匈牙利表示法表示的,下面这个表就是API原型中那些前缀的详细解释
资料来源:MicroSoft MSDN Platform SDK 参考
为便于开发Windows应用程序,Windows的开发者新定义了一些数据类型。这些数据类型或是与C/C++中已有的数据类型同义,或是一些新的结构数据类型。引入这些类型的主要目的是为便于程序员开发Windows应用程序,同时也是为了增强程序的可读性;另一个目的是为了便于程序将来能被移植到其它种类的计算机平台上或适应Windows将来的新版本的变化。例如,本教程目前使用16位API(Application Program Interface),现在Windows的版本使用32位API,只要将HANDLE等句柄类型定义为32位长,然后重新编译程序,就可以很方便地将一个使用16位API的Windows应用程序改为使用32位API的程序,使其能运行在32位API Windows上。大部分的数据类型在Windows.h中定义,下面是在这个文件中定义的部分类型:
#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还定义了一些新的结构类型。这些结构类型的名字也使用大写形式的标识符:
类型 说明
MSG 消息结构
WNDCLASS 窗口的类的结构
PAINTSTRUCT 绘图结构
POINT 点的坐标的结构
RECT 矩形结构
我们在这里以类型MSG为例来说明类型的定义方法,对于其它类型,在以后用到时再作详细地说明。类型MSG是一个消息结构,它的定义方式及其各域的含义如下:
typedef struct tagMSG { HWND hWnd; // 窗口对象的标识符,该条消息传递到它所标识的窗口上 UINT message; // 消息标识符,标识某个特定的消息 WPARAM wParam; // 随同消息传递的16位参数 LPARAM lParam; // 随同消息传递的32位参数 DWORD time; // 消息产生的时间 POINT pt; // 产生消息时光标在屏幕上的坐标 } MSG;
typedef MSG FAR *LPMSG; 其中的POINT类型的定义是:
typedef struct tagPOINT { int x; /* X坐标 */ int y; /* Y坐标 */ } POINT;
typedef POINT FAR *LPPOINT; Windows.h在定义大部分类型的同时,还定义了该类型的指针类型。例如,上例中的LPPOINT和LPMSG等,其中字母前缀LP表示远指针类型;若使用NP作为一个类型的前缀,则表示近指针类型;若使用P作为一个类型的前缀时,则表示一般的指针类型,这时由编译程序时所使用的内存模块决定这种指针是远指针或是近指针。在Windows.h中说明的大部分指针类型都采用这里介绍的方法进行说明,例如,LPRECT,它表示一个RECT类型的远指针。
在Windows.h中说明的大部分指针类型使用了C/C++的关键字const,如果一个指针类型的名字前缀为LPC、NPC或PC,则其中的字母C表示这种类型的指针变量所指向的变量不能通过该指针变量来修改,这种指针类型一般采用下述方法进行说明:
typedef const POINT FAR * LPCPOINT;
typedef const REC FAR * LPCRECT; 一个使用const修饰的指针(称其为const指针)可以指向没有使用const修饰的变量,但没有使用const修饰的指针不能指向const修饰的变量,例如:
const POINT pt;
LPCPOINT lpPoint = &pt; // 正确 LPPOINT lpPoint = &pt; // 错误 当向函数传递参数时,必须特别注意这个问题,例如:
void fun(LPPOINT lppt) ;
......
LPCPOINT lpPoint ;
fun(lpPoint) ; 编译器将指示这个函数调用语句是错误的。所以,在一个函数不修改一个指针参数所指向的变量的情况下,最好将该参数说明为const指针,使const类型的指针也能用于该函数的参数。Windows.h中说明的大部分函数使用了const指针参数。
在Windows.h中,大多数语句是用于定义一个常量,例如:
#denfine WM_QUIT 0X0012 该语句用标识符WM_QUIT来表示编号为0X0012的消息。每个常量由一个前缀和表示其含义的单词组成的标识符组成,两者之间用下画线隔开。前缀表明这些常量所属的一般范畴。下面是一些前缀和它们所属的范畴的说明。
类型 说明
CS 窗口类的风格(Class Style)
IDI 预定义的图标对象的标识符(IDentity of Icon)
IDC 预定义的光标对象的标识符(IDentity of Cursor)
WS 窗口的风格(Windows Style)
CW 创建窗口(Create Windows)
WM 窗口消息(Windows Message)
DT 绘制文本(Drawing Text)
在变量名的表示方法方面,Windows推荐使用一种称为“匈牙利表示法”的方法。每个变量名用小写字母或描述了变量的数据类型的字母作为前缀,变量的名字紧跟其后,且用大写字母开始的单词(一个或多个单词)表示其含义,这样每个变量都能附加上其数据类型的助记符。例如:
WORD wOffset ; /* w表示WORD类型 */ DWORD dwValue ; /* dw表示DWORD类型 */ 下面是Windows中常使用的一些字母前缀和它们所代表的数据类型:
类型 说明
b BOOL,布尔类型
by BYTE类型
c char类型
dw DWORD类型
fn 函数类型
i 整型
l LONG类型
lp 远(长)指针(long pointer)
n 短整型
np 近(短)指针(near pointer)
p 指针
s 字符串
sz 以'\0'结尾的字符串
w WORD类型
x short,用于表示X坐标时
y short,用于表示Y坐标时
Windows程序员也可以根据上述思想和使用目的,发明一些其他的前缀,但要注意,对这些前缀的使用必须保持前后一致。在Windows中,所有的函数根据其用途来命名,它们一般由2到3个英文单词组成,每个单词的第一个字母大写,例如,函数CreateWindow(),由该函数的名字可以知道它的用途是创建一个窗口。
比如说API函数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
);
那么根据上述前缀表可以得出,dwExStyle需要一个双字值,lpClassName与lpWindowName需要一个指向字符串的长指针(在MASM中则是偏移地址),x、y表示需传递整数值,nWidth与nHeight表示传递短整数,hWndParent表示需要一个窗口句柄,hMenu表示传递一个菜单句柄,hInstance表示传递的是程序实例句柄,lpParam表示可以传递长指针(地址)。
注意看前缀时请不要看前面的类型说明符,而是要看词的前缀,如DWORD dwExStyle,只需要看dwExStyle就知道传递的是双字数。
另外还有其它的组合,只要稍注意就能行,比如说lpfn表示指向函数的长指针,在MASM中则是一个函数的地址,,还有像lpSecurityAttributes之类的,则是指向SECURITY_ATTRIBUTES结构的长指针(地址),lpvBuffer表示传递一个缓存(Buffer)长指针(lp)或者为空(void),还有一些没有前缀的则是这个词已经足够说明它的意思了。等等,熟悉这些前缀的含义可以让你在学习API的时候进行快速的掌握。并能排除一些错误。
为了更好的了解WINDOWS编程,这里我必须介绍几个基本的概念:
1,句柄:它是WINDOWS编程的基础。一个句柄是指WINDOWS在内存中使用的一个唯一的整数质,是一个4个字节长的数值,用于标识应用程序中不同对象和相同对象的不同实例。
这里我列出几种WINDOWS常用的句柄:
HWND: 标示窗口句柄
HINSTANCE:标示当前实例句柄
HCOURSOR:标示光标句柄
HFONT: 标示字体句柄
HPEN:标示画笔句柄
HBRUSH:标示画刷句柄
HDC:标示设备环境句柄
HB99vMP:标示位图句柄
HICON:标示图标句柄
HMENU:标示菜单句柄
HFILE:标示文件句柄
由于WINDOWS应用程序利用WINDOWS消息来与其它的WINDOWS应用程序及WINDOWS系统进行消息交换。所以消息是一个十分重要的对象它的结构如下。
typedef struct{
HWND hwnd; //检索消息的窗口句柄
UN99v message; //代表一个消息的消息质
WPARAM wParam; //消息附加信息的字参数
LPARAM lParam; //消息附加信息的长字参数
DWORD time; //消息入队时间
POINT pt; //消息发送时鼠标的位置 point.x;point.y;
} tagMSG;
2,消息:VC++中消息都用前缀标示消息所属的分类,下面我来介绍一下这些前缀
BM表示按钮控制消息
CB表示组合框控制消息
DM表示默认下压式按钮控制消息
EM表示编辑控制消息
LB表示列表框控制消息
SBM表示滚动条控制消息
WM表示窗口消息
现在我来对系统常用的一些消息进行说明:
1,WM_LBUTTONDOWN: 单击鼠标左键时产生
2,WM_LBUTTONUP: 放开鼠标左键时产生
3,WM_RBUTTONUP: 放开鼠标右键时产生
4,WM_LBUTTONBLCLK: 双击鼠标左键时产生
5,WM_RBUTTONBLCLK: 双击鼠标右键时产生
6,WM_KEYDOWN: 按下了一个非系统键时产生的消息
7,WM_CHAR: 同上
8,WM_CREATE: 由CreateWindow函数发出的消息
9,WM_DESTROY: 消除窗口时发出的消息
10,WM_QU99v: 退出程序时发送的消息
11,WM_PAINT: 做任何移动操作时发出的消息
介绍了以上的这些基础入门知识,我们就可以简单的了解一下WINDOWS API 程序的组成基本结构。它是由入口函数WinMain和窗口函数基本框架,并包含各种数据类型、数据结构与函数等应用组建组成的。其中入口函数WinMain和窗口函数是WINDOWS应用程序的主体。
一个基本的WinMain函数应该具有以下的功能:
1,注册窗口类,建立窗口及执行其他必要的初始化工作
2,进入消息循环,根据从应用程序消息队列接受的消息,调用相应的处理过程。
3,当消息循环检索到WM_QU99v消息时中止程序运行
WinMain函数有三个基本组成部分:函数说明、初始化和消息循环。
(1)函数说明
int WINAPI WinMain
(
HINSTANCE hThisInst, //应用程序当前实例句柄
HINSTANCE hPrevInst, //应用程序其它实例句柄
LPSTR lpszCmdLine, //指向程序命令行参数的指针
int nCmdShow //应用程序开始执行时窗口显示方式的整数值标示
)
(2)初始化
初始化包括窗口类的定义、注册、创建窗口实例和显示窗口四部分。(在以后的程序中我将详细的介绍它们具体的实现方法)
(3)消息循环
WINDOWS应用程序的运行是以消息为核心的。WINDOWS将产生的消息放入应用程序的消息队列中,而应用程序的WinMain函数从消息循环提取队列中的消息,并将其传递给窗口函数的相应过程处理。
它的基本写法如下:
MSG Meg;//定义消息
//(...)省略了一些内容
while (GetMessage(&Meg,NULL,0,0)
{
TranslanteMessage(&Meg);
DispatchMessage(&Meg);
}