私はd3dで作業している間、基本的なWin32機能をクラスにラップすることを実験していましたが、CreateWindowEx関数が失敗してクラスが存在しないと言われていない理由を困惑しています。の:\。私は何かばかげた小さなことを逃している気がしますが、私はそれを見つけることができません。ここでは、コードの一部です:登録が成功したにもかかわらず、CreateWindowExがエラー1407で失敗しましたか?
それはクラス名と簡略化され、コンストラクタの通常のstd ::文字列を持つように私は、このようWNDCLASSEXを拡張するクラスを持っている:
#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;
}
、結論では、これは非常に混乱しているので、WindowClassオブジェクトのRegister関数は正常に戻りますが、その名前の有効なクラス(エラー1407)がないため、WindowAbstractオブジェクトでcreate関数が失敗します。どう?
ああ、そうした:P。コンストラクタ内でc_str()関数を呼び出すと、コンストラクタのスコープ内にある限り、メンバーが正しく有効であると仮定します。したがって、コンストラクタが終了し、Registerメンバを呼び出すときに間違っていました。今私はレジスタメンバーを完全に去って、コンストラクタの最後にRegisterClassExを呼び出し、私のウィンドウはうまく作成されました(YAY!)。あなたの提案をありがとう!:P – FatalCatharsis
私は実際にあなたのアドバイスを受け取りました。lpszClassName = className.c_str();を省略して、以前のようにm_classNameメンバに渡された文字列を割り当てました。ステートメントをコンストラクタに挿入し、lpszClassName = m_className.c_str();を入力します。私がRegister会員にクラスを登録する直前に。それは魅力的に機能していたので、今でもRegisterClassExが失敗しているかどうかを確認できます。 WOOT:P。結論として、私は今、string :: c_str()によって返されたchar *がローカルであり、現在のスコープに対してのみ有効であることを知りました。 – FatalCatharsis
'string :: c_str()'によって返される 'char *'は有効です(文字列の次の非constメソッド呼び出し(または文字列が破壊される)まで)](http://www.cplusplus.com/参照/文字列/文字列/ c_str /)。 –