解决方法
您可以使用键盘钩子获取全局MouseWheel.
@H_403_8@using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
using BOOL = System.Boolean;
using DWORD = System.UInt32;
using HHOOK = SafeHookHandle;
using HINSTANCE = System.IntPtr;
using HOOKPROC = HookProc;
using LPARAM = System.IntPtr;
using LRESULT = System.IntPtr;
using POINT = System.Drawing.Point;
using ULONG_PTR = System.IntPtr;
using WPARAM = System.IntPtr;
public delegate LRESULT HookProc(int nCode,WPARAM wParam,LPARAM lParam);
internal static class NativeMethods
{
[DllImport("User32.dll",SetLastError = true)]
internal static extern HHOOK SetWindowsHookEx(
HookType idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);
[DllImport("User32.dll")]
internal static extern LRESULT CallNextHookEx(
HHOOK hhk,int nCode,LPARAM lParam);
[DllImport("User32.dll",SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern BOOL UnhookWindowsHookEx(
IntPtr hhk);
[DllImport("kernel32.dll",CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
}
internal static class NativeTypes
{
internal enum MSLLHOOKSTRUCTFlags : uint
{
LLMHF_INJECTED = 0x00000001U,}
[StructLayout(LayoutKind.Sequential)]
internal struct MSLLHOOKSTRUCT
{
internal POINT pt;
internal DWORD mouseData;
internal MSLLHOOKSTRUCTFlags flags;
internal DWORD time;
internal ULONG_PTR dwExtraInfo;
}
}
internal static class NativeConstants
{
internal const int WH_MOUSE_LL = 14;
internal const int HC_ACTION = 0;
internal const int WM_MOUSEWHEEL = 0x020A;
internal const int WM_MOUSEHWHEEL = 0x020E;
internal const int WHEEL_DELTA = 120;
}
public enum HookType
{
LowLevelMouseHook = NativeConstants.WH_MOUSE_LL
}
public enum HookScope
{
LowLevelGlobal,}
public class SafeHookHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeHookHandle() : base(true) { }
public static SafeHookHandle SetWindowsHook(HookType idHook,HookProc lpfn,IntPtr hMod,uint dwThreadId)
{
var hhk = NativeMethods.SetWindowsHookEx(idHook,lpfn,hMod,dwThreadId);
if(hhk.IsInvalid)
{
throw new Win32Exception();
}
else
{
return hhk;
}
}
public IntPtr CallNextHook(int nCode,IntPtr wParam,IntPtr lParam)
{
return NativeMethods.CallNextHookEx(this,nCode,wParam,lParam);
}
protected override bool ReleaseHandle()
{
return NativeMethods.UnhookWindowsHookEx(this.handle);
}
}
public abstract class WindowsHook : IDisposable
{
private SafeHookHandle hhk;
private HookProc lpfn;
protected WindowsHook(HookType idHook,HookScope scope)
{
this.lpfn = this.OnWindowsHook;
switch(scope)
{
case HookScope.LowLevelGlobal:
IntPtr moduleHandle = NativeMethods.GetModuleHandle(null);
this.hhk = SafeHookHandle.SetWindowsHook(idHook,this.lpfn,moduleHandle,0U);
return;
default:
throw new InvalidEnumArgumentException("scope",(int)scope,typeof(HookScope));
}
}
protected virtual IntPtr OnWindowsHook(int nCode,IntPtr lParam)
{
return this.hhk.CallNextHook(nCode,lParam);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(disposing)
{
if(this.hhk != null) { this.hhk.Dispose(); }
}
}
}
public class LowLevelMouseHook : WindowsHook
{
public event MouseEventHandler MouseWheel;
public LowLevelMouseHook() : base(HookType.LowLevelMouseHook,HookScope.LowLevelGlobal) { }
protected sealed override IntPtr OnWindowsHook(int nCode,IntPtr lParam)
{
if(nCode == NativeConstants.HC_ACTION)
{
var msLLHookStruct = (NativeTypes.MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam,typeof(NativeTypes.MSLLHOOKSTRUCT));
switch(wParam.ToInt32())
{
case NativeConstants.WM_MOUSEWHEEL:
case NativeConstants.WM_MOUSEHWHEEL:
this.OnMouseWheel(new MouseEventArgs(Control.MouseButtons,msLLHookStruct.pt.X,msLLHookStruct.pt.Y,(int)msLLHookStruct.mouseData >> 16));
break;
}
}
return base.OnWindowsHook(nCode,lParam);
}
protected virtual void OnMouseWheel(MouseEventArgs e)
{
if(this.MouseWheel != null)
{
this.MouseWheel(this,e);
}
}
}
样品用法:
@H_403_8@using (LowLevelMouseHook hook = new LowLevelMouseHook()) { hook.MouseWheel += (sender,e) => { Console.WriteLine(e.Delta); }; Application.Run(); }该代码提供了一个类LowLevelMouseHook,其中包含事件MouseWheel,其行为类似于内建窗体控件类的事件.
(此外,代码分为一个抽象类WindowsHooks,用于其他钩子,一个SafeHookHandle类以确保句柄被释放,并且本机方法的辅助类)
你应该看看SetWindowsHookEx
和CALLBACK LowLevelMouseProc
了解这个背后的技术.
此事件不仅限于您的应用程序,而且还将捕获表单外的鼠标,因此它也适用于您不能使用本地事件的操作.