Windowsx.h 港控/mmm° 2021-11-17 21:22 200阅读 0赞 先安装Visual C++,再安PlatForm SDK,安装完之后点Visual Studio Registration. Registration之后,就可以编译源程序了, 自己编译时,注意它的源代码的后缀名为".cpp",不是".c".否则会产生很多错误. 关于第一章中的一些问题, windowsx.h头文件:(全部都是网上查的) http://www.codeproject.com/win32/msgcrackwizard.asp 第一部分: 介绍: WINDOWSX.H 头文件为W32SDK的程序员提供方便(工具?) 很多初中级程序员用C/C++编写Windwos API的程序时,经常面对面条式的switch...case语句块 当你在Window过程(回调函数、下称过程)中加入大量诸如WM\_COMMAND or WM\_CHAR的消息捕获时。真是一场噩梦。 关于上千行代码的Window过程的问题,随着 C/C++ 7.0 编译器和Windows SDK for Windows 3.1发行时带的一个头文件而被解决。 这个头文件是 以及所包含的大量的有用的宏。按照微软的说法:这些头文件所带来的便利可重复用于下面这些地方(Groups) : .在C程序中使用STRICT宏进行严格的类型检查。 .在windows程序中用宏简化公共性操作。 .使用控件宏同windows控件进行通讯。 .windows环境下的消息解析器(message crackers)(是一个方便的、可移植的、类型安全的处理消息的方法)以及和他相关的参数和返回值。 因为消息解析器向导是用于消息解析器的,其他由这头文件带来的一些有用的宏,我就跳过不讲了,如果你想看看关于 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) 好,让我们说下消息解析器的优点,当然也包括为什么这里提供的这个工具是如此有用。 当你使用W32 SDK编程,用windows过程(通常叫做WndProc)处理窗口和对话框消息时,使用swich-case来捕获你需要处理的消息是 非常普遍的做法。假设你想处理WM\_COMMAND, WM\_KEYUP, WM\_CLOSE and WM\_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, and OnDestroy) 还有一个真正的好处,你可以在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), // WPARAM 的低16位是控件ID,高16位是通知码 (LPARAM)GetDlgItem(hwnd, ID\_USERCTL)); //LPARAM 为控件句柄 这是相当复杂的语法。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, UINT codeNotify) 那么,这些解析的参数也同样用于消息前驱宏,这样上面那使人混乱的SendMessage调用可以简化为: FORWARD\_WM\_COMMAND (hwndParent, IDC\_USERCTL, GetDlgItem(hwnd, ID\_USERCTL), BN\_DBLCLK, SendMessage); 使用所有这些消息解析器支持的消息简单可行。(第一部分完) 在使用消息分流器来处理一个消息之前,应该打开Wi n d o w s X . h文件并搜索要处理的消息。例如,如果搜索W M \_ C O M M A N D,将会找到文件中包含下面代码行的部分: /\* void Cls\_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) \*/ \#define HANDLE\_WM\_COMMAND(hwnd, wParam, lParam, fn) / ((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), (UINT)HIWORD(wParam)), 0L) \#define FORWARD\_WM\_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) / (void)(fn)((hwnd), WM\_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl)) 第一行是注释行,展示要编写的函数原型。下一行是H A N D L E \_ W M \_ \*宏,我们已经讨论过。最后一行是消息转发器( f o r w a r d e r)。假定在你处理W M \_ C O M M A N D消息时,你想调用默认的窗口过程,并让它为你做事。这个函数应该是这个样子: void Cls\_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) \{ //Do some normal processing. //Do default processing. FORWARD\_WM\_COMMAND(hwnd, id, hwndCtl, codeNotify, DefWindowProc); \} F O RWA R D \_ W M \_ \*宏将分流开的消息参数重新构造成等价的w P a r a m和l P a r a m。然后这个宏再调用你提供的函数。在上面的例子中,宏调用D e f Wi n d o w P r o c函数,但你可以简单地使用S e n d M e s s a g e或P o s t M e s s a g e。实际上,如果你想发送(或登记)一个消息到系统中的任何窗口,可以使用一个F O RWA R D \_ W M \_ \*宏来帮助合并各个参数。 应注意Windows.h和Windowsx的不同之处. 2.tchar.h 头文件 http://msdn2.microsoft.com/zh-cn/library/c426s321(VS.80).aspx 3.CmnHdr.h 头文件 它包含宏及链接程序指令. 读者要想建立本书的示例程序,必须要对编译程序和链接程序的开关选项进行设置,笔者已经将设置方面的细节 放在了CmmHdr.h头文件中了 因为无法将所有的设置都放在这个头文件里,我们对每个示例程序的项目设置做了一些改变。对每个项目,我们显示Project Settings对话框,然后做下面所说的改变。 • 在G e n e r a l栏,设定Output Files目录,这样所有最终的. e x e和. d l l文件都在一个目录之下。 • 在C / C + +栏,选择Code Generation 条目,并对Use Run-Time Library 字段选择Multithreaded DLL。 注意要对每个项目的D e b u g建立和R e l e a s e建立都做上述两个改变。 所有的示例程序都要包含C m m H d r. h头文件,并且要在其他头文件之前包含.这是因为CmnHdr.h头文件中有一些链接程序指令,比如\#define \_WIN32\_WINNT 0x0500 (它是Windows版本建立选项)的定义必须放在Windows.h之前,才能调用了Microsoft Windows 2000中提供的新函数.否则编译程序将产生错误。微软用\_ W I N 3 2 \_ W I N N T符号来保护这些函数,以使程序员开发的应用程序能够运行在Windows 98及Windows NT的多个版本上。 Unicode建立选项. 笔者编写的所有这些示例程序既可按A N S I来编译,也可按U n i c o d e来编译。当针对x 8 6 C P U体系结构来编译这些程序时, A N S I为默认选择,这样程序可以在Windows 98上执行。但对其他C P U体系结构建立程序就要用U n i c o d e,这样程序可以占用较少的内存,并且执行得更快。 为了对x 8 6体系结构建立U n i c o d e版本,只需将定义U N I C O D E的那一行代码的注释符去掉,并重建程序。通过在CmnHd r. h定义U N I C O D E宏,可以很容易地控制如何建立示例程序。关于U n i c o d e的详细内容,可参见第2章。 窗口定义和第四级警告 本节我确保警告级设定为3,而且C m nH d r. h包含标准的Wi n d o w s . h头文件。当包含了Wi n d o w s . h时,在我编译其余代码时就设置第4级警告。在第4级警告上,编译程序对那些我不认为有问题的内容发出“警告”,这样我通过使用\#pragma warning指令显式地告诉编译程序忽略某些良性的警告错。 Pragma消息帮助宏 使用chMsg宏,例如\#pragma chMSG(Fix this later),这个宏让编译程序输出源代码文件的名字,以及p r a g m a出现的行号。使用Microsoft Visual Developer Studio,在输出窗口上双击这一行,将会自动定位到相应文件的确切位置上。还有一个方便之处, c h M S G宏不要求对文本串使用引号。. chINRANGE和chDIMOF宏 chINRANGE 宏用来查看一个数值是否在另外两个数值之间. chDIMOF只是返回一个数组中元素的数目,这个宏是用s i z e o f操作符先计算整个数组的字节数,然后再用这个数除以数组中一个数据项所占的字节数,从而得出结果。 chBEGINTHREADEX宏 多线程示例程序都使用了微软的C/C + +运行时函数库中的\_ b e g i n t h r e a d e x函数,而不是操作系统的C r e a t e T h r e a d函数。我使用这个函数是因为\_ b e g i n t h r e a d e x函数为新线程做好了准备,使新线程能够使用C / C + +运行时函数库中的函数,而且还因为它保证在线程返回时清除每个线程的C / C + +运行时库信息. 尽管\_ b e g i n t h r e a d e x函数用的参数值同C r e a t e T h r e a d函数用的参数值是一样的,但二者的参数的数据类型都不相匹配。 为了避免编译程序警告,我在C m n H d r. h中定义了一个c h B E G I N T H RE A D E X宏,替我执行所有这些转换: chMB宏 c h M B宏只是显示一个消息框。消息框的标题是调用进程可执行代码的全路径名 chASSERT和chVERIFY宏 在我开发这些示例程序时,为了查找潜在的问题,我在整个代码中多处使用c h A S S E RT宏。这个宏测试由x所标识的表达式是否为T R U E,如果不是,则显示一个消息框指出失败的文件、行和表达式。在程序的发行建立中,这个宏什么也不做。c h V E R I F Y宏与c h A S S E RT宏差不多,区别在于不论是调试建立(debug build)还是发行建立(release build),c h V E R I F Y都要对表达式进行测试。 chHANDLE\_DLGMSG宏 当你通过对话框使用消息分流器时,不应该使用微软的Wi n d o w s X . h 头文件中的H A N D L E \_ M S G宏,因为这个宏并不能返回T R U E或FA L S E来指出消息是否由对话框的过程来处理。我定义的c h H A N D L E \_ D L G M S G宏会通知窗口消息的返回值,适当地处理返回值,以便在一个对话框过程中使用。 chSETDLGICONS宏 由于多数示例程序使用一个对话框作为主窗口,你必须手工改变对话框图标,以便让它正确地显示在Ta s k b a r(任务条)、任务切换窗口和程序本身的标题上。当对话框接收到一个W M \_ I N I T D I A L O G消息时,总要调用c h S E T D L G I C O N S宏,以正确设置图标。 OS版本检查内联函数 本书的大多数示例程序可运行在所有平台上,但也有一些程序要求一些Windows 95和Windows 98所不支持的特性,有些程序要求一些只在Windows 2000中提供的特性。每个程序在初始化时要检查宿主系统的版本,如果要求更适用的操作系统时,就显示一个通知。 对那些不能在Windows 95和Windows 98上运行的程序,你会看到,在程序的\_ t Wi n M a i n函数中有一个对Wi n d o w s 9 x N o t A l l o w e d函数的调用。对于要求Windows 2000的示例程序,你会看到在程序的\_ t Wi n M a i n函中有一个对c h Wi n d o w s 2 0 0 0 R e q u i r e d函数的调用。 确认宿主系统是否支持Unicode 有一种办法能够知道我的程序是对U n i c o d e建立的,但可能在Windows 98系统上运行。所以我建立了一个CUnicodeSupported C++类。这个类的构造函数只是检查宿主系统是不是对U n i c o d e有良好的支持,如果不是,就显示一个消息框,并且进程结束。 读者会看到在C m n H d r. h中,我建立了这个类的一个全局的静态实例。当我的程序启动时,C / C + +运行时库启动代码调用这个对象的构造函数。如果这个构造函数检测到操作系统完全支持U n i c o d e,构造函数返回而程序继续执行。通过建立这个类的全局实例,我不需要在每个示例程序的源代码模块中再增加特殊的代码。对于非U n i c o d e的程序建立,不需要声明或实例化上述的C + +类。让程序只管运行就是。 强制链接程序寻找(w)WinMain进入点函数 我在C m n H d r. h中加入了一个p r a g m a,强制链接程序去寻找( w ) Wi n M a i n进入点函数,即使是用Visual C++建立了一个Win32 ConsoleA p p l i c a t i o n项目. 转载于:https://www.cnblogs.com/maqiang/archive/2012/08/04/2622734.html
还没有评论,来说两句吧...