将 WS_CHILD 替换为 WS_POPUP 后,CWnd::CreateEx() 失败
Posted
技术标签:
【中文标题】将 WS_CHILD 替换为 WS_POPUP 后,CWnd::CreateEx() 失败【英文标题】:CWnd::CreateEx() fails after replacing WS_CHILD with WS_POPUP 【发布时间】:2013-08-21 17:09:13 【问题描述】:当用户点击一个按钮时,我想打开另一个窗口。所以在 OnBnClicked..() 函数中,我添加了以下代码:
CWnd* window = new CWnd;
BOOL result = window->CreateEx(WS_EX_CLIENTEDGE, _T("STATIC"), _T("Hi"), WS_CHILD | WS_VISIBLE, 0, 0, 20, 20, m_hWnd, (HMENU)1234);
window->ShowWindow(SW_SHOW);
这可行,只是它创建了一个子窗口。我需要的是一个单独的窗口。所以我修改了代码,将“WS_CHILD”更改为“WS_POPUP”,将“m_hWnd”更改为“NULL”。
CWnd* window = new CWnd;
BOOL result = window->CreateEx(WS_EX_CLIENTEDGE, _T("STATIC"), _T("Hi"), WS_POPUP | WS_VISIBLE, 0, 0, 20, 20, NULL, (HMENU)1234);
window->ShowWindow(SW_SHOW);
但是现在,CreateEx() 调用返回 FALSE。我将不胜感激。
[编辑:]
我将代码更新如下。但仍然看到同样的问题。此外,即使 CreateEx() 返回 FALSE,GetLastError() 实际上也返回 0。
CWnd* window = new CalibrationWindow;
LPCTSTR className = NULL;
if (!className)
className = AfxRegisterWndClass(
CS_VREDRAW | CS_HREDRAW,
::LoadCursor(NULL, IDC_ARROW),
(HBRUSH) ::GetStockObject(WHITE_BRUSH),
::LoadIcon(NULL, IDI_APPLICATION));
BOOL isValid = ::IsWindow(GetSafeHwnd());
BOOL result = window->CreateEx(0, _T(className), _T("Hi"), WS_POPUP | WS_VISIBLE, 0, 0, 20, 20, m_hWnd, (HMENU)1234);
DWORD errorCode;
if (!result)
errorCode = GetLastError();
window->ShowWindow(SW_SHOW);
【问题讨论】:
如果 CreateEx 返回 FALSE,则调用 GetLastError() 以获取有关失败原因的更多信息。 用CWnd创建一个窗口是没有意义的。您无法在窗口中执行任何操作,因为您无法接收发送到该窗口的消息。请改用从 CWnd 派生的类,以便添加消息处理程序。 @ScottMcP-MVP,我同意您对使用 CWnd 的评论。但这不应该影响窗口创建行为,对吧?CreateEx
的第二个参数错误。 className
已经属于 LPCTSTR
类型,删除 _T
宏。当您启用 UNICODE 时,这将不会编译。此外,当您不创建WS_CHILD
-window 时,HMENU
参数实际上是菜单句柄。通过有效的HEMNU
或NULL
。
@IInspectable,感谢您指出 HMENU 问题。将其设置为 NULL 解决了这个问题。
【参考方案1】:
CWnd::CreateEx
的 nID
或 nIDorHMenu
参数是一个“重载”参数,用于指定控件 ID 或菜单 ID。
对于子窗口(@987654322@ 窗口样式),它是控件标识符。您可以指定任何值,只要它在具有相同父窗口的所有子窗口中是唯一的即可。
另一方面,对于弹出窗口(具有WS_CHILD
窗口样式的窗口),它是菜单标识符。在这种情况下,它必须是有效的HMENU
。传递一个虚构的值会导致窗口创建失败。
【讨论】:
【参考方案2】:以下是使用不同方法从 CWnd 派生类创建窗口的方法:
CWndDerived myWnd;
LPCTSTR className = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,
nullptr,
(HBRUSH) ::GetStockObject(WHITE_BRUSH),
nullptr);
myWnd.CreateEx(
0, // WS_EX_TOPMOST
className,
_T("Title"),
WS_POPUP | WS_BORDER | WS_CAPTION | WS_MAXIMIZEBOX | WS_SYSMENU,
0, 0, 300, 200,
m_hWnd,
nullptr,
nullptr);
这使您可以将 CWndDerived myWnd
作为其他窗口的成员变量(如果需要),并保留 MSVC 的 MFC 类编辑器附带的所有优点。
希望对你有帮助
【讨论】:
以上是关于将 WS_CHILD 替换为 WS_POPUP 后,CWnd::CreateEx() 失败的主要内容,如果未能解决你的问题,请参考以下文章
MFC窗口风格 WS_style/WS_EX_style(超详细)