Mfc CWnd::CreateEx()在用WS\u弹出窗口替换WS\u子对象后失败

Mfc CWnd::CreateEx()在用WS\u弹出窗口替换WS\u子对象后失败,mfc,Mfc,当用户点击一个按钮时,我想打开另一个窗口。因此,在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); 除了创

当用户点击一个按钮时,我想打开另一个窗口。因此,在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”

但是现在,createx()调用返回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);

nID
nIDorHMenu
参数是一个“重载”参数,指定控件ID或菜单ID

对于子窗口(窗口样式),它是控件标识符。可以指定任何值,只要该值在具有相同父窗口的所有子窗口中是唯一的


另一方面,对于弹出窗口(具有
WS\u CHILD
窗口样式的窗口),它是菜单标识符。在这种情况下,它必须是有效的。传递虚构的值将导致窗口创建失败。

下面介绍如何使用不同的方法从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);
这允许您将
cwnderived myWnd
作为其他窗口的成员变量(如果需要),并保留MSVC的MFC类编辑器附带的所有功能


我希望这能有所帮助

如果CreateEx返回FALSE,则调用GetLastError()以获取有关失败原因的更多信息。使用CWnd创建窗口没有意义。您无法在该窗口中执行任何操作,因为您无法接收发送到该窗口的消息。请改用从CWnd派生的类,这样您就可以添加消息处理程序。@ScottMcP MVP,我同意您关于使用CWnd的评论。但是这不应该影响windows的创建行为,对吗?您的
CreateEx
的第二个参数是错误的
className
的类型已经是
LPCTSTR
,请删除
\T
宏。启用UNICODE时将不会编译此文件。此外,当您不创建
WS_CHILD
-窗口时,
humenu
参数实际上是菜单的句柄。请通过有效的
HEMNU
NULL
@IInspectable,谢谢您指出了HMENU问题。将其设置为NULL解决了问题。
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);