gpt4 book ai didi

winapi - 如何使用 Win32 API 将 EDIT 控件放入自定义弹出窗口中?

转载 作者:行者123 更新时间:2023-12-02 00:58:02 24 4
gpt4 key购买 nike

我正在尝试将一个 EDIT 控件添加到用作自定义组合框控件的下拉列表的窗口。最初,此下拉窗口是作为桌面的子 (WS_CHILD) 窗口实现的,类似于真正的组合框使用的“ComboLbox”窗口。这工作得很好,但是当它被放入这样的下拉窗口时,编辑窗口似乎只是拒绝接受焦点。 IE。例如,它已启用并对鼠标右键单击使用react,但单击它或调用 SetFocus() 失败(后者将最后一个错误设置为 ERROR_INVALID_PARAMETER)。

正因为如此,也因为自定义弹出窗口在许多示例中的实现方式,包括 Raymond Chen 的 fakemenu sample ,我已经将下拉菜单实现更改为使用 WS_POPUP,主应用程序窗口作为所有者。当显示弹出窗口时,从所有者窗口窃取激活有一个已知问题,但是这可以通过从弹出窗口的 WM_MOUSEACTIVATE 处理程序返回 MA_NOACTIVATE 来解决,它确实最初运行良好,即所有者窗口在弹出窗口出现时保持激活状态。但是只要我单击弹出窗口中的 EDIT 控件,它就会从其默认窗口过程中调用 SetFocus() 将焦点设置到自身,这会停用父窗口。

我的问题是如何防止这种情况发生?我知道这是可以做到的,因为 WinForms ToolStripManager设法允许在不停用父窗口的情况下编辑下拉列表中的文本,并且它还为弹出窗口使用 WS_POPUP 样式。但它是如何做到的呢?

最佳答案

在评论中提出了一个解决方案 “通过处理 WM_NCACTIVATE 防止主机窗口明显显示为非事件状态” 这应该如下例所示工作。

当菜单窗口打开时,宿主窗口(HostProc)将收到WM_NCACTIVATE消息。主机将查找 "menuclass",如果找到菜单类,则主机将返回 DefWindowProc(hwnd, WM_NCACTIVATE, TRUE, lparam); 以防止主机窗口出现标题栏变得不活跃。

您还需要在假菜单窗口中处理 WM_NCACTIVATE。当菜单窗口失去焦点时,MenuProc 接收到 WM_NCACTIVATE,此时菜单可以自行关闭。

#include <windows.h>

const wchar_t* menuclass = L"menuclass";

LRESULT CALLBACK MenuProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_CREATE:
CreateWindow(L"Edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 160, 30,
hwnd, NULL, NULL, NULL);
break;

case WM_NCACTIVATE:
{
if(!wparam)
{
//close the menu if its losing focus
PostMessage(hwnd, WM_CLOSE, 0, 0);

//tell parent to paint inactive, if user clicked on a different program
POINT pt;
GetCursorPos(&pt);
HWND hit = WindowFromPoint(pt);
HWND hparent = GetParent(hwnd);
if(hit != hparent && !IsChild(hparent, hit))
DefWindowProc(hparent, WM_NCACTIVATE, FALSE, 0);
}
break;
}

case WM_LBUTTONDOWN:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
//also handles other mouse/key messages associated with a menu...
}

return DefWindowProc(hwnd, msg, wparam, lparam);
}

LRESULT CALLBACK HostProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_NCACTIVATE:
//paint the window as active when custom menu starts
if(!wparam && FindWindow(menuclass, NULL))
return DefWindowProc(hwnd, WM_NCACTIVATE, TRUE, lparam);
break;
case WM_RBUTTONUP:
{
//show the custom menu
POINT pt;
GetCursorPos(&pt);
CreateWindow(menuclass, NULL, WS_VISIBLE | WS_POPUP | WS_BORDER,
pt.x, pt.y, 200, 400, hwnd, 0, 0, 0);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hwnd, msg, wparam, lparam);
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
{
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.lpfnWndProc = HostProc;
wcex.lpszClassName = L"hostwnd";
RegisterClassEx(&wcex);

wcex.lpfnWndProc = MenuProc;
wcex.lpszClassName = menuclass;
RegisterClassEx(&wcex);

CreateWindow(L"hostwnd", L"Right click for menu ...",
WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 600, 400, 0, 0, hInstance, 0);

MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (int)msg.wParam;
}

关于winapi - 如何使用 Win32 API 将 EDIT 控件放入自定义弹出窗口中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52797898/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com