很经常操作电脑,点点点的好麻烦,有时候命令行可以做的更好,但是总不能一言不合打开命令行敲代码吧?
保存为bat,vbs之类的脚本工具是可以有,但是太占用面积了,找起来也麻烦;
是不是觉得有些杀dou毒bi软件的加速球萌萌的?
今天来做个桌面小球工具,可以添加很多命令行快捷方式,但是并不占用你的桌面图标,使用也相对方便;
/***************** 分割线 ***********************/
1:预期效果图:
2:开始:
2.1使用VS新建一个标准的窗体工程;这个不赘述;
2.2修改主窗体的属性:
窗体FormBoradStyle为无.去掉窗体的边框,因为不需要,多出边框的话计算坐标也麻烦;
设置窗口TopMost=True始终在前,ShowInTaskbar不显示任务栏;
添加NotifyIcon通知栏控件,用于隐藏小球后恢复显示,可见属性Visible=false,图标自选;
添加一个ProgressBar控件,用来显示加速球的半缸子水状态,初始值可以指定为40%方便查看,后期可以加入实时计算机内存使用率;
控件的大小,布局并不重要,因为要用代码来重新设置尺寸和布局;
2.3添加窗体的Paint事件,绘制窗体只显示一个圆形:
///
/// 小圆点直径
///
private const int ZhiJing = 50;
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
this.Width = ZhiJing;
this.Height = ZhiJing;
progressBar1.Location = new Point(0, 0);
progressBar1.Width = ZhiJing;
progressBar1.Height = ZhiJing;
GraphicsPath myPath = new GraphicsPath();
myPath.AddPie(0, 0, ZhiJing, ZhiJing, 0, 360);
this.Region = new Region(myPath);
}
以上代码完成最简单的小球的显示.小球从左到右显示为半绿半灰的图形;
水平方向的进度条不好看,将它改为竖直方向的进度条.没有旋转控件的方法,所以要重写ProgressBar控件的一个方法;选择进度条status,跳转到定义,修改ProcessBar为VerticalProgressBar,这时候会提示你,没有这个类.按提示"在新文件添加类VerticalProgressBar",新建类,添加以下代码:
internal class VerticalProgressBar : ProgressBar
{
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.Style |= 0x04;
return cp;
}
}
}
最后,在Form*.Designer.cs修改进度条的定义和初始化两个地方都是VerticalProgressBar.进度条就是竖直方向的了;
2.4添加窗体拖动效果:
小球的外观已经完成,那么继续实现拖动;
手写或者用界面设计器给窗体和进度条(其实只要窗体最上方的,用户可见的进度条就可以)添加三个鼠标事件:
///
/// 小圆点拖动效果参数
///
bool isMouseDown = false;
Point mouseOffset;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
int xOffset;
int yOffset;
if (e.Button == MouseButtons.Left)
{
this.Cursor = Cursors.Hand;
xOffset = -e.X;
yOffset = -e.Y;
mouseOffset = new Point(xOffset, yOffset);
isMouseDown = true;
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (isMouseDown)
{//获取鼠标的位置
Point mousePos = Control.MousePosition;
mousePos.Offset(mouseOffset.X, mouseOffset.Y);
Location = mousePos;
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
isMouseDown = false;
this.Cursor = Cursors.Default;
}
2.5添加窗体贴边隐藏效果:
给鼠标放开事件添加代码:
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
isMouseDown = false;
this.Cursor = Cursors.Default;
//贴边隐藏判断
int x0 = this.Location.X;
int y0 = this.Location.Y;
int x1 = x0 + this.Width;
int y1 = y0 + this.Height;
bool xOver = (x0 < 0) || (x1 > Screen.GetWorkingArea(this.Location).Width);
bool yOver = (y0 < 0) || (y1 > Screen.GetWorkingArea(this.Location).Height);
if (xOver || yOver)
{
this.Visible = false;
notifyIcon1.Visible = true;
}
}
含义是松开鼠标后,若窗体的如果超出工作区(有效的桌面范围).则隐藏窗体,此处还可以给notifyIcon1设置标题,气泡等效果;
给NotifyIcon控件设置单击事件:
private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Visible = true;
notifyIcon1.Visible = false;
int newX = 1000;
int newY = 200;
this.Location = new Point(newX, newY);
this.Activate();
}
}
左键单击小图标,显示窗体,隐藏小图标;
2.6:添加右键菜单效果:
现在一个小球的外观已经完成,但是内容还未添加.
在设计页面,给窗体添加一个ContextMenuStrip控件,
窗体的ContextMenuStrip属性设置为这个控件,然后编辑这个控件分别赋给单击事件即可.
若果要小图标也有右键菜单,也给它的ContextMenuStrip属性赋菜单对象;
3:实现命令行执行代码:
很多命令需要执行命令行,所以按需要完成一些命令行的方法;
3.1实现一个固定命令的,不返回内容的命令行:
private void ExecuteNoReply(string cmd)
{
try
{
using (Process p = new Process())
{
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动
p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
p.StartInfo.CreateNoWindow = true;//不显示程序窗口
p.Start();//启动程序
p.StandardInput.WriteLine(cmd);
p.StandardInput.AutoFlush = true;
p.StandardInput.WriteLine("exit");
p.WaitForExit();
}
}
catch (Exception ex)
{
string err = string.Format("执行命令:[{0}]发生异常,信息:[{1}]", cmd, ex.Message);
MessageBox.Show(err, "错误信息");
}
}
3.2实现一个固定命令的,返回文本命令结果的命令行:
//参考我的另一个文章:winform和命令行交互
3.3实现一个手动输入命令的,返回命令结果的命令行:
//参考我的另一个文章:winform和命令行交互
4:使用命令行完成功能:
举出一些常用的功能的命令行用法:
打开设备管理器:
ExecuteNoReply("start devmgmt.msc");
打开桌面文件夹:
string dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
ExecuteNoReply("start explorer.exe /e," + dir);
打开网络适配器:
ExecuteNoReply("explorer.exe ::{7007ACC7-3202-11D1-AAD2-00805FC1270E}");
打开记事本:
ExecuteNoReply("start notepad.exe");
5:添加实时CPU和内存使用率显示:
添加一个线程,并在显示页面时候启动,关闭页面时关闭;
private void FormMain_Load(object sender, EventArgs e)
{
PerformanceCounter pcCpuLoad = new PerformanceCounter("Processor", "% Processor Time", "_Total");
newThread = new Thread(ThreadForCpuView);
newThread.Start(pcCpuLoad);
}
Thread newThread;
delegate void SetLabelTextDele(float cpu,float neicun);
private void ThreadForCpuView(object pfc)
{
PerformanceCounter pcCpuLoad = (PerformanceCounter)(pfc);
SetLabelTextDele setTextDele = new SetLabelTextDele(SetLabelText);
while (true)
{
Thread.Sleep(1000);
float cpuLoad = pcCpuLoad.NextValue();
MEMORY_INFO MemInfo;
MemInfo = new MEMORY_INFO();
GlobalMemoryStatus(ref MemInfo);
float neicunLoad = MemInfo.dwMemoryLoad;
this.Invoke(setTextDele, new object[] { cpuLoad, neicunLoad });
//
}
}
private void SetLabelText(float cpu,float neicun)
{
//cpustatus.Value = (int)cpu;//CPU使用率进度条,0-100
neicunstatus.Value = (int)neicun;//内存使用率进度条,0-100
}
[DllImport("kernel32")]
public static extern void GetSystemDirectory(StringBuilder SysDir, int count);
[DllImport("kernel32")]
public static extern void GetSystemInfo(ref CPU_INFO cpuinfo);
[DllImport("kernel32")]
public static extern void GlobalMemoryStatus(ref MEMORY_INFO meminfo);
[DllImport("kernel32")]
public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo);
//定义CPU的信息结构
[StructLayout(LayoutKind.Sequential)]
public struct CPU_INFO
{
public uint dwOemId;
public uint dwPageSize;
public uint lpMinimumApplicationAddress;
public uint lpMaximumApplicationAddress;
public uint dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public uint dwProcessorLevel;
public uint dwProcessorRevision;
}
//定义内存的信息结构
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_INFO
{
public uint dwLength;
public uint dwMemoryLoad;
public uint dwTotalPhys;
public uint dwAvailPhys;
public uint dwTotalPageFile;
public uint dwAvailPageFile;
public uint dwTotalVirtual;
public uint dwAvailVirtual;
}
//定义系统时间的信息结构
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME_INFO
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (newThread != null)
{
newThread.Abort();
newThread = null;
}
}
CPU和内存使用率可以交替显示,也可以只显示一种,也可以再加一个竖直进度条显示;
每次编程实现代码是不必要的,很多功能能输入不同,但是对输入的处理是一致的,我们可以用XML文件来实现命令扩展,一次编译后,只需修改xml即可扩展菜单上的功能;
新建XML文件:
对于Commamd节点,有两个属性name和value,前一个作为菜单文字,后一个作为单击事件的执行输入;
在页面加载时,执行读xml文件函数,往菜单栏中添加菜单项:
private void ReadList(string dir)
{
if(false == File.Exists(dir))
{
return;
}
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(dir); //加载你的XML文件
XmlNode xmlno = xmlDoc.GetElementsByTagName("AppConfig")[0];//找到AppConfig元素
//逐个读出
foreach (XmlNode xmlvalno in xmlno.ChildNodes)
{
string value="",name="";
try
{
value = xmlvalno.Attributes["value"].Value;
name = xmlvalno.Attributes["name"].Value;
}
catch
{//某个节点出错,读下一个节点
continue;
}
//name和value属性都存在,添加到上下文菜单栏
this.XmlCmdList.DropDownItems.Add(name, null, (o, e1) =>
{
ExecuteNoReply(value);
});
//
}
}
catch
{
MessageBox.Show("从XML文件取命令出错");
}
}
/*********************** 结尾 ********************/
因为没有常规窗体的关闭按钮,所以建议在右键菜单加入关闭程序的
Application.Exit()代码;
有一个注意的地方是,程序退出是,如果小图标还在,是不会自动消失的.