Jump to content
  • Advertisement
Sign in to follow this  
Robulus

DirectX and Windows Event Loop

This topic is 2859 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi All,

I've got a simple DirectX page-flipping program which creates a test image and then flips the frames so that the left and right eye see a different image. I'm using NVIDIA GeForce 9800 and NVIDIA glasses. The Stereoscopic viewing is working fine, but when it comes time to exit the fullscreen window and return to my base program, my DirectX window will not close until after my base program closes (I think) and I can't get to my base program because DirectX is on top and covering the whole screen. (Think of this like an image viewer. First I have to load the images, and then initiate Direct3D to view in stereo.) If I push ALT+F4, nothing noticeable happens and if I push ALT+F4 a second time, the DirectX window closes and so does my base window. Any advice you can give me? (source below)

Thanks,

Rob


// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch(message)
{
// keyboard event
case WM_KEYDOWN:
{
// destroy window
DestroyWindow(hWnd);
PostQuitMessage(0);
}
break;

// this message is read when the window is closed
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return (0);
}
// break;

default : ;
}

// Handle any messages the switch statement didn't
return (DefWindowProc (hWnd, message, wParam, lParam));
}

// stereo 3D entry point
void STEREO3D_Activate(HWND hParent)
{
// this struct holds information for the window class
WNDCLASSEX WindowClass;

// clear out the window class for use
ZeroMemory(&WindowClass, sizeof(WNDCLASSEX));

// fill in the struct with the needed information
WindowClass.cbSize = sizeof(WNDCLASSEX);
WindowClass.style = CS_HREDRAW | CS_VREDRAW;
WindowClass.lpfnWndProc = WindowProc;
WindowClass.hInstance = (HINSTANCE)GetWindowLong(hParent, GWL_HINSTANCE);
WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);

// wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
WindowClass.lpszClassName = "WindowClass1";

// register the window class
RegisterClassEx(&WindowClass);

// create the window and use the result as the handle
STEREO3D_hWnd = CreateWindowEx(NULL, // default style
"WindowClass1", // name of window class
"3DVision Test", // title of window
WS_EX_TOPMOST | WS_POPUP, // fullscreen values
0, 0, // x,y position of the window
STEREO3D_Width, // width of the window
STEREO3D_Height, // height of the window
NULL, // no parent window
NULL, // no menus
WindowClass.hInstance, // application handle
NULL); // for multiple windows

// display 3D window on screen
ShowWindow(STEREO3D_hWnd, SW_SHOWNORMAL);

// create the Direct3D interface
STEREO3D_Direct3D9 = Direct3DCreate9(D3D_SDK_VERSION);

// create a struct to hold various device information
D3DPRESENT_PARAMETERS Direct3DPresentParameters;

// clear out the struct for use
ZeroMemory(&Direct3DPresentParameters, sizeof(Direct3DPresentParameters));

// configure device
Direct3DPresentParameters.Windowed = FALSE; // program fullscreen
Direct3DPresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames
Direct3DPresentParameters.hDeviceWindow = STEREO3D_hWnd; // set the window to be used by Direct3D
Direct3DPresentParameters.BackBufferFormat = D3DFMT_A8R8G8B8; // set the back buffer format to 32 bit
Direct3DPresentParameters.BackBufferWidth = STEREO3D_Width;
Direct3DPresentParameters.BackBufferHeight = STEREO3D_Height;
Direct3DPresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
Direct3DPresentParameters.BackBufferCount = 1;

// create a device class using this information and information from the Direct3DPresentParameters stuct
STEREO3D_Direct3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, STEREO3D_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &Direct3DPresentParameters, &STEREO3D_Direct3DDevice9);

// create the surface
STEREO3D_Direct3DDevice9->CreateOffscreenPlainSurface(STEREO3D_Width*2, STEREO3D_Height+1, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &STEREO3D_ImageSourceSurface, NULL);

