【问题标题】:Attempting to trap window message in VB.NET DLL试图在 VB.NET DLL 中捕获窗口消息
【发布时间】:2014-08-19 20:01:07
【问题描述】:

我正在尝试拦截使用 WINAPI 函数“BroadcastSystemMessage”发送的 Windows 消息(来自创建新工作簿时发送此消息的 XLL)。

我尝试使用两种方法来做到这一点,但每种方法都有其缺点:

1) 使用托管监听窗口:

但是,我不想冒用户关闭此侦听窗口的风险,并且,

listenForm.Show()
listenForm.visible = false

看起来很草率。

2) 使用钩子:

但是,“SetWindowsHookEx”的回调只有几个参数:

Protected Function HookCallBack(code As Integer, wParam As IntPtr, lParam As IntPtr) As Integer

我正在寻找一种访问“msg”结构的方法,该结构包含我在“RegisterWindowMessage”中注册的信息。

这里,“lParam”指向这个结构,我可以使用:

Dim output(100) As Byte
Marshal.Copy(e.lParam, output, 0, 100)

取消引用这个指针。我不知道如何解析结果,而且我在离托管宇宙这么远的地方徘徊也让我很困扰。

我的问题:每种方式的缺点都可以解决吗?拦截消息或做类似事情的标准方法是什么?

【问题讨论】:

  • 我不一定说它的好坏,但为此目的创建一个隐藏窗口是很常见的做法。您可以将窗口调整得非常小,也可以将其移动到屏幕边界之外,以确保用户无法关闭它。
  • 知道了,那就继续吧,谢谢。

标签: vb.net windows messages


【解决方案1】:

Show() 方法调用只是创建本地窗口的方法之一。你也可以在构造函数中自己简单地创建:

Public Sub new
    InitializeComponent()
    Me.CreateHandle()
End Sub

或者如果你不能避免 Show() 调用,因为它是你的应用程序的启动形式,那么这样做:

Protected Overrides Sub SetVisibleCore(value As Boolean)
    If Not Me.IsHandleCreated then
        value = False
        Me.CreateHandle()
    End If
    MyBase.SetVisibleCore(value)
End Sub

请注意,在这两种情况下都不会触发 Load 事件,因此请将其中的任何代码移至表单类的构造函数中。


不要使用窗口挂钩,您只需覆盖 WndProc() 子例程即可查看广播消息:

Protected Overrides Sub WndProc(ByRef m As Message)
    If m.Msg = theRegisteredMessage Then
        '' etc...
    End If
    MyBase.WndProc(m)
End Sub

使用 HWND_BROADCAST 的普通 SendMessage() 优于 BroadcastSystemMessage()。或者更好的是,一个 Socket,这样你就不必大声喊叫了。

【讨论】:

  • 像往常一样感谢汉斯的有用回答。
  • 汉斯,如果您愿意,我还有一个关于最佳实践的问题。使用此侦听窗口的方法位于 dll 中,不是基于表单的应用程序;它意味着一旦 Excel 准备就绪,它就会延迟绑定到 Excel。我目前正在使用 .showdialog() 在新线程中运行此侦听窗口。有没有更自然的方式来启动根本不需要出现的监听窗口?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多