很多高端机械键盘,支持宏定义,例如我们可以设置"D"键为"dota",这样当我们按一下宏开启键,再按一下"D"键,就等价于分别按了"d" "o" "t" "a"四个键。这时就可以把一些敲代码时常用的模板定义成键盘宏,到时候一键补全代码,既高效又装X。另外,玩游戏时想按出“下前下前拳”这样的组合技能也容易多了。

那么问题来了。。

山里来的买不起机械键盘的穷B同时又是程序员应该怎么办。。

其实这样简单的功能不一定非要硬件支持,借助一些现有软件模拟一下键盘就好了,在windows下有按键精灵和AutoHotKey这些神器,模拟起来很容易,而且体验非常完美。

我是借助按键精灵实现的,按键精灵语法很简单,例如 KeyPress "A", 3 就表示按A键3次,而且支持全局快捷键启动,支持监听用户输入,真是简单到无情。

不过问题又来了。。

键盘宏主要是按一系列按键,如果每个按键都写一行 KeyPress "X", 1 ,有的还得配合Shift键才能按出来,也是累,而且一行一句代码,看上去不直观,容易写错。

那就写个代码生成器就好了,我是用C语言+std::string实现的,直接把宏写成字符串,生成器自动输出相应的按键,粘贴到按键精灵中编译保存就好了。

贴一下代码:

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <string> using std::string; enum class OpType {
Press,
Down,
Up
}; enum class CombKey {
Shift,
Ctrl,
Alt
}; void initTransHash(); //初始化按shift才能打出的字符
void transfer(char c); //shift打出的字符转化为真正的按键
void procOpType(OpType type); //输出按键操作
void callKey(OpType type, char key, int count=); //按键
void callKey(OpType type, string key, int count=); //重载,按功能键
void keyComb(CombKey comb, char key); //组合键 const int delay = ;
string transChar;
char transHash[]; int main() {
initTransHash(); string keys = "function() {\n},"; for(char key : keys) {
if(strchr(transChar.c_str(), key) != NULL) {
transfer(key);
} else {
if(isupper(key)) {
keyComb(CombKey::Shift, key);
} else {
callKey(OpType::Press, key);
}
}
}
} void initTransHash() {
memset(transHash, , sizeof(transHash)); //
// ~ ! @ # $ % ^ & * ( ) _ + { } | : \" < > ?
// ` 1 2 3 4 5 6 7 8 9 0 - = [ ] \\ ; ' , . / transChar = "~!@#$%^&*()_+{}|:\"<>? \n";
string keys = "`1234567890-=[]\\;',./\0\0"; // transChar空格后面的字符不加入hash表
for(int i = ; i < keys.size(); i++) {
transHash[transChar[i]] = keys[i];
}
} void transfer(char c) {
if(transHash[c]) {
keyComb(CombKey::Shift, transHash[c]);
return;
}
switch(c) {
case '\n':
callKey(OpType::Press, "Enter");
break; case ' ':
callKey(OpType::Press, "Space");
break; default:
printf("[Red] cant transfer: %c\n", c);
break;
}
} void procOpType(OpType type) {
switch(type) {
case OpType::Press:
printf("KeyPress "); break;
case OpType::Down:
printf("KeyDown "); break;
case OpType::Up:
printf("KeyUp "); break;
}
} void callKey(OpType type, char key, int count) {
procOpType(type);
printf("\"%c\", %d\n", islower(key) ? key- : key, count);
printf("Delay %d\n", delay); //每次按键后延迟10毫秒
} void callKey(OpType type, string key, int count) {
procOpType(type);
//printf("\"%s\"\n", key.c_str());
printf("\"%s\", %d\n", key.c_str(), count);
printf("Delay %d\n", delay); //每次按键后延迟10毫秒
} void keyComb(CombKey comb, char key) {
string combKey;
switch(comb) {
case CombKey::Shift:
combKey = "Shift"; break;
case CombKey::Ctrl:
combKey = "Ctrl"; break;
case CombKey::Alt:
combKey = "Alt"; break;
default:
return;
} callKey(OpType::Down, combKey);
callKey(OpType::Press, key);
callKey(OpType::Up, combKey);
}

按键精灵_键盘宏_代码生成器

然后把每一个键盘宏写成一个函数,通过按下按键精灵的全局快捷键启动,然后脚本监听用户按键,然后调用相应函数执行键盘宏就可以了,模板类似这样:

 choose = WaitKey()
TracePrint choose Select Case choose
Case
KeyPress "BackSpace",
Call F()
Case
KeyPress "BackSpace",
Call H()
End Select // 按下F键
Sub F()
End Sub // 按下H键
Sub H()
End Sub

按键精灵_键盘宏_模板

(宏键也会打印出来,所以我在调用函数打印键盘宏之前,调用BackSpace删除了宏键的字符)

然后问题又来了。。

上班用的是Mac,Mac没有按键精灵呀。最简单的办法是安装windows虚拟机,物理机和虚拟机共享代码目录,在虚拟机中敲代码,其他工作仍然在物理机中进行,不影响工作流。(其实用了5个月的Mac了,个人感觉,在新鲜感过了之后,实用性比windows差远了)

另外如果不想通过虚拟机的方式,还可以使用AppleScript,但是AppleScript本身没有像按键精灵那样的全局启动快捷键,可以通过Automator把AppleScript设置为系统服务,然后给服务设置快捷键,但是AppleScript不方便监听用户按键事件,目前我只能通过dialog读取用户输入,所以做不到按键精灵那样完美,上面的生成器的代码稍微改动一下,就能作为AppleScript的键盘宏生成器了,下面是AppleScript的模板:

 tell application "System Events"
