Notes of Visual C++ 6.0
1. 资源符号
表格 1 资源符号定义的常用前缀
类别 | 资源符号前缀 | 代表的资源或对象 |
资源 | IDR_ IDD_ IDC_ IDI_ IDB_ | 加速键或菜单及相关资源 对话框资源 光标资源 图标资源 位图资源 |
菜单项命令控制 | IDM_ ID_ IDC_ | 菜单项 命令项 控件 |
字符串 | IDS_ IDP_ | 字符串表中的字符串 消息框中使用的字符串 |
2. API(Application Programming Interface)是应用程序编程接口的缩写。Windows API是Windows系统和Windows应用程序间的标准程序接口。
根据Windows API完成的功能,可将其分为三类:
l 窗口管理函数:实现窗口的创建、移动和修改功能;
l 图形设备(GDI)函数:实现与设备无关的图形操作功能;
l 系统服务函数:实现与操作系统有关的多种功能。
到目前为止,Microsoft已经发布了几个Windows API版本,其中WIN32用于Windows NT,Windows 98的API接近于WIN32。
3. 句柄和Windows消息
l 句柄(handle)是整个Windows编程的基础。一个句柄是指Windows使用的一个唯一的整数值,是一个4字节长的数值,用于标识应用程序中不同的对象和同类对象中不同的实例,诸如一个窗口、按钮、图标、滚动条、输出设备、控件或者文件等。应用程序通过句柄能够访问相应的对象信息。
l Windows应用程序Windows消息(Message)与其他的Windows应用程序及Windows系统进行信息交换。
Windows中消息由三部分组成:消息号、字参数和长字参数。消息号由事先定义好的消息名标识;字参数(wParam)和长字参数(lParam)用于提供消息的附加信息,附加信息的含义与具体消息号的值有关。在Windows中,消息往往用一个结构体MSG来表示,结构体MSG的定义如下:
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
}MSG;
其中:
l hwnd是用以检索消息的窗口句柄,若此参数为null,则可检索所有驻留在消息队列中的消息。
l message是代表一个消息的消息值,每个Windows消息都有一个消息值,该值由windows.h头文件中的宏定义来标识。
l wParam和lParam是包含有关消息的附加信息,它随不同的消息而有所不同。
l time指定消息送至队列的时间。
l pt指定消息发送时,屏幕光标的位置。pt的数据POINT也是一个结构体,POINT的定义如下:
typedef struct tagPOINT
{
LONG x,y; //x和y分别表示屏幕的横坐标和纵坐标
}POINT;
4. 系统定义的消息前缀如下:
l BM表示按钮控制消息
l CB表示组合框控制消息
l DM表示默认下压式按钮控制消息
l EM表示编辑控制消息
l LB表示列表框控制消息
l WM表示窗口消息
5. Windows应用程序的组成
表格 2 Windows应用程序五种文件的扩展名及类型
扩展名 | 文件类型 | 备注 |
.c或.cpp | C语言源程序文件 |
|
.H | 头文件 | 头文件包含源程序文件需要的外部常量、变量、数据结构和函数及其说明 |
.DEF | 模块定义文件 | 模块定义文件定义程序模块的属性,在Windows95/98中,该文件可省略 |
.RC | 资源描述文件 | 资源描述文件定义源程序使用的资源 |
.MAK | 工程文件 | 各种源程序文件编译后生成工程文件,经进一步编译成为可执行文件 |
6. 源程序组成结构
Windows的应用程序具有相对固定的基本结构,其中由入口函数WinMain和窗口函数构成基本框架,并包含各种数据类型、数据结构与函数等。入口函数WinMain和窗口函数是Windows应用程序的主体。
1) WinMain函数
WinMain函数是所有Windows应用程序的入口,类似C语言中的Main函数,其功能是完成一系列的定义和初始化工作,并产生消息循环。消息循环是整个程序运行的核心。
WinMain函数实现以下功能:
l 注册窗口类,建立窗口及执行其他必要的初始化工作。
l 进入消息循环,根据从应用程序消息队列接收的消息,调用相应的处理过程。
l 当消息循环检索到WM_QUIT消息时终止程序运行。
WinMain函数有三个基本的组成部分:函数说明、初始化和消息循环。
(1). 函数说明
WinMain函数的说明如下:
Int WINAPI WinMain
(
HINSTANCE hThisInst, //应用程序当前实例句柄
HINSTANCE hPrevInst, //应用程序其他实例句柄
LPSTR lpszCmdLine, //指向程序命令行参数的指针
int nCmdShow //应用程序开始执行时窗口显示方式的整数值标识
)
Windows系统将应用程序每一次执行称为该应用程序的一个实例(instance),并使用一个实例句柄来唯一地标识它。
(2) 初始化
初始化包括窗口类的定义、注册。创建窗口实例和显示窗口四部分。
a)窗口类定义
在Windows应用程序中,窗口类定义了窗口的形式与功能。窗口类定义通过给窗口类数据结构WNDCLASS赋值完成,该数据结构中包含窗口类的各种属性。窗口定义常用以下函数:
l LoadIcon函数
LoadIcon函数的作用是在应用程序中加载一个窗口图标。其原型为:
HICON LoadIcon
(
HINSTANCE hInstance, //图标资源所在的模块句柄;如为NULL,则使用系统预定义图标
LPCTSTR lpIconName //图标资源名或系统预定义图标标识名
)
l LoadCursor函数
LoadCursor函数的作用是在应用程序中加载一个窗口光标。其原型为:
HCURSOR LoadCursor
(
HINSTANCE hInstance, //光标资源所在的模块句柄;如为NULL,则使用系统预定义光标
LPCTSTR lpCursorName //光标资源名或系统预定义光标标识名
)
l GetStockObject函数
应用程序还经常调用函数GetStockObject获取系统提供的背景刷,其原型为:
HBRUSH GetStockObject(int nBrush); //nBrush为系统提供的背景刷的标识名
b) 注册窗口类
Windows系统本身提供部分预定义的窗口类,程序员也可以自定义窗口,窗口类必须先注册后使用。窗口类的注册由函数RegisterClass()实现。其形式为:
RegisterClass(&wndclass); //wndclass为窗口类结构
RegisterClass函数的返回值为布尔型,注册成功则返回值为真。
c) 创建窗口
创建一个窗口类的实例由函数CreateWindows()实现,该函数的原型为:
HWND CreateWindow
(
LPCTSTR lpszClassName, //窗口类名
LPCTSTR lpszTitle, //窗口标题名
DWORD dwStyle, //创建窗口的样式,常用窗口样式如表3所示
int x, //窗口左上角横坐标
int y, //窗口左上角纵坐标
int nWidth, //窗口宽度
int nHeight, //窗口高度
HWND hwndParent, //该窗口的父窗口句柄
HMENU hMenu, //窗口主菜单句柄
HINSTANCE hInstance, //创建窗口的应用程序当前句柄
LPVOID lpParam //指向一个传递给窗口的参数值的指针
)
表格 3 常用窗口样式
标识 | 说明 |
WS_BORDER | 创建一带边框的窗口 |
WS_CAPITION | 创建一带标题栏的窗口 |
WS_HSCROLL | 创建一带水平滚动条的窗口 |
WS_MAXMIZEBOX | 创建一带最大化按钮的窗口 |
WS_MAXMIZE | 创建一带最大化的窗口 |
WS_MINMIZEBOX | 创建一带最小化按钮的窗口 |
WS_MINMIZE | 创建一带最小化的窗口 |
WS_OVERLAPPED | 创建一带边框和标题栏的窗口 |
WS_OVERLAPPEDWINDOW | 创建一带边框、标题栏、系统菜单及最大、最小化按钮的窗口 |
WS_POPUP | 创建一弹出式窗口 |
WS_POPUPWINDOW | 创建一带边框和系统菜单的弹出式窗口 |
WS_SYSMENU | 创建一带系统菜单的窗口 |
WS_VSCROLL | 创建一带垂直滚动条的窗口 |
d) 显示窗口
窗口类的显示由ShowWindow和UpdateWindow函数实现。应用程序调用ShowWindow函数在屏幕上显示窗口,其形式为:
ShowWindow(hwnd,nCmdShow);
其中,hwnd为窗口句柄,nCmdShow为窗口显示形式标识,表4列出了常用显示形式标识及其说明。
表格 4 常用显示形式标识及其标识说明
标识 | 说明 |
SW_HIDE | 隐藏窗口 |
SW_SHOWNORMAL | 显示并激活窗口 |
SW_SHOWMINIMIZE | 显示并最小化窗口 |
SW_SHOWMAXIMIZE | 显示并最大化窗口 |
SW_SHOWNOACTIVE | 显示但不激活窗口 |
SW_RESTORE | 恢复窗口的原来位置及尺寸 |
显示窗口后,应用程序常常调用UpdateWindow函数更新并绘制用户区,并发出WM_PAINT消息。其形式为:UpdateWindow(hwnd);
(3) 消息循环
Windows应用程序的运行以消息为核心。Windows将产生的消息放入应用程序的消息队列中,而应用程序的WinMain函数从消息循环提取队列中的消息,并将其传递给窗口函数的相应过程处理。
消息循环的常见格式如下:
MSG Msg;
…
while(GetMessage(&Msg,NULL,0,0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
其中,函数GetMessage的作用是从消息队列中读取一条消息,并将消息放在一个MSG结构中。其形式为:
GetMessage
(
lpMSG; //指向MSG结构的指针
hwnd,
nMsgFilterMin, //用于消息过滤的最小消息号值
nMsgFilterMax //用于消息过滤的最大消息号值
)
通过设置参数nMsgFilterMin和nMsgFilterMax可实现消息的过滤,即仅处理所确定的消息号范围内的消息。如果两个参数都为0,则不过滤消息。
TranslateMessage函数负责将消息的虚拟键转换为字符信息,其形式为:
TranslateMessage(lpMSG);
DispatchMessage函数将参数lpMSG指向的消息传送到指定窗口函数,其形式为:
DispatchMessage(lpMSG);
当GetMessage函数返回零值,即检索到WM_QUIT消息时,程序将结束循环并退出。
2) 窗口函数
窗口函数是应用程序处理接收到的消息的函数,其中包含了应用程序对各种可能接收到的消息的处理过程。
窗口函数的一般形式如下:
LRESULT CALLBACK WndProc
(
HWND hwnd, //窗口句柄
UINT message, //代表所处理消息的消息值
WPARAM wParam, //消息的附加参数
LPARAM lParam //消息的附加参数
)
{
…
switch(message)
{
case…
…
break;
…
case WM_DESTROY:
PostQuitMessage(0);
default:
return DefWindowProc(hwnd,message,wParam,lParam);
}
return(0);
}
程序员只需根据窗口可能收到的消息在case语句中编写相应的处理程序段即可。
其中,一般有对消息WM_DESTROY的处理,该消息是关闭窗口时发出的。一般情况下,应用程序调用函数PostQuitMessage响应这条消息。PostQuitMessage函数的原型如下:
void PostQuitMessage(int nExitCode); //nExitCode为应用程序退出代码
函数PostQuitMessage的作用是向应用程序发出WM_QUIT消息,请求退出。除此之外,应用程序通过在消息处理程序段中加入如下语句,为未定义处理过程的消息提供
默认处理:
default:return DefWindowProc(hwnd,message,wParam,lParam);
函数DefWindowProc是系统默认的处理过程,以保证所有发送到该窗口的消息均得以处理。
3) 数据类型
Windows.h是用户调用系统功能的关键,该文件中定义了Windows系统使用的数据类型,其中包括许多简单类型和结构。
表格 5 常用的部分Windows数据类型及其说明
数据类型 | 说明 |
WORD | 16位无符号整数 |
LONG | 32位有符号整数 |
DWORD | 32位无符号整数 |
HANDLE | 句柄 |
UINT | 32位无符号整数 |
BOOL | 布尔值 |
LPISTR | 指向字符串的32位指针 |
LPCTSTR | 指向字符串常量的32位指针 |
4) 数据结构
(1)MSG
数据结构MSG中包含一个消息的全部信息,既是消息发送的格式,也是Windows编程最基本的数据结构之一。
(2)WNDCLASS
结构WNDCLASS包含一个窗口类的全部信息,也是Windows编程中使用的基本数据结构之一。应用程序通过定义一个窗口类确定窗口的属性。其定义如下:
typedef struct tagWNDCLASS
{
UINT style; //窗口类的样式,一般设置为0
WINDPROC lpfnWndProc; //指向窗口函数的指针
Int cbClsExtra; //分配在窗口类结构后的字节数
Int cbWndExtra; //分配在窗口实例后的字节数
HINSTANCE hInstance; //定义窗口类的应用程序的实例句柄
HICON hIcon; //窗口类的图标
HCURSOR hCursor; //窗口类的光标
HBRUSH hbrBackground; //窗口类的背景刷
LPCTSTR lpszMenuName; //窗口类菜单资源名
LPCTSTR lpszClassName; //窗口类名
}WNDCLASS;
(3)POINT
POINT结构定义了屏幕上或窗口中的一个点的X坐标和Y坐标。POINT结构也是应用程序中最常用的结构之一。
(4) RECT
RECT结构定义了一个矩形区域,其中包含该矩形区域的左上角和右下角两个点的X坐标和Y坐标。其定义如下:
typedef struct tagRECT
{
LONG left; //矩形框左上角X坐标
LONG top; //矩形框左上角Y坐标
LONG right; //矩形框右下角X坐标
LONG bottom; //矩形框右下角Y坐标
}RECT;
7. Windows图形设备接口(GDI,Graphics Device Interface)具有设备无关性
GDI基本概念:
设备描述表(Device Context)是一个用来确定任何设备的GDI输出的位置和形象的属性的集合。应用程序并不能直接存取设备描述表,但是,应用程序可以使用设备描述表的句柄来间接地存取设备描述表及其属性。当程序为设备描述表要求一个句柄时,就将创建一个设备描述表。
表格 6 设备描述表属性及相关函数
属性 | 默认值 | 相关函数 |
背景色 | WHITE | GetBkColor SetBkColor |
背景模式 | OPAQUE | GetBkMode SetBkMode |
位图 | NONE | CreateBitMap CreateBitMapIndirect CreateCompatibleBitMap SelectObject |
画刷 | WHITE_BRUSH | CreateBrushIndirect CreateDIBPatternBrush CreateHatchBrush CreatePatternBrush CreateSolidBrush SelectObject |
画刷起始位置 | (0,0) | GetBrushOrg SetBrushOrg UnrealizeObject |
剪截域 | DISPLAY SURFACE | ExcludeClipRect IntersectClipRect OffsetClipRgn SelectClipPath SelectObject SelectClipRgn |
颜色调色板 | DEFAULT_PALETTE | CreatePalette RealizePalette SelectPalette |
当前笔的位置 | (0,0) | GetCurrentPosition LineTo PolyLineTo MoveTo |
绘图模式 | R2_COPYPEN | GetROP2 SetROP2 |
字体 | SYSTEM_FONT | CreateFont CreateFontIndirect SelectObject |
字符间距 | 0 | GetTextCharacterExtra SetTextCharacterExtra |
映像模式 | MM_TEXT | GetMapMode SetMapMode |
画笔 | BLACK_PEN | CreatePen CreatePenIndirect SelectObject |
多边形填充模式 | ALTERNATE | GetPolyFillMode SetPolyFillMode |
缩放模式 | BLACKONWHITE | SetStretchBltMode GetStretchBltMode |
文本颜色 | BLACK | GetTextColor SetTextColor |
视图范围 | (1,1) | GetViewportExt SetMapMode SetViewportExt ScaleViewportExt |
视图原点 | (0,0) | GetViewportOrg OffsetViewportOrg SetViewportOrg |
窗口范围 | (1,1) | GetWindowExt SetMapMode SetWindowExt ScaleWindowExt |
窗口原点 | (0,0) | GetWindowOrg OffsetWindowOrg SetWindowOrg |