// create supporting bitmap info structure
STEREO3D_BitmapInfo = (BITMAPINFO *)malloc(sizeof(BITMAPINFO));

// load bitmap parameters for use
STEREO3D_BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFO);
STEREO3D_BitmapInfo->bmiHeader.biWidth = STEREO3D_BitmapL1.bmWidth;
STEREO3D_BitmapInfo->bmiHeader.biHeight = STEREO3D_BitmapL1.bmHeight;
STEREO3D_BitmapInfo->bmiHeader.biPlanes = 1;
STEREO3D_BitmapInfo->bmiHeader.biBitCount = STEREO3D_BitmapL1.bmBitsPixel;
STEREO3D_BitmapInfo->bmiHeader.biCompression = 0;
STEREO3D_BitmapInfo->bmiHeader.biSizeImage = STEREO3D_BitmapL1.bmWidthBytes * STEREO3D_BitmapL1.bmHeight;
STEREO3D_BitmapInfo->bmiHeader.biXPelsPerMeter = 0;
STEREO3D_BitmapInfo->bmiHeader.biYPelsPerMeter = 0;
STEREO3D_BitmapInfo->bmiHeader.biClrUsed = 0;
STEREO3D_BitmapInfo->bmiHeader.biClrImportant = 0;

// copy left image data to left half of surface
CopyBitmapToSurface(STEREO3D_ImageSourceSurface, &STEREO3D_BitmapL1, 0, 0, STEREO3D_Width, STEREO3D_Height);

// copy right image data to right half of surface
CopyBitmapToSurface(STEREO3D_ImageSourceSurface, &STEREO3D_BitmapR1, STEREO3D_Width, 0, STEREO3D_Width, STEREO3D_Height);

// Lock the stereo image
D3DLOCKED_RECT LockedRect;
STEREO3D_ImageSourceSurface->LockRect(&LockedRect, NULL, 0);

// write stereo signature in the last raw of the stereo image
LPNVSTEREOIMAGEHEADER pStereoImageHeader = (LPNVSTEREOIMAGEHEADER)(((unsigned char *) LockedRect.pBits) + (LockedRect.Pitch * (STEREO3D_Height)));

// Update the signature header values
pStereoImageHeader->dwSignature = NVSTEREO_IMAGE_SIGNATURE;
pStereoImageHeader->dwBPP = 32;
// pStereoImageHeader->dwFlags = SIH_SWAP_EYES; // unnecessary (source image has left on left and right on right)
pStereoImageHeader->dwWidth = STEREO3D_Width*2;
pStereoImageHeader->dwHeight = STEREO3D_Height;

// Unlock surface
STEREO3D_ImageSourceSurface->UnlockRect();

// set destRect
RECT destRect;
destRect.left = 0;
destRect.top = 0;
destRect.right = STEREO3D_Width;
destRect.bottom = STEREO3D_Height;

// this struct holds Windows event messages
MSG msg;

// Enter the infinite message loop
while (TRUE)
{
// Check to see if any messages are waiting in the queue
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);

// send the message to the WindowProc function
DispatchMessage(&msg);
}

// If the message is WM_QUIT, exit the while loop
if(msg.message == WM_QUIT)
break;

// begins the 3D scene
STEREO3D_Direct3DDevice9->BeginScene();

// Get the Backbuffer then Stretch the Surface on it.
STEREO3D_Direct3DDevice9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &STEREO3D_BackBufferSurface);
STEREO3D_Direct3DDevice9->StretchRect(STEREO3D_ImageSourceSurface, NULL, STEREO3D_BackBufferSurface, &destRect, D3DTEXF_NONE);

// end 3D scene creation
STEREO3D_Direct3DDevice9->EndScene();

// displays the created frame
STEREO3D_Direct3DDevice9->Present(NULL, NULL, NULL, NULL);
}

// free resources
free(STEREO3D_BitmapInfo);

