这是“使用 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 类,所以状态栏信息只好直接显示在状态栏上。
上一篇:使用 C# 开发智能手机软件:推箱子(二十二)
下一篇:使用 C# 开发智能手机软件:推箱子(二十四)
返回目录