【问题标题】:CreateWindowEx called on button click fails按钮单击时调用的 CreateWindowEx 失败
【发布时间】:2021-06-11 08:33:59
【问题描述】:

我正在尝试通过单击主窗口过程的 WM_COMMAND 中的按钮窗口创建一个对话框窗口。

case WM_CREATE: 
            hwndRegister = CreateWindow(TEXT("BUTTON"), TEXT("Register"), WS_VISIBLE | WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT, 100, 50, hwnd, (HMENU)REGISTER_WINDOW, NULL, NULL);
            break;

        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            {
                case REGISTER_WINDOW:
                    DisplayRegisterDialog(hwndRegister);
                    break;
            }
            break;

如果点击了hwndRegister,它应该会弹出新的对话框窗口,并在另一个cpp文件中定义和注册。

CONST wchar_t DIALOG_WINDOW_NAME[] = L"DialogClass";
void RegisterDialog(HINSTANCE hInstance) 
{
    WNDCLASS dialogBox = { };

    dialogBox.lpfnWndProc = DialogProc;
    dialogBox.lpszClassName = DIALOG_WINDOW_NAME;
    dialogBox.hInstance = hInstance;
    dialogBox.hCursor = LoadCursor(NULL, IDC_ARROW);

    RegisterClass(&dialogBox);
}

void DisplayRegisterDialog(HWND hwnd) 
{
    if (!hwnd) 
    {
        MessageBox(NULL, L"Window Creation faile", L"WINDOW CREATION FAILED", MB_ICONERROR);
    }
    HWND hwndDialogWindow = CreateWindowEx(0, DIALOG_WINDOW_NAME, L"Register User", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, hwnd, (HMENU)DIALOG_REGISTER_WINDOW, NULL, NULL);
}

我正在从主应用程序的 winapi winmain 获取实例以注册对话框。

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
RegisterDialog(hInstance);
}

目前我没有收到任何可见的错误,程序运行顺利。但是,不会创建对话窗口,也不会引发错误。 编辑 - 对话程序实现:

LRESULT CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

在遵循 IInspectable 关于手动检查错误的建议后,我还想注意一下。如果正在注册窗口,我会这样做

if (RegisterClass(&dialogBox) == 0) {
        MessageBox(NULL, L"Dialog window registration failed", L"Error", 0);
        throw GetLastError();
    }

此代码抛出 Microsoft C++ 异常:unsigned long at memory location 0x0078F828。

编辑 2- 好的。我终于发现错误代码 1410 类的问题已经存在。我对这些 Windows 类有不同的名称。是因为 hInstance 吗?

【问题讨论】:

  • 我倾向于遇到类似的问题,其中大多数与窗口过程返回到WM_CREATE消息的内容有关。你的DialogProc 的代码是什么?来自docs.microsoft.com/en-us/windows/win32/winmsg/wm-create:“如果应用程序处理此消息,它应该返回零以继续创建窗口。如果应用程序返回 –1,则窗口被销毁并且 CreateWindowEx 或 CreateWindow 函数返回一个 NULL 句柄。”你检查hwndDialogWindowNULL 了吗?
  • 另一点有点离题:您创建的是另一个主(“重叠”)窗口,而不是对话框。您可能希望将对话框创建为资源并使用DialogBox
  • 嗨,@Iziminza 感谢您的及时回复。该dialogProc 是现在要创建的对话框窗口的过程,我只在其中定义了WM_CLOSE。从主窗口过程调用创建和命令,创建只创建注册窗口按钮。
  • 嘿,我已经检查了对话框,但我认为我不能随意操作该框。我的对话框应该包含至少 2 个输入框,用于输入名称和密码以及提交按钮。对话框可以吗?
  • Windows API 是一个 C 接口。错误不会向您“抛出”。您将不得不手动发现错误情况。 RegisterClass 可能会失败,但代码选择忽略其返回值。 CreateWindow 也可能失败,但代码选择不观察错误情况。首先添加观察错误的代码。

标签: c++ winapi


【解决方案1】:

你的函数DialogProc实际上是一个普通的窗口过程,而不是一个对话框过程,所以你必须将未处理的消息传递给DefWindowProc,像这样:

LRESULT CALLBACK DialogProc /*misnomer!*/(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_CLOSE:
        MessageBox(hwnd, L"Test", L"Test", 0);
        break;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam); // important!!
}

如果你改写return 0;,窗口将在调用WM_CREATE返回后立即销毁。

【讨论】:

  • 嗨@Iziminza 谢谢你,但我已经有了这个,我仍然面临这个问题。
  • @ShanksLimbu 请编辑您的问题以包含minimal reproducible example,显示您的DialogProc() 的实际实施方式。
【解决方案2】:

错误是由于在 hwndDialogWindow 中设置了 HMENU。它必须为空。还有大约 1410 错误。我也对此感到困惑。代码是

RegisterClass(&dialogBox);
if (RegisterClass(&dialogBox) == 0) {
        int nresult = GetLastError();
        MessageBox(NULL, L"Dialog window registration failed", L"Error", 0);
    }

我不知道上面的代码是如何产生 1410 错误的。我删除了要注册的第一行,错误就消失了。

也感谢 RemyLebeau 指出错误的方法,Inspectable 提供了非常有用的手动检查错误的建议,以及 Iziminza 提供了我将用于其他按钮的对话框 rss 脚本。

【讨论】:

  • 错误 1410 是 ERROR_CLASS_ALREADY_EXISTS。不足为奇,因为您尝试注册完全相同的课程两次。连续。目前尚不清楚您在这里尝试做什么,尽管您可能远远获得一些 Windows API 的学习材料(例如 Petzold 的“Programming Windows - 5th Ed.”)。猜测不会是一种可持续、有效或高效的方法。
  • 你传递的HMENU不必是NULL,但如果不是,它必须是一个菜单句柄,而不是一个菜单资源标识符。这意味着您必须先使用LoadMenu 函数加载它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-02
  • 2015-02-23
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多