您的位置:首页 > 其它

关于windowsx.h的介绍

2013-03-14 19:54 197 查看
很多初中级程序员用C/C++编写WindwosAPI的程序时,经常面对面条式的switch...case语句块

当你在Window过程(回调函数、下称过程)中加入大量诸如WM_COMMAND orWM_CHAR的消息捕获时。真是一场噩梦。

关于上千行代码的Window过程的问题,随着 C/C++ 7.0 编译器和Windows SDK for Windows3.1发行时带的一个头文件而被解决。

这个头文件是 <windowsx.h>以及所包含的大量的有用的宏。按照微软的说法:这些头文件所带来的便利可重复用于下面这些地方(Groups)



.在C程序中使用STRICT宏进行严格的类型检查。

.在windows程序中用宏简化公共性操作。

.使用控件宏同windows控件进行通讯。

.windows环境下的消息解析器(messagecrackers)(是一个方便的、可移植的、类型安全的处理消息的方法)以及和他相关的参数和返回值



因为消息解析器向导是用于消息解析器的,其他由这头文件带来的一些有用的宏,我就跳过不讲了,如果你想看看关于

WINDOWSX.H的简要介绍,可以看 MS Knowledge Base Article #83456.

(http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q83/4/56.asp)

好,让我们说下消息解析器的优点,当然也包括为什么这里提供的这个工具是如此有用。

当你使用W32SDK编程,用windows过程(通常叫做WndProc)处理窗口和对话框消息时,使用swich-case来捕获你需要处理的消息是

非常普遍的做法。假设你想处理WM_COMMAND, WM_KEYUP, WM_CLOSE andWM_DESTROY消息,你是这样作的:

LRESULT CALLBACK MainWndProc (HWND hwnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

case WM_COMMAND:

// ...

break;

case WM_KEYUP:

// ...

break;

case WM_CLOSE:

// ...

break;

case WM_DESTROY:

//...

break;

default:

return DefWindowProc(hwnd, msg, wParam, lParam);

}

}

这是自从Windows1.0诞生以来处理消息最常见的风格了。而且很肯定,它工作得很好。

但问题是,当你加入一个或多个复杂的特色到你的程序中时,如MDI,OLE 公共控件等等,

结果形成了一个上千行的Window过程,你开始用PageDn和PageUp来查找你想要修改的消息处理代码了。

消息解析器的第一个好处就是:他把面条式的case标签转换成类似MFC中易于维护和处理的函数。

第二个好处是:处理函数中合适的参数。你可以简单使用switch(id)代替原先的switch(LOWORD(wparam)),

因为消息解析器传递给你的是 "已解析 "的参数,他等价于LOWORD(wparam)。

HANDLE_MSG 这个消息处理宏在windowx.h中的定义如下:

#define HANDLE_MSG(hwnd, message, fn) \

case (message) : return HANDLE_##message((hwnd), (wParam),(lParam), (fn))

你想要把你的代码做成 "消息解析 "版的,你需要提供一个解析宏HANDLE_MSG及其函数来处理你的消息.

在window过程里HANDLE_MSG宏需要三个参数:窗口句柄(hwnd),消息(WM_XXXX),处理你消息的函数(function)。

为更好地解释这个:看下面,我们把上面那段代码转换成了下面的代码:

LRESULT CALLBACK MainWndProc (HWND hwnd, UINT msg, WPARAM wParam,LPARAM lParam)

{

switch(msg)

{

HANDLE_MSG (hwnd, WM_COMMAND, OnCommand);

HANDLE_MSG (hwnd, WM_KEYUP, OnKeyup);

HANDLE_MSG (hwnd, WM_CLOSE, OnClose);

HANDLE_MSG (hwnd, WM_DESTROY, OnDestroy);

default:

return DefWindowProc(hwnd, msg, wParam, lParam);

}

}

哇,太好了,紧凑且易于管理的window过程。现在你可以去定义你的消息处理函数了(OnKeyUp, OnClose, andOnDestroy)

还有一个真正的好处,你可以在visual studio IDE 环境中直接跳转到消息处理函数。

图片:...(看原文)

有个问题是:当你每加入一个消息处理,你必须在windowx.h中查找相关参数的定义。

因为消息处理参数的格式是明确的而不能由你随心所欲。但在头文件中进行重复搜索是乏味且易出错的。

消息解析向导工具用于解决这个:他允许你粘贴你需要的函数参数,

而你如果只是打草稿,他也会在在你消息处理中写上一个模板化的window或对话框过程 (??这句有疑问)

消息前驱宏(message fowarding): WINDOWSX.H 的另一个特色 (消息前向?)

WINDOWSX.H另一个特色是消息前驱的可能性,

它是用于 "解压 "消息处理参数到其他函数调用(如PostMessage, SendMessage,CallWindowProc等)所需要的合适的WPARAM和LPARAM值。

假设我们想用SendMessage发送一个WM_COMMAND消息到父窗口, "模拟"一个在名为IDC_USERCTL控件上的双击(通过发送BN_DBLCLK的通知码)

我们通常这么做的:

SendMessage (hwndParent, WM_COMMAND,

MAKEWPARAM(IDC_USERCTL, BN_DBLCLK),

(LPARAM)GetDlgItem(hwnd, ID_USERCTL));

这是相当复杂的语法。SendMessage希望WPARAM参数的低字是控件ID而高字是通知码,LPARAM参数是控件句柄,句柄我们通过GetDlgItem这

个API函数得到。

上述代码可以被转换为WINDOWSX.H的消息前驱宏,FORWARD_WM_xxxxx。

对于每个消息,消息前向宏用同样的方式 "打包 "消息解析向导创建的函数参数,

并且传递给你的处理函数 "已解压 "的参数(LPARAM/WPARAMs)。

例如:对于一个myWnd窗口的WM_COMMAND消息,消息解析器向导将生成如下的函数原形:

void myWnd_OnCommand (HWND hwnd, int id, HWND hwndCtl, UINTcodeNotify)

那么,这些解析的参数也同样用于消息前驱宏,这样上面那使人混乱的SendMessage调用可以简化为:

FORWARD_WM_COMMAND (hwndParent, IDC_USERCTL,

GetDlgItem(hwnd, ID_USERCTL), BN_DBLCLK, SendMessage
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: