Search
Module:
Directory

   Desktop Functions:

   Smart Device Functions:


Show Recent Changes
Subscribe (RSS)
Misc. Pages
Comments
FAQ
Helpful Tools
Playground
Suggested Reading
Website TODO List
Support Forum
Download Visual Studio Add-In

Terms of Use
Privacy Policy
SendMessage (user32)
 
.
Summary
Sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message.

To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.

C# Signature:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

Common C# Overloads:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, StringBuilder lParam);
//If you use '[Out] StringBuilder', initialize the string builder with proper length first.

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);
//Also can add 'ref' or 'out' ahead of 'String lParam', don't use CharSet.Auto since we use MarshalAs(..) in this
//example.

//Works for unicode. One can also use CharSet = CharSet.Unicode instead of [MarshalAs(UnmanagedType.LPWStr)]
[DllImport("user32.dll", EntryPoint = "SendMessageW")]
static extern IntPtr SendMessageW(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref RECT lParam);

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref POINT lParam);

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);

Note: it has been observed on Windows Mobility 6 (ARM) that the message parameter (parameter 2) of SendMessage() must be an int, not a System.UInt32.

//If you want to prevent an (unreferenced) managed object from possibly being garbage collected
//during a call to SendMessage, you can wrap the handle in a HandleRef structure.
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(HandleRef hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

VB.NET Signature:

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function

Common VB.NET Overloads:

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As HandleRef, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
End Function

VB Signature:

Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

Common VB Overloads:

Declare Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer,
   ByVal wParam As IntPtr, ByRef lParam As StringBuilder) As IntPtr

Declare Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer,
   ByVal wParam As IntPtr, ByRef RECT As IntPtr) As IntPtr

Declare Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer,
   ByVal wParam As IntPtr, ByRef POINT As IntPtr) As IntPtr

Notes:

1) Use IntPtr instead of UIntrPtr: The UIntPtr type is not CLS-compliant

2) NEVER use "int" or "integer" as lParam. Your code WILL crash on 64-bit windows. ONLY use IntPtr, a "ref" structure, or an "out" structure.

3) NEVER use "bool", "int", or "integer" as the return value. Your core WILL crash on 64-bit windows. ONLY use IntPtr. It's not safe to use bool - pInvoke cannot marshal an IntPtr to a boolean.

4) Use "IntPtr" as the return value, EVEN if the message says it doesn't return any useful information.

5) Microsoft defines the Msg member of the System.Windows.Forms.Message structure to be System.Int32[1]. At the same time the SendMessage native API defines message as type UINT[2], which is a 32-bit unsigned value.[3]

A listing of common Msg codes can be found here: http://www.vbcode.com/Asp/showsn.asp?theID=11797

6) You can safely type "hWnd" as an "IntPtr" instead of a "HandleRef", but make sure you understand what you are doing. If you are operating on a window handle provided by an unmanaged component or external application, things will just work (as well as can ever be guaranteed when other apps are free to manipulate the window themselves). However, using IntPtr with managed forms and controls may cause your code to crash under race conditions, because .NET can and will dispose of your window handle during the call. Used properly, GC.KeepAlive() can help with this. None of this has anything to do with pinning, which would NOT help here. Pinning is about keeping data from moving around; using a HandleRef or GC.KeepAlive is about preventing the runtime from destroying your handle.

7) When passing integer values to lParam and wParam, use IntPtr as they get <MarshalAs(UnmanagedType.SysInt)> attributes by default. You should avoid mixing IntPtr and Integer as parameter types. Use IntPtr.

8) The wParam and lParam paramters are defined as type WPARAM and LPARAM respectivly

   WPARAM is defined as UINT_PTR
   LPARAM is defined as LONG_PTR

LONG_PTR is "Signed long type for pointer precision." and is a signed 32-bit or signed 64-bit depending on the platform.

UINT_PTR is "Unsigned INT_PTR", and is unsigned 32-bit or unsigned 64-bit depending on the platform.

You could use IntPtr (http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx) and UIntPtr (http://msdn.microsoft.com/en-us/library/system.uintptr(VS.71).aspx) for the platform dependant types, but UIntPtr is not CLS-compliant.

Tips & Tricks:

1) As the number of messages are varied, just keep overloading the function as you need.

2) The return IntPtr of SendMessage might be IntPtr.Zero.

3) C# - SendMessage() to Turn the Screensaver On or Off :

    [DllImport("User32.DLL")]
    public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);

    public const Int32 WM_SYSCOMMAND = 0x112;
    public const Int32 SC_SCREENSAVE = 0xF140;

    private void button1_Click(object sender, EventArgs e)
    {
        // Start the screen saver.
        SendMessage(this.Handle, WM_SYSCOMMAND, SC_SCREENSAVE, 0);
    }

4) C# - SendMessage to Enable/Disable the "ApplyButton" in a PropSheet:

    uint PSM_CHANGED = (WM.USER + 104);
    uint PSM_UNCHANGED = (WM.USER + 109);

    SendMessage(GetParent(hWin32Dlg), (uint)PSM_CHANGED, hWin32Dlg, IntPtr.Zero);
    SendMessage(GetParent(hWin32Dlg), (uint)PSM_UNCHANGED, hWin32Dlg, IntPtr.Zero);

5) C# - Use SendMessage to set a text property of Edit control (TextBox control)

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);

    IntPtr textBoxHandle = /*Get the handle to a textbox control*/

    //Set textbox text
    //0x000C (or WM_SETTEXT) is a window message (for setting a text property)
    StringBuilder sb = new StringBuilder("Hello Pagli Usha");
    int result = SendMessage(textBoxHandle, 0x000C, (IntPtr)sb.Length, sb.ToString());

6) C# - Use SendMessage to set the tab width of a TextBox to a given number of characters

    private const UInt32 EM_SETTABSTOPS = 0x00CB;
    private const int unitsPerCharacter = 4;

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, ref IntPtr lParam);

    public static void SetTextBoxTabStopLength(TextBox tb, int tabSizeInCharacters)
    {
        // 1 means all tab stops are the the same length
        // This means lParam must point to a single integer that contains the desired tab length
        const uint regularLength = 1;

        // A dialog unit is 1/4 of the average character width
        int length = tabSizeInCharacters * unitsPerCharacter;

        // Pass the length pointer by reference, essentially passing a pointer to the desired length
        IntPtr lengthPointer = new IntPtr(length);
        SendMessage(tb.Handle, EM_SETTABSTOPS, (IntPtr)regularLength, ref lengthPointer);
    }

Sample Code:

A more complex example of using SendMessage with a struct containing a string can be found here: http://www.pinvoke.net/default.aspx/user32/TCITEM.html

References

1. Message.Msg Property (http://msdn.microsoft.com/en-us/library/system.windows.forms.message.msg.aspx)

2. SendMessage function (http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx)

3. Windows Data Types (http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx)

Alternative Managed API:

Do you know one? Please contribute it!..

Documentation
SendMessage on MSDN

What about managed types marshaled to unmanaged ones? Will they cause memory leaks? Who is responsible of freeing the given unmanaged objects?

Please edit this page!

Do you have...

  • helpful tips or sample code to share for using this API in managed code?
  • corrections to the existing content?
  • variations of the signature you want to share?
  • additional languages you want to include?

Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).

 
Access PInvoke.net directly from VS:
Terms of Use
Edit This Page
Find References
Show Printable Version
Revisions