   [SOLVED] problem while changing windowed/fullscreen mode
  Hi,I'm developing a 2d game engine with directx and cpp language.By pressing the F2 key the player can switch between fullscreen and windowed mode. I correctly use the TestCooperativeLevel and device Reset, releasing and reacquiring all textures, I obtain the switch between the two modes but i have a problem when i change the window style.The code, (inside an Update function called every window main loop) after device reset and objects reallocation is as follow:if(this->full_screen_mode){   ::SetWindowLongPtr(this->hWnd, GWL_EXstyle, 0);   ::SetWindowLongPtr(this->hWnd, GWL_style, WS_EX_TOPMOST | WS_VISIBLE | WS_POPUP);}else{   ::SetWindowLongPtr(this->hWnd, GWL_EXstyle, 256);   ::SetWindowLongPtr(this->hWnd, GWL_style, WS_OVERLAPPEDWINDOW);}::SetWindowPos(this->hWnd, NULL, CW_USEDEFAULT, CW_USEDEFAULT, this->Get_screen_width(),this->Get_screen_height(), SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW);I start in windowed mode and send to a text file the GWL_style and GWL_EXstyle by using getWindowLong, the value of GWL_EXstyle is 256 as set by the initial CreateWindow winapi.After switching to full screen mode i find the correct value for GWL_style but the value 8 for GWL_EXstyle in place of 0. Then, switching to windowed mode again i find inside the logfile the GWL_style with the correct value but the GWL_EXstyle with value 264 (=256 + 8 (00001000 binary coded)) in place of 256.Why are my settings ignored by windows? A collateral effect is that after switching from the initial windowed mode to fullscreen and windowed mode again, the fps drops from 60fps to 34fps, my window remains always on top and if i press ALT-TAB my window loose focus but the other windows remains always behind it. I've tryed lots of changes without having the right result. I'm coming crazy!Thank you for your help(i'm sorry, this problem was formerly posted in the wrong section "General Programming", now i moved it into the more appropriate Directx section; i've tried to find between other posts but anyone seems to have the same problem)[Edited by - fabry on June 25, 2009 4:53:52 AM]
  8 in the extended style is WS_EX_TOPMOST. That explains why your window is always on top. As for why you get a lower FPS; is the window the correct size? You'll probably have to resize the window when going to windowed mode, since you'll need to account for the window borders (Much like how you need to use AdjustWindowRectEx when you create the window).Also, this looks wrong to me:::SetWindowLongPtr(this->hWnd, GWL_style, WS_EX_TOPMOST | WS_VISIBLE | WS_POPUP);You can't mix extended and non-extended styles like that.   ;  Hi Steve, thank you very much for your quickly answer.mmmhhhh the size should be correct, i use the same variables, screen_width and screen_height, used inside the initialization function (the one which contains the CreateWindow). I sent the two values to the log file and seem to be ok (1024x768).I've also tryed to reduce the size of the window with ::SetWindowPos(.......,screen_width - 200, screen_height - 200,....) to see what happens but i still obtain a maximized window. Windows simply ignore the setting.Is the ::SetWindowPos ok for resizing the window? Or it must be replaced by the AdjustWindowRectEx api?I'll take a deeper look at the ::SetWindowLongPtr api documentationWhat sounds strange to me is that while toggling to windowed mode, I change the GWL_EXstyle to 256 to avoid the flag WS_EX_TOPMOST but the log reports to me that the GWL_EXstyle is still 264 so the flag i set   ;Quote:Original post by fabryHi Steve, thank you very much for your quickly answer.mmmhhhh the size should be correct, i use the same variables, screen_width and screen_height, used inside the initialization function (the one which contains the CreateWindow). I sent the two values to the log file and seem to be ok (1024x768).I've also tryed to reduce the size of the window with ::SetWindowPos(.......,screen_width - 200, screen_height - 200,....) to see what happens but i still obtain a maximized window. Windows simply ignore the setting.Is the ::SetWindowPos ok for resizing the window? Or it must be replaced by the AdjustWindowRectEx api?SetWindowPos is fine; but if your window has borders (I.e. has the WS_OVERLAPPED style) you should be using AdjustWindowRectEx to determine the correct window size to use - If you pass 1024,768 to CreateWindowEx, the window is 1024x768, but the client area will be something like 1018x742 because of the size of the borders and title bar. That means that if your backbuffer is 1024x768, you don't have a 1 to 1 mapping of backbuffer pixels to window pixels, which can give you weird effects, and totally breaks picking.When you're specifying the size for the window with SetWindowPos(), you are removing the SWP_NOSIZE flag, right?Quote:Original post by fabryWhat sounds strange to me is that while toggling to windowed mode, I change the GWL_EXstyle to 256 to avoid the flag WS_EX_TOPMOST but the log reports to me that the GWL_EXstyle is still 264 so the flag i setWhy do you set it to 256? You should be using WS_EX_WINDOWEDGE or nothing at all - depending on what you want.My fullscreen toggle code is:// Change window style to remove border in fullscreen modeDWORD dwStyle;if(m_thePresentParams.Windowed)dwStyle = (WS_OVERLAPPEDWINDOW | WS_VISIBLE) & ~WS_THICKFRAME;elsedwStyle = WS_POPUP;SetWindowLongPtr(m_hWnd, GWL_STYLE, dwStyle);// Make sure the changes are flushedSetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);I never touch the extended style, because my code doesn't need any extended style bits set.   ;  Hi Steve, I have no need in my code to change the size of the window. I have a resolution of 1024x768 and i'd like to use the same resolution as for fullscreen as for the size of the window; the size is initially set in the winmain CreateWindow and i'd like that the winodowed mode maintains the same size (borders and titlebar included). I call the SetWindowPos only for having the changes made by SetWindowLongPtr flushed.I changed my code according to your advices and now the style changing during toggle is made as you do in your engine but I always have the same problem with some important changes:1° case: start in windowed mode, 60fps, the window is 1024x768 and hides the win taskbar, it's big as the entire screen. If I press ALT-TAB another window get the focus and correctly covers my window. I ALT-TAB to gain focus again and I double-click on the titlebar of my window. At this point the win taskbar appears at the bottom of the screen cutting the bottom of my, the fps drops from 60 to 34 but ALT-TAB works, my window is covered  by another window. I  regain focus and i double-click again on my titlebar, my window covers the win taskbar and the frame rate come back from 34 to 60fps. I've also noticed, placing a timer that starts before the device->Present() and stops just after the device->Preset() to calculate the swap time between the front and backbuffer, that when 60fps the swap time is 13ms, when 34fps it raises to 25ms. I don't know the reason because the Presentation interval is always the same.When at 34fps the sprite objects have a jerkily movements and anyway I have a better fluid motion in windowed mode at initial 60fps than in fullscreen at 50fps.2° case: start in windowed mode at 60fps, toggle to fullscreen at 50fps and back to windowed mode again with a drop to  34fps with a swap buffers time raised from 13ms to 25ms. In this case, the window remains always on top, if I ALT-TAB the other windows stay behind my window. I formerly changed the extended style (now removed from my code) just for this reason, hoping to prevent this behaviour, unsetting the topmost flag, but as i told, it didn't work, my window was still on top. Now if I'm in windowed mode and I drag my window with one or two borders out of the screen the image starts to flicker and the flickering amount is as more as a bigger portion of the window is outside the edges of the screen (The weird effects you were talking about in your previous post?). It seems like at every frame swap, the images in the front and backbuffer are not aligned.This is what happens in details during the toggle, I used alt-tab to minimize the window and use Win Spy++ to watch the style and extended style of the window (I cut the WS_MINIMIZE flag because it's due to the alt-tab to watch the Spy++)- start in winmode with 60fps: style: 34cb 0000 (WS_CAPTION, WS_VISIBLE, WS_CLIPSIBLING, WS_SYSMENU, WS_OVERLAPPED, WS_MINIMIZEBOX, WS_MAXIMIZEBOX)ex_style: 0000 0100 (WS_EX_LEFT, WS_LTRREADING, WS_EX_RIGHTSCROLLBAR, WS_EX_WINDOWEDGE)- hit F2 to toggle to full screen mode with 50fps:style: b400 0000 (WS_POPUP, WS_VISIBLE, WS_CLIPSIBILINGS)ex_style: 0000 0008 (WS_EX_LEFT, WS_LTRREADING, WS_EX_RIGHTSCROLLBAR, WS_EX_TOPMOST)- hit F2 to come back to windowed mode, 34fps, here the problem starts:style: 34cb 0000 (WS_CAPTION, WS_VISIBLE, WS_CLIPSIBLING, WS_SYSMENU, WS_OVERLAPPED, WS_MINIMIZEBOX, WS_MAXIMIZEBOX)ex_style: 0000 0108 (WS_EX_LEFT, WS_LTRREADING, WS_EX_RIGHTSCROLLBAR, WS_EX_TOPMOST, WS_EX_WINDOWEDGE)NOTE: also without change the extended style I find the WS_EX_TOPMOST flag setI post some code hoping you could help me to understandwinmain.cpp:int WINAPI WinMain(....){MSG msg; WNDCLASSEX wc;HWND hWnd; DWORD dw_style;//RegisterClass(hInstance);wc.cbSize=sizeof(WNDCLASSEX);wc.style=CS_HREDRAW | CS_VREDRAW;wc.lpfnWndProc=(WNDPROC)WinProc;wc.cbClsExtra=0;wc.cbWndExtra=0;wc.hInstance=hInstance;wc.hIcon=NULL;wc.hCursor=LoadCursor(NULL, IDC_ARROW);wc.hbrBackground=NULL;wc.lpszMenuName=NULL;wc.lpszClassName=g_engine->GetWinTitle();wc.hIconSm=NULL;RegisterClassEx(&wc);//at the beginning g_engine->Get_full_screen_mode() returns false, we start always in windowed modeif(g_engine->Get_full_screen_mode())dw_style = WS_POPUP;elsedw_style = (WS_OVERLAPPEDWINDOW | WS_VISIBLE) & ~WS_THICKFRAME;//window creationhWnd=CreateWindow(g_engine->GetWinTitle(),//win classg_engine->GetWinTitle(),//title bardw_style,//styleCW_USEDEFAULT,//win x posCW_USEDEFAULT,//win y posg_engine->Get_screen_width(),//widthg_engine->Get_screen_height(),//heightNULL,//parent winNULL,//menuhInstance,//istanza applicazioneNULL);//win parametersif(hWnd==NULL)return 0;//display winShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);//Create an instance of Engine class called g_engine   g_engine = new Engine();//Game initializationif(!g_engine->Init(hWnd))return 0;bGame_Over=false;//Message Loopwhile( !bGame_Over ){if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){TranslateMessage(&msg);DispatchMessage(&msg);}g_engine->Update();//Process game loop} //end while trueg_engine->End();//Game cleanupdelete g_engine;return msg.wParam;} //WinMain endEngine class:Engine::Engine(){..........this->deviceLost = false;this->toggling_WinFullScreenMode = false;}void Engine::Shutdown(void){bGame_Over = true;}int Engine::Init(HWND hWnd)//D3D Initialization{D3DDISPLAYMODE dm; this->hWnd = hWnd;......this->d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm);//this->p_d3dpp_windowedMode holds Presentation_parameters for windowed modeZeroMemory(&(this->p_d3dpp_windowedMode), sizeof(this->p_d3dpp_windowedMode));this->p_d3dpp_windowedMode.Windowed = true;this->p_d3dpp_windowedMode.SwapEffect = D3DSWAPEFFECT_DISCARD;this->p_d3dpp_windowedMode.BackBufferFormat=D3DFMT_UNKNOWN;this->p_d3dpp_windowedMode.PresentationInterval = D3DPRESENT_INTERVAL_ONE;this->p_d3dpp_windowedMode.hDeviceWindow = this->hWnd;//and this->p_d3dpp_fullScreenMode for fullscreen modeZeroMemory(&(this->p_d3dpp_fullScreenMode), sizeof(this->p_d3dpp_fullScreenMode));this->p_d3dpp_fullScreenMode.Windowed = false;this->p_d3dpp_fullScreenMode.SwapEffect = D3DSWAPEFFECT_DISCARD;this->p_d3dpp_fullScreenMode.BackBufferFormat=dm.Format;this->p_d3dpp_fullScreenMode.BackBufferCount = 1;this->p_d3dpp_fullScreenMode.BackBufferWidth = this->screen_width;this->p_d3dpp_fullScreenMode.BackBufferHeight = this->screen_height;this->p_d3dpp_fullScreenMode.PresentationInterval = D3DPRESENT_INTERVAL_ONE;this->p_d3dpp_fullScreenMode.hDeviceWindow = this->hWnd;//this->p_d3dpp holds the parameters for device->Reset and device->CreateDeviceif(this->full_screen_mode){//FULL screen mode::ShowCursor(FALSE);this->p_d3dpp = this->p_d3dpp_fullScreenMode;}elsethis->p_d3dpp = this->p_d3dpp_windowedMode;//Create device D3D devicethis->d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,this->hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&this->p_d3dpp,&(this->d3ddev));if(this->d3ddev==NULL){MessageBox(NULL, "Engine::Init - Error creating D3D Device", "ERROR", MB_OK);return 0;}.... }void Engine::ToggleScreenMode(void){//function called if F2 key hit by user to toggle between windowed and fullcreen modethis->full_screen_mode = !this->full_screen_mode;this->deviceLost = true;this->toggling_WinFullScreenMode = true;if(this->full_screen_mode)this->p_d3dpp = this->p_d3dpp_fullScreenMode;elsethis->p_d3dpp = this->p_d3dpp_windowedMode;}void Engine::Update(){//Called in the window main loop at every frameHRESULT result;//Check if the device is lost (ALT-TAB in fullscreen mode) or user hits F2 for togglingif(this->deviceLost){result = this->d3ddev->TestCooperativeLevel();if(result == D3DERR_DEVICELOST){::Sleep(100);return;//leave Update method and go to the win main loop} //endif(result == D3DERR_DEVICELOST)if( (result == D3DERR_DEVICENOTRESET) || (this->toggling_WinFullScreenMode) ){//device->Reset can be tried or user hits F2 key//Release of all resources and call device->Resetthis->onLostDevice();result = this->d3ddev->Reset(&this->p_d3dpp);if(result == D3D_OK){//Reset is OKthis->deviceLost = false;//Try to reacquire all resources previously releasedif( !this->onResetDevice() ) {this->Shutdown(); //something wrong, shutdown and kill the application}if(this->toggling_WinFullScreenMode) { //if true the user press F2 for toggling modethis->toggling_WinFullScreenMode = false;DWORD dwStyle;if(this->full_screen_mode){//change style for full screen modedwStyle = WS_POPUP;::ShowCursor(FALSE);}else{//change win style for windowed modedwStyle = (WS_OVERLAPPEDWINDOW | WS_VISIBLE) & ~WS_THICKFRAME;::ShowCursor(TRUE);}//change the win style and flush changes::SetWindowLongPtr(this->hWnd, GWL_STYLE, dwStyle);::SetWindowPos(this->hWnd, NULL, 0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);} //endif(this->toggling_WinFullScreenMode)}else{ //the device->Reset goes wrong, return, leave Update method and go back to the win main loopreturn;} //endif(result == D3D_OK)}//endif(result == D3DERR_DEVICENOTRESET)if(result != D3D_OK){////something wrong, shutdown and kill the applicationthis->Shutdown();} //endif(result != D3D_OK)} //endif(this->deviceLost) --- end of section that manages the devicelost and the toggle mode //Call the extern function Game_Run() wich update 2d objects position according to the keys hit by userGame_Run();//it updates objects not managed by the Engine class but managed by the extern functions//automatically update the objects managed by the Engine class contained inside a std::list objectthis->Update2D_Entities();//Perform collision detection testing, I omitted the code//update with 60fps timing using a stopwatch of 14ms. If from the previous call the time passed is less than //14ms sleep(1) and jump the code belowif (!timedUpdate.stopwatch(14)) {Sleep(1);}else {  //more than 14ms passed before last call, I can write on backbuffer and present the scene//update input devices and audio system, code omitted//Render objectsif(this->Start_Render()) //execute this->d3ddev->BeginScene();{this->d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 200), 1.0f, 0); //Clear the scenethis->Start_Render2d(); //execute D3DXSprite->Begin(D3DXSPRITE_ALPHABLEND))this->Draw2D_Entities(); //execute the D3DXSprite->Draw() for the objects managed by the Engine class contained inside a std::list objectGame_Render2d(); //extern function that does the D3DXSprite->Draw() for the objects not managed by the Engine class but managed by the extern functionsthis->Stop_Render2d(); //execute D3DXSprite->End();this->Stop_Render(); //execute the this->d3ddev->EndScene() and the this->d3ddev->Present(NULL, NULL, NULL, NULL);//if the d3ddev->Present() get back a D3DERR_DEVICELOST =====> this->deviceLost = true;}//automatically remove the dead objects managed by the Engine class and contained inside a std::list objectthis->Bury2D_Entities();} //endelse} //End of Engine::Update [Edited by - fabry on June 23, 2009 2:57:39 AM];  Hi,also tryed leaving the screen res to 1024x768 but change the game res to 800x600. I always start in win mode, toggle to fullscreen and go back to window mode: the fps is ok(60) but the window is always on top (i have no code portion for it).Also tryed to drag the window outside the screen edge. This causes some weird effects, the image flickers and the center of the image is not aligned with the bottom and the top. It doesn't happen when i first start the game but only after coming back to win mode after double toggling from the first win mode and the second full screen mode. Maybe something wrong with the backbuffer? I've tryed different solutions but without a good result.I posted the code in the previous post.I hope you can help, thanks in advance...   ;  What CPU, GPU and OS do you have? In windowed mode, Present() causes a BitBlt() from the backbuffer to the window client area, but only if the client area size matches the backbuffer. If the sizes differ, Present() will be forced to call StretchBlt(), which will obviously be slower - perhaps substantially.So - have you checked that the size of your client area (From GetClientRect()) is always the same as your backbuffer size?   ;  It's a notebook with an Intel Pentium M (centrino running at 1.7Ghz), an integrated GPU Intel 82855 GME Graphics controller running Windows XP Pro.Between the window mode at the beginning (where all is ok, fps is good, there is no flickering and no weird effects) and the window mode after double toggling, there's no change of the size of the client area and backbuffer, i always use the same variables and I restore the same win styles and d3d settings, for this reason this fact sounds so strange to me.Anyway i try to send to logfile these details and check again.Thank you   ;Quote:Original post by fabryIt's a notebook with an Intel Pentium M (centrino running at 1.7Ghz), an integrated GPU Intel 82855 GME Graphics controller running Windows XP Pro.Between the window mode at the beginning (where all is ok, fps is good, there is no flickering and no weird effects) and the window mode after double toggling, there's no change of the size of the client area and backbuffer, i always use the same variables and I restore the same win styles and d3d settings, for this reason this fact sounds so strange to me.Anyway i try to send to logfile these details and check again.Thank youThat's exactly the sort of spec where I'd expect to see a difference between BitBlt and StretchBlt performance. You could also try explicitly specifying a backbuffer size for windowed mode, in case the backbuffer is being created at say 1024x768 when re-entering windowed mode, but then the window is resized to 1024x768 which will make the client area smaller than that.   ;Quote:That's exactly the sort of spec where I'd expect to see a difference between BitBlt and StretchBlt performance. You could also try explicitly specifying a backbuffer size for windowed mode, in case the backbuffer is being created at say 1024x768 when re-entering windowed mode, but then the window is resized to 1024x768 which will make the client area smaller than thatGreat!!!!!! The second time i switch to win mode i have the backbuffer at 800x600 and the client area size of 794x575. Why does it happen if i use the same identical style used in CreateWindow?   