C#项目实战:NewArticle

C#项目实战:NewArticle

  • 2018年3月3日
  • C#

花了一晚上做了一个快速新建Hexo文章的软件,预计支持的功能主要有: 快捷键呼出,输入文章标题后按下Enter键打开Typora编辑器编辑新的Markdown文件。这篇文章记录的是我在制作该软件的过程中的笔记,主要用于个人以后查阅,对其他的人可能可读性不高,大家凑合着看吧,或许会有能够帮到你的也不一定哦~

1. 窗口启动居中

修改MainWindow.xaml文件,给Window元素添加属性WindowStartupLocation="CenterScreen"

2. 使用DMSkinUI库

Step1 引用右键->添加引用->导入DMSkin.WPF.Small.dll

Step2 using DMSkin.WPF.Small以及继承DMSkinWindow

如:

1
2
3
4
5
6
7
8
9
10
11
12
using DMSkin.WPF.Small;

namespace MyFirstWpf
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : DMSkinWindow
{
public MainWindow() => InitializeComponent(); //初始化
}
}

Step3 修改MainWindow.xaml文件

<Window x:Class="projectName.MainWindow"换成<DMSkin:DMSkinWindow x:Class="projectName.MainWindow"这时会提示缺少引用,将光标移至划波浪线处,Alt+Enter自动补全引用

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 <DMSkin:DMSkinWindow
xmlns:DMSkin="clr-namespace:DMSkin.WPF.Small;assembly=DMSkin.WPF.Small" x:Class="NewArticle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:NewArticle"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>

</Grid>
</DMSkin:DMSkinWindow>

3. 无边框拖动(配合DMSkin使用)

Step1MainWindow.xaml.cs中添加Window_MouseDown事件

如:

1
2
3
4
5
6
7
8
9
10
11
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
try
{
DragMove(); //实现无边框窗体的拖动
}
catch
{
// do nothing
}
}

注:用try..catch语句是因为防止抛异常

Step2MainWindow.xaml中绑定事件MouseDown="Window_MouseDown"

4. DMSkin常见接口

1. 隐藏窗体最大化、最小化按钮

修改MainWindow.xaml文件,添加以下属性

1
2
DMShowMax="False"
DMShowMin="False"

2. 设置窗体四周边框阴影的大小

修改MainWindow.xaml文件,添加以下属性

1
DMWindowShadowSize="20"			<!--四周边框阴影大小-->

3. 其它属性

DMShowClose 是否显示关闭窗口按钮

5. TextBox相关设置

1. 将TextBox的边框设置为圆角

将修改的样式写在TextBox的resource中

如:

1
2
3
4
5
6
7
8
9
10
<TextBox>

<TextBox.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="BorderBrush" Value="#c1d0dc"/>
</Style>
</TextBox.Resources>

</TextBox>

2. 将TextBox的光标居中

设置TextBox的属性为VerticalContentAlignment="Center"

如:

1
<TextBox VerticalContentAlignment="Center" />

3. 指定TextBox的光标颜色

设置TextBox的属性为CaretBrush="#c2c3c9"

如:

1
<TextBox CaretBrush="#c2c3c9" />

4. 添加Enter事件

Step1 添加keydown事件

Step2 判断按下的键是否是Enter键

如:

1
2
3
4
5
6
7
private void TextBox_col_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
//Here is your code
}
}

6. cmd执行类

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
using System.Diagnostics;
using System.Text;

namespace NewArticle
{
class Cmd
{
private static string CmdPath = @"C:\Windows\System32\cmd.exe";
/// <summary>
/// 执行cmd命令
/// 多命令请使用批处理命令连接符:
/// <![CDATA[
/// &:同时执行两个命令
/// |:将上一个命令的输出,作为下一个命令的输入
/// &&:当&&前的命令成功时,才执行&&后的命令
/// ||:当||前的命令失败时,才执行||后的命令]]>
/// 其他请百度
/// </summary>
/// <param name="cmd"></param>
/// <param name="output"></param>
public static void RunCmd(string cmd, out string output)
{
cmd = cmd.Trim().TrimEnd('&') + "&exit";//说明:不管命令是否成功均执行exit命令,否则当调用ReadToEnd()方法时,会处于假死状态
using (Process p = new Process())
{
p.StartInfo.StandardOutputEncoding = Encoding.UTF8; // 使用UTF-8编码
p.StartInfo.FileName = CmdPath;
p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动
p.StartInfo.RedirectStandardInput = true; //接受来自调用程序的输入信息
p.StartInfo.RedirectStandardOutput = true; //由调用程序获取输出信息
p.StartInfo.RedirectStandardError = true; //重定向标准错误输出
p.StartInfo.CreateNoWindow = true; //不显示程序窗口
p.Start();//启动程序

//向cmd窗口写入命令
p.StandardInput.WriteLine(cmd);
p.StandardInput.AutoFlush = true;

//获取cmd窗口的输出信息
output = p.StandardOutput.ReadToEnd();
p.WaitForExit();//等待程序执行完退出进程
p.Close();
}
}
}
}

7. 正则匹配

1
2
3
4
foreach (Match match in Regex.Matches(string,pattern))
{
pos = match.Index;
}

8. 判断文件是否存在

1
File.Exists(string directory)

9. 延迟几秒再执行

Step1 将方法改成异步(async),并且用Action封装一个方法,再用await Task.Run()指定异步方法

如:

1
2
3
4
5
6
7
async void label1_Click(object sender, EventArgs e)
{
message1.Show();
//用Action封装一个方法,再用await Task.Run()执行异步方法
Action action= AsyncMethod;
await Task.Run(action);
}

Step2 创建异步方法AsyncMethod

如:

1
2
3
4
5
6
7
8
public void AsyncMethod()
{
Thread.Sleep(2000); //延时2秒
message1.Text = "抱歉,未检查到新版本!";
Thread.Sleep(2000);
version_message1.Hide();
message1.Text = "正在检查更新...";
}

注: WPF程序不允许非UI线程更新UI内容,但可以通过委托曲线救国:

1
控件名.Dispatcher.Invoke(new System.Action(delegate { 控件名.IsEnabled = false; }));

10. 退出程序

  1. this.Close(); 只是关闭当前窗口,若不是主窗体的话,是无法退出程序的,另外若有托管线程(非主线程),也无法干净地退出;

  2. Application.Exit(); 强制所有消息中止,退出所有的窗体,但是若有托管线程(非主线程),也无法干净地退出;

  3. Application.ExitThread(); 强制中止调用线程上的所有消息,同样面临其它线程无法正确退出的问题;

  4. System.Environment.Exit(0); 这是最彻底的退出方式,不管什么线程都被强制退出,把程序结束的很干净。

    值得注意的是: this.Close(); 仅仅是关闭当前窗体,如果窗体中有循环,循环仍会继续运行。


最后,展示一下我的成品^_^