VB.NET-совместимые API sendmessage и sendmessagetimeout - PullRequest
0 голосов
/ 26 января 2012

В основном: я хотел бы, чтобы sendmessage и sendmessagetimeout API для VB.NET использовались и знали другие.

Мне нужен API для sendmessage и sendmessage timeout для моего приложения VB .net. Я довольно долго искал, и все, что я нашел, похоже, не работает: либо сообщение просто не кажется отправленным, либо кажется, что сообщение отправлено с параметром msg, всегда равным 0, и настройкой wparam, как я ввожу для настройки сообщения. Pinvoke также, кажется, всегда создает исключение AccessViolationException, так как я не знаю, по какой причине Я попытался поиграться с, может быть, просто тем, куда я поместил переменную, но неудивительно, что нет простого логического переключения переменных.

Я попробовал пинвоук:

<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

и Аллапи:

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 для sendmessage и / или sendmessage timeout вы знаете об этой работе! Если для этих функций просто нет правильных API-интерфейсов для VB.net, какие альтернативные функции я мог бы использовать для выполнения той же задачи, что и эти 2?

Заранее благодарим вас за любую информацию, которую вы имеете:)

РЕДАКТИРОВАТЬ:

в качестве альтернативы, возможно, я отправляю сообщение неправильно, так что просто чтобы убедиться, что это не проблема:

Я хочу отправить WM_WININICHANGE, поэтому я использую:

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

но я пробовал с другими значениями для wparam и lparam обычно без разницы. при попытке отправить сообщение через тайм-аут я также использую:

  • flags = SMTO_ABORTIFHUNG = 2
  • время ожидания = 1000 = 1 секунда
  • затем 0 для результата.

1 Ответ

4 голосов
/ 26 января 2012

Да, первый правильный.Не используйте объявления старого стиля 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 во все окна верхнего уровня, используйте функцию SendMessageTimeout с параметром hwnd, установленным на HWND_BROADCAST.

Хорошо, по крайней мере, вы уже правильно поняли эту часть.Следующим направлением деятельности является написание кода для фактического вызова функции и трансляции сообщения.Что-то вроде:

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 и если вы получаете значимый код ошибки, но всегда стоит проверять успех или неудачу.

...