"拍牌神器"是怎样炼成的(三)---注册全局热键

要想在上海拍牌的超低中标率中把握机会、占得先机,您不仅需要事先准备好最优的竞拍策略,还要制定若干套应急预案,应对不时之需。既定策略交给计算机自动执行,没有问题。可是谁来召唤应急预案呢?使用全局热键应该是个不错的选择。

正确使用全局热键,您得按下面的步骤来:

  1. 向系统注册HotKey(可以是一个键,也可以是组合键)。
  2. 接收系统WM_HOTKEY消息,触发你的HOTKEY事件。
  3. 完成你的事件处理程序。
  4. 程序结束时,记得注销HotKey。

注册HotKey

先来看看,我们需要用到哪些WinAPI函数:

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern ushort GlobalAddAtom(string lpString);

GlobalAddAtom函数的功能是向系统全局原子表添加原子,全局原子表是系统用来共享信息的,我们在这里用它产生一个唯一标识号,供RegisterHotKey函数使用,避免注册的热键与其他程序的热键冲突。

RegisterHotKey注册热键函数的3个传入参数含义分别如下

  • hWnd 响应热键事件的窗口句柄。
  • id 一个唯一标识号,通过GlobalAddAtom函数获得
  • fsModifiers 组合键CTRL、ALT、SHIFT等键(我一般不用,加个组合键影响操作速度)。
  • vk 热键键值

注销HotKey

注册的逆向操作而已,仅给出WinAPI函数声明吧。

[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
static extern ushort GlobalDeleteAtom(ushort nAtom);       

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool UnregisterHotKey(IntPtr hWnd, int id);

接收HotKey消息

我们需要写一个实现IMessageFilter接口的类,并把这个类实例通过System.Windows.Forms.Application.AddMessageFilter(IMessageFilter)方法添加到消息筛选器中去,当消息产生时会调用IMessageFilter接口的PreFilterMessage方法,通过PreFilterMessage方法可以触发我们自己的消息处理函数。

下面的代码,定义了一个简单的筛选器类:

public delegate void HotkeyEventHandler(int HotKeyID);

public class HotKey : System.Windows.Forms.IMessageFilter
{
    IntPtr hWnd;
    readonly int WM_HOTKEY = 0x312;
    public enum KeyFlags { MOD_ALT = 0x1, MOD_CONTROL = 0x2, MOD_SHIFT = 0x4, MOD_WIN = 0x8 }

    System.Collections.Hashtable keyIDs = new System.Collections.Hashtable();

    public event HotkeyEventHandler OnHotkey;

    [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    static extern ushort GlobalAddAtom(string lpString);

    [DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
    static extern ushort GlobalDeleteAtom(ushort nAtom);

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    public HotKey(IntPtr hWnd)
    {
        this.hWnd = hWnd; 
		System.Windows.Forms.Application.AddMessageFilter(this); //添加到消息筛选器
    }

    public int RegisterHotkey(System.Windows.Forms.Keys Key, KeyFlags keyflags)
    {
        String keyname = System.Guid.NewGuid().ToString();
        int hotkeyid = GlobalAddAtom(keyname);		//添加全局原子表
        RegisterHotKey((IntPtr)hWnd, hotkeyid, (UInt32)keyflags, (UInt32)Key); //注册热键
        keyIDs.Add(keyname,hotkeyid);          
        return hotkeyid;        
    }

    public void UnregisterHotkeys() //注销HotKeys
    {
        System.Windows.Forms.Application.RemoveMessageFilter(this);
        foreach (int key in keyIDs.Values)           
        {
            UnregisterHotKey(hWnd, key); 
            GlobalDeleteAtom((ushort)key);
        }
    }

    public bool PreFilterMessage(ref System.Windows.Forms.Message m) //IMessageFilter接口实现
    {
        if (m.Msg == WM_HOTKEY)
        {
            if (OnHotkey != null)
            {
                foreach (int key in keyIDs.Values)
                {
                    if ((int)m.WParam == key)
                    {
                        OnHotkey((int)m.WParam);
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

代码中如何使用

在WinForm程序中,调用方法如下:

HotKey hotKey;
private void Form1_Load(object sender, EventArgs e)
{
	...
	hotKey = new HotKey(this.Handle);
	hotKey.RegisterHotkey(Keys.F2, 0);
	hotKey.OnHotkey += hotkey_OnHotkey;
}

void hotkey_OnHotkey(int HotKeyID)
{
	...
    MessageBox.Show("OnHotkey" + HotKeyID);
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (hotKey != null)
        hotKey.UnregisterHotkeys();
}

结束语

本讲结束了,如何使用计算机替代的工作进行拍牌也讲完了,接下来,我们要开始介绍如何用计算机替代的工作(验证码识别)。

本次的例子,在键鼠模拟之WinAPI的例子中已经包含,可在这里下载

原文地址:https://www.cnblogs.com/shenwx/p/5416117.html