C++ 即使注册成功,CreateWindowEx仍会失败并出现错误1407?

C++ 即使注册成功,CreateWindowEx仍会失败并出现错误1407?,c++,winapi,C++,Winapi,在使用d3d时,我一直在尝试将一些基本的win32功能包装到类中,我很难理解为什么CreateWindowEx函数在使用RegisterClassEx创建一个有效的类后失败,并说一个类不存在,没有错误:\。我觉得我错过了一些愚蠢的小事,但我找不到它。下面是一些代码: 我有一个像这样扩展WNDCLASSEX的类,因此它有一个普通的std::string作为类名和一个简化的构造函数: #ifndef WINDOWCLASS_H #define WINDOWCLASS_H #include <

在使用d3d时,我一直在尝试将一些基本的win32功能包装到类中,我很难理解为什么CreateWindowEx函数在使用RegisterClassEx创建一个有效的类后失败,并说一个类不存在,没有错误:\。我觉得我错过了一些愚蠢的小事,但我找不到它。下面是一些代码:

我有一个像这样扩展WNDCLASSEX的类,因此它有一个普通的std::string作为类名和一个简化的构造函数:

#ifndef WINDOWCLASS_H
#define WINDOWCLASS_H

#include <Windows.h>
#include <string>
#include "WindowAbstract.h"
using namespace std;

class WindowClass : public WNDCLASSEX
{
public:
    WindowClass(string className, WindowAbstract * window);
    ~WindowClass();

    bool Register();
    string ClassName() {return m_className;}

    friend class WindowAbstract;

private:
    string m_className;
};

#endif
下面是构造后要调用的寄存器函数:

bool WindowClass::Register()
{
    if(RegisterClassEx(this) == 0)
        return false;

    return true;
}
WindowAbstract类包含窗口过程,首先创建它,将指向其函数的指针传递给WindowClass对象

#ifndef WINDOWABSTRACT_H
#define WINDOWABSTRACT_H

#include <Windows.h>
#include <string>
using namespace std;

class WindowAbstract
{

public:
    WindowAbstract();
    ~WindowAbstract();

    bool Create(string windowTitle, string className, DWORD styles, DWORD extendedStyles, int top, int left, int bot, int right, HWND parent, HMENU id);
    void Show();

    friend class WindowClass;

private:
    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    HWND m_hwnd;

};

#endif
在看到所有这些之后,这里是我测试它的实际winmain:

#include "WindowAbstract.h"
#include "WindowClass.h"


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
    DWORD error;
    bool result;
    char buffer[100];

    WindowAbstract * window = new WindowAbstract();
    WindowClass * myClass = new WindowClass("myClass", window);

    result = myClass->Register();
    if(!result)
    {
        error = GetLastError();
        sprintf_s(buffer, "error: %i", error);
        MessageBox(NULL, buffer, "Registration Failed!", MB_OK);
    }

    result = window->Create("my Window", myClass->ClassName(), WS_OVERLAPPEDWINDOW, WS_EX_CLIENTEDGE, 20, 20, 200, 200, NULL, NULL);
    if(!result)
    {
        error = GetLastError();
        sprintf_s(buffer, "error: %i", error);
        MessageBox(NULL, buffer, "Window Creation Failed!", MB_OK);

    }

    window->Show();

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if(window)
    {
        delete window;
        window = 0;
    }

    if(myClass)
    {
        delete myClass;
        myClass = 0;
    }

    return msg.wParam;
}
总之,这是非常令人困惑的,因为WindowClass对象的Register函数返回的很好,但是WindowAbstract对象中的create函数失败,因为没有有效的类,错误1407,具有该名称?什么?

我认为问题在于WindowClass构造函数中的lpszClassName=className.c_str。一般来说,您不应该依赖于从c_str返回的值在任何时间内都是可用的

在本例中,您实际上获取了一个局部变量的地址,该变量在调用RegisterClassEx时可能已经不存在了。所以RegisterClassEx成功了,但谁知道它看到的是什么名字呢

lpszClassName=m_className.c_str如果您首先指定m_className,可能会起作用,但它仍然很粗略。最好在调用RegisterClassEx之前立即调用c_str。

我认为问题在于WindowClass构造函数中的lpszClassName=className.c_str。一般来说,您不应该依赖于从c_str返回的值在任何时间内都是可用的

在本例中,您实际上获取了一个局部变量的地址,该变量在调用RegisterClassEx时可能已经不存在了。所以RegisterClassEx成功了,但谁知道它看到的是什么名字呢


lpszClassName=m_className.c_str如果您首先指定m_className,可能会起作用,但它仍然很粗略。最好在调用RegisterClassEx之前立即调用c_str。

不清楚是哪一行

hInstance     = hInstance; 

目的在于完成。事实上,它所做的只是初始化自身,因此实际上是未初始化的。该未初始化的值可能与传递给CreateWindowEx的值不同。

不清楚该行是什么

hInstance     = hInstance; 

目的在于完成。事实上,它所做的只是初始化自身,因此实际上是未初始化的。这个未初始化的值可能与传递给CreateWindowEx的值不同。

ah,这实际上是一个意外,因为hInstance有一个参数被传递到函数中,而我最初只是创建一个包含WNDCLASSEX成员的类。现在我应该用hInstance=GetModuleHandleNULL替换它;感谢您的关注,但这并没有解决我最初的问题:\n使用实际模块的实例句柄。啊,这实际上是一个意外,因为hInstance有一个参数被传递到函数中,而我最初只是创建一个包含WNDCLASSEX成员的类。现在我应该用hInstance=GetModuleHandleNULL替换它;感谢您的关注,但这并没有解决我最初的问题:\n使用实际模块的实例句柄。啊,就是这样:P.当我在构造函数中调用c_str函数时,我假设该成员只有在构造函数范围内才正确有效,所以当构造函数结束时,我调用Register成员时,它是不正确的。现在我完全删除了Register成员,只在构造函数末尾调用了RegisterClassEx,我的窗口创建得很好。谢谢你的建议!:PI实际上接受了您的建议,像以前一样将传入的字符串分配给m_className成员,省略了lpszClassName=className.c_str;语句,然后将lpszClassName=m_className.c_str;就在我在注册会员中注册班级之前。这就像一个符咒,所以现在我仍然可以检查注册表类失败。胡特:P。总之,我现在了解到string::c_str返回的char*是本地的,并且只对当前作用域有效。string::c_str返回的char*是有效的。啊,就是这样:P。当我在构造函数中调用c_str函数时,我假设成员只有在构造函数作用域中才正确有效,所以当构造函数结束,我调用Register成员时,它是不正确的。现在我完全删除了Register成员,只在构造函数末尾调用了RegisterClassEx,我的窗口创建得很好。谢谢你的建议
开PI实际上接受了您的建议,像以前一样将传入的字符串分配给m_className成员,省略了lpszClassName=className.c_str;语句,然后将lpszClassName=m_className.c_str;就在我在注册会员中注册班级之前。这就像一个符咒,所以现在我仍然可以检查注册表类失败。胡特:P。总之,我现在了解到string::c_str返回的char*是本地的,并且只对当前作用域有效。string::c_str返回的char*是有效的。
hInstance     = hInstance;