Hier ist ein Code, der die Empfindlichkeit auf Gerätebasis sowohl erhöhen als auch verringern kann (Sie können die Empfindlichkeit einer Maus verringern, die andere jedoch nicht beeinflussen).
Es verwendet RawInput (aus Geschwindigkeitsgründen in einer C # -DLL implementiert) und SetWindowsHookEx (in reiner AHK implementiert) für das Blockieren.
Beachten Sie, dass ich diese Methode erst kürzlich zum Laufen gebracht habe, sodass es durchaus Probleme und Dinge geben kann, die verbessert werden können. Ich habe hier in den AHK-Foren einen Thread , in dem meine Bemühungen detailliert beschrieben werden - möglicherweise gibt es dort aktuellere oder funktionsreichere Versionen.
C # -Code
Neues Klassenbibliotheksprojekt starten, Verweis auf SharpDX.RawInput über NuGet-DLL hinzufügen sollte MouseDelta.dll heißen und muss sich im selben Ordner befinden.
Wenn Sie erstellen, sollte es zwei SharpDX-DLLs in den Erstellungsordner ausgeben - Ihr Skript benötigt diese ebenfalls.
using System;
using System.Windows.Forms;
using SharpDX.Multimedia;
using SharpDX.RawInput;
using System.Threading;
using System.Collections.Generic;
public class MouseDelta
{
private readonly Thread messagePump;
public dynamic relativeMoveCallback;
public dynamic wheelCallback;
static private Dictionary<IntPtr, string> seenMice = new Dictionary<IntPtr, string>();
static private string subscribedMouse = null;
private AutoResetEvent messagePumpRunning = new AutoResetEvent(false);
public MouseDelta()
{
// start message pump in its own thread
messagePump = new Thread(RunMessagePump) { Name = "ManualMessagePump" };
messagePump.Start();
messagePumpRunning.WaitOne();
}
public void SubscribeRelativeMove(dynamic callback, string mouseId = null)
{
SetSubscribedMouse(mouseId);
relativeMoveCallback = callback;
}
public void SubscribeWheel(dynamic callback, string mouseId = null)
{
SetSubscribedMouse(mouseId);
wheelCallback = callback;
}
private void SetSubscribedMouse(string mouseId)
{
if (mouseId != null)
{
subscribedMouse = mouseId == "0" ? null : mouseId;
}
}
// the message pump thread
private void RunMessagePump()
{
// Create control to handle windows messages
MessageHandler messageHandler = new MessageHandler();
// Register for RawInput mouse messages
Device.RegisterDevice(UsagePage.Generic, UsageId.GenericMouse, DeviceFlags.InputSink, messageHandler.Handle);
Device.MouseInput += ProcessMouseInput;
messagePumpRunning.Set();
Application.Run();
}
private void ProcessMouseInput(object sender, MouseInputEventArgs args)
{
//Console.WriteLine(string.Format("(x,y):({0},{1}) Buttons: {2} State: {3} Wheel: {4}\r\n", args.X, args.Y, args.ButtonFlags, args.Mode, args.WheelDelta));
// Handle mouse filtering
if (!seenMice.ContainsKey(args.Device))
{
DeviceInfo info = null;
var devices = Device.GetDevices();
foreach (var dev in devices)
{
if (dev.Handle == args.Device)
{
info = dev;
break;
}
}
if (info == null)
return;
string item = info.DeviceName;
item = item.Substring(4);
string[] split = item.Split('#');
//string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
//string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
seenMice.Add(args.Device, id_02);
}
if (subscribedMouse != null && subscribedMouse != seenMice[args.Device])
{
return;
}
// Fire appropriate Callback
if (args.Mode == MouseMode.MoveRelative && relativeMoveCallback != null && (Math.Abs(args.X) + Math.Abs(args.Y) > 0))
{
relativeMoveCallback(args.X, args.Y, seenMice[args.Device]);
}
else if (args.WheelDelta != 0 && wheelCallback != null)
{
wheelCallback(args.WheelDelta / 120, seenMice[args.Device]);
}
}
}
// Useful SO post on handling messages - code for overriding WndProc
// https://stackoverflow.com/questions/2443867/message-pump-in-net-windows-service
// Although the above code is not quite complete. This blog post has the implementation for MessageData
// http://joe-bq-wang.iteye.com/blog/1882661
// However, by overriding WndProc, we have to process all messages, and then you do not get a SharpDX object..
// ... you just appear to get a raw WM_INPUT message
// For now, this seems to serve our purposes
internal class MessageHandler : NativeWindow
{
public MessageHandler()
{
CreateHandle(new CreateParams());
}
}
Haupt-AHK-Skript (Sie müssen dies nur bearbeiten)
; ================= USER SCRIPT ================
#SingleInstance force
#NoEnv
#include CLR.ahk
#include MouseDelta.ahk
OnExit, UnhookAndClose
GoSub, Hook
Gui, Add, Text, , Select Mouse:
mdw := new MouseDeltaWrapper("x+5 yp-3 w200")
mdw.SubscribeMove(Func("MoveEvent"))
mdw.SubscribeWheel(Func("WheelEvent"))
Gui, Show
return
^Esc::
UnhookAndClose:
GuiClose:
GoSub, UnHook
ExitApp
Hook:
hHookMouse := SetWindowsHookEx(WH_MOUSE_LL := 14, RegisterCallback("MouseMove", "Fast"))
return
UnHook:
UnhookWindowsHookEx(hHookMouse)
return
MoveEvent(x, y, mouseId){
Global mdw
if (mdw.SelectedMouse == 0 || mdw.SelectedMouse == mouseId){
DllCall("mouse_event",uint,1,int, x ,int, y,uint,0,int,0)
}
}
WheelEvent(value, mouseId){
ToolTip % "Wheel: " value ", ID: " mouseId
}
AHK-Wrapper
Als MouseDelta.ahk im selben Ordner speichern
; ================= WRAPPER LIBRARY ================
class MouseDeltaWrapper {
SeenMice := {}
SelectedMouse := 0
MoveCallback := 0
__New(guiOptions := "", dllPath := "MouseDelta.dll"){
this.Callback := callback
Gui, +HwndHwnd
this.GuiHwnd := Hwnd
Gui, Add, DDL, % "hwndhDDL " guiOptions, Any||
this.hDDL := hDDL
fn := this._UserSelectedMouse.Bind(this)
GuiControl, +g, % this.hDDL, % fn
asm := CLR_LoadLibrary(dllPath)
md := asm.CreateInstance("MouseDelta")
md.SubscribeRelativeMove(this._MoveEvent.Bind(this))
md.SubscribeWheel(this._WheelEvent.Bind(this))
this.md := md
this._UserSelectedMouse()
}
SubscribeMove(callback){
this.MoveCallback := callback
}
SubscribeWheel(callback){
this.WheelCallback := callback
}
_UserSelectedMouse(){
GuiControlGet, mouseId, , % this.hDDL
this.SelectedMouse := mouseId == "Any" ? 0 : mouseId
if (this.MoveCallback != 0)
this.md.SubscribeRelativeMove(this._MoveEvent.Bind(this), this.SelectedMouse)
if (this.WheelCallback != 0)
this.md.SubscribeWheel(this._WheelEvent.Bind(this), this.SelectedMouse)
}
_AddMouseToDDL(mouseId){
GuiControl, , % this.hDDL, % mouseId
}
_UpdateMice(mouseId){
if (!this.SeenMice.HasKey(mouseId)){
this.SeenMice[mouseId] := 1
this._AddMouseToDDL(mouseId)
}
}
_MoveEvent(x, y, mouseId){
this._UpdateMice(mouseId)
if (this.MoveCallback != 0 && (this.SelectedMouse == 0 || this.SelectedMouse == mouseId)){
this.MoveCallback.Call(x, y, mouseId)
}
}
_WheelEvent(value, mouseId){
this._UpdateMice(mouseId)
if (this.WheelCallback != 0 && (this.SelectedMouse == 0 || this.SelectedMouse == mouseId)){
this.WheelCallback.Call(value, mouseId)
}
}
}
MouseMove(nCode, wParam, lParam)
{
Critical
SetFormat, Integer, D
If !nCode && (wParam = 0x200){
; Mouse movement - process
if (NumGet(lParam+0, 12, "int")){
; if the LLMHF_INJECTED flag is set, this is "injected" input (Came from mouse_event)
; Let this input through
Return CallNextHookEx(nCode, wParam, lParam)
} else {
; Block the input
Return 1
}
} else {
; Other mouse message - let through
Return CallNextHookEx(nCode, wParam, lParam)
}
}
SetWindowsHookEx(idHook, pfn)
{
;Return DllCall("SetWindowsHookEx", "int", idHook, "Uint", pfn, "Uint", DllCall("GetModuleHandle", "Uint", 0), "Uint", 0)
;The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process
DllCall("SetWindowsHookEx", "int", idHook, "Uint", pfn, "Uint", 0, "Uint", 0)
}
UnhookWindowsHookEx(hHook)
{
Return DllCall("UnhookWindowsHookEx", "Uint", hHook)
}
CallNextHookEx(nCode, wParam, lParam, hHook = 0)
{
Return DllCall("CallNextHookEx", "Uint", hHook, "int", nCode, "Uint", wParam, "Uint", lParam)
}
CLR-Bibliothek - Ermöglicht AHK die Interaktion mit C # -DLLs.
Speichern Sie dies als CLR.ahk im selben Ordner oder im AHK Lib-Ordner
; ==========================================================
; .NET Framework Interop
; http://www.autohotkey.com/forum/topic26191.html
; ==========================================================
;
; Author: Lexikos
; Version: 1.2
; Requires: AutoHotkey_L v1.0.96+
;
; Modified by evilC for compatibility with AHK_H as well as AHK_L
; "null" is a reserved word in AHK_H, so did search & Replace from "null" to "_null"
CLR_LoadLibrary(AssemblyName, AppDomain=0)
{
if !AppDomain
AppDomain := CLR_GetDefaultDomain()
e := ComObjError(0)
Loop 1 {
if assembly := AppDomain.Load_2(AssemblyName)
break
static _null := ComObject(13,0)
args := ComObjArray(0xC, 1), args[0] := AssemblyName
typeofAssembly := AppDomain.GetType().Assembly.GetType()
if assembly := typeofAssembly.InvokeMember_3("LoadWithPartialName", 0x158, _null, _null, args)
break
if assembly := typeofAssembly.InvokeMember_3("LoadFrom", 0x158, _null, _null, args)
break
}
ComObjError(e)
return assembly
}
CLR_CreateObject(Assembly, TypeName, Args*)
{
if !(argCount := Args.MaxIndex())
return Assembly.CreateInstance_2(TypeName, true)
vargs := ComObjArray(0xC, argCount)
Loop % argCount
vargs[A_Index-1] := Args[A_Index]
static Array_Empty := ComObjArray(0xC,0), _null := ComObject(13,0)
return Assembly.CreateInstance_3(TypeName, true, 0, _null, vargs, _null, Array_Empty)
}
CLR_CompileC#(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
{
return CLR_CompileAssembly(Code, References, "System", "Microsoft.CSharp.CSharpCodeProvider", AppDomain, FileName, CompilerOptions)
}
CLR_CompileVB(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
{
return CLR_CompileAssembly(Code, References, "System", "Microsoft.VisualBasic.VBCodeProvider", AppDomain, FileName, CompilerOptions)
}
CLR_StartDomain(ByRef AppDomain, BaseDirectory="")
{
static _null := ComObject(13,0)
args := ComObjArray(0xC, 5), args[0] := "", args[2] := BaseDirectory, args[4] := ComObject(0xB,false)
AppDomain := CLR_GetDefaultDomain().GetType().InvokeMember_3("CreateDomain", 0x158, _null, _null, args)
return A_LastError >= 0
}
CLR_StopDomain(ByRef AppDomain)
{ ; ICorRuntimeHost::UnloadDomain
DllCall("SetLastError", "uint", hr := DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+20*A_PtrSize), "ptr", RtHst, "ptr", ComObjValue(AppDomain))), AppDomain := ""
return hr >= 0
}
; NOTE: IT IS NOT NECESSARY TO CALL THIS FUNCTION unless you need to load a specific version.
CLR_Start(Version="") ; returns ICorRuntimeHost*
{
static RtHst := 0
; The simple method gives no control over versioning, and seems to load .NET v2 even when v4 is present:
; return RtHst ? RtHst : (RtHst:=COM_CreateObject("CLRMetaData.CorRuntimeHost","{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}"), DllCall(NumGet(NumGet(RtHst+0)+40),"uint",RtHst))
if RtHst
return RtHst
EnvGet SystemRoot, SystemRoot
if Version =
Loop % SystemRoot "\Microsoft.NET\Framework" (A_PtrSize=8?"64":"") "\*", 2
if (FileExist(A_LoopFileFullPath "\mscorlib.dll") && A_LoopFileName > Version)
Version := A_LoopFileName
if DllCall("mscoree\CorBindToRuntimeEx", "wstr", Version, "ptr", 0, "uint", 0
, "ptr", CLR_GUID(CLSID_CorRuntimeHost, "{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}")
, "ptr", CLR_GUID(IID_ICorRuntimeHost, "{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}")
, "ptr*", RtHst) >= 0
DllCall(NumGet(NumGet(RtHst+0)+10*A_PtrSize), "ptr", RtHst) ; Start
return RtHst
}
;
; INTERNAL FUNCTIONS
;
CLR_GetDefaultDomain()
{
static defaultDomain := 0
if !defaultDomain
{ ; ICorRuntimeHost::GetDefaultDomain
if DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+13*A_PtrSize), "ptr", RtHst, "ptr*", p:=0) >= 0
defaultDomain := ComObject(p), ObjRelease(p)
}
return defaultDomain
}
CLR_CompileAssembly(Code, References, ProviderAssembly, ProviderType, AppDomain=0, FileName="", CompilerOptions="")
{
if !AppDomain
AppDomain := CLR_GetDefaultDomain()
if !(asmProvider := CLR_LoadLibrary(ProviderAssembly, AppDomain))
|| !(codeProvider := asmProvider.CreateInstance(ProviderType))
|| !(codeCompiler := codeProvider.CreateCompiler())
return 0
if !(asmSystem := (ProviderAssembly="System") ? asmProvider : CLR_LoadLibrary("System", AppDomain))
return 0
; Convert | delimited list of references into an array.
StringSplit, Refs, References, |, %A_Space%%A_Tab%
aRefs := ComObjArray(8, Refs0)
Loop % Refs0
aRefs[A_Index-1] := Refs%A_Index%
; Set parameters for compiler.
prms := CLR_CreateObject(asmSystem, "System.CodeDom.Compiler.CompilerParameters", aRefs)
, prms.OutputAssembly := FileName
, prms.GenerateInMemory := FileName=""
, prms.GenerateExecutable := SubStr(FileName,-3)=".exe"
, prms.CompilerOptions := CompilerOptions
, prms.IncludeDebugInformation := true
; Compile!
compilerRes := codeCompiler.CompileAssemblyFromSource(prms, Code)
if error_count := (errors := compilerRes.Errors).Count
{
error_text := ""
Loop % error_count
error_text .= ((e := errors.Item[A_Index-1]).IsWarning ? "Warning " : "Error ") . e.ErrorNumber " on line " e.Line ": " e.ErrorText "`n`n"
MsgBox, 16, Compilation Failed, %error_text%
return 0
}
; Success. Return Assembly object or path.
return compilerRes[FileName="" ? "CompiledAssembly" : "PathToAssembly"]
}
CLR_GUID(ByRef GUID, sGUID)
{
VarSetCapacity(GUID, 16, 0)
return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "ptr", &GUID) >= 0 ? &GUID : ""
}