電腦遊戲製作開發設計論壇 首頁 電腦遊戲製作開發設計論壇
任何可以在PC上跑的遊戲都可以討論,主要以遊戲之製作開發為主軸,希望讓台灣的遊戲人有個討論、交流、教學、經驗傳承的園地
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入 

Google
在全螢幕跟視窗兩種模式之間做切換

 
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫
上一篇主題 :: 下一篇主題  
發表人 內容
還是零分
散播福音的祭司


註冊時間: 2007-09-19
文章: 164

652.83 果凍幣

發表發表於: 2011-2-23, PM 4:23 星期三    文章主題: 在全螢幕跟視窗兩種模式之間做切換 引言回覆

好久沒在這一區發言了~~

雖然切換視窗模式是沒啥大不了的功能
玩家也不怎麼在意
不過應該還算實用吧
尤其要從別人寫的框架裡挖出切換方法是很不容易的
至少對我而言是如此

以下做法對一般應用程式以及OpenGL都行的通
D3D則不適用
代碼:

// g_fullScreen是個flag,用來紀錄當下程式處於哪個模式
// g_width跟g_height是紀錄畫面長寬的全域變數

void ToggleFullscreen( void )
{
   if( g_fullScreen )      // 如果現在是全螢幕的話
   {
      /* 就把程式變成視窗模式 */
      RECT   WindowRect;
      WindowRect.left   = (long)0;
      WindowRect.right  = (long)g_width;
      WindowRect.top    = (long)0;
      WindowRect.bottom = (long)g_height;
      
      ChangeDisplaySettings( NULL, 0 );
      
      ShowWindow( hWnd, SW_HIDE );
      
      AdjustWindowRect( &WindowRect, WS_OVERLAPPEDWINDOW, false );
      SetWindowLong( hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW );   // 更改視窗樣式
      
      SetWindowPos(   hWnd,
                  HWND_NOTOPMOST,
                  0,0,
                  (int)(WindowRect.right-WindowRect.left),
                  (int)(WindowRect.bottom-WindowRect.top),
                  SWP_SHOWWINDOW );
      
      ShowWindow( hWnd, SW_SHOW );
      
      g_fullScreen = false;
   }
   else
   {
      /* 把遊戲變成全螢幕模式 */
      DEVMODE      DeviceMode;
      ZeroMemory( &DeviceMode, sizeof(DeviceMode) );
      DeviceMode.dmSize = sizeof( DeviceMode );
      EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &DeviceMode );
      DeviceMode.dmPelsWidth  = g_width;
      DeviceMode.dmPelsHeight = g_height;
      DeviceMode.dmBitsPerPel = 32;
      DeviceMode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
      
      ChangeDisplaySettings( &DeviceMode, CDS_FULLSCREEN );
      
      SetWindowLong( hWnd, GWL_STYLE, WS_POPUP );
      
      SetWindowPos(   hWnd,
                  HWND_NOTOPMOST,
                  0,
                  0,
                  g_width,
                  g_height,
                  SWP_SHOWWINDOW );
      
      g_fullScreen = true;
   }
}

ShowWindow( hWnd, SW_HIDE )跟ShowWindow( hWnd, SW_SHOW )這兩行的搭配用意是希望變回視窗後
桌面可以正常顯示
而不是黑掉一大塊

以上做法我無法套用到D3D身上
只好改D3D設備的參數了(這似乎也是唯一的方法)

做法如下
但我不大確定就是了
哪裡搞錯還麻煩各位不吝指教

代碼:

// ResizeGameWindow()這個函式是我們自己寫來調整投影矩陣的函式
// d3dpp是全域變數,"Windowed"之外的成員變數都寫好了
// Reset的時候只改"Windowed"而已
void ToggleFullscreen( void )
{
   if( g_fullScreen )
   {
      /* 把遊戲變成視窗模式 */
      RECT   WindowRect;
      WindowRect.left   = (long)0;
      WindowRect.right  = (long)g_width;
      WindowRect.top    = (long)0;
      WindowRect.bottom = (long)g_height;
      AdjustWindowRect( &WindowRect, WS_OVERLAPPEDWINDOW, false );
      
      d3dpp.Windowed = TRUE;      // 這是重點

      // 先釋放資源,如頂點之類的
      g_D3DDevice->Reset(&d3dpp);   // 重新設定D3D設備的參數
      // 然後再重新配置
      
      // 還有一些設定要再設一次
      g_D3DDevice->SetRenderState(D3DRS_ZENABLE,  TRUE ); // 深度測試吧?!?!?
      g_D3DDevice->SetRenderState(D3DRS_CULLMODE, TRUE ); // 背面剔除
      g_D3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE ); // 光照
      
      ResizeGameWindow( g_width, g_height );// 投影矩陣也要重做
      
      SetWindowPos(   hWnd,
                  HWND_NOTOPMOST,
                  0,0,
                  (int)(WindowRect.right-WindowRect.left),
                  (int)(WindowRect.bottom-WindowRect.top),
                  SWP_SHOWWINDOW );
      
      g_fullScreen = false;
   }
   else
   {
      /* 把遊戲變成全螢幕模式 */
      d3dpp.Windowed = FALSE;

      // 先釋放資源,如頂點之類的
      g_D3DDevice->Reset(&d3dpp);
      // 然後再重新配置
      
      g_D3DDevice->SetRenderState(D3DRS_ZENABLE,  TRUE );
      g_D3DDevice->SetRenderState(D3DRS_CULLMODE, TRUE );
      g_D3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE );
      
      ResizeGameWindow( g_width, g_height );

      // 這裡不用SetWindowPos()了,連視窗Style不改成WS_POPUP都沒關係
      
      g_fullScreen = true;
   }
}

經過Reset的D3D簡直像得了失憶症一樣
什麼都要重做
必須整理好架構以備"重設"之需
架構D3D遊戲時本來就要去考慮到這點
它動不動就會需要Reset的
像是一時手賤按到Windows鍵的時候
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
從之前的文章開始顯示:   
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫 所有的時間均為 台灣時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
可以 在這個版面附加檔案
可以 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作