如何在钩子程序中将复选框绘制到消息框上?
How to draw checkbox onto message box in hook procedure?
我正在 Win32 中制作自定义消息框 api。因此,我按照 here 中的教程创建了挂钩过程和其他东西。
我成功更改了按钮文本,但是,当我在消息框上绘制一个复选框并按下其中一个消息框按钮时,该复选框被绘制到主 window !
我的代码:
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");
}
只要我按下消息框上的两个按钮之一,复选框就会绘制到主 window 上。它甚至使用完全相同的 X 和 Y 坐标以及相同的宽度、高度和文本绘制。
我以为我获取消息框句柄的方法不对,但我看到消息框句柄的地址不等于主句柄window。
我传递函数指针而不是仅仅编写代码的原因是,当它真正起作用时,我会把它放在一个 c++ 包装器中 class。
如果我在这个简单的程序中测试它,它就会工作:
#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;
}
也许您在删除挂钩之前在同一个线程中创建了其他一些 window?
您的代码体现了错误的方法。你想制作一个带有复选框的本地消息对话框。 TaskDialogIndirect
就是为此目的而提供的。
您的方法,即使您修复了它,它也无法适应未来 Windows 版本中实现的变化。使用提供的系统 API.
我正在 Win32 中制作自定义消息框 api。因此,我按照 here 中的教程创建了挂钩过程和其他东西。
我成功更改了按钮文本,但是,当我在消息框上绘制一个复选框并按下其中一个消息框按钮时,该复选框被绘制到主 window !
我的代码:
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");
}
只要我按下消息框上的两个按钮之一,复选框就会绘制到主 window 上。它甚至使用完全相同的 X 和 Y 坐标以及相同的宽度、高度和文本绘制。
我以为我获取消息框句柄的方法不对,但我看到消息框句柄的地址不等于主句柄window。
我传递函数指针而不是仅仅编写代码的原因是,当它真正起作用时,我会把它放在一个 c++ 包装器中 class。
如果我在这个简单的程序中测试它,它就会工作:
#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;
}
也许您在删除挂钩之前在同一个线程中创建了其他一些 window?
您的代码体现了错误的方法。你想制作一个带有复选框的本地消息对话框。 TaskDialogIndirect
就是为此目的而提供的。
您的方法,即使您修复了它,它也无法适应未来 Windows 版本中实现的变化。使用提供的系统 API.