记:用c#实现记事本

本文内容

用C#语言实现简易记事本(代码)。

思路分析

功能需求

参照win10的记事本,此次实现的简易记事本应当具有如下菜单控件:

Q`7C@VB2$~P3C28Y{7TEY2R.png

各分类下又包括:

功能.png

实现顺序

考虑到即使是简易的记事本需要实现的功能也较多,所以可以采取先实现记事本(界面)框架再逐步填充逻辑代码的顺序完成任务。

这样做的好处是可以对照界面完善代码,不容易产生遗漏。

具体实现

界面设计

实际上对win10自带的记事本界面略作修改,即可成为此次界面的模板。接下来所需要做的,就是将已有的界面逆向还原成C#中的各个组件。

先新建一个windows窗体应用程序,再将右下角属性中的text 修改为“记事本”,这样,最大的外边框就实现了。

Notepad.png

MenuStrip(菜单控件)

这一步实现各菜单选项。

Q`7C@VB2$~P3C28Y{7TEY2R.png

先在工具箱中找到menustrip并拖动到窗体中,并将右下角属性中的Name修改为“mnusNotepad”(注:这里修改Name是为了方便后续操控,Name可自由定义,下同)。

Menu.png

下面要做的就是将上图中的各控件一一填入menustrip中。

看上去内容较多且存在差异,但操作方法基本相同。单击menustrip输入【文件(&F)】、【编辑(&E)】、【格式(&O)】、【查看(&V)】和【帮助(&H)】,其中“&”作用为实现字母下面那条下划线。输入完成后,实际完成的是一级菜单,也就是图中“记事本”下第一行水平的菜单。

这时,还应该继续点击一级分类菜单,输入二层菜单(也就是图中的下拉框的部分)。以“文件”下的二级菜单为例,点击“文件”,分别输入:新建(&N)、打开(&O)、保存(&S)、另存为(&A)、输入“-”可生成分割横线以及退出(&X)。

下图为具体属性:

PR7FR)X__I_2DFY_Y(NFS.png

{{@6I5GFO@TCD{Z{%BL06.png

依次点击各控件修改属性即可。

至此菜单栏框架设置完成。

ToolStrip(工具栏控件)(不建议添加)

在工具箱中找到“ToolStrip”并拖动到窗体中,在属中修改Name为“tlsNotepad”。

再右击工具栏,选择插入标准项,可完成图形布置。

工具栏.png

实现效果如图。但现在的记事本中实际上没有该工具栏,而且该工具栏也影响整体美观,功能重复,所以不建议在程序中添加。

RichTextBox(多格式文本框控件)

仍然是在工具箱中先找到“RichTextBox”,再拖动到窗体中,并在属性中修改Name为“rtxtNotepad”。

这里还要将Anchor属性选择为“Top,Bottom,Left,Right”,这样当窗体大小改变时,RichTextBox控件的大小才会跟着改变。

文本框.png

这里实现的文本框就是图中白色的部分,用来在其中编辑文字。

StatusStrip(状态栏控件)

先添加StatusStrip控件,将其Name属性设为“stsNotepad”,再将Dock属性设为“Bottom”再将Anchor属性设为“Bottom,Left,Right”。实际上,这里Anchor属性最终会自动变为“Top, Left”。

这个设置也是为了在框体大小发生改变时,底部的状态栏能随之变化。

再右键打开【项集合编辑器】对话框,下拉列表中保留默认的选择“StatusLabel”,然后单击【添加】按钮,依次添加2个StatusLabel,并分别命名为“tssLbl1”和“tssLbl2”,再将tssLbl1的Text属性设为“就绪”, tssLbl2的Text属性设为“显示日期、时间”。

状态栏.png

这里如果要实现图中的效果,需要进一步设置2个StatusLabel的padding或margin属性值。在默认情况下,2个StatusLabel相互贴靠。还有一点需要注意的是,“显示日期、时间”实际上是为后续的时间显示充当占位符。

各对话框

OpenFileDialog(打开对话框)

从工具箱中找到OpenFileDialog直接拖入窗体中 单击属性
当用户单击记事本的【文件】→【打开】菜单项时,使用打开对话框OpenFileDialog打开文件。OpenFileDialog控件的Name属性为“odlgNotepad”,Filter属性设为“RTF文件|.rtf|所有文件|.*”。

SaveFileDialog(保存对话框)

从工具箱中找到SaveFileDialog直接拖入窗体中 单击属性
当用户单击记事本的【文件】→【保存】(或【另存为】)菜单项时,使用保存对话框SaveFileDialog保存文件。SaveFileDialog控件的Name属性为“sdlgNotepad”,FileName属性改为“无标题”,Filter属性设为“RTF文件|*.rtf”。

FontDialog(字体对话框)

从工具箱中找到FontDialog直接拖入窗体中 单击属性
当用户单击记事本的【格式】→【字体】菜单项时,使用字体对话框FontDialog设置文本字体。FontDialog控件的Name属性为“fdlgNotepad”。

Timer(计时器控件)

从工具箱中找到Timer直接拖入窗体中 单击属性
本章介绍的记事本在状态栏中显示了时钟,这就需要使用一个Timer控件来实现。Timer控件的Name属性设为“tmrNotepad”,Enabled(激活的可行的)属性设为“True”,Interval(间隔,间距,幕间时间)属性设为“1000”,表示1秒种触发一次Tick事件,即1秒钟改变一次时钟。

关于记事本

单击vs【项目】的【添加Windows窗体】菜单项,添加一个名为“frmAbout”的窗体,并给窗体“frmAbout”添加几个Label、Button、LinkLabel和PictrueBox控件,按照下图信息设置好属性。

IFCLB3PPJW@IAYMELBA%N.png

完成后应有如下各控件显示:

4DSPF_KSWGJAN]MBCH1%0{2.png

})91XO`CO]{6]O)_A%4ERAW.png

至此用户界面设计完毕。

逻辑代码

点击进入Gitee查看代码

首先,在代码中的通用段声明以下两个布尔型的公共变量,“b”用于判断文件是新建的还是从磁盘打开的,“s”用于判断文件是否被保存。再分别完成多格式文本框(rtxtNotepad)、菜单(mnusNotepad)、工具栏(tlsNotepad)、计时器(tmrNotepad)对象的逻辑代码。

由于篇幅关系,此处不做一一讲解,Gitee源代码中包含注解。在这里选取“新建”功能的程序进行补充解释。

private void tsmiNew_Click(object sender, EventArgs e)
{
    // 判断当前文件是否从磁盘打开,或者新建时文档不为空,并且文件未被保存
    if (b == true || rtxtNotepad.Text.Trim() != "")
    {
        // 若文件未保存
        if (s == false)
        {
            string result;
            result = MessageBox.Show("文件尚未保存,是否保存?", 
                "保存文件", MessageBoxButtons.YesNoCancel).ToString();
            switch (result)
            {
                case "Yes":
                    // 若文件是从磁盘打开的
                    if (b == true)
                    {
                        // 按文件打开的路径保存文件
                        rtxtNotepad.SaveFile(odlgNotepad.FileName);
                    }
                    // 若文件不是从磁盘打开的
                    else if (sdlgNotepad.ShowDialog() == DialogResult.OK)
                    {
                        rtxtNotepad.SaveFile(sdlgNotepad.FileName);
                    }
                    s = true;
                    rtxtNotepad.Text = "";
                    break;
                case "No":
                    b = false;
                    rtxtNotepad.Text = "";
                    break;
            }
        }
    }
}

复制代码

事实上,该段代码将“新建”的功能已基本完成,但存在一个小bug。代码中着重考虑了“新建时文档不为空,并且文件未被保存”的情况。

如果此时是在刚打开并输入文字的情况下,不会出现什么问题。但是如果此时是在先点击“打开”,编辑原本已有的rtf文件并保存后(或不做编辑),再点击“新建”的情况下,代码执行的效果就不尽如人意了:程序并不会生成一个新的文本框供用户编辑,用户操作的仍是先前已打开的源文件

对前后代码稍作分析可以知道,由于“保存”与“另存为”命令最后都会将变量s置为true,那么在打开一个已保存的文件后,“打开”命令的代码并不会满足if (s == false)这一条件,所以这整段代码并不会执行,也就不会有新的文本框生成了。

对这个bug的修改也不难,只需要补上s == true时的情况即可。

      private void tsmiNew_Click(object sender, EventArgs e)
        {
            
            // 判断当前文件是否从磁盘打开,或者新建时文档不为空,并且文件未被保存
            if (b == true || rtxtNotepad.Text.Trim() != "")
            {
                // 若文件未保存
                if (s == false)
                {
                    string result;
                    result = MessageBox.Show("文件尚未保存,是否保存?",
                        "保存文件", MessageBoxButtons.YesNoCancel).ToString();
                    switch (result)
                    {
                        case "Yes":
                            // 若文件是从磁盘打开的
                            if (b == true)
                            {
                                // 按文件打开的路径保存文件
                                rtxtNotepad.SaveFile(odlgNotepad.FileName);
                            }
                            // 若文件不是从磁盘打开的
                            else if (sdlgNotepad.ShowDialog() == DialogResult.OK)
                            {
                                rtxtNotepad.SaveFile(sdlgNotepad.FileName);
                            }
                            s = true;
                            rtxtNotepad.Text = "";
                            break;
                        case "No":
                            b = false;
                            rtxtNotepad.Text = "";
                            break;
                    }
                }
                else
                {
                    rtxtNotepad.Text = "";
                    b = false;
                }
            }

        }
复制代码

可以看出,最后补上的else { rtxtNotepad.Text = ""; b = false; }s == true时的情况考虑到了执行情况中,b = false;表示该文件是新建的,rtxtNotepad.Text = "";清空文本框,这样,就实现了新建一个文件的情况。

下面是部分执行情况:

ZUSO]5PVL%AG${{WGY3@S.png

6K4]6FG6%4H0QHH%`9%)K8L.png

$JH%DRVWY88GY}X2YM@S`3N.png

TOI)204CRKM7J$9Y2C~ZX)L.png

})91XO`CO]{6]O)_A%4ERAW.png

以上就是本文的全部内容。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享