display dialog "choose" default answer ""
set ans to text returned of result if ans = "p" then
keystroke ""
keystroke ""
keystroke ""
keystroke ""
keystroke ""
else
display dialog "unknown"
end if end tell

AppleScript_键盘宏_模板

但是焦点会被dialog获取,需要在键盘宏之前把接收键盘宏的进程设为最前。

tell process "XXXXXX"
set frontmost to true
end tell

还是安装虚拟机好得多。。

自己动手,丰衣足食。普通键盘实现键盘宏(Windows和Mac版)的更多相关文章

  1. Synergy 多系统共享鼠标键盘 Windows 和 Mac 完全配置教程

    公司终于配上了双主机双系统双屏幕,编码是爽了,但是桌上的键盘有多了一套,有没有什么软件能够在不同的电脑之间共享键盘和鼠标呢?后来发下了Synergy这款软件.不仅免费而且开源(支持下). 让办公桌上的 ...

  2. 从0开始编写dapper核心功能、压榨性能、自己动手丰衣足食

    我偶然听说sqlsugar的性能比dapper强.对此我表示怀疑(由于我一直使用的dapper存在偏见吧),于是自己测试了sqlsugar.freesql.dapper发现他们的给我的结果是 sqls ...

  3. 升级Windows 10 正式版过程记录与经验

    升级Windows 10 正式版过程记录与经验 [多图预警]共50张,约4.6MB 系统概要: 预装Windows 8.1中文版 64位 C盘Users 文件夹已经挪动到D盘,并在原处建立了符号链接. ...

  4. Windows 10正式版历代记:Version 和 Build 对应关系

    2017年10月中下旬,微软面向正式版用户推送了Windows 10创意者更新秋季版.这是自发布以来,Windows 10的第五个大版本. 在这篇文章中,我们来回顾一下Windows 10正式版的历史 ...

  5. Eclipse怎么样添加智能感知提示功能(含Windows版和Mac版)

    近日感兴趣于安卓,开始学习Android开发……第一次使用Eclipse,用久了VS,也习惯了他的智能提示,刚转到Eclipse下实在是不习惯…… 网上有人说按Alt + / 可以实现单词补全功能,实 ...

  6. Windows 10正式版历代记:Version 1709、Build 16299都是什么鬼?

    Windows 10免费用!创意者更新秋季版激活秘籍 2017年10月中下旬,微软面向正式版用户推送了Windows 10创意者更新秋季版.这是自发布以来,Windows 10的第五个大版本. 在这篇 ...

  7. 从Windows转mac遇到的一些坑

    本屌由于运气,分了一台imac来办公,由于以前一直都在用windows,现在用Mac有很多不适应的地方.下面介绍一下Mac与Windows有明显区别的地方: mac与windows鼠标滑轮方向不同. ...

  8. Windows 7旗舰版产品密钥

    http://www.xitongcheng.com/jiaocheng/win7_article_45903.html 一.Windows 7旗舰版产品密钥 零售版: Windows 7 Ultim ...

  9. Windows与MAC使用差异有感(还会不断更新体验)

    Windows与MAC使用差异有感(还会不断更新体验) 关于键盘 这上是MAC与Windows的⌨️按键区别 我们现在都是USB键盘,而PS/2键盘是已经淘汰掉的(插头是圆孔的),看上图会发现Comm ...

随机推荐

  1. linux-cat/less/more/tail

    都可以查看文件 不同点 cat:全部查看不分屏显示 定位到ccc结尾的那行 [root@besttest tmp]# cat yumyum.log|grep ccc$ aaaaaaaaaaaaaaaa ...

  2. [转]Asp.Net MVC 扩展联想控件

    本文转自:http://www.cnblogs.com/bright-lin/archive/2013/02/06/MVC_SuggestBox.html 在web中,为改善用户体验,我们常会将一些文 ...

  3. [设计模式]<<设计模式之禅>>模板方法模式

    1 辉煌工程——制造悍马 周三,9:00,我刚刚坐到位置上,打开电脑准备开始干活. “小三,小三,叫一下其他同事,到会议室开会”,老大跑过来吼,带着坏笑.还没等大家坐稳,老大就开讲了:“告诉大家一个好 ...

  4. 【模拟】UVa 12108 - Extraordinarily Tired Students

    When a student is too tired, he can't help sleeping in class, even if his favorite teacher is right ...

  5. hdu 4670 树的点分治

    思路:首先当然是要用树的点分治了.根节点为root,那么经过root的合法路径数求出来这题就解决了.因为我们可以用分治枚举根,最后将所有根的路径数加起来就是结果.当然这里的根不是整棵树的根,是子树根. ...

  6. 转:基于Webrtc的跨平台实时语音通信解决方案(讲座)

    转:http://edu.csdn.net/course/detail/320/

  7. Linux 命令 - uniq: 通知或忽略重复行

    给定一个已排好序的文件,uniq 会删除重复行并将结果输出到标准输出中.uniq 通常与 sort 结合使用以删除 sort 输出内容中的重复行. 命令格式 uniq [OPTION]... [INP ...

  8. Networking - ICMP 协议

    发送到远程计算机的数据通常发经过一个或多个路由器,这些路由器在把数据传输到最终目的地的过程中可能发生多种问题.路由器利用 ICMP 把问题通知给源 IP.ICMP 还有用于其他调试和排错的功能. IC ...

  9. js解析json读取List中的实体对象示例

    1.由后台action 传给前台是需要将map 转成json格式 复制代码代码如下: Map<String, List> resultMap: JSONObject json = JSON ...

  10. Android之线程终止

    Hanlder是线程与Activity通信的桥梁,利用handler接收到任务线程,放到任务队列里面派对执行. 1.初始化的时候,定义启动的线程为一个守护线程,这样当主线程消亡掉的时候,其他线程也会被 ...