// release surfaces
STEREO3D_ImageSourceSurface->Release();
STEREO3D_BackBufferSurface->Release();

// close and release the 3D device
STEREO3D_Direct3DDevice9->Release();

// close and release Direct3D API
STEREO3D_Direct3D9->Release();

// unregister display class (cleanup windows overhead)
UnregisterClass(WindowClass.lpszClassName, WindowClass.hInstance);
}
//---------------------------------------------------------------------------

Share this post


Link to post
Share on other sites
Advertisement
This code will cause a WM_QUIT message to be sent to your thread when the window is closed (Alt+F4, clicking the 'X' close button, etc):

case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return (0);
}


which will cause STEREO3D_Activate to return. Is that not what happens?

Share this post


Link to post
Share on other sites
as near as I can tell with my log file, the STEREO3D_hWnd window continues to process messages until ALT+F4 is pressed the second time... the ideal behavior would be to exit when the VK_ESC is pressed, but I can't seem to get that either... at this point, I'll settle for any keyboard event... ;)


LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
// keyboard event
case WM_KEYDOWN:
{
// destroy window
DestroyWindow(hWnd);
PostQuitMessage(0);
}
break;

// this message is read when the window is closed
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return (0);
}

default : ;
}

return (DefWindowProc (hWnd, message, wParam, lParam));
}

Share this post


Link to post
Share on other sites
here's an update... if I branch for WM_KEYUP (or VK_ESCAPE) in my loop, then I can exit the Window as expected...

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;

default :
return (DefWindowProc (hWnd, message, wParam, lParam));
}

return (0);
}


while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

if (msg.wParam == VK_ESCAPE)
break;

STEREO3D_Direct3DDevice9->BeginScene();
STEREO3D_Direct3DDevice9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &STEREO3D_BackBufferSurface);
STEREO3D_Direct3DDevice9->StretchRect(STEREO3D_ImageSourceSurface, NULL, STEREO3D_BackBufferSurface, &destRect, D3DTEXF_NONE);
STEREO3D_Direct3DDevice9->EndScene();
STEREO3D_Direct3DDevice9->Present(NULL, NULL, NULL, NULL);
}

Share this post


Link to post
Share on other sites
...making progress. I've got the DirectX window closing, but my WinProc callback function is still being called. I suspect the program is stalling as windows gives the "Program has stopped responding" error message.

I have unregistered the window. If I use DestroyWindow() then my parent window closes as well, though everything looks clean. Any suggestions? This code is not part of a standard WinMain() function, but rather a function called by a parent window...


MSG ThisMessage;

do
{
if (PeekMessage(&ThisMessage, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&ThisMessage);
DispatchMessage(&ThisMessage);
}

STEREO3D_Direct3DDevice9->BeginScene();

STEREO3D_Direct3DDevice9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &STEREO3D_BackBufferSurface);

STEREO3D_Direct3DDevice9->StretchRect(STEREO3D_ImageSourceSurface, NULL, STEREO3D_BackBufferSurface, &destRect, D3DTEXF_NONE);

STEREO3D_Direct3DDevice9->EndScene();

STEREO3D_Direct3DDevice9->Present(NULL, NULL, NULL, NULL);
}
while (ThisMessage.wParam != VK_ESCAPE);

free(STEREO3D_BitmapInfo);

STEREO3D_ImageSourceSurface->Release();
STEREO3D_BackBufferSurface->Release();
STEREO3D_Direct3DDevice9->Release();
STEREO3D_Direct3D9->Release();

UnregisterClass(WindowClass.lpszClassName, WindowClass.hInstance);

Share this post


Link to post
Share on other sites
I have confirmed that the program is crashing in the call to DefWindowProc() inside my WindowProc callback after I have released everything. :(

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return (0);
}
// break;

default : ;
}

LRESULT ThisResult = DefWindowProc(hWnd, message, wParam, lParam);

return (ThisResult);
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!