還是零分 散播福音的祭司
註冊時間: 2007-09-19 文章: 164
653.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鍵的時候 |
|