Ошибка CreateWindowEx с ошибкой 1407, даже если регистрация прошла успешно? - PullRequest
1 голос
/ 05 февраля 2012

Я экспериментировал с обёртыванием некоторых базовых функций win32 в классах, пока я работаю с d3d, и зашел в тупик из-за того, что функция 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

А вот и конструктор для класса:

WindowClass::WindowClass(string className, WindowAbstract * window)
{

    cbSize        = sizeof(WNDCLASSEX);
    style         = 0;
    lpfnWndProc   = window->WndProc;
    cbClsExtra    = 0;
    cbWndExtra    = 0;
    hInstance     = hInstance;
    hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    hCursor       = LoadCursor(NULL, IDC_ARROW);
    hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    lpszMenuName  = NULL;
    lpszClassName = className.c_str();
    hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    m_className = className;
}

вот функция регистра, которая будет вызвана после ее создания:

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

А вот и функция создания:

bool WindowAbstract::Create(string windowTitle, string className, DWORD styles, DWORD extendedStyles, int top, int left, int bot, int right, HWND parent, HMENU id)
{
    m_hwnd = CreateWindowEx(extendedStyles, className.c_str() , windowTitle.c_str(), styles, top, left, bot, right, parent, id, GetModuleHandle(NULL), NULL);
    if(!m_hwnd)
        return false;

    return true;
}

так что, увидев все это, вот собственно 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;
}

Итак, в заключение, это так запутанно, потому что функция Register объекта WindowClass возвращает нормально, но функция create завершается ошибкой в ​​объекте WindowAbstract, потому что нет допустимого класса (ошибка 1407) с таким именем? Whuh

Ответы [ 2 ]

5 голосов
/ 06 февраля 2012

Я думаю, что проблема в lpszClassName = className.c_str() в конструкторе WindowClass.В общем, вы не должны полагаться на то, что значение, возвращаемое из c_str(), будет доступно в течение любого промежутка времени.

В этом случае вы (фактически) берете адрес локальной переменной, которая может иметьперестал существовать к тому времени, как вы позвоните RegisterClassEx.Итак, RegisterClassEx успешен, но кто знает, какое имя он видит?

lpszClassName = m_className.c_str(), вероятно, сработает (если вы сначала назначите m_className), но это все еще отрывочно.Лучше позвонить c_str() непосредственно перед тем, как позвонить RegisterClassEx.

3 голосов
/ 06 февраля 2012

Не ясно, для чего предназначена строка

hInstance     = hInstance; 

.На самом деле он инициализирует hInstance сам по себе, поэтому он фактически не инициализирован.Это неинициализированное значение, вероятно, не совпадает со значением, переданным CreateWindowEx.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...