我正在Win32 api中创建一个自定义消息框。所以,我按照here的教程创建了钩子程序和事物。
我成功更改了按钮文字,但是,当我在消息框上绘制一个复选框时,我按下其中一个消息框按钮,该复选框被绘制到主窗口上!
我的代码:
typedef void (*mbxdraw)(HWND);
static HHOOK hMsgHk; // internal linkage; local to this file
static mbxdraw drawproc; // internal linkage
LRESULT CALLBACK CBTProc(int nCode, WPARAM wp, LPARAM lp)
{
HWND hwndMsgbx;
if (nCode < 0)
return CallNextHookEx(hMsgHk, nCode, wp, lp);
switch (nCode) {
case HCBT_ACTIVATE:
// obtain the message box handle
hwndMsgbx = (HWND) wp;
drawproc(hwndMsgbx); // calls function pointer
return 0;
}
return CallNextHookEx(hMsgHk, nCode, wp, lp);
}
int msgbox(HWND hOwner, char *text, char *cap, UINT flags, mbxdraw md)
{
int ret;
hMsgHk = SetWindowsHookEx(WH_CBT, CBTProc, NULL, GetCurrentThreadId());
drawproc = md;
ret = MessageBox(hOwner, text, cap, flags);
UnhookWindowsHookEx(hMsgHk);
return ret;
}
在我传递的函数(main.cpp)中:
void draw(HWND hMsg)
{
// this is the checkbox:
CreateWindow("BUTTON", "Check", WS_CHILD | WS_VISIBLE | BS_CHECKBOX,
10, 70, 65, 10, hMsg, (HMENU) CHKID, GetModuleHandle(NULL), NULL);
SetWindowText(GetDlgItem(hMsg, IDYES), "Save Changes");
}
只要按下消息框中的两个按钮之一,复选框就会被绘制到主窗口上。它甚至可以使用相同的X坐标和Y坐标以及相同的宽度,高度和文本进行绘制。
我想也许我正在以错误的方式获取消息框句柄,但是我看到消息框句柄的地址不等于主窗口的句柄。
我传递函数指针而不仅仅是编写代码的原因是因为稍后,当它实际工作时,我会把它放在一个c ++包装类中。
答案 0 :(得分:1)
您的代码体现了错误的方法。您想要使用复选框创建本机消息对话框。 TaskDialogIndirect
是为此目的而提供的。
您的方法,即使您修复它,它对未来Windows版本中的实现更改也不健壮。使用系统提供的API。
答案 1 :(得分:0)
如果我在这个简单的程序中测试它,它就有效:
#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"user32.lib")
#define CHKID 100
typedef void (*mbxdraw)(HWND);
static HHOOK hMsgHk; // internal linkage; local to this file
static mbxdraw drawproc; // internal linkage
LRESULT CALLBACK CBTProc(int nCode, WPARAM wp, LPARAM lp)
{
HWND hwndMsgbx;
if (nCode < 0)
return CallNextHookEx(hMsgHk, nCode, wp, lp);
switch (nCode) {
case HCBT_ACTIVATE:
// obtain the message box handle
hwndMsgbx = (HWND) wp;
drawproc(hwndMsgbx); // calls function pointer
return 0;
}
return CallNextHookEx(hMsgHk, nCode, wp, lp);
}
void draw(HWND hMsg)
{
// this is the checkbox:
CreateWindow("BUTTON", "Check", WS_CHILD | WS_VISIBLE | BS_CHECKBOX,
10, 70, 65, 10, hMsg, (HMENU) CHKID, GetModuleHandle(NULL), NULL);
SetWindowText(GetDlgItem(hMsg, IDYES), "Save Changes");
}
int msgbox(HWND hOwner, char *text, char *cap, UINT flags, mbxdraw md)
{
int ret;
hMsgHk = SetWindowsHookEx(WH_CBT, CBTProc, NULL, GetCurrentThreadId());
drawproc = md;
ret = MessageBox(hOwner, text, cap, flags);
UnhookWindowsHookEx(hMsgHk);
return ret;
}
int main(int argc, char *argv[])
{
msgbox(NULL, "The quick brown fox jumps over the lazy dog", "The brown fox", MB_YESNO, draw);
Sleep(2000);
return 0;
}
也许你在删除钩子之前在同一个线程中创建了一些其他窗口?