gpt4 book ai didi

c# - 拖放时可以使用鼠标滚轮吗?

转载 作者:太空狗 更新时间:2023-10-29 17:43:55 27 4
gpt4 key购买 nike

在 WinForms 中,在调用 DoDragDrop 开始拖动项目后,控件不再使用鼠标滚轮滚动,并且控件的 MouseWheel 事件不再被调用,直到用户放下他拖动的任何东西。

有没有办法让鼠标滚轮在拖动时起作用?

最佳答案

您可以获得带有键盘 Hook 的全局 MouseWheel

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,
WPARAM wParam,
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 wParam, IntPtr lParam)
{
return this.hhk.CallNextHook(nCode, wParam, 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 wParam, 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, 0, msLLHookStruct.pt.X, msLLHookStruct.pt.Y, (int)msLLHookStruct.mouseData >> 16));
break;
}
}

return base.OnWindowsHook(nCode, wParam, lParam);
}

protected virtual void OnMouseWheel(MouseEventArgs e)
{
if(this.MouseWheel != null)
{
this.MouseWheel(this, e);
}
}
}

示例用法:

using (LowLevelMouseHook hook = new LowLevelMouseHook())
{
hook.MouseWheel += (sender, e) =>
{
Console.WriteLine(e.Delta);
};
Application.Run();
}

该代码提供了一个类 LowLevelMouseHook 和一个事件 MouseWheel,其行为类似于来自内置 Windows 窗体控件类的事件。

(此外,代码被拆分为一个抽象类 WindowsHooks 以与其他 Hook 一起使用,一个 SafeHookHandle 类以确保释放句柄和辅助类对于本地方法)

你应该看看SetWindowsHookExCALLBACK LowLevelMouseProc了解这背后的技术。


此事件不仅限于您的应用程序,还会捕获表单外的鼠标,因此它也适用于您不能使用本地事件的操作。

关于c# - 拖放时可以使用鼠标滚轮吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4820095/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com