Sign in to follow this  
malborojones

DirectX 9 switching window state

Recommended Posts

Hellow :)
I've searched for about 2 hours around the web for a guide on how to switch a window from windowed to full screen after runtime.
I can do it fine at run time but I want to be able to switch back and forth.

I've made this method but when it's called the screen just goes white:

First it creates the new window style and updates the window

[code]


//Create new window style
DWORD style = (windowed) ?
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX :
WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE;

//set new window style
SetWindowLong(mHwnd, GWL_STYLE, style);
ShowWindow(mHwnd, SW_SHOW);
UpdateWindow(mHwnd);

[/code]


then updates the present parameters for the device

[code]

mPresent.hDeviceWindow = mHwnd;
mPresent.Windowed = (windowed) ? TRUE : FALSE;
mPresent.BackBufferFormat = (windowed) ? D3DFMT_UNKNOWN : D3DFMT_X8R8G8B8;
[/code]


mPresent are the present parameters used initially to create the device so I just update the values that need to be changed.

Next I call reset with the new parameters

[code]

hr = mDevice->Reset(&mPresent);

if (FAILED(hr))
{
if(hr == D3DERR_DEVICELOST)
ErrMsg("Device Lost");

if(hr == D3DERR_DEVICEREMOVED)
ErrMsg("Device Removed");

if(hr == D3DERR_DRIVERINTERNALERROR)
ErrMsg("Driver Error");

if(hr == D3DERR_OUTOFVIDEOMEMORY)
ErrMsg("Out of memory");
}
[/code]


After this is done I don't get any of the errors that the MS site says it returns so none of the messages are shown but if I check if hr has failed I do get an error and hr has the value -2005530516

So what am I doing wrong? I keep seeing something about "state blocks" being released before calling Reset but I have no idea what they are and presume I haven't used any that need to be released.

So, any idea how to go about this correctly?

Thanks, Mal.
[img]http://public.gamedev.net/public/style_emoticons/default/ph34r.gif[/img]

Share this post


Link to post
Share on other sites
try searching MSDN for [i]Window Features [/i](my links seam to point to my local one, but ill try to link to the online one)
[url="http://msdn.microsoft.com/en-us/library/ms632599%28v=vs.85%29.aspx"]This might be the online version[/url]

the local one has [b]too[/b] much text to paste here.
ill update when i find it

Share this post


Link to post
Share on other sites
[quote name='malborojones' timestamp='1306251201' post='4815152']
[quote name='ryan20fun' timestamp='1306250986' post='4815150']
Try Reading This
[/quote]

What's this? xD
[/quote]

link pointed to my local one :P

Share this post


Link to post
Share on other sites
I understand the whole windows style stuff (that's what the link you gave me seems to be on)
when I try switching, the style of the window changes as it should e.g. the borders disappear when it should be full screen and show again when it's set to windowed but the window just goes white. That doesn't really make much sense because my render function clears the screen black before anything else.

Also before changing I have two sprites on the screen that I can move around with the arrow keys, once I try to switch mode they disappear as well as the screen going white.

Share this post


Link to post
Share on other sites
the DirectX device could be lost, i hade that when i was experimenting with Fullscreen and then minimizeing it.
you need to resoet the device and reload your assets (refer to the DirectX documentation on what needs to be reloaded, but as far as i know you have to reser and reload everything but shaders)

Share this post


Link to post
Share on other sites
what you can do is create a borderless window at the current screen resolution to fake full screen.
what you could do is to reset the device with nre presentation params that state that it should be fullscreen.

Share this post


Link to post
Share on other sites
May I direct you to the very well written tutorial/article of Evil Steve about this particular subject [url="http://thetavern.servebeer.com/?p=articles&a=D3DTutorial3"]here[/url]? Hope this helps.

Share this post


Link to post
Share on other sites
[quote]So do you mean that all textures have to be reloaded, sprites remade etc.?[/quote]
Not if they're created with D3DPOOL_MANAGED...

You only have to release and recreate unmanaged resources when you do a device reset. In most cases, the only reason you would ever create an unmanaged resource is if it can't be managed (e.g. D3DUSAGE_DYNAMIC).

Share this post


Link to post
Share on other sites
If I may add my 2 pennies worth of limited knowledge on this -

When you change from full to windowed or visa versa, you need to release any resources that you created with the *POOL_DEFAULT parameter. If I've read the docs correctly, the ones created with MANAGED will live through the change without problems - I'm open to be corrected on this.

I hope this helps some. And yes, I do believe you load everything back in.

Share this post


Link to post
Share on other sites
[quote name='auto.magician' timestamp='1306257683' post='4815203']
If I may add my 2 pennies worth of limited knowledge on this -

When you change from full to windowed or visa versa, you need to release any resources that you created with the *POOL_DEFAULT parameter. If I've read the docs correctly, the ones created with MANAGED will live through the change without problems - I'm open to be corrected on this.

I hope this helps some. And yes, I do believe you load everything back in.


[/quote]

yip, i think that is about right too :cool:

Share this post


Link to post
Share on other sites
Ughhhhh that sounds so annoying x)

