如何更改 MessageBox 窗口(添加控件并更改文本)?
本文描述了如何更改 MessageBox 窗口(添加控件和更改文本)。
引言
在本文中,我们将学习如何向 MessageBox 添加控件或更改其按钮文本。您可以使用此方法创建(完整的)多语言程序(只是一个建议!)。有几种方法可以做到这一点,我选择了钩子方法。
钩子 MessageBox 的步骤
钩子 MessageBox
- 使用
SetWindowsHookEx ()
函数,参数为WH_CALLWND
,并将其传递给 hookproc。 - 声明一个钩子过程。
- 在 hookproc 中,使用
SetWindowLong ()
函数来处理 MessageBox 窗口创建过程(也许这是一个好名字)。 - 声明一个
CALLBACK
函数来处理 MessageBox 窗口创建过程。 - 将
CALLBACK
函数作为SetWindowLong ()
函数的new long
参数传递。 - 最后,将您的代码放在
CALLBACK
函数中(用于窗口创建的代码)。
SetWindowsHookEx() 函数
此函数安装一个钩子过程。使用此函数,您可以钩住窗口事件。换句话说,当您安装钩子过程时,您就是在告诉系统在调用所需事件时通知您。
根据 MSDN 的说法: SetWindowsHookEx
函数将应用程序定义的钩子过程安装到钩子链中。您会安装一个钩子过程来监视系统中的某些类型的事件。这些事件与特定线程或与调用线程的同一个桌面中的所有线程相关。
如何使用 SetWindowsHookEx() 函数安装钩子过程?
g_hHook = SetWindowsHookEx (WH_CALLWNDPROC, (HOOKPROC)SetHook, NULL, GetCurrentThreadId ());
其中 g_hHook
是一个全局变量,SetHook
是我的 HookProc;
什么是 WH_CALLWNDPROC?
使用此参数安装一个钩子过程,该过程在系统将消息发送到目标窗口过程之前监视消息(MSDN)。
声明 HookProcedure
在您的头文件中使用以下声明
LRESULT CALLBACK SetHook(int nCode,WPARAM wParam,LPARAM lParam);
这将声明一个名为 SetHook
的钩子过程。请参阅此代码片段
LRESULT CALLBACK SetHook(int nCode,WPARAM wParam,LPARAM lParam) { if (nCode==HC_ACTION) { CWPSTRUCT* pwp = (CWPSTRUCT*)lParam; if (pwp->message==WM_INITDIALOG) oldProc=(WNDPROC)SetWindowLong(pwp>hwnd, GWL_WNDPROC,(LONG)HookWndProc); } return CallNextHookEx(g_hHook,nCode,wParam,lParam); }
此代码片段是我的 SetHook
过程。
什么是 GWL_WNDPROC?
此参数为窗口过程设置新的地址。(我认为这足够了)。
什么是 CWPSTRUCT?
这是一个结构,包含有关窗口消息的信息,例如窗口的句柄(hwnd
)。我们传递该结构的指针以在回调函数中使用 hwnd
成员。
而 HookWndProc
是一个处理窗口创建代码的函数。
处理窗口创建过程
为此,您必须声明一个 CALLBACK
函数。
LRESULT CALLBACK HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
这是我的 HookWndProc
过程。
LRESULT CALLBACK HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { //Let OS to perform basic operation LRESULT rc = CallWindowProc( oldProc, hWnd, uMsg, wParam, lParam ); //If MessageBox wanted to initialized, do something if (uMsg==WM_INITDIALOG) { if (m_hIcon) SetIcon(hWnd,m_hIcon); CreateButton(hWnd); if (m_strCaption) SetCaption(hWnd); } if (uMsg==WM_COMMAND&&wParam==IDC_CHECKBOX) //If user clicked the check box handle it! SetOut(wParam); if (uMsg==WM_NCDESTROY) //On exit Uninstall the hook procedure //If we don't do that every message box will have //A check box on it! UnInstallHook(g_hHook); return rc; }
主要操作已完成。我的意思是 hwnd
。在获得此 hwnd
后,我们可以对 MessageBox 窗口执行任何操作。但别忘了调用 CallWindowProc
函数。
CallWindowProc
是做什么的?
根据 MSDN: CallWindowProc
函数将消息信息传递给指定的窗口过程。
我使用此函数是因为我不想自己绘制 MessageBox 窗口,而只想更改一些文本。如果您想绘制主窗口,我认为您不应该调用此函数!
有关 SetWindowsHookEx
、SetWindowLong
和 CallWindowProc
的更多信息,请使用 MSDN Library。(我认为这是最好的参考资料)。
最后,我想提醒您:调用 CallNextHookEx ()
函数,因为如果您不这样做,其他可能已安装钩子链的应用程序将不会收到钩子信息,我知道您不希望这样。
像往常一样,根据 MSDN 的说法:调用 CallNextHookEx
函数链接到下一个钩子过程是可选的,但强烈推荐;否则,已安装钩子的其他应用程序将收不到钩子通知,并可能因此行为不当。您应该调用 CallNextHookEx
,除非您绝对需要阻止其他应用程序看到通知。
最后的话
首先,我要感谢 Nicolas Bonamy 先生。他的文章对我帮助很大。
有一个演示应用程序,如果您愿意,可以下载。在该项目中,我有一个类,其中包含一些用于向 MessageBox 添加 CheckBox、更改按钮文本以及用于将控件放置在正确且良好位置的一些函数。
我想说我的英语不太好,这也是我写一些函数 MSDN Library 定义的原因(请原谅我的糟糕语法)。
最后,我建议您使用 Visual Assist X,因为它是一个非常有用的 Visual Studio 插件。
如果您觉得本文有趣且信息丰富,请投我一票。欢迎提出意见和评论。
G.K.Z - King Zoser。