Basically: I would like a sendmessage
and sendmessagetimeout
API for VB.NET that others have used and know works.
I need an API for sendmessage
and sendmessagetimeout
for my VB .net application. I have searched quite a bit, and everything I find doesn't seem to work: either the message just doesn't seem to be sent, or the message appears to be sent with the msg
parameter always 0, and the wparam
setting as what I enter for the msg
setting. Pinvoke's also always seems to throw an AccessViolationException
for I have no idea what reason. I tried playing around with maybe just where I put the variable, but unsurprisingly, there is not a simple logical switch of the variables.
I have tried pinvoke's:
<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
and allapi's:
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
among others, and they just don't seem to work.
So I would like to know of whatever APIs for sendmessage
and/or sendmessagetimeout
you know of that work! If there just aren't correct APIs for VB.net for these functions, what alternative functions that I could use to accomplish the same task as those 2?
EDIT:
Alternatively I may be sending the message incorrectly, so just to make sure that shouldn't be the issue:
I want to send WM_WININICHANGE
, so I am using:
but I have tried with other values for wparam
and lparam
with no difference usually. When trying sendmessagetimeout
, I also use:
Yes, the first one is correct. Don't use the old style Declare Function...Lib
declarations; they're supported only for compatibility with VB 6. The new style P/Invoke definitions look like this:
<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
But sending WM_WININICHANGE
is probably not; this message is long obsolete. The docs say explicitly:
Note: The
WM_WININICHANGE
message is provided only for compatibility with earlier versions of the system. Applications should use theWM_SETTINGCHANGE
message.
So I recommend using WM_SETTINGCHANGE
, even though the Windows headers technically define them to be the same value. That's not a contract, and your code will be much more readable if you use the correct names. Reading the documentation for that one, it says:
Applications should send
WM_SETTINGCHANGE
to all top-level windows when they make changes to system parameters. (This message cannot be sent directly to a window.) To send theWM_SETTINGCHANGE
message to all top-level windows, use theSendMessageTimeout
function with thehwnd
parameter set toHWND_BROADCAST
.
Good, at least you've got that part right already. Next order of business is writing the code to actually call the function and broadcast the message. Something like:
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
Notice that I'm checking the return value of the SendMessageTimeout
function. I forget exactly how this works when you specify HWND_BROADCAST
and if you get a meaningful error code, but it's always worth checking for success or failure.