gpt4 book ai didi

c++ - CreateWindowEx 失败

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:11:43 30 4
gpt4 key购买 nike

我正在学习 NeHe gamedev 教程(同时将它们更改为面向对象),但我遇到了 CreateWindowEx 演示 (http://nehe.gamedev.net/tutorial/creating_an_opengl_window_(win32)/13001) 的问题/).

我试图通过 lpParam 向 WndProc 传递指向我的 Window 对象的指针(详见此处:http://web.archive.org/web/20051125022758/www.rpi.edu/~pudeyo/articles/wndproc/),但如果我尝试这样做,CreateWindowEx 将失败,GetLastError 返回 1400 - ERROR_INVALID_WINDOW_HANDLE。

我是 Windows API 的完全初学者,已经用尽了我所知道的解决此问题的所有方法,您能在这里指出我的错误吗?相关代码如下:

LRESULT CALLBACK cog::WindowProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) {
// Member method as windowproc: http://web.archive.org/web/20051125022758/www.rpi.edu/~pudeyo/articles/wndproc/

if(msg == WM_NCCREATE) {
LPCREATESTRUCT cs = (LPCREATESTRUCT)lParam;
SetWindowLong(window, GWL_USERDATA, (long)cs->lpCreateParams);
}

cog::Window* w = (cog::Window*)GetWindowLong(window, GWL_USERDATA);
if(w) {
return w->windowProc(msg, wParam, lParam);

} else {
return DefWindowProc(window, msg, wParam, lParam);
}
}

cog::Window::Window(int width, int height, int bits, bool fullscreen) :
fullscreen(fullscreen), appInstance(GetModuleHandle(NULL)), active(FALSE) {

// Generate a rectangle corresponding to the window size
RECT winRect = {0, 0, width, height};

WNDCLASS winClass;
winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
winClass.lpfnWndProc = (WNDPROC) cog::WindowProc; // WndProc Handles Messages
winClass.cbClsExtra = 0; // No Extra Window Data
winClass.cbWndExtra = sizeof(this); // Window Data - pointer to Window object
winClass.hInstance = this->appInstance; // Set The Instance
winClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
winClass.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
winClass.hbrBackground = NULL; // No Background Required For GL
winClass.lpszMenuName = NULL; // We Don't Want A Menu
winClass.lpszClassName = TEXT("OpenGL");

if(!RegisterClass(&winClass)) {
throw cog::WindowException(std::string("Failed to register class"));
}

if(this->fullscreen) {
DEVMODE screenSettings;
memset(&screenSettings, 0, sizeof(DEVMODE));

screenSettings.dmSize = sizeof(DEVMODE);
screenSettings.dmPelsWidth = width;
screenSettings.dmPelsHeight = height;
screenSettings.dmBitsPerPel = bits;
screenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

if(DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&screenSettings, CDS_FULLSCREEN)) {
if(MessageBox(NULL, "Cannot start in full screen mode - start in windowed mode instead?", "OpenGL", MB_YESNO | MB_ICONEXCLAMATION)) {
this->fullscreen = FALSE;

} else {
throw cog::WindowException(std::string("Refused to launch program in windowed mode"));

}
}
}

DWORD winExStyle;
DWORD winStyle;
if(fullscreen) {
winExStyle = WS_EX_APPWINDOW;
winStyle = WS_POPUP;
ShowCursor(FALSE);

} else {
winExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
winStyle = WS_OVERLAPPEDWINDOW;
}

AdjustWindowRectEx(&winRect, winStyle, FALSE, winExStyle);

/*
* !! BLOWS UP AT THIS CALL - WindowException triggered
*/
if(!(this->window = CreateWindowEx(
winExStyle,
TEXT("OpenGL"),
TEXT("OpenGL Testing"),
winStyle,
0, 0,
winRect.right - winRect.left,
winRect.bottom - winRect.top,
NULL,
NULL,
this->appInstance,
this))) {
throw cog::WindowException(std::string("Failed to create window"));
}

// ... cut here ...
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE lPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
MSG msg;
cog::Window* w = NULL;

try {
w = new cog::Window(100, 100, 16, TRUE);

// ... cut here ...

} catch(cog::Exception e) {
MessageBox(NULL, e.what(), "Exception Raised", MB_OK | MB_ICONEXCLAMATION);
}

if(w) {
delete w;
}
}

成员windowProc:

LRESULT CALLBACK cog::Window::windowProc(UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_ACTIVATE:
if(HIWORD(wParam)) {
this->active = FALSE;

} else {
this->active = TRUE;
}

return 0;;

case WM_SYSCOMMAND:
switch(wParam) {
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}

break;

case WM_CLOSE:
PostQuitMessage(0);
return 0;

case WM_KEYDOWN:
this->keys[wParam] = TRUE;
break;

case WM_KEYUP:
this->keys[wParam] = FALSE;
break;

case WM_SIZE:
this->resize(LOWORD(lParam), HIWORD(lParam));
return 0;

default:
break;
}

