Skip to main content
gamedev.net
🔒 Locked

Strange fullscreen/windowed problem

Started by ouraqt Jan 24, 2007 at 1:31 AM 9 replies 1.6k views
Original Post
ouraqt
ouraqt
I'm working on a 3D engine that uses D3D 9 (unmanaged). After lots of confusion I finally came up with some code that will switch between fullscreen and windowed mode. Here is most of it: // Determine the new window style DWORD dwstyle = (FullScreen)?dwstyleFull:dwstyleWin; // Apply the new window style ShowWindow(hWnd, SW_HIDE); SetWindowLong(hWnd, GWL_style, dwstyle); SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); ShowWindow(hWnd, SW_SHOW); // Calculate the new size of the window based on the client size RECT clientArea = {0, 0, D3DPP.BackBufferWidth, D3DPP.BackBufferHeight}; AdjustWindowRect(&clientArea, dwstyle, false); // Apply the new window position MoveWindow(hWnd, 0, 0, clientArea.right-clientArea.left, clientArea.bottom-clientArea.top, true); // Apply the new fullscreen mode and size to the backbuffer D3DPP.Windowed = !FullScreen; D3DPP.FullScreen_RefreshRateInHz = (D3DPP.Windowed)?0:iRefreshRate; D3DPP.BackBufferFormat = (D3DPP.Windowed)?(D3DFMT_UNKNOWN):(D3DFMT_X8R8G8B8); // Reset the device Reset(); The code makes a few calls to internal engine functions, but it should be clear what's going on. The problem is that after I switch from fullscreen mode to windowed mode, the window always stays on top! I can bring other windows into focus, but for some reason they remain behind the D3D window. I'm not sure if the problem lies within the code above but any help would be greatly appreciated. Also, if there is a better way to switch between fullscreen/window, please do tell. (Should I use 2 separate windows, and hide the inactive one?) I haven't seen any documentation on this.
Kambiz
Kambiz
I think you are passing WS_EX_TOPMOST as an window style to CreateWindowEx(…). If this is true just delete WS_EX_TOPMOST.
ouraqt
ouraqt
I'm sure I'm not. Just to make sure, I did a quick string search for "WS_EX_TOPMOST", 0 results.

Anyway, it might have to do with the way I'm handling my windows messages. I use this as part of the program loop:

// Recieve Windows messages
MSG Msg;
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

and my window procedure only processes the WM_SIZE and WM_CLOSE messages. WM_SIZE is only used to sync the backbuffer size with the window (client) size.

Has anyone ever had a problem like this before?
Kambiz
Kambiz
What about WS_EX_PALETTEWINDOW ?
Because WS_EX_PALETTEWINDOW Combines the WS_EX_WINDOWEDGE, WS_EX_TOOLWINDOW, and WS_EX_TOPMOST styles.

What is the value of dwstyleWin ?
ouraqt
ouraqt
dwstyleWin is WS_OVERLAPPEDWINDOW.
dwstyleFull is WS_POPUP.

Actually, there is a setting that allows the window to not be resizeable (ie. there is no resize border or maximize button), which changes dwstyleWin to WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX. But I didn't have this mode enabled, so it shouldn't be a problem (well, it shouldn't be a problem anyway).

The problem may lie in changing window styles. Am I doing this correctly using SetWindowLong(...)?

Even stranger, this glitch only happens after I have switched from fullscreen mode to windowed mode.
Endurion
Endurion
AFAIK Direct3d subclasses your HWND and also sets the WS_EX_TOPMOST during fullscreen. But it doesn't remove it.

This means if you switch from fullscreen to windowed you have to remove the style yourself. Just use SetWindowLong with GWL_style_EX to remove that style.
Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>
ouraqt
ouraqt
Thank you so much - I'll try it out. I didn't know D3D changed the window - and what is subclassing?

And one more thing. Is it necessary to hide the window before changing its style? I can't seem to change the style of a visible window using SetWindowLong(...) and SetWindowPos(...) without my computer freaking out.

Edit: I couldn't get it to work. I'm getting the same error as before. How do most people switch between fullscreen/windowed modes?

Perhaps I need to use two windows.

[Edited by - ouraqt on January 26, 2007 10:28:33 AM]
Endurion
Endurion
It's not necessary to hide and show the window.

You have to reset the border styles and after the call to SetWindowLong you need to call SetWindowPos with the SWP_FRAME_CHANGED flag set.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>
ouraqt
ouraqt
I was using SWP_FRAME_CHANGED (I think it's actually SWP_FRAMECHANGED, and I was using that). What is meant by "reset the border styles?" Isn't that what I was doing?
Endurion
Endurion
Yes, if your dwstyleFull and dwstyleWin contain the whole style flags you're doing it almost. You also need to store the extended style flags.

In my code i additionally keep the WINDOWPLACEMENT for the windowed mode so the window keeps it's position and state when returning from fullscreen.

Also i remove the WS_EX_TOPMOST style after i reset the window to windowed mode.
Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>
ouraqt
ouraqt
I actually am using a WINDOWPLACEMENT struct now - it's a lot cleaner that keeping all the window position, size, show state, etc. in separate variables (like I was doing before!).

Quote:

Also i remove the WS_EX_TOPMOST style after i reset the window to windowed mode.
And this is because D3D adds this window style when in fullscreen mode, correct? I would think that Direct3D would clean up its own mess. Anyway, I tried it with no luck.

Quote:
Yes, if your dwstyleFull and dwstyleWin contain the whole style flags you're doing it almost. You also need to store the extended style flags.
Well, at this point I'm just using 0 as my extended window style.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.