2. 調(diào)整窗體尺寸
在第2章中曾經(jīng)討論過(guò),如果改變了設(shè)備的方向,窗體的尺寸就會(huì)發(fā)生改變。這種情況可能發(fā)生在用戶將應(yīng)用程序最小化,對(duì)設(shè)備進(jìn)行重新配置或者只是旋轉(zhuǎn)了有重力感應(yīng)功能的新設(shè)備時(shí)。
當(dāng)窗體大小發(fā)生改變時(shí),需要調(diào)整游戲以適應(yīng)新的尺寸。這可能需要我們對(duì)游戲中的圖形進(jìn)行重新定位(甚至要加載全新的圖形)或者顯示一條消息說(shuō)明該游戲在新的屏幕方向上不能正常工作。
然而我們需要做出響應(yīng),使游戲引擎攔截到該事件,并執(zhí)行所需的操作。正如Activated 事件一樣,我們要在CGameEngineGDIBase類的構(gòu)造函數(shù)中為窗體添加Resize事件處理程序。這次調(diào)用GameFormResize函數(shù),該函數(shù)如程序清單4-21所示。
程序清單4-21 對(duì)游戲窗體大小發(fā)生改變進(jìn)行響應(yīng)
/// <summary>
/// Respond to the game form resize event
/// </summary>
private void GameFormResize(object sender, EventArgs e)
{
// If we have no back buffer or its size differs from
// that of the game form, we need to re-prepare the game.
if (_backBuffer == null ||
GameForm.ClientSize.Width != _backBuffer.Width ||
GameForm.ClientSize.Height != _backBuffer.Height)
{
// Re-prepare the game.
Prepare();
// Force the whole form to repaint
ForceRepaint();
}
}
該函數(shù)的主要目的是再次調(diào)用Prepare方法(游戲引擎就是在這里完成對(duì)Resize事件的響應(yīng)的),并強(qiáng)制執(zhí)行一次重繪,這樣在新尺寸的窗體中對(duì)全部對(duì)象進(jìn)行渲染。
但是,Resize事件會(huì)經(jīng)常不定期地被觸發(fā)(例如,當(dāng)窗體被打開時(shí))。為了忽略這些虛假的調(diào)用,我們將窗體的尺寸同后臺(tái)緩沖區(qū)中的窗體大小進(jìn)行對(duì)比。如果兩者匹配,就忽略該調(diào)用。只有在檢測(cè)到確實(shí)發(fā)生了尺寸變化時(shí),才調(diào)用Prepare方法和ForceRepaint方法。
3. 處理SIP
在觸摸屏設(shè)備上,SIP隨時(shí)都可能會(huì)打開和關(guān)閉。當(dāng)SIP關(guān)閉時(shí),它占用的區(qū)域如果不包含在移動(dòng)區(qū)域中,就會(huì)保持原樣而不進(jìn)行繪制,這將看上去很不協(xié)調(diào),而使用戶感到很不適應(yīng)。因此,我們需要捕獲SIP的關(guān)閉事件,當(dāng)它發(fā)生時(shí)就強(qiáng)制執(zhí)行重繪。
對(duì)該事件的響應(yīng)方式與前面其他的窗體事件是完全相同的,只是如果嘗試在一個(gè)smart phone設(shè)備上與InputPanel控件進(jìn)行交互的話,就會(huì)拋出一個(gè)異常,這使情況稍微復(fù)雜了一些。因此,在添加事件處理程序之前要檢測(cè)游戲是否運(yùn)行在smart phone平臺(tái)上(如果是,那么設(shè)備上不會(huì)包含SIP,也不需要對(duì)其事件進(jìn)行處理)。
為了實(shí)現(xiàn)該功能,要在類中添加一個(gè)名為_inputPanel的InputPanel類變量,在CgameEngine-
GDIBase類的構(gòu)造函數(shù)中使用程序清單4-22中的代碼對(duì)它進(jìn)行初始化。
程序清單4-22 初始化SIP事件處理程序
// If we are running on a touch-screen device, instantiate the inputpanel
if (!IsSmartphone)
{
_inputPanel = new Microsoft.WindowsCE.Forms.InputPanel();
// Add the event handler
_inputPanel.EnabledChanged += new System.EventHandler(SIPEnabledChanged);
}