return DefWindowProc(this->window, msg, wParam, lParam);
}

最佳答案

您请求全屏显示是否会导致问题? w = new cog::Window(100, 100, 16, TRUE);

如果有帮助,这在我的代码库中有效:

HWND impl::window_impl::create_window_(
window_impl* window // associated window object
) {
auto const INSTANCE = ::GetModuleHandleW(L"");

WNDCLASSEXW const wc = {
sizeof(WNDCLASSEXW),
CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
window_impl::top_level_wnd_proc_,
0,
0,
INSTANCE,
nullptr,
::LoadCursorW(nullptr, MAKEINTRESOURCE(IDC_ARROW)),
nullptr,
nullptr,
CLASS_NAME,
nullptr
};

::RegisterClassExW(&wc); // ignore return value

auto const result = ::CreateWindowExW(
0,
CLASS_NAME,
L"window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
(HWND)nullptr ,
(HMENU)nullptr,
INSTANCE,
window
);

return result;
}

[编辑]我认为您对 CreateWindowExW 的调用的参数顺序错误——特别是实例参数。您是否使用 STRICT 进行编译?它应该检测到这种问题。

[编辑]没有直接关系,但是当编译为 64 位代码时您的实现将不起作用,并且它不会检查可能的错误——您应该使用类似的东西:

//--------------------------------------------------------------------------
//! Get the userdata for the window given by @c hwnd (our window object).
//! @throw bklib::platform::windows_exception
//--------------------------------------------------------------------------
impl::window_impl* get_window_ptr(HWND hwnd) {
::SetLastError(0);
auto const result = ::GetWindowLongPtrW(hwnd, GWLP_USERDATA);

if (result == 0) {
auto const e = ::GetLastError();
if (e) {
BOOST_THROW_EXCEPTION(bklib::platform::windows_exception()
<< bklib::platform::windows_error_code(e)
);
}
}

return reinterpret_cast<impl::window_impl*>(result);
}

//--------------------------------------------------------------------------
//! Set the userdata for the window given by @c hwnd to be our
//! window object.
//! @throw bklib::platform::windows_exception
//--------------------------------------------------------------------------
void set_window_ptr(HWND hwnd, impl::window_impl* ptr) {
::SetLastError(0);
auto const result = ::SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(ptr));

if (result == 0) {
auto const e = ::GetLastError();
if (e) {
BOOST_THROW_EXCEPTION(bklib::platform::windows_exception()
<< bklib::platform::windows_error_code(e)
);
}
}
}

[edit] 更多代码以防有帮助

//------------------------------------------------------------------------------
//! Top level window procedure which forwards messages to the appropriate
//! impl::window_impl instance.
//! @throw noexcept
//! Swallows all exceptions at the API boundary.
//------------------------------------------------------------------------------
LRESULT CALLBACK impl::window_impl::top_level_wnd_proc_(
HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam
) try {
// set the instance pointer for the window given by hwnd if it was just created
if (msg == WM_NCCREATE) {
auto const cs =
reinterpret_cast<CREATESTRUCTW const*>(lParam);
auto const window_ptr =
reinterpret_cast<window_impl*>(cs->lpCreateParams);

set_window_ptr(hwnd, window_ptr);
}

// the window object to forward the message to
auto const window = get_window_ptr(hwnd);

if (window) {
return window->window_proc_(hwnd, msg, wParam, lParam);
} else {
// it's possible we will receive some messages beofre WM_NCCREATE;
// use the default handler
return ::DefWindowProcW(hwnd, msg, wParam, lParam);
}
} catch (std::exception&) {
::PostQuitMessage(-1);
return 0;
} catch (...) {
::PostQuitMessage(-1);
return 0;
}

//------------------------------------------------------------------------------
//! Called by the top level window proc. Dispatches messages to their
//! appropriate handler function.
//------------------------------------------------------------------------------
LRESULT impl::window_impl::window_proc_(
HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam
) {
return ::DefWindowProcW(hwnd, msg, wParam, lParam);
}

//------------------------------------------------------------------------------
void impl::window_impl::create() {
handle_ = create_window_(this);
}

//------------------------------------------------------------------------------
void impl::window_impl::show(bool visible) {
::ShowWindow(handle_, SW_SHOWDEFAULT);
::InvalidateRect(handle_, nullptr, FALSE);
::UpdateWindow(handle_);
}

关于c++ - CreateWindowEx 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14026875/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com