C#SetWinEventHook停止移动鼠标时发送消息

时间:2019-06-26 12:52:14

标签: c# wpf windows events hook

在我的C#WPF应用程序中。

我正在窗口初始化回调中设置钩子:

   <div class='chat-message chat-message-sender'>
      <img class='chat-image chat-image-default' v-bind:src='./../assets/user.jpg' />
      <div class='chat-message-wrapper'>
        <div class='chat-message-content'>
          <img v-bind:src="{{imageData}}" class="startImage">
          <p>Check this image please</p>
        </div>
        <div class='chat-details'>
          <span class='chat-message-localisation font-size-small'>Time</span>
        </div>
      </div>
    </div>

我正在将消息记录在回调中

[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,  uint idThread, uint dwFlags);

IntPtr hookHandle = SetWinEventHook(EVENT_MIN, EVENT_MAX, IntPtr.Zero, TestCallback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS | WINEVENT_SKIPOWNTHREAD);

但是,每当我将鼠标悬停在WPF窗口中的空白处时。

事件完全停止发送。

在可能无关的音符上,我得到了

  

对象引用未设置为对象的实例

有时系统dll之一中有未处理的异常。

为什么鼠标悬停会导致赢钩失败?

我的最终目标是每当在桌面上创建/显示一个新窗口时都发生一个事件,这样我就不必在占用大量CPU的循环中对其进行轮询。

1 个答案:

答案 0 :(得分:0)

我怀疑这里的问题是垃圾收集器(GC)最终收集了传递给非托管TestCallback函数的SetWinEventHook委托。

由于GC无法跟踪由本机代码保存的引用,因此您应该自己在WinEventDelegate字段中存储对回调的引用,例如:

private IntPtr hookHandle;
private readonly WinEventDelegate callback;

public Window1()
{
    InitializeComponent();
    callback = new WinEventDelegate(TestCallback);
}

protected override void OnInitialized(EventArgs e)
{
    hookHandle = SetWinEventHook(EVENT_MIN, EVENT_MAX, IntPtr.Zero, callback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS | WINEVENT_SKIPOWNTHREAD);
}

//...

请注意,您还应该跟踪IntPtr函数返回的SetWinEventHook,以便无论何时要删除该钩子,都可以将其传递给UnhookWinEvent方法当窗口关闭时。