All the images I load are using POOL_DEFAULT which means I'm going to have to add something that keeps track of all images that are loaded and then some way of reloading all images and recreating all the sprites D:

I've been trying the workaround ryan suggested with making it look full screen by changing the screen resolution but can't figure out how to do that in C++
I tried changing my method to do this:

[code]

if (!windowed)
{
//setup the device mode
DEVMODE devmode;
devmode.dmSize = sizeof(DEVMODE);
devmode.dmPelsWidth = mGameWindow.GetWidth();
devmode.dmFields |= DM_PELSWIDTH;
devmode.dmPelsHeight = mGameWindow.GetHeight();
devmode.dmFields |= DM_PELSHEIGHT;
devmode.dmBitsPerPel = 32;
devmode.dmFields |= DM_BITSPERPEL;

//position the window to 0, 0
mGameWindow.SetPosition(0, 0);
//change screen resolution
ChangeDisplaySettings(&devmode, 0);
} else {
//set screen resolution to initial settings
ChangeDisplaySettings(&initDev, 0);
//position window in middle of the screen
mGameWindow.CenterScreen();
}
[/code]


But that doesn't seem to do anything at all, the window moves like I tell it to (0,0 for full screen and back to the middle for windowed) and the border disappears and comes back when windowed like it should but the screen resolution itself doesn't change. Any ideas how to do this? it'll save having to do all the reloading of textures etc.

Share this post


Link to post
Share on other sites
[quote name='ryan20fun' timestamp='1306253205' post='4815166']
the DirectX device could be lost, i hade that when i was experimenting with Fullscreen and then minimizeing it.
you need to resoet the device and reload your assets (refer to the DirectX documentation on what needs to be reloaded, but as far as i know you have to reser and reload everything but shaders)
[/quote]

Your probably right, the device gets lost on an alt + TAB, and what ive seen in Luna code, you change the back buffer dimensions etc, and then you have to reset the change to enable full screen

Share this post


Link to post
Share on other sites
[quote name='malborojones' timestamp='1306262390' post='4815238']
Ughhhhh that sounds so annoying x)

All the images I load are using POOL_DEFAULT which means I'm going to have to add something that keeps track of all images that are loaded and then some way of reloading all images and recreating all the sprites D:

I've been trying the workaround ryan suggested with making it look full screen by changing the screen resolution but can't figure out how to do that in C++
I tried changing my method to do this:

[code]

if (!windowed)
{
//setup the device mode
DEVMODE devmode;
devmode.dmSize = sizeof(DEVMODE);
devmode.dmPelsWidth = mGameWindow.GetWidth();
devmode.dmFields |= DM_PELSWIDTH;
devmode.dmPelsHeight = mGameWindow.GetHeight();
devmode.dmFields |= DM_PELSHEIGHT;
devmode.dmBitsPerPel = 32;
devmode.dmFields |= DM_BITSPERPEL;

//position the window to 0, 0
mGameWindow.SetPosition(0, 0);
//change screen resolution
ChangeDisplaySettings(&devmode, 0);
} else {
//set screen resolution to initial settings
ChangeDisplaySettings(&initDev, 0);
//position window in middle of the screen
mGameWindow.CenterScreen();
}
[/code]


But that doesn't seem to do anything at all, the window moves like I tell it to (0,0 for full screen and back to the middle for windowed) and the border disappears and comes back when windowed like it should but the screen resolution itself doesn't change. Any ideas how to do this? it'll save having to do all the reloading of textures etc.
[/quote]

so, that code imatates fullscreen ?
can you post the code that creates the window ?

what i would do is this (i have my screen set to 1024x768)
set window position to 0,0
and screen width and height to 1024,768
and make it a borderless window (i hade the code to do this but i dont think i have it anymore, but you should only need to set the borderstyle to none)

Share this post


Link to post
Share on other sites
Excellent, I changed the size of the window instead of having to change the actual screen resolution and it worked perfectly.
The only problem is that if the window is an odd shape the images and sprites get stretched (mine is 800x600 so it was fine scaling wise)
That's why I'd rather actually change the screen resolution if it's possible, but thank's for the help, that will do for now until I can find a better way or can be bothered to actually use the reset device method [img]http://public.gamedev.net/public/style_emoticons/default/tongue.gif[/img]

Thanks, Mal [img]http://public.gamedev.net/public/style_emoticons/default/cool.gif[/img]

Share this post


