使 Autohotkey 忽略字符串中的任何特殊字符
Make Autohotkey ignore any special characters in string
我们正在使用一个解析器程序(我无权访问)来解析一堆计算机生成的邮件,但需要一些帮助来决定它必须做什么。因此,员工 kann 使用主题行来执行其他命令。由于我们每天向程序提供 500 多封邮件,并且命令看起来都类似于:Ba,Vi;#TD*; x0003
,因此不可能手动编写它们。所以我写了一个小的 C# 脚本来创建一个 Autohotkey 脚本,它完成了 90% 的工作。理论上。它有效,但前提是我不使用任何特殊字符,例如 , : & % etc
.
我试过了:
clipboard := Ba{,}Vi{;}{#}TD{*}{;} x0003
clipboard := "Ba,Vi;#TD*; x0003"
clipboard := Ba',Vi';'#TD'*'; x0003
clipboard := {raw} Ba,Vi;#TD*; x0003
(plus some others that I probably forgot here)
这是带有注释的整个 AHK 脚本。在 Outlook 中选择电子邮件时启动它:
;Win+z -> start script
#z::
;Currently only one iteration
loop,1
{
;CTRL+F to forward selected mail,
;which then automatically selects the "To:" line
Send, {CTRLDOWN}f{CTRUP}
Sleep, 500
Send, someemail@adress
Sleep, 500
;Initialize GUI
Gui, +AlwaysOnTop
Gui, Font, S5, Verdana, bold
Gui, Add, Text,, SCANNING-BOOSTER:
Gui, Color, F4A460
;Example for the C# generated buttons below (they all do the same thing):
;Clicking the Button "Google" will run the following script
;Start:
;clipboard := www.Google.com
;return
;This is the part where AHK fails because instead
;of www.Google.com I have codes like "Ba,Vi;#TD*; x0003" which crash AHK
Gui,add,Button,gLabel,Google
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
..... (around 60 more auto-generated buttons)
Gui,show
Return
Label:
;run the script that has the same name as the Button
;in this case it would be Google.ahk
Run, % A_GuiControl ".ahk"
GuiClose:
Gui, Hide
Sleep, 1000
;after the user has pressed a button and the according code
;has been copied to the clipboard, the GUI closes, the
;mail window becomes active again and we can continue to paste
;the code into the subject line
;Go to subject line
Send, {ALTDOWN}r{ALTUP}
Sleep, 500
;CTRL+a
Send, {CTRLDOWN}a{CTRUP}
Sleep, 500
;Write text from your clipboard to the subject line
Send, %clipboard%
Sleep, 500
return
}
显然,目前无法在 Autohotkey 中将(或多或少)随机字符串复制到您的剪贴板,然后将其粘贴到其他地方而不会收到如此多的错误,因此值得一试。除了自己用 C# 编写所有程序外,我别无选择。这是我的做法:
首先,启动一个新的控制台应用程序,然后将其更改为 Windows 应用程序
How to change a console application to a windows form application?
这是使程序对用户完全不可见的最简单方法。
接下来,我们需要一个关键的监听器。这是我使用的那个:
https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/
我建议你把它放在一个新的 class 中。这段代码无论如何都需要稍微修改一下,因为它会将每次按键都打印到控制台。我们不想要那个,我们想从中调用一个方法。将 HookCallback
更改为:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (KeyPressed == vkCode)
DoWork();
}
return CallNextHookEx(_HookID, nCode, wParam, lParam);
}
为了使上面的代码正常工作,我们需要向 class:
添加一个新的委托和一个新的 int 变量
private static int KeyPressed;
public delegate void SomethingToDo();
private static SomethingToDo DoWork;
SetHook 也需要一些小改动:
private static IntPtr SetHook(KeyboardProc _proc, int KeyCode, SomethingToDo GiveMeWork)
{
DoWork = GiveMeWork;
KeyPressed = KeyCode;
...(leave the rest as it is)...
}
该程序现在完全不可见,并且可以对按键做出反应。我们反其道而行之,模拟按键!
Ctrl key kept down after simulating a ctrl key down event and ctrl key up event
这要简单得多。我做了三个方法,PressKey、ReleaseKey和TapKey。请记住,ALT 和 F10 是特殊的系统键,可能不起作用。
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private const int KeyPressCode = 0x0001;
private const int KeyReleaseCode = 0x0002;
public static void PressKey(System.Windows.Forms.Keys Key)
{
keybd_event((byte)Key, 0, KeyPressCode | 0, 0);
Thread.Sleep(10);
}
public static void ReleaseKey(System.Windows.Forms.Keys Key)
{
keybd_event((byte)Key, 0, KeyPressCode | KeyReleaseCode, 0);
Thread.Sleep(10);
}
public static void TapKey(System.Windows.Forms.Keys Key)
{
PressKey(Key);
ReleaseKey(Key);
}
就是这样,一个可以处理字符串的基本Autohokey-Clone。如果你想更进一步,为它制作一个尝试图标:
https://translate.google.de/translate?sl=de&tl=en&js=y&prev=_t&hl=de&ie=UTF-8&u=https%3A%2F%2Fdotnet-snippets.de%2Fsnippet%2Fvorlage-fuer-tray-notifyicon-anwendung%2F541&edit-text=&act=url
显示带有按钮的 GUI 也非常简单:
using (Form _form = new Form())
{
_form.size = ...
//....
Button MyButton = new Button();
//....
//closing is also pretty simple, just like your everyday Windows Forms Application:
MyButton.Click += new EventHandler((sender, e) => { Application.Exit(); });
_form.ShowDialog();
}
在 main 方法中将所有内容放在一起:
private static NotifyIcon TrayIcon = new NotifyIcon();
[STAThread]
static void Main(string[] args)
{
bool WindowOpen = true;
try
{
//Make a new method above or below Main() and replace DoSomething with it.
//It will be executed everytime the F2 key is pressed.
KeyListener._HookID = KeyListener.SetHook(proc, System.Windows.Forms.Keys.F2, DoSomething);
System.Windows.Forms.ContextMenu SmallMenu = new System.Windows.Forms.ContextMenu();
System.Windows.Forms.MenuItem MenuElement;
int MenuIndex = 0;
MenuElement = new System.Windows.Forms.MenuItem();
MenuElement.Index = ++MenuIndex;
MenuElement.Text = "Close";
MenuElement.Click += new EventHandler((sender, e) => { WindowOpen = false; System.Windows.Forms.Application.Exit(); });
SmallMenu.MenuItems.Add(MenuElement);
TrayIcon.Icon = new System.Drawing.Icon("Ghost.ico");
TrayIcon.Text = "String Compatible AHK";
TrayIcon.Visible = true;
TrayIcon.ContextMenu = SmallMenu;
while (WindowOpen)
System.Windows.Forms.Application.Run();
}
finally
{
TrayIcon.Dispose();
KeyListener.UnhookWindowsHookEx(KeyListener._HookID);
}
}
我们正在使用一个解析器程序(我无权访问)来解析一堆计算机生成的邮件,但需要一些帮助来决定它必须做什么。因此,员工 kann 使用主题行来执行其他命令。由于我们每天向程序提供 500 多封邮件,并且命令看起来都类似于:Ba,Vi;#TD*; x0003
,因此不可能手动编写它们。所以我写了一个小的 C# 脚本来创建一个 Autohotkey 脚本,它完成了 90% 的工作。理论上。它有效,但前提是我不使用任何特殊字符,例如 , : & % etc
.
我试过了:
clipboard := Ba{,}Vi{;}{#}TD{*}{;} x0003
clipboard := "Ba,Vi;#TD*; x0003"
clipboard := Ba',Vi';'#TD'*'; x0003
clipboard := {raw} Ba,Vi;#TD*; x0003
(plus some others that I probably forgot here)
这是带有注释的整个 AHK 脚本。在 Outlook 中选择电子邮件时启动它:
;Win+z -> start script
#z::
;Currently only one iteration
loop,1
{
;CTRL+F to forward selected mail,
;which then automatically selects the "To:" line
Send, {CTRLDOWN}f{CTRUP}
Sleep, 500
Send, someemail@adress
Sleep, 500
;Initialize GUI
Gui, +AlwaysOnTop
Gui, Font, S5, Verdana, bold
Gui, Add, Text,, SCANNING-BOOSTER:
Gui, Color, F4A460
;Example for the C# generated buttons below (they all do the same thing):
;Clicking the Button "Google" will run the following script
;Start:
;clipboard := www.Google.com
;return
;This is the part where AHK fails because instead
;of www.Google.com I have codes like "Ba,Vi;#TD*; x0003" which crash AHK
Gui,add,Button,gLabel,Google
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
..... (around 60 more auto-generated buttons)
Gui,show
Return
Label:
;run the script that has the same name as the Button
;in this case it would be Google.ahk
Run, % A_GuiControl ".ahk"
GuiClose:
Gui, Hide
Sleep, 1000
;after the user has pressed a button and the according code
;has been copied to the clipboard, the GUI closes, the
;mail window becomes active again and we can continue to paste
;the code into the subject line
;Go to subject line
Send, {ALTDOWN}r{ALTUP}
Sleep, 500
;CTRL+a
Send, {CTRLDOWN}a{CTRUP}
Sleep, 500
;Write text from your clipboard to the subject line
Send, %clipboard%
Sleep, 500
return
}
显然,目前无法在 Autohotkey 中将(或多或少)随机字符串复制到您的剪贴板,然后将其粘贴到其他地方而不会收到如此多的错误,因此值得一试。除了自己用 C# 编写所有程序外,我别无选择。这是我的做法:
首先,启动一个新的控制台应用程序,然后将其更改为 Windows 应用程序
How to change a console application to a windows form application?
这是使程序对用户完全不可见的最简单方法。
接下来,我们需要一个关键的监听器。这是我使用的那个:
https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/
我建议你把它放在一个新的 class 中。这段代码无论如何都需要稍微修改一下,因为它会将每次按键都打印到控制台。我们不想要那个,我们想从中调用一个方法。将 HookCallback
更改为:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (KeyPressed == vkCode)
DoWork();
}
return CallNextHookEx(_HookID, nCode, wParam, lParam);
}
为了使上面的代码正常工作,我们需要向 class:
添加一个新的委托和一个新的 int 变量private static int KeyPressed;
public delegate void SomethingToDo();
private static SomethingToDo DoWork;
SetHook 也需要一些小改动:
private static IntPtr SetHook(KeyboardProc _proc, int KeyCode, SomethingToDo GiveMeWork)
{
DoWork = GiveMeWork;
KeyPressed = KeyCode;
...(leave the rest as it is)...
}
该程序现在完全不可见,并且可以对按键做出反应。我们反其道而行之,模拟按键!
Ctrl key kept down after simulating a ctrl key down event and ctrl key up event
这要简单得多。我做了三个方法,PressKey、ReleaseKey和TapKey。请记住,ALT 和 F10 是特殊的系统键,可能不起作用。
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private const int KeyPressCode = 0x0001;
private const int KeyReleaseCode = 0x0002;
public static void PressKey(System.Windows.Forms.Keys Key)
{
keybd_event((byte)Key, 0, KeyPressCode | 0, 0);
Thread.Sleep(10);
}
public static void ReleaseKey(System.Windows.Forms.Keys Key)
{
keybd_event((byte)Key, 0, KeyPressCode | KeyReleaseCode, 0);
Thread.Sleep(10);
}
public static void TapKey(System.Windows.Forms.Keys Key)
{
PressKey(Key);
ReleaseKey(Key);
}
就是这样,一个可以处理字符串的基本Autohokey-Clone。如果你想更进一步,为它制作一个尝试图标:
https://translate.google.de/translate?sl=de&tl=en&js=y&prev=_t&hl=de&ie=UTF-8&u=https%3A%2F%2Fdotnet-snippets.de%2Fsnippet%2Fvorlage-fuer-tray-notifyicon-anwendung%2F541&edit-text=&act=url
显示带有按钮的 GUI 也非常简单:
using (Form _form = new Form())
{
_form.size = ...
//....
Button MyButton = new Button();
//....
//closing is also pretty simple, just like your everyday Windows Forms Application:
MyButton.Click += new EventHandler((sender, e) => { Application.Exit(); });
_form.ShowDialog();
}
在 main 方法中将所有内容放在一起:
private static NotifyIcon TrayIcon = new NotifyIcon();
[STAThread]
static void Main(string[] args)
{
bool WindowOpen = true;
try
{
//Make a new method above or below Main() and replace DoSomething with it.
//It will be executed everytime the F2 key is pressed.
KeyListener._HookID = KeyListener.SetHook(proc, System.Windows.Forms.Keys.F2, DoSomething);
System.Windows.Forms.ContextMenu SmallMenu = new System.Windows.Forms.ContextMenu();
System.Windows.Forms.MenuItem MenuElement;
int MenuIndex = 0;
MenuElement = new System.Windows.Forms.MenuItem();
MenuElement.Index = ++MenuIndex;
MenuElement.Text = "Close";
MenuElement.Click += new EventHandler((sender, e) => { WindowOpen = false; System.Windows.Forms.Application.Exit(); });
SmallMenu.MenuItems.Add(MenuElement);
TrayIcon.Icon = new System.Drawing.Icon("Ghost.ico");
TrayIcon.Text = "String Compatible AHK";
TrayIcon.Visible = true;
TrayIcon.ContextMenu = SmallMenu;
while (WindowOpen)
System.Windows.Forms.Application.Run();
}
finally
{
TrayIcon.Dispose();
KeyListener.UnhookWindowsHookEx(KeyListener._HookID);
}
}