0

我可以在 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。这有效,但按钮不是没有父母的..

那么有没有办法给一个按钮一个ID(以便在WM_COMMAND中识别它),同时让它的父级为NULL,以便我以后可以设置父级?Windows 窗体是如何做到的?在您执行 Form.add(ButtonName); 之前,按钮可以是无父的。

在WINAPI中能达到同样的效果吗?

4

2 回答 2

4

从表面上看,这是一个非常愚蠢的问题。

按钮控件根据定义是子控件,因此对CreateWindowEx用于创建按钮的函数的调用也应该指定WS_CHILD样式。

当然,正如您所提到的,您不能创建没有父级的子控件;你会得到一个错误。没有顶级子窗口之类的东西。

那么,最初的问题的答案

我可以在 WINAPI 中创建没有父级的按钮吗?

显然没有。按钮是子控件,所有子控件都必须有父控件。

仅仅因为 Windows 允许您WS_POPUP在创建按钮控件时指定标志而不意味着它是有效的组合。

我强烈建议重新阅读该函数的文档。CreateWindowEx特别要注意,hMenu参数的含义是重载的。如果您正在创建一个重叠或弹出窗口(WS_OVERLAPPEDWS_POPUP),它指定一个菜单句柄。如果您正在创建子窗口 ( WS_CHILD),它会指定子窗口的标识符。根据窗口的样式,对这两种情况使用相同的参数这一事实应该告诉你一些事情。

Windows 窗体是如何做到的?在您执行 Form.add(ButtonName); 之前,按钮可以是无父的。

他们肯定不能。在将按钮控件添加到窗体或其他父控件之前,不会创建按钮控件。类System.Windows.Forms.Button构造函数不会创建 Win32 窗口。它只包含一组必要的样式,用于在适当的时候创建底层 Win32 窗口。

当然,您可以通过编写 C++Button类来做同样的事情。一个简单的实现将只有与参数相对应的成员变量CreateWindowEx和一个成员函数,一旦所有成员都已设置,该Create成员函数将实际调用以创建 Win32 窗口。如果尚未将必要成员之一设置为有效值,则CreateWindowEx该方法可能会引发异常。Create

我解决了。我必须将 HWND_MESSAGE 作为父参数传递。当您调用 SetParent 时,该参数将更改为 Parent 的句柄,一切都很好。

不,这确实不是问题的“解决方案”。正如kero 指出的那样,您只需将按钮控件的父级设置为仅消息窗口。同样,这似乎可行,但这是一件相当奇怪的事情,我几乎不推荐它作为解决方案。

如果您真的想破解它,我建议您创建自己的隐藏顶级窗口,以用作“无父”子控件的父级。然后,您可以使用相同的调用技巧来SetParent重新设置它们。

于 2013-03-10T12:39:01.717 回答
1

我解决了。我必须将 HWND_MESSAGE 作为父参数传递。当您调用 SetParent 时,该参数将更改为 Parent 的句柄,一切都很好。

不,您没有得到“无父按钮”:仅消息按钮的父窗口是“主”仅消息窗口(“消息”类)。

于 2013-03-09T23:30:23.030 回答