Link to post
Share on other sites
[quote name='malborojones' timestamp='1306266121' post='4815268']
Excellent, I changed the size of the window instead of having to change the actual screen resolution and it worked perfectly.
The only problem is that if the window is an odd shape the images and sprites get stretched (mine is 800x600 so it was fine scaling wise)
That's why I'd rather actually change the screen resolution if it's possible, but thank's for the help, that will do for now until I can find a better way or can be bothered to actually use the reset device method [img]http://public.gamedev.net/public/style_emoticons/default/tongue.gif[/img]

Thanks, Mal [img]http://public.gamedev.net/public/style_emoticons/default/cool.gif[/img]
[/quote]

when you figure that out, can you PM me or post it here ?

Share this post


Link to post
Share on other sites
I found a way of changing the screen resolution, I wasn't far off already:

[code]


DEVMODE dm;
dm.dmSize = sizeof(DEVMODE);

if(windowed)
{
dm.dmPelsWidth = initDev.dmPelsWidth;
dm.dmPelsHeight = initDev.dmPelsHeight;
dm.dmFields = (DM_PELSWIDTH | DM_PELSHEIGHT);
} else {
dm.dmPelsWidth = mGameWindow.GetWidth();
dm.dmPelsHeight = mGameWindow.GetHeight();
dm.dmFields = (DM_PELSWIDTH | DM_PELSHEIGHT);
}

ChangeDisplaySettings(&dm, 0);

[/code]


But it would seem that it causes the device to be lost because the contents of the window go white again [img]http://public.gamedev.net/public/style_emoticons/default/sad.gif[/img]
I suppose the only way of doing it is to reset everything which is just so annoying D: I'll work on it tomorrow maybe.
Thanks for all the help [img]http://public.gamedev.net/public/style_emoticons/default/smile.gif[/img]

Share this post


Link to post
Share on other sites
Device can even lost from a popup window that rapes your frame buffer. You can not avoid coding this if you creates a directx based application.

Share this post


Link to post
Share on other sites
[quote name='malborojones' timestamp='1306282098' post='4815368']
I found a way of changing the screen resolution, I wasn't far off already:

[code]


DEVMODE dm;
dm.dmSize = sizeof(DEVMODE);

if(windowed)
{
dm.dmPelsWidth = initDev.dmPelsWidth;
dm.dmPelsHeight = initDev.dmPelsHeight;
dm.dmFields = (DM_PELSWIDTH | DM_PELSHEIGHT);
} else {
dm.dmPelsWidth = mGameWindow.GetWidth();
dm.dmPelsHeight = mGameWindow.GetHeight();
dm.dmFields = (DM_PELSWIDTH | DM_PELSHEIGHT);
}

ChangeDisplaySettings(&dm, 0);

[/code]


But it would seem that it causes the device to be lost because the contents of the window go white again [img]http://public.gamedev.net/public/style_emoticons/default/sad.gif[/img]
I suppose the only way of doing it is to reset everything which is just so annoying D: I'll work on it tomorrow maybe.
Thanks for all the help [img]http://public.gamedev.net/public/style_emoticons/default/smile.gif[/img]
[/quote]

i am unfimiliar with the DEVMODE structure, and what i found on it says that is ise used for printer or screen settings or something.
why do you use it ? / what benifet does it have over not using it ?

Share this post


Link to post
Share on other sites
[quote name='Geri' timestamp='1306284660' post='4815381']
Device can even lost from a popup window that rapes your frame buffer. You can not avoid coding this if you creates a directx based application.
[/quote]

but the documentation said that you only have to recreate the data if the device is lost,
or did i miss sometihng ?

Share this post


Link to post
Share on other sites
The documentation also says that if you change the presentation parameters, which needs to be done when switching between full screen to windowed or back again, then the device needs to be reset, to reset the device you need to manage the unmanaged resources as they will be lost from the graphics card memory.

Share this post


Link to post
Share on other sites
[quote name='ryan20fun' timestamp='1306305987' post='4815470']
[quote name='Geri' timestamp='1306284660' post='4815381']
Device can even lost from a popup window that rapes your frame buffer. You can not avoid coding this if you creates a directx based application.
[/quote]

but the documentation said that you only have to recreate the data if the device is lost,
or did i miss sometihng ?
[/quote]

You must create new device and upload all data to dx again.

Share this post


Link to post
Share on other sites
Not really sure ^_^ that's the only way I could find to do it. I think it's just needed for the parameter of "ChangeDisplaySettings" You can use DEVMODE to set the colour depth also from what I've seen and some other display setting stuff like refresh rate, then just pass it into ChangeDisplaySettings and everything changes. When the program starts I also fill in the "initDev" with the initial setting so that they can be restored when the program closes, it works so I don't question it [img]http://public.gamedev.net/public/style_emoticons/default/tongue.gif[/img]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this