改进的AutoHotInterception,愿愿。

本文介绍AutoHotInterception的一些改进,在AutoHotInterception-3.4中生成了AutoHotInterception.dll,但用起来发现鼠标响应有问题,它是用C#编写的,看了源代码之后,愿愿推测,一方面是鼠标的处理过程太长,sleep时间设置太长。所以,想把它改进下。

首先设置,循环查询设备的数量定为8个,而不是20个,想法很简单,循环次数越小,那么鼠标的响应就越可靠。还有,把sleep时间设置为4ms,而不是原来的10ms,设置过短,占用cpu资源太多,设置过长鼠标响应会变得不可靠。所以,设置为4。

修改它的代码,本人安装了vs2010,由于AutoHotInterception是用C#6,编写的所以对语法稍作修改。具体:修改代码如下:

ManagedWrapper.cs文件不变,与原版相同。

DeviceIds目标是设置键盘在1到4,鼠标设备在11到14。

注意紫色代码:

        public void SetContextCallback(int id, dynamic callback)
        {
            SetFilterState(false);
            if (id < 1 || id > 14||(id>4&&id<11))
            {
                throw new ArgumentOutOfRangeException("id ", "DeviceIds must be between 1 and 4 or 11 and 14");
            }

            _contextCallbacks[id] = callback;
            _filteredDevices[id] = true;

            SetFilterState(true);
            SetThreadState(true);
        }

名字空间由于C#版本不对,所以做如下改动:

using static AutoHotInterception.Helpers.HelperFunctions;

扫描二维码关注公众号,回复: 5093553 查看本文章

变为,在调用方法前加入HelperFunctions,把上句变为using AutoHotInterception.Helpers;

HelperFunctions.IsValidDeviceId(false, id);

等等吧。

继续改动:

        public int GetDeviceId(bool isMouse, int vid, int pid, int instance = 1)
        {
            var start = isMouse ? 11 : 1;
            var max = isMouse ? 15 : 5;

            for (var i = start; i < max; i++)
            {
                var handle = ManagedWrapper.GetHardwareStr(_deviceContext, i, 1000);
                int foundVid = 0, foundPid = 0;
                HelperFunctions.GetVidPid(handle, ref foundVid, ref foundPid);
                if (foundVid != vid || foundPid != pid) continue;
                if (instance == 1)
                {
                    return i;
                }
                instance--;
            }

            //ToDo: Should throw here?
            return 0;
        }

