2. 调整窗体尺寸
在第2章中曾经讨论过,如果改变了设备的方向,窗体的尺寸就会发生改变。这种情况可能发生在用户将应用程序最小化,对设备进行重新配置或者只是旋转了有重力感应功能的新设备时。
当窗体大小发生改变时,需要调整游戏以适应新的尺寸。这可能需要我们对游戏中的图形进行重新定位(甚至要加载全新的图形)或者显示一条消息说明该游戏在新的屏幕方向上不能正常工作。
然而我们需要做出响应,使游戏引擎拦截到该事件,并执行所需的操作。正如Activated 事件一样,我们要在CGameEngineGDIBase类的构造函数中为窗体添加Resize事件处理程序。这次调用GameFormResize函数,该函数如程序清单4-21所示。
程序清单4-21 对游戏窗体大小发生改变进行响应
/// <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();
}
}
该函数的主要目的是再次调用Prepare方法(游戏引擎就是在这里完成对Resize事件的响应的),并强制执行一次重绘,这样在新尺寸的窗体中对全部对象进行渲染。
但是,Resize事件会经常不定期地被触发(例如,当窗体被打开时)。为了忽略这些虚假的调用,我们将窗体的尺寸同后台缓冲区中的窗体大小进行对比。如果两者匹配,就忽略该调用。只有在检测到确实发生了尺寸变化时,才调用Prepare方法和ForceRepaint方法。
3. 处理SIP
在触摸屏设备上,SIP随时都可能会打开和关闭。当SIP关闭时,它占用的区域如果不包含在移动区域中,就会保持原样而不进行绘制,这将看上去很不协调,而使用户感到很不适应。因此,我们需要捕获SIP的关闭事件,当它发生时就强制执行重绘。
对该事件的响应方式与前面其他的窗体事件是完全相同的,只是如果尝试在一个smart phone设备上与InputPanel控件进行交互的话,就会抛出一个异常,这使情况稍微复杂了一些。因此,在添加事件处理程序之前要检测游戏是否运行在smart phone平台上(如果是,那么设备上不会包含SIP,也不需要对其事件进行处理)。
为了实现该功能,要在类中添加一个名为_inputPanel的InputPanel类变量,在CgameEngine-
GDIBase类的构造函数中使用程序清单4-22中的代码对它进行初始化。
程序清单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);
}