在我的项目中,我有两个类:'Window'和'Context'。 “Window”类使用WinAPI实例化一个窗口,一切正常。 例如。这段代码按照假设:
Window win("Hello,", 600, 400);
Window win2("World!", 600, 400);
类'Context'创建一个OpenGL 4.0 Context。为了做到这一点, 它需要创建一个临时窗口和一个临时上下文来检索所有OpenGL 4.0指针,作为回报,需要创建一个OpenGL 4.0上下文。 例如。这段代码也适用:
Window win("Context", 600, 400);
Context ctx(win);
一切正常。
但是,我正在重构代码。由于窗口根本只有一个上下文,我决定窗口应该管理上下文,因此它应该实例化并自行删除它。但这导致了我奇怪的错误。
// Constructor of window
// We're at the end of the constructor
if(true == bOWnContext)
pContext = internal::Context(*this);
}; // Constructor ends here
执行应用程序时,我收到异常/错误:“类已经注册”。 这很奇怪,因为以下代码适用于我:
Window winA(...);
Window winB(...);
// or
Context ctx(winA);
// This works like a charm
有些同事建议,我应该只注册一次窗口类, 所以我在构造函数中尝试了以下内容:
static bool bRegistered = false;
if(false == bRegistered){
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.hInstance = GetModuleHandle(nullptr);
wc.lpfnWndProc = internal::WndProc;
wc.lpszClassName = pTitle;
wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
if(0 == RegisterClassEx(&wc)){
//
// The exception class will contain the error code and
// a error discription.
//
std::error_code err_code(GetLastError(), std::system_category());
throw std::system_error(err_code);
}
bRegistered = true;
}
然而,这给了我另一个错误“找不到窗口类。”
有人可以启发我,为什么我的代码不起作用?
答案 0 :(得分:0)
你开始做错了假设:
...由于窗口只能有一个上下文,...
不。
可以有任意数量的上下文,实际上上下文与特定窗口无关。
只要窗口的pixelformat与上下文的pixelformat匹配,就可以在窗口中使上下文变为当前。如果你有几个线程,你可以同时在相同的窗口上创建不同的上下文当前(假设上下文与窗口的pixelformat兼容)。
答案 1 :(得分:0)
所以问题是,该类正在多次注册。我对这个问题的第一个解决方案是尝试引用一个可能不存在的类。 我的工作解决方案创建了一个类,并通过以下方式记住它的引用:
static const char* pcClassName;
if(nullptr == pcClassName){
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.hInstance = ((HINSTANCE)&__ImageBase);
wc.lpfnWndProc = internal::WndProc;
wc.lpszClassName = pTitle;
wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
if(0 == RegisterClassEx(&wc)){
//
// The exception class will contain the error code and
// a error description.
//
std::error_code err_code(GetLastError(), std::system_category());
throw std::system_error(err_code);
}
pcClassName = pTitle;
}
该类的名称用于在实际创建窗口后引用窗口类。例如。像这样:
pHandle->handle = CreateWindowEx(
bFullscreen ? WS_EX_APPWINDOW : NULL,
pcClassName,
pTitle,
bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW, // NOTE: Perhaps I'll create a window config struct?
GetSystemMetrics(SM_CXSCREEN) / 2,
GetSystemMetrics(SM_CYSCREEN) / 2,
clientArea.right - clientArea.left,
clientArea.bottom - clientArea.top,
nullptr, // We're not having a parent window
nullptr, // nor a win32 menu.
((HINSTANCE)&__ImageBase),
pHandle // Is needed for the router 'WndProc'.
);
但是,由于我将此代码编译为DLL,因此我使用@IInspectable解决方案来检索正确的“HINSTANCE”。 有关详细信息,请查看他的评论。
__ ImageBase 的定义如下:
EXTERN_C IMAGE_DOS_HEADER __ImageBase;