继续改动:


        private void PollThread()
        {
            ManagedWrapper.Stroke stroke = new ManagedWrapper.Stroke();

            while (true)
            {
                // Iterate through all Keyboards
                for (var i = 1; i < 5; i++)
                {
                    var isMonitoredKeyboard = IsMonitoredDevice(i) == 1;
                    var hasSubscription = false;
                    var hasContext = _contextCallbacks.ContainsKey(i);

                    // Process any waiting input for this keyboard
                    while (ManagedWrapper.Receive(_deviceContext, i, ref stroke, 1) > 0)
                    {
                        var block = false;
                        // If this is not a monitored keyboard, skip.
                        // This check should not really be needed as the IsMonitoredDevice() predicate should only match monitored keyboards...
                        // ... but in case it does, we want to ignore this bit and pass the input through
                        if (isMonitoredKeyboard && _keyboardMappings.ContainsKey(i))
                        {
                            // Process Subscription Mode
                            var code = stroke.key.code;
                            var state = stroke.key.state;

                            #region KeyCode, State, Extended Flag translation
                            // Begin translation of incoming key code, state, extended flag etc...
                            var processMappings = true;
                            if (code == 54)
                            {
                                // Interception seems to report Right Shift as 54 / 0x36...
                                // ... this code is normally unused (Alt-SysRq according to linked page) ...
                                // ... and AHK uses 54 + 256 = 310 (0x36 + 0x100 = 0x136)...
                                // ... so just keep the key code and behave as if the extended flag was set
                                state += 2;
                            }

                            // If state is shifted up by 2 (1 or 2 instead of 0 or 1), then this is an "Extended" key code
                            if (state > 1)
                            {
                                if (code == 42)
                                {
                                    // Shift (42/0x2a) with extended flag = the key after this one is extended.
                                    // Example case is Delete (The one above the arrow keys, not on numpad)...
                                    // ... this generates a stroke of 0x2a (Shift) with *extended flag set* (Normal shift does not do this)...
                                    // ... followed by 0x53 with extended flag set.
                                    // We do not want to fire subsriptions for the extended shift, but *do* want to let the key flow through...
                                    // ... so that is handled here.
                                    // When the extended key (Delete in the above example) subsequently comes through...
                                    // ... it will have code 0x53, which we shift to 0x153 (Adding 256 Dec) to signify extended version...
                                    // ... as this is how AHK behaves with GetKeySC()

                                    // Set flag to stop Context Mode from firing
                                    hasSubscription = true;
                                    // Set flag to indicate disable mapping processing
                                    processMappings = false;
                                }
                                else
                                {
                                    // Extended flag set
                                    // Shift code up by 256 (0x100) to signify extended code
                                    code += 256;
                                    state -= 2;
                                }
                            }
                            #endregion

                            // Code and state now normalized, proceed with checking for subscriptions...
                            if (processMappings && _keyboardMappings[i].ContainsKey(code))
                            {
                                hasSubscription = true;
                                var mapping = _keyboardMappings[i][code];
                                if (mapping.Block)
                                {
                                    block = true;
                                }

                                ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(1 - state));
                            }
                        }

                        // If the key was blocked by Subscription Mode, then move on to next key...
                        if (block) continue;

                        // If this key had no subscriptions, but Context Mode is set for this keyboard...
                        // ... then set the Context before sending the key
                        if (!hasSubscription && hasContext)
                        {
                            _contextCallbacks[i](1);
                        }

                        // Pass the key through to the OS.
                        ManagedWrapper.Send(_deviceContext, i, ref stroke, 1);

                        // If we are processing Context Mode, then Unset the context variable after sending the key
                        if (!hasSubscription && hasContext)
                        {
                            _contextCallbacks[i](0);
                        }
                    }
                }

                // Process Mice
                for (var i = 11; i < 15; i++)
                {
                    var isMontioredMouse = IsMonitoredDevice(i) == 1;
                    var hasSubscription = false;
                    var hasContext = _contextCallbacks.ContainsKey(i);

                    while (ManagedWrapper.Receive(_deviceContext, i, ref stroke, 1) > 0)
                    {
                        //Debug.WriteLine($"AHK| Mouse {i} seen - flags: {stroke.mouse.flags}, raw state: {stroke.mouse.state}");
                        var block = false;
                        if (isMontioredMouse)
                        {
                            if (stroke.mouse.state != 0 && _mouseButtonMappings.ContainsKey(i))
                            {
                                // Mouse Button
                                //Debug.WriteLine($"AHK| Mouse {i} seen - flags: {stroke.mouse.flags}, raw state: {stroke.mouse.state}");
                                var btnState = HelperFunctions.StrokeStateToButtonState(stroke);
                                if (_mouseButtonMappings[i].ContainsKey(btnState.Button))
                                {
                                    hasSubscription = true;
                                    var mapping = _mouseButtonMappings[i][btnState.Button];
                                    if (mapping.Block)
                                    {
                                        block = true;
                                    }

                                    var state = btnState;
                                    ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(state.State));
                                }
                                //Console.WriteLine($"AHK| Mouse {i} seen - button {btnState.Button}, state: {stroke.mouse.state}, rolling: {stroke.mouse.rolling}");
                            }
                            else if ((stroke.mouse.flags & (ushort) ManagedWrapper.MouseFlag.MouseMoveAbsolute) ==
                                     (ushort) ManagedWrapper.MouseFlag.MouseMoveAbsolute
                                     && _mouseMoveAbsoluteMappings.ContainsKey(i))
                            {
                                // Absolute Mouse Move
                                hasSubscription = true;
                                var mapping = _mouseMoveAbsoluteMappings[i];
                                if (mapping.Block)
                                {
                                    block = true;
                                }

                                var x = stroke.mouse.x;
                                var y = stroke.mouse.y;
                                ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
                            }
                            else if ((stroke.mouse.flags & (ushort)ManagedWrapper.MouseFlag.MouseMoveRelative) ==
                                     (ushort)ManagedWrapper.MouseFlag.MouseMoveRelative
                                     && _mouseMoveRelativeMappings.ContainsKey(i))
                            {
                                // Relative Mouse Move
                                hasSubscription = true;
                                var mapping = _mouseMoveRelativeMappings[i];
                                if (mapping.Block)
                                {
                                    block = true;
                                }

                                var x = stroke.mouse.x;
                                var y = stroke.mouse.y;
                                ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
                            }
                        }
                        // If this key had no subscriptions, but Context Mode is set for this mouse...
                        // ... then set the Context before sending the button
                        if (!hasSubscription && hasContext)
                        {
                            // Set Context
                            _contextCallbacks[i](1);
                        }
                        if (!(block))
                        {
                            ManagedWrapper.Send(_deviceContext, i, ref stroke, 1);
                        }
                        // If we are processing Context Mode, then Unset the context variable after sending the button
                        if (!hasSubscription && hasContext)
                        {
                            // Unset Context
                            _contextCallbacks[i](0);
                        }
                    }
                }
                Thread.Sleep(4);
            }
        }

继续改动:


        public static void IsValidDeviceId(bool isMouse, int id)
        {
            var start = isMouse ? 11 : 1;
            var end = start + 3;

            if (id < start || id > end)
            {
                var s =string.Format("Invalid id ID: {0} for device type {1}. Device IDs for this type should be between {2} and {3}",id,(isMouse ? "Mouse" : "Keyboard"),start,end);
                throw new ArgumentOutOfRangeException("id", s);
            }
        }

        public static DeviceInfo[] GetDeviceList(IntPtr deviceContext)
        {
            var ret = new List<DeviceInfo>();
            var j = 1;
            for (var i = 1; i < 9 ; i++)
            {
                if (i > 4) { j = i + 6; }
                else {j=i;}

                var handle = ManagedWrapper.GetHardwareStr(deviceContext, j, 1000);
                if (handle == "") continue;
                int foundVid = 0, foundPid = 0;
                GetVidPid(handle, ref foundVid, ref foundPid);
                if (foundVid == 0 || foundPid == 0) continue;

                ret.Add(new DeviceInfo { Id = j, Vid = foundVid, Pid = foundPid, IsMouse = j > 4 });
            }

            return ret.ToArray();
        }

大致如此,剩下的细枝末节就不说了,幸运的话代码可以生成了,将新的AutoHotInterception.dll,.lib拷入自己的程序库文件夹中,

由于本人完成这个修改已经是前几天了,可能还有报错,请自行解决。

猜你喜欢

转载自blog.csdn.net/tom_xuzg/article/details/86665713
今日推荐