在我的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的循环中对其进行轮询。
答案 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
方法当窗口关闭时。