   Problem With My WndProc
  I have created a simple window wrapping class again, but now I have a problem. When I try to handle closing the window down, everything goes bad and I find the app trying to access NULL memory. Can someone tell me what's going wrong here? I get my NULL memory access in the WndProc when trying to set mainLoopDone to true.void App::Destroy(void){if(parameters.exitFunc)parameters.exitFunc();if(d3dObject)d3dObject->Release();if(d3dDevice)d3dDevice->Release();UnregisterClass(parameters.wndClass.lpszClassName, GetModuleHandle(NULL));if(window)DestroyWindow(window);}HRESULT App::MainLoop(void){if(!initialized)return E_FAIL;MSG msg = { 0 };while(!mainLoopDone){if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){TranslateMessage(&msg);DispatchMessage(&msg);}else{if(parameters.preRenderFunc)parameters.preRenderFunc();if(parameters.renderFunc)parameters.renderFunc();if(parameters.postRenderFunc)parameters.postRenderFunc();}}Destroy();return (int)msg.wParam;}LRESULT App::WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam){switch(message){case WM_CLOSE:mainLoopDone = true;return 0;}return DefWindowProc(hwnd, message, wparam, lparam);}LRESULT CALLBACK App::StaticWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam){App* app;if(message == WM_NCCREATE){LPCREATESTRUCT cs = (LPCREATESTRUCT)lparam;SetWindowLong(hwnd, GWL_USERDATA, (long)cs->lpCreateParams);}app = (App*)GetWindowLong(hwnd, GWL_USERDATA);return app->WndProc(hwnd, message, wparam, lparam);}
  First, in your StaticWndProc, you need to check if the App * you get from GetWindowLong is NULL or not. If it's NULL, you should just pass the message on to DefWindowProc.Second, you should be calling DestroyWindow before trying to unregister the window's classname.   ;  That didn't actually solve the problem, but I probably should've been doing that anyway so thanks. With that in place, now my window closes but it keeps going through the main loop which is not a good thing considering the window is gone so it can't render to it any more.   ;  get rid of the "return 0" statement in the WM_CLOSE handling so that DefWindowProc can do its business and call DestroyWindow   ;  Again, the app just keeps running. The window gets destroyed no matter what, but I need to get my app out of the loop when the user hits close.   ;  Add a PostQuitMessage(0) to your WM_CLOSE handler.;  PostQuitMessage should be called from WM_DESTROY processing, not WM_CLOSE   ;Quote:Original post by Anonymous PosterPostQuitMessage should be called from WM_DESTROY processing, not WM_CLOSEActually, it doesn't matter. You can call PostQuitMessage from anywhere.However, I just realized that PostQuitMessage wouldn't make any difference here. His loop is supposed to terminate when mainLoopDone is true. Since the loope isn't terminating, it would appear that his WM_CLOSE handler is never getting executed.I would suggest putting a breakpoint in there to confirm whether it is even calling the app's window procedure.;  I've attempted to rewrite my app class into a singleton class because this is what I'd prefer. I only want the ability to have one window so the style fits my needs. I believe I've done everything correct as far as a singleton class (I believe), but I still get errors with it trying to read data from it, specifically in the App::Destroy() function. Here's the class and usage if anyone can help me out.EDIT: Turns out that I had a small problem which I caught and corrected in the code below so now it works perfectly. If anyone wants to use the class, feel free. It is a simple wrapper for a single window, Direct3D 9 application. I think it works rather well.App.h#pragma once#include <windows.h>#include <d3d9.h>class AppParameters{public:AppParameters(LPCSTR name, int w, int h, bool f, int cmdShow){wndClass.cbClsExtra = 0;wndClass.cbSize = sizeof(WNDCLASSEX);wndClass.cbWndExtra = 0;wndClass.hbrBackground = NULL;wndClass.hIcon= NULL;wndClass.hIconSm = NULL;wndClass.hCursor = NULL;wndClass.hInstance = GetModuleHandle(NULL);wndClass.lpszClassName = "AppClass";wndClass.style = CS_HREDRAW | CS_VREDRAW;wndClass.lpfnWndProc = NULL;wndClass.lpszMenuName = NULL;if(f){winStyle = WS_POPUP | WS_VISIBLE;x = y = 0;width = GetSystemMetrics(SM_CXSCREEN);height = GetSystemMetrics(SM_CYSCREEN);}else{winStyle = WS_OVERLAPPED | WS_SYSMENU | WS_VISIBLE;x = y = CW_USEDEFAULT;width = w;height = h;}fullscreen = f;winName = name;show = cmdShow;d3dAdapter = D3DADAPTER_DEFAULT;d3dDevType = D3DDEVTYPE_HAL;d3dFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;ZeroMemory(&pp, sizeof(pp));pp.BackBufferCount = 1;pp.BackBufferWidth = w;pp.BackBufferHeight = h;if(fullscreen){pp.BackBufferFormat = D3DFMT_X8R8G8B8;pp.Windowed = FALSE;}else{pp.BackBufferFormat = D3DFMT_UNKNOWN;pp.Windowed = TRUE;}pp.EnableAutoDepthStencil = FALSE;pp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;pp.MultiSampleType = D3DMULTISAMPLE_NONE;pp.SwapEffect = D3DSWAPEFFECT_DISCARD;}WNDCLASSEXwndClass;LPCSTRwinName;DWORDwinStyle;intx, y, width, height, show;boolfullscreen;UINTd3dAdapter;D3DDEVTYPEd3dDevType;DWORDd3dFlags;D3DPRESENT_PARAMETERSpp;bool(*initFunc)();HRESULT(*volatileInitFunc)();HRESULT(*volatileFreeFunc)();HRESULT(*preRenderFunc)();HRESULT(*renderFunc)();HRESULT(*postRenderFunc)();void(*exitFunc)();};enum AppReturn {APP_SUCCESS = 1,APP_FAIL_REGISTERCLASS = -1,APP_FAIL_CREATEWINDOW = -2,APP_FAIL_D3DCREATEOBJECT = -3,APP_FAIL_D3DGETDISPLAYMODE = -4,APP_FAIL_D3DCHECKDEVICE = -5,APP_FAIL_D3DCREATEDEVICE = -6,APP_FAIL_USERFUNC = -7,APP_FAIL_MAINLOOP = -8};class App{public:static AppReturn Init(AppParameters* = NULL);static void Destroy(void);static AppReturn MainLoop(void);static void EndMainLoop(void);static HWNDGetWindowHandle(void){ return app->window; }static IDirect3DDevice9*GetD3DDevice(void){ return app->d3dDevice; }private:static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);static App* app;App(void);~App(void);AppParametersparameters;HWNDwindow;IDirect3D9*d3dObject;IDirect3DDevice9*d3dDevice;boolinitialized, mainLoopDone;};App.cpp#include "App.h"App* App::app = NULL;App::App(void):parameters("App Window", 640, 480, false, 1), initialized(false), mainLoopDone(false){window = NULL;d3dObject = NULL;d3dDevice = NULL;}App::~App(void){}AppReturn App::Init(AppParameters* ap){if(!app)app = new App;if(ap != NULL)app->parameters = (*ap);app->parameters.wndClass.lpszMenuName = NULL;app->parameters.wndClass.lpfnWndProc = App::WndProc;app->parameters.wndClass.hInstance = GetModuleHandle(NULL);HRESULT hr;hr = RegisterClassEx(&app->parameters.wndClass);if(FAILED(hr))return APP_FAIL_REGISTERCLASS;RECT winRect = { 0, 0, app->parameters.width, app->parameters.height };    AdjustWindowRect(&winRect, app->parameters.winStyle, FALSE);app->window = CreateWindow(app->parameters.wndClass.lpszClassName, app->parameters.winName, app->parameters.winStyle,app->parameters.x, app->parameters.y, winRect.right - winRect.left, winRect.bottom - winRect.top,NULL, NULL, GetModuleHandle(NULL), app);if(!app->window)return APP_FAIL_CREATEWINDOW;app->d3dObject = Direct3DCreate9(D3D_SDK_VERSION);if(!app->d3dObject)return APP_FAIL_D3DCREATEOBJECT;D3DDISPLAYMODE mode;hr = app->d3dObject->GetAdapterDisplayMode(app->parameters.d3dAdapter, &mode);if(FAILED(hr))return APP_FAIL_D3DGETDISPLAYMODE;hr = app->d3dObject->CheckDeviceType(app->parameters.d3dAdapter, app->parameters.d3dDevType, mode.Format, app->parameters.pp.BackBufferFormat, app->parameters.pp.Windowed);if(FAILED(hr))return APP_FAIL_D3DCHECKDEVICE;hr = app->d3dObject->CreateDevice(app->parameters.d3dAdapter, app->parameters.d3dDevType, app->window,   app->parameters.d3dFlags, &app->parameters.pp, &app->d3dDevice);if(FAILED(hr))return APP_FAIL_D3DCREATEDEVICE;if(app->parameters.initFunc)if(!app->parameters.initFunc())return APP_FAIL_USERFUNC;app->initialized = true;return APP_SUCCESS;}void App::Destroy(void){if(!app->initialized || !app)return;if(app->parameters.exitFunc)app->parameters.exitFunc();if(app->d3dObject)app->d3dObject->Release();if(app->d3dDevice)app->d3dDevice->Release();delete app;PostQuitMessage(0);}AppReturn App::MainLoop(void){if(!app->initialized || !app)return APP_FAIL_MAINLOOP;HRESULT hr;MSG msg;while(!app->mainLoopDone){if(PeekMessage(&msg, app->window, 0, 0, PM_REMOVE)){TranslateMessage(&msg);DispatchMessage(&msg);}hr = app->d3dDevice->TestCooperativeLevel();if(SUCCEEDED(hr)){if(app->parameters.preRenderFunc){hr = app->parameters.preRenderFunc();if(FAILED(hr)){if(hr != D3DERR_DEVICELOST &&hr != D3DERR_DEVICENOTRESET)return APP_FAIL_USERFUNC;}}if(SUCCEEDED(hr)){if(app->parameters.renderFunc){hr = app->parameters.renderFunc();if(FAILED(hr)){if(hr != D3DERR_DEVICELOST &&hr != D3DERR_DEVICENOTRESET)return APP_FAIL_USERFUNC;}}if(SUCCEEDED(hr)){if(app->parameters.postRenderFunc){hr = app->parameters.postRenderFunc();if(FAILED(hr)){if(hr != D3DERR_DEVICELOST &&hr != D3DERR_DEVICENOTRESET)return APP_FAIL_USERFUNC;}}}}}if(hr == D3DERR_DEVICELOST){Sleep(500);if(app->parameters.volatileFreeFunc){hr = app->parameters.volatileFreeFunc();if(FAILED(hr))return APP_FAIL_USERFUNC;}}else if(hr == D3DERR_DEVICENOTRESET){hr = app->d3dDevice->Reset(&app->parameters.pp);if(SUCCEEDED(hr)){if(app->parameters.volatileInitFunc){hr = app->parameters.volatileInitFunc();if(FAILED(hr))return APP_FAIL_USERFUNC;}}}else if(FAILED(hr))APP_FAIL_MAINLOOP;}return APP_SUCCESS;}void App::EndMainLoop(void){if(app)app->mainLoopDone = true;}LRESULT CALLBACK App::WndProc(HWND win, UINT msg, WPARAM wparam, LPARAM lparam){if(!app)return DefWindowProc(win, msg, wparam, lparam);switch(msg){case WM_CLOSE:app->mainLoopDone = true;break;default:return DefWindowProc(win, msg, wparam, lparam);}return 0;}main.cpp#include <windows.h>#include <d3d9.h>#include <d3dx9.h>#include <dxerr9.h>#include "App.h"bool Init(void){return true;}void Exit(void){}HRESULT PreRender(void){return S_OK;}HRESULT Render(void){return S_OK;}HRESULT PostRender(void){return S_OK;}int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int cmdShow){AppParameters ap("Racing", 1024, 768, false, cmdShow);ap.pp.EnableAutoDepthStencil = TRUE;ap.pp.AutoDepthStencilFormat = D3DFMT_D24X8;ap.initFunc = Init;ap.preRenderFunc = PreRender;ap.renderFunc = Render;ap.postRenderFunc = PostRender;ap.exitFunc = Exit;App::Init(&ap);App::MainLoop();App::Destroy();return 0;}[Edit: Content wider than the browser window is annoying. - Oluseyi]   ;Quote:Original post by NickGravelynI've attempted to rewrite my app class into a singleton class because this is what I'd prefer.It's a bad design. Singletons are basically "OO" globals. And globals should be very carefully deployed because of the absence of ownership semantics.Congratulations on fixing your bug, though.   