From 1ef28a890a2bb1ee0c3258104eb62fc056ece30e Mon Sep 17 00:00:00 2001 From: dahall Date: Thu, 31 Dec 2020 20:13:35 -0700 Subject: [PATCH] POTENTIALLY BREAKING CHANGE: Revamped SendMessage overloads to reduce accidential use of wrong overload. Most uses still work except passing a class in as lParam. --- PInvoke/User32/WinUser.Message.cs | 1080 +++++++++++++++++++++++++------ UnitTests/PInvoke/User32/User32Tests.cs | 46 +- 2 files changed, 936 insertions(+), 190 deletions(-) diff --git a/PInvoke/User32/WinUser.Message.cs b/PInvoke/User32/WinUser.Message.cs index 6560b54b..e5c8ef65 100644 --- a/PInvoke/User32/WinUser.Message.cs +++ b/PInvoke/User32/WinUser.Message.cs @@ -2039,11 +2039,12 @@ namespace Vanara.PInvoke /// 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. + /// 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. /// /// /// + /// Type: HWND /// /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, @@ -2055,17 +2056,52 @@ namespace Vanara.PInvoke /// /// /// + /// Type: UINT /// The message to be sent. /// For lists of the system-provided messages, see System-Defined Messages. /// - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - // LRESULT WINAPI SendMessage( _In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam); https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx - [DllImport(Lib.User32, SetLastError = false, CharSet = CharSet.Auto)] - [PInvokeData("Winuser.h", MSDNShortId = "ms644950")] + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + [DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)] [System.Security.SecurityCritical] - public static extern IntPtr SendMessage(HWND hWnd, uint msg, [In] IntPtr wParam = default, [In] IntPtr lParam = default); + public static extern IntPtr SendMessage(HWND hWnd, uint msg, [In, Optional] IntPtr wParam, [In, Out, Optional] IntPtr lParam); /// /// @@ -2073,11 +2109,12 @@ namespace Vanara.PInvoke /// 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. + /// 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. /// /// /// + /// Type: HWND /// /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, @@ -2089,17 +2126,52 @@ namespace Vanara.PInvoke /// /// /// + /// Type: UINT /// The message to be sent. /// For lists of the system-provided messages, see System-Defined Messages. /// - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - // LRESULT WINAPI SendMessage( _In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam); https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx - [DllImport(Lib.User32, SetLastError = false, CharSet = CharSet.Auto)] - [PInvokeData("Winuser.h", MSDNShortId = "ms644950")] + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + [DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)] [System.Security.SecurityCritical] - public static extern IntPtr SendMessage(HWND hWnd, uint msg, [In] IntPtr wParam, string lParam); + public static extern IntPtr SendMessage(HWND hWnd, uint msg, [In, Optional] IntPtr wParam, string lParam); /// /// @@ -2107,11 +2179,12 @@ namespace Vanara.PInvoke /// 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. + /// 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. /// /// /// + /// Type: HWND /// /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, @@ -2123,15 +2196,50 @@ namespace Vanara.PInvoke /// /// /// + /// Type: UINT /// The message to be sent. /// For lists of the system-provided messages, see System-Defined Messages. /// - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - // LRESULT WINAPI SendMessage( _In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam); https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx - [DllImport(Lib.User32, SetLastError = false, CharSet = CharSet.Auto)] - [PInvokeData("Winuser.h", MSDNShortId = "ms644950")] + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + [DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)] [System.Security.SecurityCritical] public static extern IntPtr SendMessage(HWND hWnd, uint msg, ref int wParam, [In, Out] StringBuilder lParam); @@ -2141,11 +2249,12 @@ namespace Vanara.PInvoke /// 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. + /// 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. /// /// /// + /// Type: HWND /// /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, @@ -2157,180 +2266,773 @@ namespace Vanara.PInvoke /// /// /// + /// Type: UINT /// The message to be sent. /// For lists of the system-provided messages, see System-Defined Messages. /// - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - // LRESULT WINAPI SendMessage( _In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam); https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx - [DllImport(Lib.User32, SetLastError = false, CharSet = CharSet.Auto)] - [PInvokeData("Winuser.h", MSDNShortId = "ms644950")] + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + [DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)] [System.Security.SecurityCritical] - public static extern IntPtr SendMessage(HWND hWnd, uint msg, [In] IntPtr wParam, [In, Out] StringBuilder lParam); + public static extern IntPtr SendMessage(HWND hWnd, uint msg, [In, Optional] IntPtr wParam, [In, Out] StringBuilder lParam); /// - /// Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window - /// and does not return until the window procedure has processed the message. + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// /// - /// The type of the value. - /// The type of the value. + /// The type of the message. This can be any type that converts to . + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// Type: WPARAM + /// Additional message-specific information. + /// Type: LPARAM + /// Additional message-specific information. + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam) + where TMsg : struct, IConvertible + => SendMessage(hWnd, Convert.ToUInt32(msg), IntPtr.Zero, IntPtr.Zero); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// The type of the parameter. This can be any type that converts to . /// - /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST ((HWND)0xffff), the - /// message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and - /// pop-up windows; but the message is not sent to child windows. + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// /// - /// The message to be sent. - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - public static IntPtr SendMessage(HWND hWnd, TEnum msg, IntPtr wParam, TLP lParam) - where TEnum : struct, IConvertible where TLP : class + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, TWP wParam, [Optional] IntPtr lParam) + where TMsg : struct, IConvertible where TWP : struct, IConvertible + => SendMessage(hWnd, Convert.ToUInt32(msg), (IntPtr)Convert.ToInt64(wParam), IntPtr.Zero); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// The type of the parameter. This can be any type that converts to . + /// + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, TWP wParam, string lParam) + where TMsg : struct, IConvertible where TWP : struct, IConvertible + => SendMessage(hWnd, Convert.ToUInt32(msg), (IntPtr)Convert.ToInt64(wParam), lParam); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, [In, Optional] IntPtr wParam, string lParam) + where TMsg : struct, IConvertible + => SendMessage(hWnd, Convert.ToUInt32(msg), (IntPtr)Convert.ToInt64(wParam), lParam); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, [In, Optional] IntPtr wParam, StringBuilder lParam) + where TMsg : struct, IConvertible + => SendMessage(hWnd, Convert.ToUInt32(msg), (IntPtr)Convert.ToInt64(wParam), lParam); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// The type of the parameter. This can be any type that converts to . + /// + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, TWP wParam, StringBuilder lParam) + where TMsg : struct, IConvertible where TWP : struct, IConvertible + => SendMessage(hWnd, Convert.ToUInt32(msg), (IntPtr)Convert.ToInt64(wParam), lParam); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// The type of the parameter. This can be any type that converts to . + /// + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, [Optional] IntPtr wParam, TLP lParam) + where TMsg : struct, IConvertible where TLP : struct, IConvertible + => SendMessage(hWnd, Convert.ToUInt32(msg), wParam, (IntPtr)Convert.ToInt64(lParam)); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// The type of the parameter. This must be a type that can be marshaled to memory. + /// + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, [Optional] IntPtr wParam, ref TLP lParam) + where TMsg : struct, IConvertible where TLP : struct + => SendMessage(hWnd, Convert.ToUInt32(msg), wParam, ref lParam); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// The type of the parameter. This can be any type that converts to . + /// The type of the parameter. This must be a type that can be marshaled to memory. + /// + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, TWP wParam, ref TLP lParam) + where TMsg : struct, IConvertible where TWP : struct, IConvertible where TLP : struct + => SendMessage(hWnd, Convert.ToUInt32(msg), (IntPtr)Convert.ToInt64(wParam), ref lParam); + + /// + /// + /// Sends the specified message to a window or windows. The SendMessage function 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. + /// + /// + /// The type of the message. This can be any type that converts to . + /// The type of the parameter. This must be a type that can be marshaled to memory. + /// The type of the parameter. This must be a type that can be marshaled to memory. + /// + /// Type: HWND + /// + /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST + /// ((HWND)0xffff), the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, + /// overlapped windows, and pop-up windows; but the message is not sent to child windows. + /// + /// + /// Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of + /// lesser or equal integrity level. + /// + /// + /// + /// Type: UINT + /// The message to be sent. + /// For lists of the system-provided messages, see System-Defined Messages. + /// + /// + /// Type: WPARAM + /// Additional message-specific information. + /// + /// + /// Type: LPARAM + /// Additional message-specific information. + /// + /// + /// Type: LRESULT + /// The return value specifies the result of the message processing; it depends on the message sent. + /// + /// + /// When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied). + /// + /// Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a + /// unique message for inter-application communication. + /// + /// + /// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= + /// WM_USER) to another process, you must do custom marshalling. + /// + /// + /// If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the + /// specified window was created by a different thread, the system switches to that thread and calls the appropriate window + /// procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The + /// sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming + /// nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. + /// For more information on nonqueued messages, see Nonqueued Messages. + /// + /// + /// An accessibility application can use SendMessage to send WM_APPCOMMAND messages to the shell to launch applications. This + /// functionality is not guaranteed to work for other types of applications. + /// + /// Examples + /// For an example, see Displaying Keyboard Input. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage + [PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")] + public static IntPtr SendMessage(HWND hWnd, TMsg msg, in TWP wParam, ref TLP lParam) + where TMsg : struct, IConvertible where TWP : struct where TLP : struct { - var m = Convert.ToUInt32(msg); - using var lp = new PinnedObject(lParam); - return SendMessage(hWnd, m, wParam, (IntPtr)lp); + using var wmem = SafeCoTaskMemHandle.CreateFromStructure(wParam); + return SendMessage(hWnd, Convert.ToUInt32(msg), wmem, ref lParam); } - /// - /// Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window - /// and does not return until the window procedure has processed the message. - /// - /// The type of the value. - /// The type of the value. - /// - /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST ((HWND)0xffff), the - /// message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and - /// pop-up windows; but the message is not sent to child windows. - /// - /// The message to be sent. - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - public static IntPtr SendMessage(HWND hWnd, TEnum msg, IntPtr wParam, ref TLP lParam) - where TEnum : struct, IConvertible where TLP : struct + private static IntPtr SendMessage(HWND hWnd, uint msg, IntPtr wParam, ref TLP lParam) { - using var lp = GetPtr(lParam); - var lr = SendMessage(hWnd, Convert.ToUInt32(msg), wParam, (IntPtr)lp); - lParam = lp.ToStructure(); - return lr; - } - - /// - /// Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window - /// and does not return until the window procedure has processed the message. - /// - /// The type of the value. - /// The type of the value. - /// The type of the value. - /// - /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST ((HWND)0xffff), the - /// message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and - /// pop-up windows; but the message is not sent to child windows. - /// - /// The message to be sent. - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - public static IntPtr SendMessage(HWND hWnd, TEnum msg, TWP wParam, TLP lParam) - where TEnum : struct, IConvertible where TWP : struct, IConvertible where TLP : class - { - using var lp = new PinnedObject(lParam); - return SendMessage(hWnd, Convert.ToUInt32(msg), new IntPtr(Convert.ToInt64(wParam)), lp); - } - - /// - /// Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window - /// and does not return until the window procedure has processed the message. - /// - /// The type of the value. - /// The type of the value. - /// - /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST ((HWND)0xffff), the - /// message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and - /// pop-up windows; but the message is not sent to child windows. - /// - /// The message to be sent. - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - public static IntPtr SendMessage(HWND hWnd, TEnum msg, TWP wParam, IntPtr lParam = default) - where TEnum : struct, IConvertible where TWP : struct, IConvertible - { - return SendMessage(hWnd, Convert.ToUInt32(msg), new IntPtr(Convert.ToInt64(wParam)), lParam); - } - - /// - /// Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window - /// and does not return until the window procedure has processed the message. - /// - /// The type of the value. - /// The type of the value. - /// The type of the value. - /// - /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST ((HWND)0xffff), the - /// message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and - /// pop-up windows; but the message is not sent to child windows. - /// - /// The message to be sent. - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - public static IntPtr SendMessage(HWND hWnd, TEnum msg, TWP wParam, ref TLP lParam) - where TEnum : struct, IConvertible where TWP : struct, IConvertible where TLP : struct - { - using var lp = GetPtr(lParam); - var lr = SendMessage(hWnd, Convert.ToUInt32(msg), new IntPtr(Convert.ToInt64(wParam)), (IntPtr)lp); - lParam = lp.ToStructure(); - return lr; - } - - /// - /// Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window - /// and does not return until the window procedure has processed the message. - /// - /// The type of the value. - /// The type of the value. - /// The type of the value. - /// - /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST ((HWND)0xffff), the - /// message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and - /// pop-up windows; but the message is not sent to child windows. - /// - /// The message to be sent. - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - public static IntPtr SendMessage(HWND hWnd, TEnum msg, in TWP wParam, TLP lParam) - where TEnum : struct, IConvertible where TWP : struct where TLP : class - { - using PinnedObject wp = new PinnedObject(wParam), lp = new PinnedObject(lParam); - return SendMessage(hWnd, Convert.ToUInt32(msg), wp, lp); - } - - /// - /// Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window - /// and does not return until the window procedure has processed the message. - /// - /// The type of the value. - /// The type of the value. - /// The type of the value. - /// - /// A handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST ((HWND)0xffff), the - /// message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and - /// pop-up windows; but the message is not sent to child windows. - /// - /// The message to be sent. - /// Additional message-specific information. - /// Additional message-specific information. - /// The return value specifies the result of the message processing; it depends on the message sent. - public static IntPtr SendMessage(HWND hWnd, TEnum msg, in TWP wParam, ref TLP lParam) - where TEnum : struct, IConvertible where TWP : struct where TLP : struct - { - using var lp = GetPtr(lParam); - var lr = SendMessage(hWnd, Convert.ToUInt32(msg), GetPtr(wParam), (IntPtr)lp); - lParam = lp.ToStructure(); - return lr; + using var lmem = SafeCoTaskMemHandle.CreateFromStructure(lParam); + var lret = SendMessage(hWnd, msg, wParam, lmem); + lParam = lmem.ToStructure(); + return lret; } /// diff --git a/UnitTests/PInvoke/User32/User32Tests.cs b/UnitTests/PInvoke/User32/User32Tests.cs index 51fd0a2a..f6d98aeb 100644 --- a/UnitTests/PInvoke/User32/User32Tests.cs +++ b/UnitTests/PInvoke/User32/User32Tests.cs @@ -97,9 +97,53 @@ namespace Vanara.PInvoke.Tests [Test()] public void SendMessageTest() { - throw new NotImplementedException(); + // WM_ERASEBKGND + SendMessage(default, WindowMessage.WM_ERASEBKGND, (IntPtr)HDC.NULL); + + // WM_GETFONT + HFONT hFont = SendMessage(default, WindowMessage.WM_GETFONT); + + // WM_GETTEXT + var sb = new StringBuilder(256); + SendMessage(default, WindowMessage.WM_GETTEXT, sb.Capacity, sb); + + // WM_GETTEXTLEN + SendMessage(default, WindowMessage.WM_GETTEXTLENGTH); + + // WM_SETFONT + SendMessage(default, WindowMessage.WM_SETFONT, (IntPtr)HFONT.NULL, true); + + // WM_SETICON + SendMessage(default, WindowMessage.WM_SETICON, ICONSZ.ICON_BIG, (IntPtr)HICON.NULL); + + // WM_SETTEXT + SendMessage(default, WindowMessage.WM_SETTEXT, default, "Text"); + SendMessage(default, WindowMessage.WM_SETTEXT, 4, "Text"); + + // WM_DRAWITEM + var dis = new DRAWITEMSTRUCT(); + SendMessage(default, WindowMessage.WM_DRAWITEM, 12, ref dis); + + // BCM_SETSPLITINFO + SendMessage(default, ButtonMessage.BCM_SETSPLITINFO, default, ref dis); + SendMessage(default, ButtonMessage.BCM_SETSPLITINFO, true, ref dis); + SendMessage(default, ButtonMessage.BCM_SETSPLITINFO, 4, ref dis); + + + // BCM_SETSPLITINFO + SendMessage(default, ButtonMessage.BCM_SETDROPDOWNSTATE, true); + } + public enum ICONSZ + { + ICON_BIG, + ICON_SMALL + } + + //public static IntPtr SendMessage(HWND hwnd, TMsg msg, THandle wParam) where TMsg : struct, IConvertible where THandle : IHandle + // => SendMessage(hwnd, Convert.ToUInt32(msg), (IntPtr)wParam, IntPtr.Zero); + [Test()] public void SendMessageTest1() {