NeHe gamedevチュートリアルに従って(OOに変更しながら)、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。
私はWindowsAPIの完全な初心者であり、これを解決するために知っているすべての方法を使い果たしました。ここで私の間違いを指摘していただけますか?以下の関連コード:
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);
}