我可以在 WINAPI 中创建没有父项的按钮吗?
我试过:
CreateWindowEx(0, "Button", "BTN", WS_POPUP | BS_PUSHBUTTON, 0, 0, 15, 15, nullptr, nullptr, nullptr, nullptr);
然后稍后将父级设置为指定窗口,并使用 ShowWindow 显示按钮。这确实创建了一个漂亮的按钮。
但是,该按钮没有 ID,并且无法在 WM_COMMAND 中识别,因为 ID 为 0。如果两个按钮没有父项,则无法区分它们。现在,如果我通过 HMENU 参数给它一个 ID:
CreateWindowEx(0, "Button", "BTN", WS_POPUP | BS_PUSHBUTTON, 0, 0, 15, 15, nullptr, 15, nullptr, nullptr);
GetLastError() 打印“无效菜单句柄”并且不会创建按钮。
如果我没有给它父级和 WS_CHILD,它会说无法创建一个可以理解的顶级子窗口。
所以我所做的是将 Parent 设置为 GetDesktopWindow() 并为按钮提供一个 ID。这行得通,但按钮不是没有 parent 的..
那么有没有办法给按钮一个 ID(以便在 WM_COMMAND 中识别它),同时让其父级为 NULL,以便我稍后可以设置父级? Windows 窗体是如何做到的?在您执行 Form.add(ButtonName); 之前,按钮可以是无父级的;
在WINAPI中可以实现同样的效果吗?
最佳答案
从表面上看,这是一个非常愚蠢的问题。
按钮控件根据定义是子控件,因此调用用于创建按钮的 CreateWindowEx
函数也应指定 WS_CHILD
样式。
当然,正如您提到的,您不能创建没有父控件的子控件;你会得到一个错误。没有顶级子窗口这样的东西。
那么,第一个问题的答案
Can I create a button without a parent in WINAPI?
显然不是。按钮是子控件,所有子控件都必须有一个父控件。
仅仅因为 Windows 允许您在创建按钮控件时指定 WS_POPUP
标志并不意味着它是一个有效的组合。
我强烈建议重新阅读 the documentation对于 CreateWindowEx
函数。特别要注意的是,hMenu
参数在其含义方面被重载了。如果您要创建重叠或弹出窗口(WS_OVERLAPPED
或 WS_POPUP
),它会指定菜单句柄。如果您正在创建子窗口 (WS_CHILD
),它会指定子窗口的标识符。根据窗口的样式,相同的参数用于这两种情况这一事实应该告诉您一些事情。
How does Windows Forms do it? The buttons can be parentless until you do Form.add(ButtonName);
他们肯定不能。在将按钮控件添加到窗体或其他父控件之前,它们不会被创建。 System.Windows.Forms.Button
类构造函数不创建 Win32 窗口。它只包含必要样式的集合,用于在适当的时候创建底层 Win32 窗口。
当然,您可以通过编写 C++ Button
类来做同样的事情。一个简单的实现只有与 CreateWindowEx
的参数对应的成员变量和一个实际调用 CreateWindowEx
来创建 Win32 窗口的 Create
成员函数一旦所有成员都设置好了。如果其中一个必需的成员尚未设置为有效值,则 Create
方法可能会引发异常。
I solved it. I had to pass HWND_MESSAGE as the Parent Parameter. When you call SetParent, that parameter gets changed to the Parent's handle and all is well.
不,这真的不是问题的“解决方案”。作为kero points out ,您只需将按钮控件的父级设置为 message-only window .同样,这似乎可行,但这是一件相当奇怪的事情,我几乎不推荐将其作为解决方案。
如果您真的想破解它,我建议您创建自己的隐藏顶层窗口以用作“无父级”子控件的父级。然后您可以使用调用 SetParent
的相同技巧来重新设置它们的父级。
关于c++ - 无父按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15308137/