一些杂七杂八的C#语法
今天,刚刚接到一个需求,逻辑上而言可以说是没难度,但是,这个语法上,由于我c#太菜了,之前为了应对一个客户端软件现学的,一段时间不用之后,是真的记不住啊。
领导的意思是,这次写的是一个后台程序,按个快捷键,采集某设备数据,然后将结果1写入在光标所在位置,将光标换到下一个单元格,结果2写入光标新的位置。
采集数据和写入数据不能互相影响,言外之意也就是哪怕设备半天不响应,你该打印也得打印出来,大不了结果为null嘛。
最坑的是那设备好像就一台,所以我的代码得先和设备“解耦”,先干写,测试不了。
说到底这东西充其量算个小工具,逻辑上虽然没啥难度,但是语法是真不会,搜索引擎成了最后的归宿。这一次也算是吸取上回的经验,虽然需求说的挺明确,但肯定远不止于此。
我预计按照大佬的一贯作风,这个小玩意至少还得有自动扫描可用com口,开机自启动,应该没啥别的了。
然后,我很疑惑的问了一句,既然这个程序不需要提供界面,那为啥还要求是winform项目呢?大佬表示exe文件对用户比较友好。本来想用java来着,那行吧。
开机自启动和最小化至托盘的代码全是从网上扒下来的,注册系统热键的代码也是网上扒下来的,serialport的使用方法也是参照网上的代码。
吸取了上次采集温湿度设备的经验,两次查询命令之间目前设为100毫秒的间隔,不知道设备能不能反应的过来,最后写了半天,感觉代码里就没几行是自己写的,上网找到的资料多为一些“古董级别”的文章。
最终有一种自己在破案的感觉,体验感极差,写到这里对java的怀念之情油然而生。为了避免下次再遇到相同的尴尬场景,我决定将代码简单整理一下(以下代码均转载自网络),首先是开机自启动:
// 获得应用程序路径 string strAssName = Application.StartupPath + @"\" + Application.ProductName + @".exe"; // 获得应用程序名称 string strShortFileName = Application.ProductName; // 打开注册表基项"HKEY_LOCAL_MACHINE" RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); if (rgkRun == null) { // 若不存在,创建注册表基项"HKEY_LOCAL_MACHINE" rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); //MessageBox.Show("添加开机启动成功"); } // 设置指定的注册表项的指定名称/值对。如果指定的项不存在,则创建该项。 rgkRun.SetValue(strShortFileName, strAssName); //MessageBox.Show("添加开机启动成功");
写上就好使,咱也不懂,咱也不敢问。
然后,是注册热键的代码:
class HotKey { // 如果函数执行成功,返回值不为0。 // 如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。 [DllImport("user32.dll", SetLastError = true)] public static extern bool RegisterHotKey( IntPtr hWnd, // 要定义热键的窗口的句柄 int id, // 定义热键ID(不能与其它ID重复) KeyModifiers fsModifiers, // 标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效 Keys vk // 定义热键的内容 ); [DllImport("user32.dll", SetLastError = true)] public static extern bool UnregisterHotKey( IntPtr hWnd, // 要取消热键的窗口的句柄 int id // 要取消热键的ID ); // 定义了辅助键的名称(将数字转变为字符以便于记忆,也可去除此枚举而直接使用数值) [Flags()] public enum KeyModifiers { None = 0, Alt = 1, Ctrl = 2, Shift = 4, WindowsKey = 8 } }
上面这个类是关键的部分,不知道哪个大佬封装的,感谢你。
// 注册热键Ctrl+B,Id号为101。HotKey.KeyModifiers.Ctrl也可以直接使用数字2来表示。 HotKey.RegisterHotKey(Handle, 101, HotKey.KeyModifiers.Ctrl, Keys.B);
这条语法是注册热键。
最终还需要给一个按快捷键后会触发的代码:
protected override void WndProc(ref Message m) { const int WM_HOTKEY = 0x0312;//如果m.Msg的值为0x0312那么表示用户按下了热键 // 按快捷键 switch (m.Msg) { case WM_HOTKEY: switch (m.WParam.ToInt32()) { case 101: // 按下的是Ctrl+B // 此处填写快捷键响应代码 break; } break; } base.WndProc(ref m); }
重写窗体的这个方法。
缩小至托盘的代码:
this.Hide(); //隐藏任务栏区图标 this.ShowInTaskbar = false; //图标显示在托盘区 notifyIcon1.Visible = true;
有一点要注意的是必须要给notifyIcon(如果你是用它实现的话,有没有其他的实现方法我就不清楚了),必须要给它设置图标,否则在最小化后是看不到的。
如果你还需要加一个右键退出程序之类的这种东西,那就会用到contextMenuStrip,这两者需要建立关联,怎么操作自行搜索一下吧,然后contextMenuStrip中添加一个按钮或者叫菜单,最后给个点击事件即可。
if (MessageBox.Show("是否确认退出程序?", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) { // 关闭所有的线程 this.Dispose(); this.Close(); }
事件中可以写入这段代码,也是我从网上扒下来又稍稍改了一小下的。
还有将文字写入光标所在位置:
private void WriteInfo() { SendKeys.Send("结果1"); SendKeys.Send("{TAB}"); SendKeys.Send("结果2"); }
开始在网上找了一些代码,大多看的我头疼,然后突然发现了一个人说可以将数据放入剪切板,再用程序模拟ctrl+v,粘上去就行了。我试了一下,真的可以,但是紧接着发现连续两次操作不同的数据的话,会将第二个数据粘贴两次。
这就有点难受了,为了能用上简单的方法,我开始自行探索,突然发现如果用SendKeys.Send方法发送字母的话,最终效果类似于用户打字,输入法会弹出来。那如果发送字符串呢?试了一下,直接打印至光标所在位置了。
这个方法还可以用来模拟其他的快捷键,具体的可以自行搜索它的用法,很好找。
希望这篇文章能够帮助到一些同病相怜的人,如果有啥疑问建议自行搜索,实在不行可以评论区讨论一下,作者大概率给不出答案,作者c#学的菜。