net: C#

实验内容

在窗口中以图形和文字的形式显示硬币数量,实现以下功能:

(1)利用键盘控制硬币个数的增加和减少;

(2)利用鼠标控制硬币个数的增加和减少;

(3)利用菜单控制硬币个数的增加和减少。

解决方式

以下是实现硬币增减的思路:

1.使用 Visual Studio 创建一个 Windows 窗体应用程序(Windows Forms Application)项目。

2.将所需的控件添加到窗体中。
1. 菜单menustrip, 按提示输入文字
2. label控件,显示硬币数量

3.为鼠标单击事件添加代码以增加或减少硬币的数量。
this.MouseClick += new MouseEventHandler(Form1_MouseClick);//增加鼠标事件

4.为窗体添加快捷键,以便使用键盘控制增加和减少硬币的数量。
this.KeyDown += new KeyEventHandler(Form1_KeyDown);//增加键盘事件

5.添加菜单控件并为其添加单击事件,以实现硬币数量的增加和减少。

以下是大致的代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public Form1()
{
InitializeComponent();
coinCount = 0; // 初始化硬币数量
UpdateCoinCount(); // 更新硬币数量显示
this.MouseClick += new MouseEventHandler(Form1_MouseClick);//增加鼠标事件
this.KeyDown += new KeyEventHandler(Form1_KeyDown);//增加键盘事件
this.Paint += new PaintEventHandler(Form1_Paint);//增加绘画事件
}
private void Form1_Load(object sender, EventArgs e)
{

}


private void UpdateCoinCount()
{
lblCoinCount.Text = "Coin Count: " + coinCount.ToString();
}
//菜单增加减少实现
private void 增加硬币ToolStripMenuItem_Click(object sender, EventArgs e)
{
coinCount++;
UpdateCoinCount();
}

private void 减少硬币ToolStripMenuItem_Click(object sender, EventArgs e)
{
coinCount--;
UpdateCoinCount();
}
//鼠标左键点击窗口增加coinCount,右键点击窗口减少coinCount
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
coinCount++;
UpdateCoinCount();
}
else if (e.Button == MouseButtons.Right)
{
if (coinCount > 0)
{
coinCount--;
UpdateCoinCount();
}
}
}
//按下A键增加coinCount,按下D键减少coinCount
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.A)
{
coinCount++;
UpdateCoinCount();
}
else if (e.KeyCode == Keys.D)
{
if (coinCount > 0)
coinCount--;
UpdateCoinCount();
}
}

其中,btnAdd、btnRemove 分别为增加和减少按钮,在单击事件中通过修改 coinCount 变量的值来增加或减少硬币数量。Form1_MouseClick 事件处理程序通过判断鼠标左右键的单击来增加或减少硬币数量。Form1_KeyDown 事件处理程序为窗体添加快捷键,通过按下 A 和 R 键来增加或减少硬币数量。menuItemAdd 和 menuItemRemove 分别为菜单中的增加和减少选项,单击事件中也是通过修改 coinCount 变量的值来实现功能。UpdateCoinCount 方法用于更新硬币数量的显示。

现在实现了硬币数量的增减,接下来就是需要图像根据硬币数量而改变。

实现硬币的图形显示:

  1. 利用循环根据硬币数量绘制出相应的图像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    		private int coinCount;
    private int coinDiameter = 100; // 硬币直径
    private int coinThickness = 20; // 硬币厚度
    private int coinX = 50; // 圆柱体的底部点的 x 坐标
    private int coinY = 50; // 圆柱体的底部点的 y 坐标
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
    Graphics g = e.Graphics;
    Rectangle rectBelow = new Rectangle(0,0,coinDiameter,coinThickness*3/2);
    Rectangle rectAbove = new Rectangle(0,0,coinDiameter,coinThickness*3/2);
    coinX = this.ClientSize.Width / 2 - coinDiameter / 2;
    coinY = this.ClientSize.Height / 2 - 20;
    Pen p = new Pen(Color.Black, 2);
    Brush brush = new SolidBrush(BackColor);
    // 绘制硬币圆柱体
    for (int i = 0; i < 2; i++)
    {
    int y = coinY - i * coinThickness;
    int x = coinX;
    rectAbove.X = x;
    rectAbove.Y = y - coinThickness;
    rectBelow.X = x;
    rectBelow.Y = y;
    g.DrawArc(p, rectBelow, 0, 180);
    g.DrawLine(p, x, y + coinThickness*3/4, x, y - coinThickness/4);
    g.DrawLine(p, x + coinDiameter, y + coinThickness*3/4, x + coinDiameter, y - coinThickness/4);
    }
    g.DrawEllipse(p, rectAbove);
    g.FillEllipse(brush, rectAbove);
    }

    问题记录:绘制的直线和下边的弧线不能严丝合缝,绘制的图像大小不合适等等,这些需要不断调整参数直至合适的状态。

  2. 发现在将循环次数改为coinCount之后绘制出的图形有明显偏差,而改为2就会十分正常,经检查这是因为coinCount初始值为0,循环可能因此出现了些问题。

直接在绘制前增加一个条件if(coinCount>0)即可,让其在coinCount=0时不再绘制图像。

  1. 最后为了在每次coinCount变化的时候进行窗体的重绘,可以将原来定义的private int coinCount 改为以下属性:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    private int _coinCount;

    public int coinCount
    {
    get { return _coinCount; }
    set
    {
    _coinCount = value;
    Invalidate(); // 窗体重绘
    }
    }
    每当获取coinCount的值时,将通过getter方法获取_coinCount的值;每当给coinCount赋值时,将通过setter方法将值赋给_coinCount,并且运行Invalidate();进行窗体重绘。

References