zoukankan      html  css  js  c++  java
  • "拍牌神器"是怎样炼成的(三)---注册全局热键

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

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

    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的例子中已经包含,可在这里下载

  • 相关阅读:
    23、Linux实操篇——RPM与YUM
    22、Linux实操篇——进程管理(重点)
    21、Linux实操篇——网络配置
    20、Linux实操篇——磁盘分区、挂载
    19、Linux实操篇——组管理和权限管理
    18、实操篇——实用指令
    17、实操篇——用户管理
    UVALive 2521 Game Prediction 题解
    UVALive 2517 Moving Object Recognition(模拟)
    UVALive 2324 Human Gene Functions(动态规划)
  • 原文地址:https://www.cnblogs.com/shenwx/p/5416117.html
Copyright © 2011-2022 走看看