这是“使用 C# 开发智能手机软件:推箱子” 系列文章的第二十三篇。在这篇文章中,介绍 Window/MainForm.Common.cs 源程序文件。这个源程序文件是 MainForm 类的一部分,该类继承自 System.Windows.Forms.Form 类,表示推箱子的主窗体。而本篇文章讲述的是 MainForm 类的一些公用方法。下面就是 MainForm.Common.cs 的源程序代码:
1
using
System;
2 using System.Drawing;
3 using System.Threading;
4 using System.Collections.Generic;
5 using System.Windows.Forms;
6 using Skyiv.Ben.PushBox.Common;
7
8 namespace Skyiv.Ben.PushBox.Window
9 {
10 partial class MainForm
11 {
12 /// <summary>
13 /// 装入当前关数据
14 /// </summary>
15 /// <param name="isReSizeClient"> 是否根据当前关尺寸改变主窗体客户区尺寸 </param>
16 void LoadLevel( bool isReSizeClient)
17 {
18 env.LoadLevel();
19 if (isReSizeClient && Environment.OSVersion.Platform != PlatformID.WinCE)
20 ClientSize = env.GetClientSize(sbrMain.Visible ? sbrMain.Height : 0 );
21 ClientSizeChanged();
22 UpdateStatus();
23 }
24
25 /// <summary>
26 /// 主窗体客户区尺寸改变时要采取的动作
27 /// </summary>
28 void ClientSizeChanged()
29 {
30 env.ClientSize = new Size(ClientSize.Width, ClientSize.Height +
31 Pub.OverY - (sbrMain.Visible ? sbrMain.Height : 0 ));
32 env.SetBoxInfo();
33 Invalidate();
34 }
35
36 /// <summary>
37 /// 恢复上次退出时保存的走法
38 /// </summary>
39 /// <param name="steps"> 走法 </param>
40 void Restore( string steps)
41 {
42 Rectangle invalid;
43 foreach ( char c in steps)
44 {
45 Step step = c;
46 if ( ! env.StepIt(step.Direct, step.IsStop, out invalid)) break ;
47 }
48 Invalidate();
49 UpdateStatus();
50 }
51
52 /// <summary>
53 /// 工人往指定方向前进一步(可能推着箱子)
54 /// </summary>
55 /// <param name="dir"> 前进的方向 </param>
56 /// <param name="isStop"> “撤销”时是否停留 </param>
57 void StepIt(Direction dir, bool isStop)
58 {
59 Rectangle invalid;
60 if ( ! env.StepIt(dir, isStop, out invalid)) return ;
61 Invalidate(invalid);
62 UpdateStatus();
63 }
64
65 /// <summary>
66 /// 工人后退一步(可能连带箱子一起后退)
67 /// </summary>
68 /// <returns> 是否完成“撤消” </returns>
69 bool Back()
70 {
71 Rectangle invalid;
72 bool isStop = env.Back( out invalid);
73 Invalidate(invalid);
74 UpdateStatus();
75 return isStop;
76 }
77
78 /// <summary>
79 /// 尝试将工人移动到鼠标点击的位置
80 /// </summary>
81 /// <returns> 是否成功 </returns>
82 bool TryMove()
83 {
84 Queue < Direction > moveQueue = env.GetMoveInfo();
85 if (moveQueue == null ) return false ;
86 if (moveQueue.Count <= 0 ) return false ;
87 int count = moveQueue.Count;
88 while (moveQueue.Count > 0 )
89 {
90 bool isStop = (count == moveQueue.Count);
91 if ( ! isStop && env.StepDelay > 0 ) Thread.Sleep(env.StepDelay);
92 StepIt(moveQueue.Dequeue(), isStop);
93 }
94 return true ;
95 }
96
97 /// <summary>
98 /// 尝试将箱子推动到鼠标点击的位置
99 /// </summary>
100 /// <returns> 是否成功 </returns>
101 bool TryPush()
102 {
103 Direction dir;
104 int steps = env.GetPushInfo( out dir);
105 if (steps <= 0 ) return false ;
106 for ( int i = 0 ; i < steps; i ++ )
107 {
108 bool isStop = (i == 0 );
109 if ( ! isStop && env.StepDelay > 0 ) Thread.Sleep(env.StepDelay);
110 StepIt(dir, isStop);
111 }
112 return true ;
113 }
114
115 /// <summary>
116 /// 更新状态栏信息和菜单项
117 /// </summary>
118 void UpdateStatus()
119 {
120 sbrMain.Text = env.StatusMessage;
121 miExit.Enabled = ! env.IsReplay && ! env.IsDesign;
122 miSystem.Enabled = ! env.IsReplay;
123 miOption.Enabled = ! env.HasError && ! env.IsReplay;
124 miSelectLevel.Enabled = ! env.IsDesign && ! env.HasError && ! env.IsReplay && ( ! env.CanUndo || env.IsFinish);
125 miSelectGroup.Enabled = ! env.IsDesign && miSelectLevel.Enabled && env.Groups.Length > 1 ;
126 miLastLevel.Enabled = miNextLevel.Enabled = miSelectLevel.Enabled && env.Level < env.MaxLevel - 1 ;
127 miFirstLevel.Enabled = miPrevLevel.Enabled = miSelectLevel.Enabled && env.Level > 0 ;
128 miLastGroup.Enabled = miNextGroup.Enabled = miSelectGroup.Enabled && env.Group < env.Groups.Length - 1 ;
129 miFirstGroup.Enabled = miPrevGroup.Enabled = miSelectGroup.Enabled && env.Group > 0 ;
130 miConfig.Enabled = miTran.Enabled = ! env.IsDesign && ! env.IsReplay && ( ! env.CanUndo || env.IsFinish);
131 miDesign.Enabled = miSelectLevel.Enabled && ! env.CanUndo;
132 miRestartOrStopOrSave.Enabled = ! env.HasError && (env.IsDesign ? ( ! env.IsReplay && env.HasWorker) : (env.IsReplay || env.CanUndo));
133 miUndoOrCancel.Enabled = miBackOrManOrBox.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || env.CanUndo);
134 miPrevLevel2OrSlot.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || (miSelectLevel.Enabled && env.Level > 0 ));
135 miNextLevel2OrWall.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || (miSelectLevel.Enabled && env.Level < env.MaxLevel - 1 ));
136 miRecordOrBrick.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || env.IsFinish);
137 miReplayOrLand.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || env.CanReplay);
138 miRestartOrStopOrSave.Text = ! env.IsDesign ? ( ! env.IsReplay ? " 〓 " : " ■ " ) : " 保存 " ;
139 miUndoOrCancel.Text = ! env.IsDesign ? " ↖ " : " 放弃 " ;
140 miBackOrManOrBox.Text = ! env.IsDesign ? " ← " : env.HasWorker ? " 箱 " : " 人 " ;
141 miPrevLevel2OrSlot.Text = ! env.IsDesign ? " ▲ " : " 槽 " ;
142 miNextLevel2OrWall.Text = ! env.IsDesign ? " ▼ " : " 墙 " ;
143 miRecordOrBrick.Text = ! env.IsDesign ? " ● " : " 砖 " ;
144 miReplayOrLand.Text = ! env.IsDesign ? " 回放 " : " 地 " ;
145 Update();
146 }
147 }
148 }
149
2 using System.Drawing;
3 using System.Threading;
4 using System.Collections.Generic;
5 using System.Windows.Forms;
6 using Skyiv.Ben.PushBox.Common;
7
8 namespace Skyiv.Ben.PushBox.Window
9 {
10 partial class MainForm
11 {
12 /// <summary>
13 /// 装入当前关数据
14 /// </summary>
15 /// <param name="isReSizeClient"> 是否根据当前关尺寸改变主窗体客户区尺寸 </param>
16 void LoadLevel( bool isReSizeClient)
17 {
18 env.LoadLevel();
19 if (isReSizeClient && Environment.OSVersion.Platform != PlatformID.WinCE)
20 ClientSize = env.GetClientSize(sbrMain.Visible ? sbrMain.Height : 0 );
21 ClientSizeChanged();
22 UpdateStatus();
23 }
24
25 /// <summary>
26 /// 主窗体客户区尺寸改变时要采取的动作
27 /// </summary>
28 void ClientSizeChanged()
29 {
30 env.ClientSize = new Size(ClientSize.Width, ClientSize.Height +
31 Pub.OverY - (sbrMain.Visible ? sbrMain.Height : 0 ));
32 env.SetBoxInfo();
33 Invalidate();
34 }
35
36 /// <summary>
37 /// 恢复上次退出时保存的走法
38 /// </summary>
39 /// <param name="steps"> 走法 </param>
40 void Restore( string steps)
41 {
42 Rectangle invalid;
43 foreach ( char c in steps)
44 {
45 Step step = c;
46 if ( ! env.StepIt(step.Direct, step.IsStop, out invalid)) break ;
47 }
48 Invalidate();
49 UpdateStatus();
50 }
51
52 /// <summary>
53 /// 工人往指定方向前进一步(可能推着箱子)
54 /// </summary>
55 /// <param name="dir"> 前进的方向 </param>
56 /// <param name="isStop"> “撤销”时是否停留 </param>
57 void StepIt(Direction dir, bool isStop)
58 {
59 Rectangle invalid;
60 if ( ! env.StepIt(dir, isStop, out invalid)) return ;
61 Invalidate(invalid);
62 UpdateStatus();
63 }
64
65 /// <summary>
66 /// 工人后退一步(可能连带箱子一起后退)
67 /// </summary>
68 /// <returns> 是否完成“撤消” </returns>
69 bool Back()
70 {
71 Rectangle invalid;
72 bool isStop = env.Back( out invalid);
73 Invalidate(invalid);
74 UpdateStatus();
75 return isStop;
76 }
77
78 /// <summary>
79 /// 尝试将工人移动到鼠标点击的位置
80 /// </summary>
81 /// <returns> 是否成功 </returns>
82 bool TryMove()
83 {
84 Queue < Direction > moveQueue = env.GetMoveInfo();
85 if (moveQueue == null ) return false ;
86 if (moveQueue.Count <= 0 ) return false ;
87 int count = moveQueue.Count;
88 while (moveQueue.Count > 0 )
89 {
90 bool isStop = (count == moveQueue.Count);
91 if ( ! isStop && env.StepDelay > 0 ) Thread.Sleep(env.StepDelay);
92 StepIt(moveQueue.Dequeue(), isStop);
93 }
94 return true ;
95 }
96
97 /// <summary>
98 /// 尝试将箱子推动到鼠标点击的位置
99 /// </summary>
100 /// <returns> 是否成功 </returns>
101 bool TryPush()
102 {
103 Direction dir;
104 int steps = env.GetPushInfo( out dir);
105 if (steps <= 0 ) return false ;
106 for ( int i = 0 ; i < steps; i ++ )
107 {
108 bool isStop = (i == 0 );
109 if ( ! isStop && env.StepDelay > 0 ) Thread.Sleep(env.StepDelay);
110 StepIt(dir, isStop);
111 }
112 return true ;
113 }
114
115 /// <summary>
116 /// 更新状态栏信息和菜单项
117 /// </summary>
118 void UpdateStatus()
119 {
120 sbrMain.Text = env.StatusMessage;
121 miExit.Enabled = ! env.IsReplay && ! env.IsDesign;
122 miSystem.Enabled = ! env.IsReplay;
123 miOption.Enabled = ! env.HasError && ! env.IsReplay;
124 miSelectLevel.Enabled = ! env.IsDesign && ! env.HasError && ! env.IsReplay && ( ! env.CanUndo || env.IsFinish);
125 miSelectGroup.Enabled = ! env.IsDesign && miSelectLevel.Enabled && env.Groups.Length > 1 ;
126 miLastLevel.Enabled = miNextLevel.Enabled = miSelectLevel.Enabled && env.Level < env.MaxLevel - 1 ;
127 miFirstLevel.Enabled = miPrevLevel.Enabled = miSelectLevel.Enabled && env.Level > 0 ;
128 miLastGroup.Enabled = miNextGroup.Enabled = miSelectGroup.Enabled && env.Group < env.Groups.Length - 1 ;
129 miFirstGroup.Enabled = miPrevGroup.Enabled = miSelectGroup.Enabled && env.Group > 0 ;
130 miConfig.Enabled = miTran.Enabled = ! env.IsDesign && ! env.IsReplay && ( ! env.CanUndo || env.IsFinish);
131 miDesign.Enabled = miSelectLevel.Enabled && ! env.CanUndo;
132 miRestartOrStopOrSave.Enabled = ! env.HasError && (env.IsDesign ? ( ! env.IsReplay && env.HasWorker) : (env.IsReplay || env.CanUndo));
133 miUndoOrCancel.Enabled = miBackOrManOrBox.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || env.CanUndo);
134 miPrevLevel2OrSlot.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || (miSelectLevel.Enabled && env.Level > 0 ));
135 miNextLevel2OrWall.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || (miSelectLevel.Enabled && env.Level < env.MaxLevel - 1 ));
136 miRecordOrBrick.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || env.IsFinish);
137 miReplayOrLand.Enabled = ! env.HasError && ! env.IsReplay && (env.IsDesign || env.CanReplay);
138 miRestartOrStopOrSave.Text = ! env.IsDesign ? ( ! env.IsReplay ? " 〓 " : " ■ " ) : " 保存 " ;
139 miUndoOrCancel.Text = ! env.IsDesign ? " ↖ " : " 放弃 " ;
140 miBackOrManOrBox.Text = ! env.IsDesign ? " ← " : env.HasWorker ? " 箱 " : " 人 " ;
141 miPrevLevel2OrSlot.Text = ! env.IsDesign ? " ▲ " : " 槽 " ;
142 miNextLevel2OrWall.Text = ! env.IsDesign ? " ▼ " : " 墙 " ;
143 miRecordOrBrick.Text = ! env.IsDesign ? " ● " : " 砖 " ;
144 miReplayOrLand.Text = ! env.IsDesign ? " 回放 " : " 地 " ;
145 Update();
146 }
147 }
148 }
149
该类的 UpdateStatus 方法用于更新状态栏信息和菜单项,我们来看看 MainForm.Designer.cs 源程序文件(该文件是由 Visual Studio 2005 IDE 自动生成的)中和“状态栏”相关的部分:
namespace
Skyiv.Ben.PushBox.Window
{
partial class MainForm
{
// 注意:省略了很多代码,仅保留和 sbrMain 相关的部分。
private void InitializeComponent()
{
this .sbrMain = new System.Windows.Forms.StatusBar();
this .sbrMain.Location = new System.Drawing.Point( 0 , 246 );
this .sbrMain.Name = " sbrMain " ;
this .sbrMain.Size = new System.Drawing.Size( 240 , 22 );
this .Controls.Add( this .sbrMain);
}
private System.Windows.Forms.StatusBar sbrMain;
}
}
{
partial class MainForm
{
// 注意:省略了很多代码,仅保留和 sbrMain 相关的部分。
private void InitializeComponent()
{
this .sbrMain = new System.Windows.Forms.StatusBar();
this .sbrMain.Location = new System.Drawing.Point( 0 , 246 );
this .sbrMain.Name = " sbrMain " ;
this .sbrMain.Size = new System.Drawing.Size( 240 , 22 );
this .Controls.Add( this .sbrMain);
}
private System.Windows.Forms.StatusBar sbrMain;
}
}
一般来说,状态栏要分为多个状态栏面板(StatusBarPanel 类),如下图(这是推箱子的 1.15 版本,只能运行在计算机上,不能运行在智能手机上)所示:
但是 Microsoft .NET Compact Framework 不支持 StatusBarPanel 类,所以状态栏信息只好直接显示在状态栏上。