VB.NET兼容sendmessage和sendmessagetimeout API

时间:2012-01-26 16:06:28

标签: .net vb.net api sendmessage

基本上:我想要一个用于VB.NET的sendmessage和sendmessagetimeout API,其他人已经使用并且知道有效。

我的VB .net应用程序需要一个sendmessage和sendmessagetimeout的API。我已经搜索了很多,我找到的所有内容似乎都不起作用:要么消息似乎没有发送,要么消息似乎与msg参数总是0一起发送,而wparam设置就像我输入的那样用于msg设置。 Pinvoke似乎总是抛出一个AccessViolationException因为我不知道是什么原因。我试着玩弄可能只是放置变量的地方,但不出所料,变量没有简单的逻辑转换。

我尝试过pinvoke的:

<DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function SendMessageTimeout(ByVal windowHandle As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByVal flags As SendMessageTimeoutFlags, ByVal timeout As Integer, ByRef result As IntPtr) As IntPtr
End Function

和allapi:

Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" (ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As String, ByVal fuFlags As Long, ByVal uTimeout As Long, lpdwResult As Long) As Long

等等,他们似乎没有工作。

所以我想知道任何关于发送消息的APIS和/或sendmessagetimeout你知道的那项工作!如果这些函数的VB.net没有正确的API,我可以使用哪些替代函数来完成与那些2相同的任务?

提前感谢您提供的任何信息:)

编辑:

或者我可能不正确地发送消息,所以只是为了确保不应该是问题:

我想发送WM_WININICHANGE,所以我正在使用:

  • hwnd = HWND_BROADCAST = 0xffff = 65535
  • msg = WM_WININICHANGE = 0x001A = 26
  • wparam和lparam of 0

但是我已经尝试过wparam和lparam的其他值,通常没有区别。在尝试sendmessagetimeout时,我也使用:

  • flags = SMTO_ABORTIFHUNG = 2
  • 超时= 1000 = 1秒
  • 然后0表示结果。

1 个答案:

答案 0 :(得分:3)

是的,第一个是正确的。不要使用旧式Declare Function...Lib声明;它们仅支持与VB 6的兼容性。新样式P / Invoke定义如下所示:

<DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function SendMessageTimeout(ByVal hWnd As IntPtr,
                                          ByVal msg As Integer,
                                          ByVal wParam As IntPtr,
                                          ByVal lParam As IntPtr,
                                          ByVal flags As SendMessageTimeoutFlags,
                                          ByVal timeout As Integer,
                                          ByRef result As IntPtr) As IntPtr
End Function

但发送WM_WININICHANGE可能不是;这条消息已经过时了。文档明确说:

  

注意:仅提供WM_WININICHANGE消息以与早期版本的系统兼容。应用程序应使用WM_SETTINGCHANGE消息。

所以我建议使用WM_SETTINGCHANGE,即使Windows标头在技术上将它们定义为相同的值。这不是合同,如果使用正确的名称,您的代码将更具可读性。阅读该文档的文档,它说:

  

当应用程序更改系统参数时,应将WM_SETTINGCHANGE发送到所有顶级窗口。 (此消息无法直接发送到窗口。)要将WM_SETTINGCHANGE消息发送到所有顶级窗口,请使用hwnd函数并将HWND_BROADCAST参数设置为{{1} }。

很好,至少你已经有了这个部分。下一步的业务是编写代码以实际调用该函数并广播该消息。类似的东西:

Public Shared ReadOnly HWND_BROADCAST As New IntPtr(&HFFFF)
Public Const WM_SETTINGCHANGE As Integer = &H001A

<Flags()> _
Public Enum SendMessageTimeoutFlags
    SMTO_NORMAL = 0
    SMTO_BLOCK = 1
    SMTO_ABORTIFHUNG = 2
    SMTO_NOTIMEOUTIFNOTHUNG = 8
End Enum  

Public Sub BroadcastChangeMessage()
    Dim returnValue As IntPtr = SendMessageTimeout(HWND_BROADCAST,
                                                   WM_SETTINGCHANGE,
                                                   IntPtr.Zero,
                                                   IntPtr.Zero,
                                                   SendMessageTimeoutFlags.SMTO_ABORTIFHUNG Or SendMessageTimeoutFlags. SMTO_NOTIMEOUTIFNOTHUNG,
                                                   5000,
                                                   IntPtr.Zero)
    If returnValue = IntPtr.Zero Then
        MessageBox.Show("Something went wrong and the function failed. Error code: " _
                        & Marshal.GetLastWin32Error().ToString())
    End If
End Sub

请注意,我正在检查SendMessageTimeout函数的返回值。当你指定HWND_BROADCAST并且你得到一个有意义的错误代码时,我完全忘记它是如何工作的,但总是值得检查成功或失败。