Vanara/PInvoke/User32/WinUser.Message.cs

3790 lines
194 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class User32
{
/// <summary>Return this value when processing a broadcast message to deny a query.</summary>
public static readonly IntPtr BROADCAST_QUERY_DENY = (IntPtr)0x424D5144;
/// <summary>
/// Used to define private messages for use by private window classes, usually of the form OCM__BASE+x, where x is an integer value.
/// </summary>
public const uint OCM__BASE = (WM_USER + 0x1c00);
/// <summary>Used to define private messages, usually of the form WM_APP+x, where x is an integer value.</summary>
public const uint WM_APP = 0x8000;
/// <summary>
/// Used to define private messages for use by private window classes, usually of the form WM_USER+x, where x is an integer value.
/// </summary>
public const uint WM_USER = 0x0400;
/// <summary>
/// An application-defined callback function used with the SendMessageCallback function. The system passes the message to the
/// callback function after passing the message to the destination window procedure. The <c>SENDASYNCPROC</c> type defines a pointer
/// to this callback function. SendAsyncProc is a placeholder for the application-defined function name.
/// </summary>
/// <param name="hwnd">
/// A handle to the window whose window procedure received the message.
/// <para>
/// If the SendMessageCallback function was called with its hwnd parameter set to HWND_BROADCAST, the system calls the SendAsyncProc
/// function once for each top-level window.
/// </para>
/// </param>
/// <param name="uMsg">The message.</param>
/// <param name="dwData">An application-defined value sent from the SendMessageCallback function.</param>
/// <param name="lResult">The result of the message processing.This value depends on the message.</param>
/// <remarks>
/// <para>
/// You install a SendAsyncProc application-defined callback function by passing a <c>SENDASYNCPROC</c> pointer to the
/// SendMessageCallback function.
/// </para>
/// <para>
/// The callback function is only called when the thread that called SendMessageCallback calls GetMessage, PeekMessage, or WaitMessage.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nc-winuser-sendasyncproc SENDASYNCPROC Sendasyncproc; void
// Sendasyncproc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ ULONG_PTR dwData, _In_ LRESULT lResult);
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
[PInvokeData("winuser.h")]
public delegate void Sendasyncproc(HWND hwnd, uint uMsg, UIntPtr dwData, IntPtr lResult);
/// <summary>Flags used by BroadcastSystemMessage and BroadcastSystemMessageEx.</summary>
[PInvokeData("winuser.h")]
[Flags]
public enum BSF
{
/// <summary>Enables the recipient to set the foreground window while processing the message.</summary>
BSF_ALLOWSFW = 0x00000080,
/// <summary>Flushes the disk after each recipient processes the message.</summary>
BSF_FLUSHDISK = 0x00000004,
/// <summary>Continues to broadcast the message, even if the time-out period elapses or one of the recipients is not responding.</summary>
BSF_FORCEIFHUNG = 0x00000020,
/// <summary>
/// Does not send the message to windows that belong to the current task. This prevents an application from receiving its own message.
/// </summary>
BSF_IGNORECURRENTTASK = 0x00000002,
/// <summary>
/// Forces a non-responsive application to time out. If one of the recipients times out, do not continue broadcasting the message.
/// </summary>
BSF_NOHANG = 0x00000008,
/// <summary>Waits for a response to the message, as long as the recipient is not being unresponsive. Does not time out.</summary>
BSF_NOTIMEOUTIFNOTHUNG = 0x00000040,
/// <summary>Posts the message. Do not use in combination with BSF_QUERY.</summary>
BSF_POSTMESSAGE = 0x00000010,
/// <summary>
/// Sends the message to one recipient at a time, sending to a subsequent recipient only if the current recipient returns TRUE.
/// </summary>
BSF_QUERY = 0x00000001,
/// <summary>Sends the message using SendNotifyMessage function. Do not use in combination with BSF_QUERY.</summary>
BSF_SENDNOTIFYMESSAGE = 0x00000100,
/// <summary/>
BSF_RETURNHDESK = 0x00000200,
/// <summary/>
BSF_LUID = 0x00000400,
}
/// <summary>System message info flags used by BroadcastSystemMessage and BroadcastSystemMessageEx.</summary>
[PInvokeData("winuser.h")]
[Flags]
public enum BSM
{
/// <summary>Broadcast to all system components.</summary>
BSM_ALLCOMPONENTS = 0x00000000,
/// <summary>Broadcast to all desktops. Requires the SE_TCB_NAME privilege.</summary>
BSM_ALLDESKTOPS = 0x00000010,
/// <summary>Broadcast to applications.</summary>
BSM_APPLICATIONS = 0x00000008,
/// <summary/>
BSM_VXDS = 0x00000001,
/// <summary/>
BSM_NETDRIVER = 0x00000002,
/// <summary/>
BSM_INSTALLABLEDRIVERS = 0x00000004,
}
/// <summary>Return values from InSendMessageEx</summary>
[PInvokeData("winuser.h")]
[Flags]
public enum ISMEX
{
/// <summary>The message was not sent.</summary>
ISMEX_NOSEND = 0x00000000,
/// <summary>The message was sent using the SendMessageCallback function. The thread that sent the message is not blocked.</summary>
ISMEX_CALLBACK = 0x00000004,
/// <summary>The message was sent using the SendNotifyMessage function. The thread that sent the message is not blocked.</summary>
ISMEX_NOTIFY = 0x00000002,
/// <summary>The window procedure has processed the message. The thread that sent the message is no longer blocked.</summary>
ISMEX_REPLIED = 0x00000008,
/// <summary>
/// The message was sent using the SendMessage or SendMessageTimeout function. If ISMEX_REPLIED is not set, the thread that sent
/// the message is blocked.
/// </summary>
ISMEX_SEND = 0x00000001,
}
/// <summary>Flags for <see cref="MsgWaitForMultipleObjectsEx"/></summary>
[PInvokeData("winuser.h", MSDNShortId = "1774b721-3ad4-492e-96af-b71de9066f0c")]
[Flags]
public enum MWMO
{
/// <summary>
/// The function returns when any one of the objects is signaled. The return value indicates the object whose state caused the
/// function to return.
/// </summary>
MWMO_ANY = 0,
/// <summary>
/// The function also returns if an APC has been queued to the thread with QueueUserAPC while the thread is in the waiting state.
/// </summary>
MWMO_ALERTABLE = 0x0002,
/// <summary>
/// The function returns if input exists for the queue, even if the input has been seen (but not removed) using a call to another
/// function, such as PeekMessage.
/// </summary>
MWMO_INPUTAVAILABLE = 0x0004,
/// <summary>
/// The function returns when all objects in the pHandles array are signaled and an input event has been received, all at the
/// same time.
/// </summary>
MWMO_WAITALL = 0x0001,
}
/// <summary>Flags used by PeekMessage.</summary>
[PInvokeData("winuser.h")]
[Flags]
public enum PM
{
/// <summary>Messages are not removed from the queue after processing by PeekMessage.</summary>
M_NOREMOVE = 0x0000,
/// <summary>Messages are removed from the queue after processing by PeekMessage.</summary>
PM_REMOVE = 0x0001,
/// <summary>
/// Prevents the system from releasing any thread that is waiting for the caller to go idle (see WaitForInputIdle).
/// <para>Combine this value with either PM_NOREMOVE or PM_REMOVE.</para>
/// </summary>
PM_NOYIELD = 0x0002,
/// <summary>Process mouse and keyboard messages.</summary>
PM_QS_INPUT = (QS.QS_INPUT << 16),
/// <summary>Process all posted messages, including timers and hotkeys.</summary>
PM_QS_POSTMESSAGE = ((QS.QS_POSTMESSAGE | QS.QS_HOTKEY | QS.QS_TIMER) << 16),
/// <summary>Process paint messages.</summary>
PM_QS_PAINT = (QS.QS_PAINT << 16),
/// <summary>Process all sent messages.</summary>
PM_QS_SENDMESSAGE = (QS.QS_SENDMESSAGE << 16),
}
/// <summary>Flags used GetQueueStatus.</summary>
[PInvokeData("winuser.h")]
[Flags]
public enum QS
{
/// <summary>An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue.</summary>
QS_ALLEVENTS = (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY),
/// <summary>Any message is in the queue.</summary>
QS_ALLINPUT = (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE),
/// <summary>A posted message (other than those listed here) is in the queue.</summary>
QS_ALLPOSTMESSAGE = 0x0100,
/// <summary>A WM_HOTKEY message is in the queue.</summary>
QS_HOTKEY = 0x0080,
/// <summary>An input message is in the queue.</summary>
QS_INPUT = (QS_MOUSE | QS_KEY | QS_RAWINPUT | QS_TOUCH | QS_POINTER),
/// <summary>A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the queue.</summary>
QS_KEY = 0x0001,
/// <summary>A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).</summary>
QS_MOUSE = (QS_MOUSEMOVE | QS_MOUSEBUTTON),
/// <summary>A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).</summary>
QS_MOUSEBUTTON = 0x0004,
/// <summary>A WM_MOUSEMOVE message is in the queue.</summary>
QS_MOUSEMOVE = 0x0002,
/// <summary>A WM_PAINT message is in the queue.</summary>
QS_PAINT = 0x0020,
/// <summary>A posted message (other than those listed here) is in the queue.</summary>
QS_POSTMESSAGE = 0x0008,
/// <summary>
/// A raw input message is in the queue. For more information, see Raw Input.
/// <para>Windows 2000: This flag is not supported.</para>
/// </summary>
QS_RAWINPUT = 0x0400,
/// <summary>A message sent by another thread or application is in the queue.</summary>
QS_SENDMESSAGE = 0x0040,
/// <summary>A WM_TIMER message is in the queue.</summary>
QS_TIMER = 0x0010,
/// <summary/>
QS_TOUCH = 0x0800,
/// <summary/>
QS_POINTER = 0x1000,
}
/// <summary>Flags used by the SendMessageTimeout function.</summary>
[PInvokeData("winuser.h")]
[Flags]
public enum SMTO
{
/// <summary>
/// The function returns without waiting for the time-out period to elapse if the receiving thread appears to not respond or "hangs."
/// </summary>
SMTO_ABORTIFHUNG = 0x0002,
/// <summary>Prevents the calling thread from processing any other requests until the function returns.</summary>
SMTO_BLOCK = 0x0001,
/// <summary>The calling thread is not prevented from processing other requests while waiting for the function to return.</summary>
SMTO_NORMAL = 0x0000,
/// <summary>The function does not enforce the time-out period as long as the receiving thread is processing messages.</summary>
SMTO_NOTIMEOUTIFNOTHUNG = 0x0008,
/// <summary>
/// The function should return 0 if the receiving window is destroyed or its owning thread dies while the message is being processed.
/// </summary>
SMTO_ERRORONEXIT = 0x0020,
}
/// <summary>
/// <para>
/// Sends a message to the specified recipients. The recipients can be applications, installable drivers, network drivers,
/// system-level device drivers, or any combination of these system components.
/// </para>
/// <para>To receive additional information if the request is defined, use the BroadcastSystemMessageEx function.</para>
/// </summary>
/// <param name="flags">
/// <para>Type: <c>DWORD</c></para>
/// <para>The broadcast option. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>BSF_ALLOWSFW 0x00000080</term>
/// <term>Enables the recipient to set the foreground window while processing the message.</term>
/// </item>
/// <item>
/// <term>BSF_FLUSHDISK 0x00000004</term>
/// <term>Flushes the disk after each recipient processes the message.</term>
/// </item>
/// <item>
/// <term>BSF_FORCEIFHUNG 0x00000020</term>
/// <term>Continues to broadcast the message, even if the time-out period elapses or one of the recipients is not responding.</term>
/// </item>
/// <item>
/// <term>BSF_IGNORECURRENTTASK 0x00000002</term>
/// <term>
/// Does not send the message to windows that belong to the current task. This prevents an application from receiving its own message.
/// </term>
/// </item>
/// <item>
/// <term>BSF_NOHANG 0x00000008</term>
/// <term>
/// Forces a non-responsive application to time out. If one of the recipients times out, do not continue broadcasting the message.
/// </term>
/// </item>
/// <item>
/// <term>BSF_NOTIMEOUTIFNOTHUNG 0x00000040</term>
/// <term>Waits for a response to the message, as long as the recipient is not being unresponsive. Does not time out.</term>
/// </item>
/// <item>
/// <term>BSF_POSTMESSAGE 0x00000010</term>
/// <term>Posts the message. Do not use in combination with BSF_QUERY.</term>
/// </item>
/// <item>
/// <term>BSF_QUERY 0x00000001</term>
/// <term>
/// Sends the message to one recipient at a time, sending to a subsequent recipient only if the current recipient returns TRUE.
/// </term>
/// </item>
/// <item>
/// <term>BSF_SENDNOTIFYMESSAGE 0x00000100</term>
/// <term>Sends the message using SendNotifyMessage function. Do not use in combination with BSF_QUERY.</term>
/// </item>
/// </list>
/// </param>
/// <param name="lpInfo">
/// <para>Type: <c>LPDWORD</c></para>
/// <para>A pointer to a variable that contains and receives information about the recipients of the message.</para>
/// <para>
/// When the function returns, this variable receives a combination of these values identifying which recipients actually received
/// the message.
/// </para>
/// <para>If this parameter is <c>NULL</c>, the function broadcasts to all components.</para>
/// <para>This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>BSM_ALLCOMPONENTS 0x00000000</term>
/// <term>Broadcast to all system components.</term>
/// </item>
/// <item>
/// <term>BSM_ALLDESKTOPS 0x00000010</term>
/// <term>Broadcast to all desktops. Requires the SE_TCB_NAME privilege.</term>
/// </item>
/// <item>
/// <term>BSM_APPLICATIONS 0x00000008</term>
/// <term>Broadcast to applications.</term>
/// </item>
/// </list>
/// </param>
/// <param name="Msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>long</c></c></para>
/// <para>If the function succeeds, the return value is a positive value.</para>
/// <para>If the function is unable to broadcast the message, the return value is 1.</para>
/// <para>
/// If the dwFlags parameter is <c>BSF_QUERY</c> and at least one recipient returned <c>BROADCAST_QUERY_DENY</c> to the corresponding
/// message, the return value is zero. To get extended error information, call GetLastError.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// If <c>BSF_QUERY</c> is not specified, the function sends the specified message to all requested recipients, ignoring values
/// returned by those recipients.
/// </para>
/// <para>
/// The system only does marshaling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshaling.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Terminating a Process.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-broadcastsystemmessage long BroadcastSystemMessage( DWORD
// flags, LPDWORD lpInfo, UINT Msg, WPARAM wParam, LPARAM lParam );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h")]
public static extern long BroadcastSystemMessage(BSF flags, ref BSM lpInfo, uint Msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam);
/// <summary>
/// <para>
/// Sends a message to the specified recipients. The recipients can be applications, installable drivers, network drivers,
/// system-level device drivers, or any combination of these system components.
/// </para>
/// <para>This function is similar to BroadcastSystemMessage except that this function can return more information from the recipients.</para>
/// </summary>
/// <param name="flags">
/// <para>Type: <c>DWORD</c></para>
/// <para>The broadcast option. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>BSF_ALLOWSFW 0x00000080</term>
/// <term>Enables the recipient to set the foreground window while processing the message.</term>
/// </item>
/// <item>
/// <term>BSF_FLUSHDISK 0x00000004</term>
/// <term>Flushes the disk after each recipient processes the message.</term>
/// </item>
/// <item>
/// <term>BSF_FORCEIFHUNG 0x00000020</term>
/// <term>Continues to broadcast the message, even if the time-out period elapses or one of the recipients is not responding.</term>
/// </item>
/// <item>
/// <term>BSF_IGNORECURRENTTASK 0x00000002</term>
/// <term>
/// Does not send the message to windows that belong to the current task. This prevents an application from receiving its own message.
/// </term>
/// </item>
/// <item>
/// <term>BSF_LUID 0x00000400</term>
/// <term>
/// If BSF_LUID is set, the message is sent to the window that has the same LUID as specified in the luid member of the BSMINFO
/// structure. Windows 2000: This flag is not supported.
/// </term>
/// </item>
/// <item>
/// <term>BSF_NOHANG 0x00000008</term>
/// <term>
/// Forces a non-responsive application to time out. If one of the recipients times out, do not continue broadcasting the message.
/// </term>
/// </item>
/// <item>
/// <term>BSF_NOTIMEOUTIFNOTHUNG 0x00000040</term>
/// <term>Waits for a response to the message, as long as the recipient is not being unresponsive. Does not time out.</term>
/// </item>
/// <item>
/// <term>BSF_POSTMESSAGE 0x00000010</term>
/// <term>Posts the message. Do not use in combination with BSF_QUERY.</term>
/// </item>
/// <item>
/// <term>BSF_RETURNHDESK 0x00000200</term>
/// <term>
/// If access is denied and both this and BSF_QUERY are set, BSMINFO returns both the desktop handle and the window handle. If access
/// is denied and only BSF_QUERY is set, only the window handle is returned by BSMINFO. Windows 2000: This flag is not supported.
/// </term>
/// </item>
/// <item>
/// <term>BSF_QUERY 0x00000001</term>
/// <term>
/// Sends the message to one recipient at a time, sending to a subsequent recipient only if the current recipient returns TRUE.
/// </term>
/// </item>
/// <item>
/// <term>BSF_SENDNOTIFYMESSAGE 0x00000100</term>
/// <term>Sends the message using SendNotifyMessage function. Do not use in combination with BSF_QUERY.</term>
/// </item>
/// </list>
/// </param>
/// <param name="lpInfo">
/// <para>Type: <c>LPDWORD</c></para>
/// <para>A pointer to a variable that contains and receives information about the recipients of the message.</para>
/// <para>
/// When the function returns, this variable receives a combination of these values identifying which recipients actually received
/// the message.
/// </para>
/// <para>If this parameter is <c>NULL</c>, the function broadcasts to all components.</para>
/// <para>This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>BSM_ALLCOMPONENTS 0x00000000</term>
/// <term>Broadcast to all system components.</term>
/// </item>
/// <item>
/// <term>BSM_ALLDESKTOPS 0x00000010</term>
/// <term>Broadcast to all desktops. Requires the SE_TCB_NAME privilege.</term>
/// </item>
/// <item>
/// <term>BSM_APPLICATIONS 0x00000008</term>
/// <term>Broadcast to applications.</term>
/// </item>
/// </list>
/// </param>
/// <param name="Msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="pbsmInfo">
/// <para>Type: <c>PBSMINFO</c></para>
/// <para>A pointer to a BSMINFO structure that contains additional information if the request is denied and dwFlags is set to <c>BSF_QUERY</c>.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>long</c></c></para>
/// <para>If the function succeeds, the return value is a positive value.</para>
/// <para>If the function is unable to broadcast the message, the return value is 1.</para>
/// <para>
/// If the dwFlags parameter is <c>BSF_QUERY</c> and at least one recipient returned <c>BROADCAST_QUERY_DENY</c> to the corresponding
/// message, the return value is zero. To get extended error information, call GetLastError.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// If <c>BSF_QUERY</c> is not specified, the function sends the specified message to all requested recipients, ignoring values
/// returned by those recipients.
/// </para>
/// <para>
/// If the caller's thread is on a desktop other than that of the window that denied the request, the caller must call
/// SetThreadDesktop <c>(hdesk)</c> to query anything on that window. Also, the caller must call CloseDesktop on the returned
/// <c>hdesk</c> handle.
/// </para>
/// <para>
/// The system only does marshaling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshaling.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-broadcastsystemmessageexa long BroadcastSystemMessageExA(
// DWORD flags, LPDWORD lpInfo, UINT Msg, WPARAM wParam, LPARAM lParam, PBSMINFO pbsmInfo );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
public static extern long BroadcastSystemMessageEx(BSF flags, ref BSM lpInfo, uint Msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam, ref BSMINFO pbsmInfo);
/// <summary>
/// Dispatches a message to a window procedure. It is typically used to dispatch a message retrieved by the GetMessage function.
/// </summary>
/// <param name="lpMsg">
/// <para>Type: <c>const MSG*</c></para>
/// <para>A pointer to a structure that contains the message.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>LRESULT</c></c></para>
/// <para>
/// The return value specifies the value returned by the window procedure. Although its meaning depends on the message being
/// dispatched, the return value generally is ignored.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// The MSG structure must contain valid message values. If the <paramref name="lpMsg"/> parameter points to a WM_TIMER message and
/// the lParam parameter of the <c>WM_TIMER</c> message is not <c>NULL</c>, lParam points to a function that is called instead of the
/// window procedure.
/// </para>
/// <para>
/// Note that the application is responsible for retrieving and dispatching input messages to the dialog box. Most applications use
/// the main message loop for this. However, to permit the user to move to and to select controls by using the keyboard, the
/// application must call IsDialogMessage. For more information, see Dialog Box Keyboard Interface.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Creating a Message Loop.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-dispatchmessage LRESULT DispatchMessage( const MSG *lpMsg );
[DllImport(Lib.User32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
public static extern IntPtr DispatchMessage(in MSG lpMsg);
/// <summary>
/// Frees the memory specified by the lParam parameter of a posted Dynamic Data Exchange (DDE) message. An application receiving a
/// posted DDE message should call this function after it has used the UnpackDDElParam function to unpack the lParam value.
/// </summary>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The posted DDE message.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>The lParam parameter of the posted DDE message.</para>
/// </param>
/// <returns>
/// <para>Type: <c>BOOL</c></para>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>An application should call this function only for posted DDE messages.</para>
/// <para>This function frees the memory specified by the lParam parameter. It does not free the contents of lParam.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dde/nf-dde-freeddelparam BOOL FreeDDElParam( UINT msg, LPARAM lParam );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("dde.h", MSDNShortId = "")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FreeDDElParam(uint msg, IntPtr lParam);
/// <summary>Determines whether there are mouse-button or keyboard messages in the calling thread's message queue.</summary>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the queue contains one or more new mouse-button or keyboard messages, the return value is nonzero.</para>
/// <para>If there are no new mouse-button or keyboard messages in the queue, the return value is zero.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getinputstate BOOL GetInputState( );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetInputState();
/// <summary>
/// <para>
/// Retrieves a message from the calling thread's message queue. The function dispatches incoming sent messages until a posted
/// message is available for retrieval.
/// </para>
/// <para>Unlike <c>GetMessage</c>, the PeekMessage function does not wait for a message to be posted before returning.</para>
/// </summary>
/// <param name="lpMsg">
/// <para>Type: <c>LPMSG</c></para>
/// <para>A pointer to an MSG structure that receives message information from the thread's message queue.</para>
/// </param>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>A handle to the window whose messages are to be retrieved. The window must belong to the current thread.</para>
/// <para>
/// If hWnd is <c>NULL</c>, <c>GetMessage</c> retrieves messages for any window that belongs to the current thread, and any messages
/// on the current thread's message queue whose <c>hwnd</c> value is <c>NULL</c> (see the MSG structure). Therefore if hWnd is
/// <c>NULL</c>, both window messages and thread messages are processed.
/// </para>
/// <para>
/// If hWnd is -1, <c>GetMessage</c> retrieves only messages on the current thread's message queue whose <c>hwnd</c> value is
/// <c>NULL</c>, that is, thread messages as posted by PostMessage (when the hWnd parameter is <c>NULL</c>) or PostThreadMessage.
/// </para>
/// </param>
/// <param name="wMsgFilterMin">
/// <para>Type: <c>UINT</c></para>
/// <para>
/// The integer value of the lowest message value to be retrieved. Use <c>WM_KEYFIRST</c> (0x0100) to specify the first keyboard
/// message or <c>WM_MOUSEFIRST</c> (0x0200) to specify the first mouse message.
/// </para>
/// <para>Use WM_INPUT here and in wMsgFilterMax to specify only the <c>WM_INPUT</c> messages.</para>
/// <para>
/// If wMsgFilterMin and wMsgFilterMax are both zero, <c>GetMessage</c> returns all available messages (that is, no range filtering
/// is performed).
/// </para>
/// </param>
/// <param name="wMsgFilterMax">
/// <para>Type: <c>UINT</c></para>
/// <para>
/// The integer value of the highest message value to be retrieved. Use <c>WM_KEYLAST</c> to specify the last keyboard message or
/// <c>WM_MOUSELAST</c> to specify the last mouse message.
/// </para>
/// <para>Use WM_INPUT here and in wMsgFilterMin to specify only the <c>WM_INPUT</c> messages.</para>
/// <para>
/// If wMsgFilterMin and wMsgFilterMax are both zero, <c>GetMessage</c> returns all available messages (that is, no range filtering
/// is performed).
/// </para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the function retrieves a message other than WM_QUIT, the return value is nonzero.</para>
/// <para>If the function retrieves the WM_QUIT message, the return value is zero.</para>
/// <para>
/// If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an
/// invalid pointer. To get extended error information, call GetLastError.
/// </para>
/// <para>Because the return value can be nonzero, zero, or -1, avoid code like this:</para>
/// <para>
/// The possibility of a -1 return value in the case that hWnd is an invalid parameter (such as referring to a window that has
/// already been destroyed) means that such code can lead to fatal application errors. Instead, use code like this:
/// </para>
/// </returns>
/// <remarks>
/// <para>An application typically uses the return value to determine whether to end the main message loop and exit the program.</para>
/// <para>
/// The <c>GetMessage</c> function retrieves messages associated with the window identified by the hWnd parameter or any of its
/// children, as specified by the IsChild function, and within the range of message values given by the wMsgFilterMin and
/// wMsgFilterMax parameters. Note that an application can only use the low word in the wMsgFilterMin and wMsgFilterMax parameters;
/// the high word is reserved for the system.
/// </para>
/// <para>
/// Note that <c>GetMessage</c> always retrieves WM_QUIT messages, no matter which values you specify for wMsgFilterMin and wMsgFilterMax.
/// </para>
/// <para>
/// During this call, the system delivers pending, non-queued messages, that is, messages sent to windows owned by the calling thread
/// using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. Then the first queued message that
/// matches the specified filter is retrieved. The system may also process internal events. If no filter is specified, messages are
/// processed in the following order:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>Sent messages</term>
/// </item>
/// <item>
/// <term>Posted messages</term>
/// </item>
/// <item>
/// <term>Input (hardware) messages and system internal events</term>
/// </item>
/// <item>
/// <term>Sent messages (again)</term>
/// </item>
/// <item>
/// <term>WM_PAINT messages</term>
/// </item>
/// <item>
/// <term>WM_TIMER messages</term>
/// </item>
/// </list>
/// <para>To retrieve input messages before posted messages, use the wMsgFilterMin and wMsgFilterMax parameters.</para>
/// <para><c>GetMessage</c> does not remove WM_PAINT messages from the queue. The messages remain in the queue until processed.</para>
/// <para>
/// If a top-level window stops responding to messages for more than several seconds, the system considers the window to be not
/// responding and replaces it with a ghost window that has the same z-order, location, size, and visual attributes. This allows the
/// user to move it, resize it, or even close the application. However, these are the only actions available because the application
/// is actually not responding. When in the debugger mode, the system does not generate a ghost window.
/// </para>
/// <para>DPI Virtualization</para>
/// <para>
/// This API does not participate in DPI virtualization. The output is in the mode of the window that the message is targeting. The
/// calling thread is not taken into consideration.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Creating a Message Loop.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessage BOOL GetMessage( LPMSG lpMsg, HWND hWnd, UINT
// wMsgFilterMin, UINT wMsgFilterMax );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetMessage(out MSG lpMsg, [Optional] HWND hWnd, [Optional] uint wMsgFilterMin, [Optional] uint wMsgFilterMax);
/// <summary>
/// Retrieves the extra message information for the current thread. Extra message information is an application- or driver-defined
/// value associated with the current thread's message queue.
/// </summary>
/// <returns>
/// <para>Type: <c>Type: <c>LPARAM</c></c></para>
/// <para>The return value specifies the extra information. The meaning of the extra information is device specific.</para>
/// </returns>
/// <remarks>To set a thread's extra message information, use the SetMessageExtraInfo function.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessageextrainfo LPARAM GetMessageExtraInfo( );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
public static extern IntPtr GetMessageExtraInfo();
/// <summary>
/// <para>Retrieves the cursor position for the last message retrieved by the GetMessage function.</para>
/// <para>To determine the current position of the cursor, use the GetCursorPos function.</para>
/// </summary>
/// <returns>
/// <para>Type: <c>Type: <c>DWORD</c></c></para>
/// <para>
/// The return value specifies the x- and y-coordinates of the cursor position. The x-coordinate is the low order <c>short</c> and
/// the y-coordinate is the high-order <c>short</c>.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// As noted above, the x-coordinate is in the low-order <c>short</c> of the return value; the y-coordinate is in the high-order
/// <c>short</c> (both represent signed values because they can take negative values on systems with multiple monitors). If the
/// return value is assigned to a variable, you can use the MAKEPOINTS macro to obtain a POINTS structure from the return value. You
/// can also use the GET_X_LPARAM or GET_Y_LPARAM macro to extract the x- or y-coordinate.
/// </para>
/// <para>
/// <c>Important</c> Do not use the LOWORD or HIWORD macros to extract the x- and y- coordinates of the cursor position because these
/// macros return incorrect results on systems with multiple monitors. Systems with multiple monitors can have negative x- and y-
/// coordinates, and <c>LOWORD</c> and <c>HIWORD</c> treat the coordinates as unsigned quantities.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessagepos DWORD GetMessagePos( );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
public static extern uint GetMessagePos();
/// <summary>
/// Retrieves the message time for the last message retrieved by the GetMessage function. The time is a long integer that specifies
/// the elapsed time, in milliseconds, from the time the system was started to the time the message was created (that is, placed in
/// the thread's message queue).
/// </summary>
/// <returns>
/// <para>Type: <c>Type: <c>LONG</c></c></para>
/// <para>The return value specifies the message time.</para>
/// </returns>
/// <remarks>
/// <para>
/// The return value from the <c>GetMessageTime</c> function does not necessarily increase between subsequent messages, because the
/// value wraps to wraps to the minimum value for a long integer if the timer count exceeds the maximum value for a long integer.
/// </para>
/// <para>
/// To calculate time delays between messages, subtract the time of the first message from the time of the second message (ignoring
/// overflow) and compare the result of the subtraction against the desired delay amount.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessagetime LONG GetMessageTime( );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
public static extern int GetMessageTime();
/// <summary>Retrieves the type of messages found in the calling thread's message queue.</summary>
/// <param name="flags">
/// <para>Type: <c>UINT</c></para>
/// <para>The types of messages for which to check. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>QS_ALLEVENTS (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY)</term>
/// <term>An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_ALLINPUT (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE)</term>
/// <term>Any message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_ALLPOSTMESSAGE 0x0100</term>
/// <term>A posted message (other than those listed here) is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_HOTKEY 0x0080</term>
/// <term>A WM_HOTKEY message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_INPUT (QS_MOUSE | QS_KEY | QS_RAWINPUT)</term>
/// <term>An input message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_KEY 0x0001</term>
/// <term>A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_MOUSE (QS_MOUSEMOVE | QS_MOUSEBUTTON)</term>
/// <term>A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).</term>
/// </item>
/// <item>
/// <term>QS_MOUSEBUTTON 0x0004</term>
/// <term>A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).</term>
/// </item>
/// <item>
/// <term>QS_MOUSEMOVE 0x0002</term>
/// <term>A WM_MOUSEMOVE message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_PAINT 0x0020</term>
/// <term>A WM_PAINT message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_POSTMESSAGE 0x0008</term>
/// <term>A posted message (other than those listed here) is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_RAWINPUT 0x0400</term>
/// <term>A raw input message is in the queue. For more information, see Raw Input. Windows 2000: This flag is not supported.</term>
/// </item>
/// <item>
/// <term>QS_SENDMESSAGE 0x0040</term>
/// <term>A message sent by another thread or application is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_TIMER 0x0010</term>
/// <term>A WM_TIMER message is in the queue.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>DWORD</c></c></para>
/// <para>
/// The high-order word of the return value indicates the types of messages currently in the queue. The low-order word indicates the
/// types of messages that have been added to the queue and that are still in the queue since the last call to the
/// <c>GetQueueStatus</c>, GetMessage, or PeekMessage function.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// The presence of a QS_ flag in the return value does not guarantee that a subsequent call to the GetMessage or PeekMessage
/// function will return a message. <c>GetMessage</c> and <c>PeekMessage</c> perform some internal filtering that may cause the
/// message to be processed internally. For this reason, the return value from <c>GetQueueStatus</c> should be considered only a hint
/// as to whether <c>GetMessage</c> or <c>PeekMessage</c> should be called.
/// </para>
/// <para>
/// The <c>QS_ALLPOSTMESSAGE</c> and <c>QS_POSTMESSAGE</c> flags differ in when they are cleared. <c>QS_POSTMESSAGE</c> is cleared
/// when you call GetMessage or PeekMessage, whether or not you are filtering messages. <c>QS_ALLPOSTMESSAGE</c> is cleared when you
/// call <c>GetMessage</c> or <c>PeekMessage</c> without filtering messages (wMsgFilterMin and wMsgFilterMax are 0). This can be
/// useful when you call <c>PeekMessage</c> multiple times to get messages in different ranges.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getqueuestatus DWORD GetQueueStatus( UINT flags );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
public static extern uint GetQueueStatus(QS flags);
/// <summary>
/// <para>
/// Determines whether the current window procedure is processing a message that was sent from another thread (in the same process or
/// a different process) by a call to the SendMessage function.
/// </para>
/// <para>To obtain additional information about how the message was sent, use the InSendMessageEx function.</para>
/// </summary>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>
/// If the window procedure is processing a message sent to it from another thread using the SendMessage function, the return value
/// is nonzero.
/// </para>
/// <para>
/// If the window procedure is not processing a message sent to it from another thread using the SendMessage function, the return
/// value is zero.
/// </para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-insendmessage BOOL InSendMessage( );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool InSendMessage();
/// <summary>
/// Determines whether the current window procedure is processing a message that was sent from another thread (in the same process or
/// a different process).
/// </summary>
/// <param name="lpReserved">
/// <para>Type: <c>LPVOID</c></para>
/// <para>Reserved; must be <c>NULL</c>.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>DWORD</c></c></para>
/// <para>
/// If the message was not sent, the return value is <c>ISMEX_NOSEND</c> (0x00000000). Otherwise, the return value is one or more of
/// the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ISMEX_CALLBACK 0x00000004</term>
/// <term>The message was sent using the SendMessageCallback function. The thread that sent the message is not blocked.</term>
/// </item>
/// <item>
/// <term>ISMEX_NOTIFY 0x00000002</term>
/// <term>The message was sent using the SendNotifyMessage function. The thread that sent the message is not blocked.</term>
/// </item>
/// <item>
/// <term>ISMEX_REPLIED 0x00000008</term>
/// <term>The window procedure has processed the message. The thread that sent the message is no longer blocked.</term>
/// </item>
/// <item>
/// <term>ISMEX_SEND 0x00000001</term>
/// <term>
/// The message was sent using the SendMessage or SendMessageTimeout function. If ISMEX_REPLIED is not set, the thread that sent the
/// message is blocked.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>To determine if the sender is blocked, use the following test:</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-insendmessageex DWORD InSendMessageEx( LPVOID lpReserved );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
public static extern ISMEX InSendMessageEx([Optional] IntPtr lpReserved);
/// <summary>Determines whether the last message read from the current thread's queue originated from a WOW64 process.</summary>
/// <returns>
/// The function returns TRUE if the last message read from the current thread's queue originated from a WOW64 process, and FALSE otherwise.
/// </returns>
/// <remarks>
/// <para>
/// This function is useful to helping you develop 64-bit native applications that can receive private messages sent from 32-bit
/// client applications, if the messages are associated with data structures that contain pointer-dependent data. In these
/// situations, you can call this function in your 64-bit native application to determine if the message originated from a WOW64
/// process and then thunk the message appropriately.
/// </para>
/// <para>Examples</para>
/// <para>
/// For compatibility with operating systems that do not support this function, call GetProcAddress to detect whether
/// <c>IsWow64Message</c> is implemented in User32.dll. If <c>GetProcAddress</c> succeeds, it is safe to call this function.
/// Otherwise, WOW64 is not present. Note that this technique is not a reliable way to detect whether the operating system is a
/// 64-bit version of Windows because the User32.dll in current versions of 32-bit Windows also contains this function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-iswow64message BOOL IsWow64Message( );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "bc0ac424-3c5b-41bf-9dae-bcb405d5b548")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWow64Message();
/// <summary>
/// <para>
/// Waits until one or all of the specified objects are in the signaled state or the time-out interval elapses. The objects can
/// include input event objects, which you specify using the dwWakeMask parameter.
/// </para>
/// <para>To enter an alertable wait state, use the MsgWaitForMultipleObjectsEx function.</para>
/// </summary>
/// <param name="nCount">
/// The number of object handles in the array pointed to by pHandles. The maximum number of object handles is
/// <c>MAXIMUM_WAIT_OBJECTS</c> minus one. If this parameter has the value zero, then the function waits only for an input event.
/// </param>
/// <param name="pHandles">
/// <para>
/// An array of object handles. For a list of the object types whose handles can be specified, see the following Remarks section. The
/// array can contain handles of objects of different types. It may not contain multiple copies of the same handle.
/// </para>
/// <para>If one of these handles is closed while the wait is still pending, the function's behavior is undefined.</para>
/// <para>The handles must have the <c>SYNCHRONIZE</c> access right. For more information, see Standard Access Rights.</para>
/// </param>
/// <param name="fWaitAll">
/// If this parameter is <c>TRUE</c>, the function returns when the states of all objects in the pHandles array have been set to
/// signaled and an input event has been received. If this parameter is <c>FALSE</c>, the function returns when the state of any one
/// of the objects is set to signaled or an input event has been received. In this case, the return value indicates the object whose
/// state caused the function to return.
/// </param>
/// <param name="dwMilliseconds">
/// The time-out interval, in milliseconds. If a nonzero value is specified, the function waits until the specified objects are
/// signaled or the interval elapses. If dwMilliseconds is zero, the function does not enter a wait state if the specified objects
/// are not signaled; it always returns immediately. If dwMilliseconds is <c>INFINITE</c>, the function will return only when the
/// specified objects are signaled.
/// </param>
/// <param name="dwWakeMask">
/// <para>
/// The input types for which an input event object handle will be added to the array of object handles. This parameter can be any
/// combination of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>QS_ALLEVENTS 0x04BF</term>
/// <term>
/// An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue. This value is a combination of QS_INPUT,
/// QS_POSTMESSAGE, QS_TIMER, QS_PAINT, and QS_HOTKEY.
/// </term>
/// </item>
/// <item>
/// <term>QS_ALLINPUT 0x04FF</term>
/// <term>
/// Any message is in the queue. This value is a combination of QS_INPUT, QS_POSTMESSAGE, QS_TIMER, QS_PAINT, QS_HOTKEY, and QS_SENDMESSAGE.
/// </term>
/// </item>
/// <item>
/// <term>QS_ALLPOSTMESSAGE 0x0100</term>
/// <term>A posted message is in the queue. This value is cleared when you call GetMessage or PeekMessage without filtering messages.</term>
/// </item>
/// <item>
/// <term>QS_HOTKEY 0x0080</term>
/// <term>A WM_HOTKEY message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_INPUT 0x407</term>
/// <term>An input message is in the queue. This value is a combination of QS_MOUSE, QS_KEY, and QS_RAWINPUT.</term>
/// </item>
/// <item>
/// <term>QS_KEY 0x0001</term>
/// <term>A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_MOUSE 0x0006</term>
/// <term>
/// A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on). This value is a combination of
/// QS_MOUSEMOVE and QS_MOUSEBUTTON.
/// </term>
/// </item>
/// <item>
/// <term>QS_MOUSEBUTTON 0x0004</term>
/// <term>A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).</term>
/// </item>
/// <item>
/// <term>QS_MOUSEMOVE 0x0002</term>
/// <term>A WM_MOUSEMOVE message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_PAINT 0x0020</term>
/// <term>A WM_PAINT message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_POSTMESSAGE 0x0008</term>
/// <term>
/// A posted message is in the queue. This value is cleared when you call GetMessage or PeekMessage, whether or not you are filtering messages.
/// </term>
/// </item>
/// <item>
/// <term>QS_RAWINPUT 0x0400</term>
/// <term>A raw input message is in the queue. For more information, see Raw Input.</term>
/// </item>
/// <item>
/// <term>QS_SENDMESSAGE 0x0040</term>
/// <term>A message sent by another thread or application is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_TIMER 0x0010</term>
/// <term>A WM_TIMER message is in the queue.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value indicates the event that caused the function to return. It can be one of the following
/// values. (Note that <c>WAIT_OBJECT_0</c> is defined as 0 and <c>WAIT_ABANDONED_0</c> is defined as 0x00000080L.)
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount 1)</term>
/// <term>
/// If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled. If bWaitAll is FALSE, the
/// return value minus WAIT_OBJECT_0 indicates the pHandles array index of the object that satisfied the wait.
/// </term>
/// </item>
/// <item>
/// <term>WAIT_OBJECT_0 + nCount</term>
/// <term>
/// New input of the type specified in the dwWakeMask parameter is available in the thread's input queue. Functions such as
/// PeekMessage, GetMessage, and WaitMessage mark messages in the queue as old messages. Therefore, after you call one of these
/// functions, a subsequent call to MsgWaitForMultipleObjects will not return until new input of the specified type arrives. This
/// value is also returned upon the occurrence of a system event that requires the thread's action, such as foreground activation.
/// Therefore, MsgWaitForMultipleObjects can return even though no appropriate input is available and even if dwWakeMask is set to 0.
/// If this occurs, call GetMessage or PeekMessage to process the system event before trying the call to MsgWaitForMultipleObjects again.
/// </term>
/// </item>
/// <item>
/// <term>WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount 1)</term>
/// <term>
/// If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled and at least one of the
/// objects is an abandoned mutex object. If bWaitAll is FALSE, the return value minus WAIT_ABANDONED_0 indicates the pHandles array
/// index of an abandoned mutex object that satisfied the wait. Ownership of the mutex object is granted to the calling thread, and
/// the mutex is set to nonsignaled. If the mutex was protecting persistent state information, you should check it for consistency.
/// </term>
/// </item>
/// <item>
/// <term>WAIT_TIMEOUT 258L</term>
/// <term>The time-out interval elapsed and the conditions specified by the bWaitAll and dwWakeMask parameters were not satisfied.</term>
/// </item>
/// <item>
/// <term>WAIT_FAILED (DWORD)0xFFFFFFFF</term>
/// <term>The function has failed. To get extended error information, call GetLastError.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>MsgWaitForMultipleObjects</c> function determines whether the wait criteria have been met. If the criteria have not been
/// met, the calling thread enters the wait state until the conditions of the wait criteria have been met or the time-out interval elapses.
/// </para>
/// <para>
/// When bWaitAll is <c>TRUE</c>, the function does not modify the states of the specified objects until the states of all objects
/// have been set to signaled. For example, a mutex can be signaled, but the thread does not get ownership until the states of the
/// other objects have also been set to signaled. In the meantime, some other thread may get ownership of the mutex, thereby setting
/// its state to nonsignaled.
/// </para>
/// <para>
/// When bWaitAll is <c>TRUE</c>, the function's wait is completed only when the states of all objects have been set to signaled and
/// an input event has been received. Therefore, setting bWaitAll to <c>TRUE</c> prevents input from being processed until the state
/// of all objects in the pHandles array have been set to signaled. For this reason, if you set bWaitAll to <c>TRUE</c>, you should
/// use a short timeout value in dwMilliseconds. If you have a thread that creates windows waiting for all objects in the pHandles
/// array, including input events specified by dwWakeMask, with no timeout interval, the system will deadlock. This is because
/// threads that create windows must process messages. DDE sends message to all windows in the system. Therefore, if a thread creates
/// windows, do not set the bWaitAll parameter to <c>TRUE</c> in calls to <c>MsgWaitForMultipleObjects</c> made from that thread.
/// </para>
/// <para>
/// When bWaitAll is <c>FALSE</c>, this function checks the handles in the array in order starting with index 0, until one of the
/// objects is signaled. If multiple objects become signaled, the function returns the index of the first handle in the array whose
/// object was signaled.
/// </para>
/// <para>
/// <c>MsgWaitForMultipleObjects</c> does not return if there is unread input of the specified type in the message queue after the
/// thread has called a function to check the queue. This is because functions such as PeekMessage, GetMessage, GetQueueStatus, and
/// WaitMessage check the queue and then change the state information for the queue so that the input is no longer considered new. A
/// subsequent call to <c>MsgWaitForMultipleObjects</c> will not return until new input of the specified type arrives. The existing
/// unread input (received prior to the last time the thread checked the queue) is ignored.
/// </para>
/// <para>
/// The function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects
/// whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. For more
/// information, see the documentation for the individual synchronization objects.
/// </para>
/// <para>
/// The <c>MsgWaitForMultipleObjects</c> function can specify handles of any of the following object types in the pHandles array:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>Change notification</term>
/// </item>
/// <item>
/// <term>Console input</term>
/// </item>
/// <item>
/// <term>Event</term>
/// </item>
/// <item>
/// <term>Memory resource notification</term>
/// </item>
/// <item>
/// <term>Mutex</term>
/// </item>
/// <item>
/// <term>Process</term>
/// </item>
/// <item>
/// <term>Semaphore</term>
/// </item>
/// <item>
/// <term>Thread</term>
/// </item>
/// <item>
/// <term>Waitable timer</term>
/// </item>
/// </list>
/// <para>
/// The <c>QS_ALLPOSTMESSAGE</c> and <c>QS_POSTMESSAGE</c> flags differ in when they are cleared. <c>QS_POSTMESSAGE</c> is cleared
/// when you call GetMessage or PeekMessage, whether or not you are filtering messages. <c>QS_ALLPOSTMESSAGE</c> is cleared when you
/// call <c>GetMessage</c> or PeekMessage without filtering messages (wMsgFilterMin and wMsgFilterMax are 0). This can be useful when
/// you call PeekMessage multiple times to get messages in different ranges.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-msgwaitformultipleobjects DWORD MsgWaitForMultipleObjects(
// DWORD nCount, const HANDLE *pHandles, BOOL fWaitAll, DWORD dwMilliseconds, DWORD dwWakeMask );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "0629f1b3-6805-43a7-9aeb-4f80939ec62c")]
public static extern uint MsgWaitForMultipleObjects(uint nCount, HANDLE[] pHandles, [MarshalAs(UnmanagedType.Bool)] bool fWaitAll, uint dwMilliseconds,
QS dwWakeMask);
/// <summary>
/// <para>
/// Waits until one or all of the specified objects are in the signaled state, an I/O completion routine or asynchronous procedure
/// call (APC) is queued to the thread, or the time-out interval elapses. The array of objects can include input event objects, which
/// you specify using the dwWakeMask parameter.
/// </para>
/// </summary>
/// <param name="nCount">
/// <para>
/// The number of object handles in the array pointed to by pHandles. The maximum number of object handles is
/// <c>MAXIMUM_WAIT_OBJECTS</c> minus one. If this parameter has the value zero, then the function waits only for an input event.
/// </para>
/// </param>
/// <param name="pHandles">
/// <para>
/// An array of object handles. For a list of the object types whose handles you can specify, see the Remarks section later in this
/// topic. The array can contain handles to multiple types of objects. It may not contain multiple copies of the same handle.
/// </para>
/// <para>If one of these handles is closed while the wait is still pending, the function's behavior is undefined.</para>
/// <para>The handles must have the <c>SYNCHRONIZE</c> access right. For more information, see Standard Access Rights.</para>
/// </param>
/// <param name="dwMilliseconds">
/// <para>
/// The time-out interval, in milliseconds. If a nonzero value is specified, the function waits until the specified objects are
/// signaled, an I/O completion routine or APC is queued, or the interval elapses. If dwMilliseconds is zero, the function does not
/// enter a wait state if the criteria is not met; it always returns immediately. If dwMilliseconds is <c>INFINITE</c>, the function
/// will return only when the specified objects are signaled or an I/O completion routine or APC is queued.
/// </para>
/// </param>
/// <param name="dwWakeMask">
/// <para>
/// The input types for which an input event object handle will be added to the array of object handles. This parameter can be one or
/// more of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>QS_ALLEVENTS 0x04BF</term>
/// <term>
/// An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue. This value is a combination of QS_INPUT,
/// QS_POSTMESSAGE, QS_TIMER, QS_PAINT, and QS_HOTKEY.
/// </term>
/// </item>
/// <item>
/// <term>QS_ALLINPUT 0x04FF</term>
/// <term>
/// Any message is in the queue. This value is a combination of QS_INPUT, QS_POSTMESSAGE, QS_TIMER, QS_PAINT, QS_HOTKEY, and QS_SENDMESSAGE.
/// </term>
/// </item>
/// <item>
/// <term>QS_ALLPOSTMESSAGE 0x0100</term>
/// <term>A posted message is in the queue. This value is cleared when you call GetMessage or PeekMessage without filtering messages.</term>
/// </item>
/// <item>
/// <term>QS_HOTKEY 0x0080</term>
/// <term>A WM_HOTKEY message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_INPUT 0x407</term>
/// <term>An input message is in the queue. This value is a combination of QS_MOUSE, QS_KEY, and QS_RAWINPUT.</term>
/// </item>
/// <item>
/// <term>QS_KEY 0x0001</term>
/// <term>A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_MOUSE 0x0006</term>
/// <term>
/// A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on). This value is a combination of
/// QS_MOUSEMOVE and QS_MOUSEBUTTON.
/// </term>
/// </item>
/// <item>
/// <term>QS_MOUSEBUTTON 0x0004</term>
/// <term>A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).</term>
/// </item>
/// <item>
/// <term>QS_MOUSEMOVE 0x0002</term>
/// <term>A WM_MOUSEMOVE message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_PAINT 0x0020</term>
/// <term>A WM_PAINT message is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_POSTMESSAGE 0x0008</term>
/// <term>
/// A posted message is in the queue. This value is cleared when you call GetMessage or PeekMessage, whether or not you are filtering messages.
/// </term>
/// </item>
/// <item>
/// <term>QS_RAWINPUT 0x0400</term>
/// <term>A raw input message is in the queue. For more information, see Raw Input.</term>
/// </item>
/// <item>
/// <term>QS_SENDMESSAGE 0x0040</term>
/// <term>A message sent by another thread or application is in the queue.</term>
/// </item>
/// <item>
/// <term>QS_TIMER 0x0010</term>
/// <term>A WM_TIMER message is in the queue.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwFlags">
/// <para>The wait type. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0</term>
/// <term>
/// The function returns when any one of the objects is signaled. The return value indicates the object whose state caused the
/// function to return.
/// </term>
/// </item>
/// <item>
/// <term>MWMO_ALERTABLE 0x0002</term>
/// <term>
/// The function also returns if an APC has been queued to the thread with QueueUserAPC while the thread is in the waiting state.
/// </term>
/// </item>
/// <item>
/// <term>MWMO_INPUTAVAILABLE 0x0004</term>
/// <term>
/// The function returns if input exists for the queue, even if the input has been seen (but not removed) using a call to another
/// function, such as PeekMessage.
/// </term>
/// </item>
/// <item>
/// <term>MWMO_WAITALL 0x0001</term>
/// <term>
/// The function returns when all objects in the pHandles array are signaled and an input event has been received, all at the same time.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value indicates the event that caused the function to return. It can be one of the following
/// values. (Note that <c>WAIT_OBJECT_0</c> is defined as 0 and <c>WAIT_ABANDONED_0</c> is defined as 0x00000080L.)
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount - 1)</term>
/// <term>
/// If the MWMO_WAITALL flag is used, the return value indicates that the state of all specified objects is signaled. Otherwise, the
/// return value minus WAIT_OBJECT_0 indicates the pHandles array index of the object that caused the function to return.
/// </term>
/// </item>
/// <item>
/// <term>WAIT_OBJECT_0 + nCount</term>
/// <term>
/// New input of the type specified in the dwWakeMask parameter is available in the thread's input queue. Functions such as
/// PeekMessage, GetMessage, GetQueueStatus, and WaitMessage mark messages in the queue as old messages. Therefore, after you call
/// one of these functions, a subsequent call to MsgWaitForMultipleObjectsEx will not return until new input of the specified type
/// arrives. This value is also returned upon the occurrence of a system event that requires the thread's action, such as foreground
/// activation. Therefore, MsgWaitForMultipleObjectsEx can return even though no appropriate input is available and even if
/// dwWakeMask is set to 0. If this occurs, call GetMessage or PeekMessage to process the system event before trying the call to
/// MsgWaitForMultipleObjectsEx again.
/// </term>
/// </item>
/// <item>
/// <term>WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount - 1)</term>
/// <term>
/// If the MWMO_WAITALL flag is used, the return value indicates that the state of all specified objects is signaled and at least one
/// of the objects is an abandoned mutex object. Otherwise, the return value minus WAIT_ABANDONED_0 indicates the pHandles array
/// index of an abandoned mutex object that caused the function to return. Ownership of the mutex object is granted to the calling
/// thread, and the mutex is set to nonsignaled. If the mutex was protecting persistent state information, you should check it for consistency.
/// </term>
/// </item>
/// <item>
/// <term>WAIT_IO_COMPLETION 0x000000C0L</term>
/// <term>The wait was ended by one or more user-mode asynchronous procedure calls (APC) queued to the thread.</term>
/// </item>
/// <item>
/// <term>WAIT_TIMEOUT 258L</term>
/// <term>The time-out interval elapsed, but the conditions specified by the dwFlags and dwWakeMask parameters were not met.</term>
/// </item>
/// <item>
/// <term>WAIT_FAILED (DWORD)0xFFFFFFFF</term>
/// <term>The function has failed. To get extended error information, call GetLastError.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>MsgWaitForMultipleObjectsEx</c> function determines whether the conditions specified by dwWakeMask and dwFlags have been
/// met. If the conditions have not been met, the calling thread enters the wait state until the conditions of the wait criteria have
/// been met or the time-out interval elapses.
/// </para>
/// <para>
/// When dwFlags is zero, this function checks the handles in the array in order starting with index 0, until one of the objects is
/// signaled. If multiple objects become signaled, the function returns the index of the first handle in the array whose object was signaled.
/// </para>
/// <para>
/// <c>MsgWaitForMultipleObjectsEx</c> does not return if there is unread input of the specified type in the message queue after the
/// thread has called a function to check the queue, unless you use the <c>MWMO_INPUTAVAILABLE</c> flag. This is because functions
/// such as PeekMessage, GetMessage, GetQueueStatus, and WaitMessage check the queue and then change the state information for the
/// queue so that the input is no longer considered new. A subsequent call to <c>MsgWaitForMultipleObjectsEx</c> will not return
/// until new input of the specified type arrives, unless you use the <c>MWMO_INPUTAVAILABLE</c> flag. If this flag is not used, the
/// existing unread input (received prior to the last time the thread checked the queue) is ignored.
/// </para>
/// <para>
/// The function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects
/// whose signaled state caused the function to return. For example, the system decreases the count of a semaphore object by one. For
/// more information, see the documentation for the individual synchronization objects.
/// </para>
/// <para>
/// The <c>MsgWaitForMultipleObjectsEx</c> function can specify handles of any of the following object types in the pHandles array:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>Change notification</term>
/// </item>
/// <item>
/// <term>Console input</term>
/// </item>
/// <item>
/// <term>Event</term>
/// </item>
/// <item>
/// <term>Memory resource notification</term>
/// </item>
/// <item>
/// <term>Mutex</term>
/// </item>
/// <item>
/// <term>Process</term>
/// </item>
/// <item>
/// <term>Semaphore</term>
/// </item>
/// <item>
/// <term>Thread</term>
/// </item>
/// <item>
/// <term>Waitable timer</term>
/// </item>
/// </list>
/// <para>
/// The <c>QS_ALLPOSTMESSAGE</c> and <c>QS_POSTMESSAGE</c> flags differ in when they are cleared. <c>QS_POSTMESSAGE</c> is cleared
/// when you call GetMessage or PeekMessage, whether or not you are filtering messages. <c>QS_ALLPOSTMESSAGE</c> is cleared when you
/// call <c>GetMessage</c> or <c>PeekMessage</c> without filtering messages (wMsgFilterMin and wMsgFilterMax are 0). This can be
/// useful when you call <c>PeekMessage</c> multiple times to get messages in different ranges.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-msgwaitformultipleobjectsex DWORD
// MsgWaitForMultipleObjectsEx( DWORD nCount, const HANDLE *pHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "1774b721-3ad4-492e-96af-b71de9066f0c")]
public static extern uint MsgWaitForMultipleObjectsEx(uint nCount, HANDLE[] pHandles, uint dwMilliseconds, QS dwWakeMask, MWMO dwFlags);
/// <summary>Packs a Dynamic Data Exchange (DDE) lParam value into an internal structure used for sharing DDE data between processes.</summary>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The DDE message to be posted.</para>
/// </param>
/// <param name="uiLo">
/// <para>Type: <c>UINT_PTR</c></para>
/// <para>A value that corresponds to the 16-bit Windows low-order word of an lParam parameter for the DDE message being posted.</para>
/// </param>
/// <param name="uiHi">
/// <para>Type: <c>UINT_PTR</c></para>
/// <para>A value that corresponds to the 16-bit Windows high-order word of an lParam parameter for the DDE message being posted.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LPARAM</c></para>
/// <para>The return value is the lParam value.</para>
/// </returns>
/// <remarks>
/// <para>
/// The return value must be posted as the lParam parameter of a DDE message; it must not be used for any other purpose. After the
/// application posts a return value, it need not perform any action to dispose of the lParam parameter.
/// </para>
/// <para>An application should call this function only for posted DDE messages.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dde/nf-dde-packddelparam LPARAM PackDDElParam( UINT msg, UINT_PTR uiLo,
// UINT_PTR uiHi );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("dde.h", MSDNShortId = "")]
public static extern IntPtr PackDDElParam(uint msg, IntPtr uiLo, IntPtr uiHi);
/// <summary>
/// Dispatches incoming sent messages, checks the thread message queue for a posted message, and retrieves the message (if any exist).
/// </summary>
/// <param name="lpMsg">
/// <para>Type: <c>LPMSG</c></para>
/// <para>A pointer to an MSG structure that receives message information.</para>
/// </param>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>A handle to the window whose messages are to be retrieved. The window must belong to the current thread.</para>
/// <para>
/// If hWnd is <c>NULL</c>, <c>PeekMessage</c> retrieves messages for any window that belongs to the current thread, and any messages
/// on the current thread's message queue whose <c>hwnd</c> value is <c>NULL</c> (see the MSG structure). Therefore if hWnd is
/// <c>NULL</c>, both window messages and thread messages are processed.
/// </para>
/// <para>
/// If hWnd is -1, <c>PeekMessage</c> retrieves only messages on the current thread's message queue whose <c>hwnd</c> value is
/// <c>NULL</c>, that is, thread messages as posted by PostMessage (when the hWnd parameter is <c>NULL</c>) or PostThreadMessage.
/// </para>
/// </param>
/// <param name="wMsgFilterMin">
/// <para>Type: <c>UINT</c></para>
/// <para>
/// The value of the first message in the range of messages to be examined. Use <c>WM_KEYFIRST</c> (0x0100) to specify the first
/// keyboard message or <c>WM_MOUSEFIRST</c> (0x0200) to specify the first mouse message.
/// </para>
/// <para>
/// If wMsgFilterMin and wMsgFilterMax are both zero, <c>PeekMessage</c> returns all available messages (that is, no range filtering
/// is performed).
/// </para>
/// </param>
/// <param name="wMsgFilterMax">
/// <para>Type: <c>UINT</c></para>
/// <para>
/// The value of the last message in the range of messages to be examined. Use <c>WM_KEYLAST</c> to specify the last keyboard message
/// or <c>WM_MOUSELAST</c> to specify the last mouse message.
/// </para>
/// <para>
/// If wMsgFilterMin and wMsgFilterMax are both zero, <c>PeekMessage</c> returns all available messages (that is, no range filtering
/// is performed).
/// </para>
/// </param>
/// <param name="wRemoveMsg">
/// <para>Type: <c>UINT</c></para>
/// <para>Specifies how messages are to be handled. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>PM_NOREMOVE 0x0000</term>
/// <term>Messages are not removed from the queue after processing by PeekMessage.</term>
/// </item>
/// <item>
/// <term>PM_REMOVE 0x0001</term>
/// <term>Messages are removed from the queue after processing by PeekMessage.</term>
/// </item>
/// <item>
/// <term>PM_NOYIELD 0x0002</term>
/// <term>
/// Prevents the system from releasing any thread that is waiting for the caller to go idle (see WaitForInputIdle). Combine this
/// value with either PM_NOREMOVE or PM_REMOVE.
/// </term>
/// </item>
/// </list>
/// <para>
/// By default, all message types are processed. To specify that only certain message should be processed, specify one or more of the
/// following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>PM_QS_INPUT (QS_INPUT &lt;&lt; 16)</term>
/// <term>Process mouse and keyboard messages.</term>
/// </item>
/// <item>
/// <term>PM_QS_PAINT (QS_PAINT &lt;&lt; 16)</term>
/// <term>Process paint messages.</term>
/// </item>
/// <item>
/// <term>PM_QS_POSTMESSAGE ((QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER) &lt;&lt; 16)</term>
/// <term>Process all posted messages, including timers and hotkeys.</term>
/// </item>
/// <item>
/// <term>PM_QS_SENDMESSAGE (QS_SENDMESSAGE &lt;&lt; 16)</term>
/// <term>Process all sent messages.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If a message is available, the return value is nonzero.</para>
/// <para>If no messages are available, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>
/// <c>PeekMessage</c> retrieves messages associated with the window identified by the hWnd parameter or any of its children as
/// specified by the IsChild function, and within the range of message values given by the wMsgFilterMin and wMsgFilterMax
/// parameters. Note that an application can only use the low word in the wMsgFilterMin and wMsgFilterMax parameters; the high word
/// is reserved for the system.
/// </para>
/// <para>
/// Note that <c>PeekMessage</c> always retrieves WM_QUIT messages, no matter which values you specify for wMsgFilterMin and wMsgFilterMax.
/// </para>
/// <para>
/// During this call, the system delivers pending, non-queued messages, that is, messages sent to windows owned by the calling thread
/// using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. Then the first queued message that
/// matches the specified filter is retrieved. The system may also process internal events. If no filter is specified, messages are
/// processed in the following order:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>Sent messages</term>
/// </item>
/// <item>
/// <term>Posted messages</term>
/// </item>
/// <item>
/// <term>Input (hardware) messages and system internal events</term>
/// </item>
/// <item>
/// <term>Sent messages (again)</term>
/// </item>
/// <item>
/// <term>WM_PAINT messages</term>
/// </item>
/// <item>
/// <term>WM_TIMER messages</term>
/// </item>
/// </list>
/// <para>To retrieve input messages before posted messages, use the wMsgFilterMin and wMsgFilterMax parameters.</para>
/// <para>
/// The <c>PeekMessage</c> function normally does not remove WM_PAINT messages from the queue. <c>WM_PAINT</c> messages remain in the
/// queue until they are processed. However, if a <c>WM_PAINT</c> message has a <c>NULL</c> update region, <c>PeekMessage</c> does
/// remove it from the queue.
/// </para>
/// <para>
/// If a top-level window stops responding to messages for more than several seconds, the system considers the window to be not
/// responding and replaces it with a ghost window that has the same z-order, location, size, and visual attributes. This allows the
/// user to move it, resize it, or even close the application. However, these are the only actions available because the application
/// is actually not responding. When an application is being debugged, the system does not generate a ghost window.
/// </para>
/// <para>DPI Virtualization</para>
/// <para>
/// This API does not participate in DPI virtualization. The output is in the mode of the window that the message is targeting. The
/// calling thread is not taken into consideration.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Examining a Message Queue.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-peekmessagea BOOL PeekMessageA( LPMSG lpMsg, HWND hWnd,
// UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg );
[DllImport(Lib.User32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PeekMessage(out MSG lpMsg, [Optional] HWND hWnd, [Optional] uint wMsgFilterMin, [Optional] uint wMsgFilterMax, [Optional] PM wRemoveMsg);
/// <summary>
/// Dispatches incoming sent messages, checks the thread message queue for a posted message, and retrieves the message (if any exist).
/// </summary>
/// <typeparam name="TMsg">The type of <paramref name="wMsgFilterMin"/> and <paramref name="wMsgFilterMax"/>.</typeparam>
/// <param name="lpMsg">
/// <para>Type: <c>LPMSG</c></para>
/// <para>A pointer to an MSG structure that receives message information.</para>
/// </param>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>A handle to the window whose messages are to be retrieved. The window must belong to the current thread.</para>
/// <para>
/// If hWnd is <c>NULL</c>, <c>PeekMessage</c> retrieves messages for any window that belongs to the current thread, and any messages
/// on the current thread's message queue whose <c>hwnd</c> value is <c>NULL</c> (see the MSG structure). Therefore if hWnd is
/// <c>NULL</c>, both window messages and thread messages are processed.
/// </para>
/// <para>
/// If hWnd is -1, <c>PeekMessage</c> retrieves only messages on the current thread's message queue whose <c>hwnd</c> value is
/// <c>NULL</c>, that is, thread messages as posted by PostMessage (when the hWnd parameter is <c>NULL</c>) or PostThreadMessage.
/// </para>
/// </param>
/// <param name="wMsgFilterMin">
/// <para>Type: <c>UINT</c></para>
/// <para>
/// The value of the first message in the range of messages to be examined. Use <c>WM_KEYFIRST</c> (0x0100) to specify the first
/// keyboard message or <c>WM_MOUSEFIRST</c> (0x0200) to specify the first mouse message.
/// </para>
/// <para>
/// If wMsgFilterMin and wMsgFilterMax are both zero, <c>PeekMessage</c> returns all available messages (that is, no range filtering
/// is performed).
/// </para>
/// </param>
/// <param name="wMsgFilterMax">
/// <para>Type: <c>UINT</c></para>
/// <para>
/// The value of the last message in the range of messages to be examined. Use <c>WM_KEYLAST</c> to specify the last keyboard message
/// or <c>WM_MOUSELAST</c> to specify the last mouse message.
/// </para>
/// <para>
/// If wMsgFilterMin and wMsgFilterMax are both zero, <c>PeekMessage</c> returns all available messages (that is, no range filtering
/// is performed).
/// </para>
/// </param>
/// <param name="wRemoveMsg">
/// <para>Type: <c>UINT</c></para>
/// <para>Specifies how messages are to be handled. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>PM_NOREMOVE 0x0000</term>
/// <term>Messages are not removed from the queue after processing by PeekMessage.</term>
/// </item>
/// <item>
/// <term>PM_REMOVE 0x0001</term>
/// <term>Messages are removed from the queue after processing by PeekMessage.</term>
/// </item>
/// <item>
/// <term>PM_NOYIELD 0x0002</term>
/// <term>
/// Prevents the system from releasing any thread that is waiting for the caller to go idle (see WaitForInputIdle). Combine this
/// value with either PM_NOREMOVE or PM_REMOVE.
/// </term>
/// </item>
/// </list>
/// <para>
/// By default, all message types are processed. To specify that only certain message should be processed, specify one or more of the
/// following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>PM_QS_INPUT (QS_INPUT &lt;&lt; 16)</term>
/// <term>Process mouse and keyboard messages.</term>
/// </item>
/// <item>
/// <term>PM_QS_PAINT (QS_PAINT &lt;&lt; 16)</term>
/// <term>Process paint messages.</term>
/// </item>
/// <item>
/// <term>PM_QS_POSTMESSAGE ((QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER) &lt;&lt; 16)</term>
/// <term>Process all posted messages, including timers and hotkeys.</term>
/// </item>
/// <item>
/// <term>PM_QS_SENDMESSAGE (QS_SENDMESSAGE &lt;&lt; 16)</term>
/// <term>Process all sent messages.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If a message is available, the return value is nonzero.</para>
/// <para>If no messages are available, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>
/// <c>PeekMessage</c> retrieves messages associated with the window identified by the hWnd parameter or any of its children as
/// specified by the IsChild function, and within the range of message values given by the wMsgFilterMin and wMsgFilterMax
/// parameters. Note that an application can only use the low word in the wMsgFilterMin and wMsgFilterMax parameters; the high word
/// is reserved for the system.
/// </para>
/// <para>
/// Note that <c>PeekMessage</c> always retrieves WM_QUIT messages, no matter which values you specify for wMsgFilterMin and wMsgFilterMax.
/// </para>
/// <para>
/// During this call, the system delivers pending, non-queued messages, that is, messages sent to windows owned by the calling thread
/// using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. Then the first queued message that
/// matches the specified filter is retrieved. The system may also process internal events. If no filter is specified, messages are
/// processed in the following order:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>Sent messages</term>
/// </item>
/// <item>
/// <term>Posted messages</term>
/// </item>
/// <item>
/// <term>Input (hardware) messages and system internal events</term>
/// </item>
/// <item>
/// <term>Sent messages (again)</term>
/// </item>
/// <item>
/// <term>WM_PAINT messages</term>
/// </item>
/// <item>
/// <term>WM_TIMER messages</term>
/// </item>
/// </list>
/// <para>To retrieve input messages before posted messages, use the wMsgFilterMin and wMsgFilterMax parameters.</para>
/// <para>
/// The <c>PeekMessage</c> function normally does not remove WM_PAINT messages from the queue. <c>WM_PAINT</c> messages remain in the
/// queue until they are processed. However, if a <c>WM_PAINT</c> message has a <c>NULL</c> update region, <c>PeekMessage</c> does
/// remove it from the queue.
/// </para>
/// <para>
/// If a top-level window stops responding to messages for more than several seconds, the system considers the window to be not
/// responding and replaces it with a ghost window that has the same z-order, location, size, and visual attributes. This allows the
/// user to move it, resize it, or even close the application. However, these are the only actions available because the application
/// is actually not responding. When an application is being debugged, the system does not generate a ghost window.
/// </para>
/// <para>DPI Virtualization</para>
/// <para>
/// This API does not participate in DPI virtualization. The output is in the mode of the window that the message is targeting. The
/// calling thread is not taken into consideration.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Examining a Message Queue.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-peekmessagea BOOL PeekMessageA( LPMSG lpMsg, HWND hWnd,
// UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg );
[PInvokeData("winuser.h")]
public static bool PeekMessage<TMsg>(out MSG lpMsg, [Optional] HWND hWnd, TMsg wMsgFilterMin, TMsg wMsgFilterMax, [Optional] PM wRemoveMsg) where TMsg : struct, IConvertible =>
PeekMessage(out lpMsg, hWnd, Convert.ToUInt32(wMsgFilterMin), Convert.ToUInt32(wMsgFilterMax), wRemoveMsg);
/// <summary>
/// <para>
/// Places (posts) a message in the message queue associated with the thread that created the specified window and returns without
/// waiting for the thread to process the message.
/// </para>
/// <para>To post a message in the message queue associated with a thread, use the PostThreadMessage function.</para>
/// </summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>A handle to the window whose window procedure is to receive the message. The following values have special meanings.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>HWND_BROADCAST ((HWND)0xffff)</term>
/// <term>
/// The message is posted to all top-level windows in the system, including disabled or invisible unowned windows, overlapped
/// windows, and pop-up windows. The message is not posted to child windows.
/// </term>
/// </item>
/// <item>
/// <term>NULL</term>
/// <term>
/// The function behaves like a call to PostThreadMessage with the dwThreadId parameter set to the identifier of the current thread.
/// </term>
/// </item>
/// </list>
/// <para>
/// Starting with Windows Vista, message posting is subject to UIPI. The thread of a process can post messages only to message queues
/// of threads in processes of lesser or equal integrity level.
/// </para>
/// </param>
/// <param name="Msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be posted.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. <c>GetLastError</c>
/// returns <c>ERROR_NOT_ENOUGH_QUOTA</c> when the limit is hit.
/// </para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>Messages in a message queue are retrieved by calls to the GetMessage or PeekMessage function.</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshaling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshaling.
/// </para>
/// <para>
/// If you send a message in the range below WM_USER to the asynchronous message functions ( <c>PostMessage</c>, SendNotifyMessage,
/// and SendMessageCallback), its message parameters cannot include pointers. Otherwise, the operation will fail. The functions will
/// return before the receiving thread has had a chance to process the message and the sender will free the memory before it is used.
/// </para>
/// <para>Do not post the WM_QUIT message using <c>PostMessage</c>; use the PostQuitMessage function.</para>
/// <para>
/// An accessibility application can use <c>PostMessage</c> to post WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>
/// There is a limit of 10,000 posted messages per message queue. This limit should be sufficiently large. If your application
/// exceeds the limit, it should be redesigned to avoid consuming so many system resources. To adjust this limit, modify the
/// following registry key.
/// </para>
/// <para><c>HKEY_LOCAL_MACHINE</c><c>SOFTWARE</c><c>Microsoft</c><c>Windows NT</c><c>CurrentVersion</c><c>Windows</c><c>USERPostMessageLimit</c></para>
/// <para>The minimum acceptable value is 4000.</para>
/// <para>Examples</para>
/// <para>
/// The following example shows how to post a private window message using the <c>PostMessage</c> function. Assume you defined a
/// private window message called <c>WM_COMPLETE</c>:
/// </para>
/// <para>You can post a message to the message queue associated with the thread that created the specified window as shown below:</para>
/// <para>For more examples, see Initiating a Data Link.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-postmessagea BOOL PostMessageA( HWND hWnd, UINT Msg,
// WPARAM wParam, LPARAM lParam );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PostMessage([Optional] HWND hWnd, uint Msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam);
/// <summary>
/// <para>
/// Places (posts) a message in the message queue associated with the thread that created the specified window and returns without
/// waiting for the thread to process the message.
/// </para>
/// <para>To post a message in the message queue associated with a thread, use the PostThreadMessage function.</para>
/// </summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>A handle to the window whose window procedure is to receive the message. The following values have special meanings.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>HWND_BROADCAST ((HWND)0xffff)</term>
/// <term>
/// The message is posted to all top-level windows in the system, including disabled or invisible unowned windows, overlapped
/// windows, and pop-up windows. The message is not posted to child windows.
/// </term>
/// </item>
/// <item>
/// <term>NULL</term>
/// <term>
/// The function behaves like a call to PostThreadMessage with the dwThreadId parameter set to the identifier of the current thread.
/// </term>
/// </item>
/// </list>
/// <para>
/// Starting with Windows Vista, message posting is subject to UIPI. The thread of a process can post messages only to message queues
/// of threads in processes of lesser or equal integrity level.
/// </para>
/// </param>
/// <param name="Msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be posted.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. <c>GetLastError</c>
/// returns <c>ERROR_NOT_ENOUGH_QUOTA</c> when the limit is hit.
/// </para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>Messages in a message queue are retrieved by calls to the GetMessage or PeekMessage function.</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshaling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshaling.
/// </para>
/// <para>
/// If you send a message in the range below WM_USER to the asynchronous message functions ( <c>PostMessage</c>, SendNotifyMessage,
/// and SendMessageCallback), its message parameters cannot include pointers. Otherwise, the operation will fail. The functions will
/// return before the receiving thread has had a chance to process the message and the sender will free the memory before it is used.
/// </para>
/// <para>Do not post the WM_QUIT message using <c>PostMessage</c>; use the PostQuitMessage function.</para>
/// <para>
/// An accessibility application can use <c>PostMessage</c> to post WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>
/// There is a limit of 10,000 posted messages per message queue. This limit should be sufficiently large. If your application
/// exceeds the limit, it should be redesigned to avoid consuming so many system resources. To adjust this limit, modify the
/// following registry key.
/// </para>
/// <para><c>HKEY_LOCAL_MACHINE</c><c>SOFTWARE</c><c>Microsoft</c><c>Windows NT</c><c>CurrentVersion</c><c>Windows</c><c>USERPostMessageLimit</c></para>
/// <para>The minimum acceptable value is 4000.</para>
/// <para>Examples</para>
/// <para>
/// The following example shows how to post a private window message using the <c>PostMessage</c> function. Assume you defined a
/// private window message called <c>WM_COMPLETE</c>:
/// </para>
/// <para>You can post a message to the message queue associated with the thread that created the specified window as shown below:</para>
/// <para>For more examples, see Initiating a Data Link.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-postmessagea BOOL PostMessageA( HWND hWnd, UINT Msg,
// WPARAM wParam, LPARAM lParam );
[PInvokeData("winuser.h")]
public static bool PostMessage<TMsg>([Optional] HWND hWnd, TMsg Msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam) where TMsg : struct, IConvertible =>
PostMessage(hWnd, Convert.ToUInt32(Msg), wParam, lParam);
/// <summary>
/// Indicates to the system that a thread has made a request to terminate (quit). It is typically used in response to a WM_DESTROY message.
/// </summary>
/// <param name="nExitCode">
/// <para>Type: <c>int</c></para>
/// <para>The application exit code. This value is used as the wParam parameter of the WM_QUIT message.</para>
/// </param>
/// <remarks>
/// <para>
/// The <c>PostQuitMessage</c> function posts a WM_QUIT message to the thread's message queue and returns immediately; the function
/// simply indicates to the system that the thread is requesting to quit at some time in the future.
/// </para>
/// <para>
/// When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the
/// system. The exit value returned to the system must be the wParam parameter of the <c>WM_QUIT</c> message.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Posting a Message.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-postquitmessage void PostQuitMessage( int nExitCode );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
public static extern void PostQuitMessage([Optional] int nExitCode);
/// <summary>
/// Posts a message to the message queue of the specified thread. It returns without waiting for the thread to process the message.
/// </summary>
/// <param name="idThread">
/// <para>Type: <c>DWORD</c></para>
/// <para>The identifier of the thread to which the message is to be posted.</para>
/// <para>
/// The function fails if the specified thread does not have a message queue. The system creates a thread's message queue when the
/// thread makes its first call to one of the User or GDI functions. For more information, see the Remarks section.
/// </para>
/// <para>
/// Message posting is subject to UIPI. The thread of a process can post messages only to posted-message queues of threads in
/// processes of lesser or equal integrity level.
/// </para>
/// <para>
/// This thread must have the <c>SE_TCB_NAME</c> privilege to post a message to a thread that belongs to a process with the same
/// locally unique identifier (LUID) but is in a different desktop. Otherwise, the function fails and returns <c>ERROR_INVALID_THREAD_ID</c>.
/// </para>
/// <para>
/// This thread must either belong to the same desktop as the calling thread or to a process with the same LUID. Otherwise, the
/// function fails and returns <c>ERROR_INVALID_THREAD_ID</c>.
/// </para>
/// </param>
/// <param name="Msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The type of message to be posted.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. <c>GetLastError</c>
/// returns <c>ERROR_INVALID_THREAD_ID</c> if idThread is not a valid thread identifier, or if the thread specified by idThread does
/// not have a message queue. <c>GetLastError</c> returns <c>ERROR_NOT_ENOUGH_QUOTA</c> when the message limit is hit.
/// </para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// The thread to which the message is posted must have created a message queue, or else the call to <c>PostThreadMessage</c> fails.
/// Use the following method to handle this situation.
/// </para>
/// <list type="bullet">
/// <item>
/// <term>Create an event object, then create the thread.</term>
/// </item>
/// <item>
/// <term>Use the WaitForSingleObject function to wait for the event to be set to the signaled state before calling <c>PostThreadMessage</c>.</term>
/// </item>
/// <item>
/// <term>
/// In the thread to which the message will be posted, call PeekMessage as shown here to force the system to create the message queue.
/// </term>
/// </item>
/// <item>
/// <term>Set the event, to indicate that the thread is ready to receive posted messages.</term>
/// </item>
/// </list>
/// <para>
/// The thread to which the message is posted retrieves the message by calling the GetMessage or PeekMessage function. The
/// <c>hwnd</c> member of the returned MSG structure is <c>NULL</c>.
/// </para>
/// <para>
/// Messages sent by <c>PostThreadMessage</c> are not associated with a window. As a general rule, messages that are not associated
/// with a window cannot be dispatched by the DispatchMessage function. Therefore, if the recipient thread is in a modal loop (as
/// used by MessageBox or DialogBox), the messages will be lost. To intercept thread messages while in a modal loop, use a
/// thread-specific hook.
/// </para>
/// <para>
/// The system only does marshaling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshaling.
/// </para>
/// <para>
/// There is a limit of 10,000 posted messages per message queue. This limit should be sufficiently large. If your application
/// exceeds the limit, it should be redesigned to avoid consuming so many system resources. To adjust this limit, modify the
/// following registry key.
/// </para>
/// <para><c>HKEY_LOCAL_MACHINE</c><c>SOFTWARE</c><c>Microsoft</c><c>Windows NT</c><c>CurrentVersion</c><c>Windows</c><c>USERPostMessageLimit</c></para>
/// <para>The minimum acceptable value is 4000.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-postthreadmessagea BOOL PostThreadMessageA( DWORD
// idThread, UINT Msg, WPARAM wParam, LPARAM lParam );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PostThreadMessage(uint idThread, uint Msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam);
/// <summary>
/// Defines a new window message that is guaranteed to be unique throughout the system. The message value can be used when sending or
/// posting messages.
/// </summary>
/// <param name="lpString">
/// <para>Type: <c>LPCTSTR</c></para>
/// <para>The message to be registered.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>UINT</c></c></para>
/// <para>If the message is successfully registered, the return value is a message identifier in the range 0xC000 through 0xFFFF.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>RegisterWindowMessage</c> function is typically used to register messages for communicating between two cooperating applications.
/// </para>
/// <para>
/// If two different applications register the same message string, the applications return the same message value. The message
/// remains registered until the session ends.
/// </para>
/// <para>
/// Only use <c>RegisterWindowMessage</c> when more than one application must process the same message. For sending private messages
/// within a window class, an application can use any integer in the range WM_USER through 0x7FFF. (Messages in this range are
/// private to a window class, not to an application. For example, predefined control classes such as <c>BUTTON</c>, <c>EDIT</c>,
/// <c>LISTBOX</c>, and <c>COMBOBOX</c> may use values in this range.)
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Finding Text.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registerwindowmessagea UINT RegisterWindowMessageA( LPCSTR
// lpString );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
public static extern uint RegisterWindowMessage(string lpString);
/// <summary>Replies to a message sent from another thread by the SendMessage function.</summary>
/// <param name="lResult">
/// <para>Type: <c>LRESULT</c></para>
/// <para>The result of the message processing. The possible values are based on the message sent.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the calling thread was processing a message sent from another thread or process, the return value is nonzero.</para>
/// <para>If the calling thread was not processing a message sent from another thread or process, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>
/// By calling this function, the window procedure that receives the message allows the thread that called SendMessage to continue to
/// run as though the thread receiving the message had returned control. The thread that calls the <c>ReplyMessage</c> function also
/// continues to run.
/// </para>
/// <para>
/// If the message was not sent through SendMessage or if the message was sent by the same thread, <c>ReplyMessage</c> has no effect.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Sending a Message.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-replymessage BOOL ReplyMessage( LRESULT lResult );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ReplyMessage(IntPtr lResult);
/// <summary>
/// Enables an application to reuse a packed Dynamic Data Exchange (DDE) lParam parameter, rather than allocating a new packed
/// lParam. Using this function reduces reallocations for applications that pass packed DDE messages.
/// </summary>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>The lParam parameter of the posted DDE message being reused.</para>
/// </param>
/// <param name="msgIn">
/// <para>Type: <c>UINT</c></para>
/// <para>The identifier of the received DDE message.</para>
/// </param>
/// <param name="msgOut">
/// <para>Type: <c>UINT</c></para>
/// <para>The identifier of the DDE message to be posted. The DDE message will reuse the packed lParam parameter.</para>
/// </param>
/// <param name="uiLo">
/// <para>Type: <c>UINT_PTR</c></para>
/// <para>The value to be packed into the low-order word of the reused lParam parameter.</para>
/// </param>
/// <param name="uiHi">
/// <para>Type: <c>UINT_PTR</c></para>
/// <para>The value to be packed into the high-order word of the reused lParam parameter.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LPARAM</c></para>
/// <para>The return value is the new lParam value.</para>
/// </returns>
/// <remarks>
/// <para>
/// The return value must be posted as the lParam parameter of a DDE message; it must not be used for any other purpose. Once the
/// return value is posted, the posting application need not perform any action to dispose of the lParam parameter.
/// </para>
/// <para>
/// Use <c>ReuseDDElParam</c> instead of FreeDDElParam if the lParam parameter will be reused in a responding message.
/// <c>ReuseDDElParam</c> returns the lParam appropriate for reuse.
/// </para>
/// <para>
/// This function allocates or frees lParam parameters as needed, depending on the packing requirements of the incoming and outgoing
/// messages. This reduces reallocations in passing DDE messages.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dde/nf-dde-reuseddelparam LPARAM ReuseDDElParam( LPARAM lParam, UINT msgIn,
// UINT msgOut, UINT_PTR uiLo, UINT_PTR uiHi );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("dde.h", MSDNShortId = "")]
public static extern IntPtr ReuseDDElParam(IntPtr lParam, uint msgIn, uint msgOut, IntPtr uiLo, IntPtr uiHi);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// 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, Optional] IntPtr wParam, [In, Out, Optional] IntPtr lParam);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// 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, Optional] IntPtr wParam, string lParam);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// 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);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// 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, Optional] IntPtr wParam, [In, Out] StringBuilder lParam);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <param name="hWnd"><para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para></param>
/// <param name="msg"><para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para></param>
/// <param name="wParam"><para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para></param>
/// <param name="lParam"><para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para></param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg>(HWND hWnd, TMsg msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam)
where TMsg : struct, IConvertible
=> SendMessage(hWnd, Convert.ToUInt32(msg), wParam, lParam);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <typeparam name="TWP">The type of the <paramref name="wParam"/> parameter. This can be any type that converts to <see cref="long" />.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg, TWP>(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), lParam);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <typeparam name="TWP">The type of the <paramref name="wParam"/> parameter. This must be a type that can be marshaled to memory.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg, TWP>(HWND hWnd, TMsg msg, in TWP wParam, [Optional] IntPtr lParam)
where TMsg : struct, IConvertible where TWP : struct
{
using var wmem = SafeCoTaskMemHandle.CreateFromStructure(wParam);
return SendMessage(hWnd, Convert.ToUInt32(msg), wmem, lParam);
}
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <typeparam name="TWP">The type of the <paramref name="wParam"/> parameter. This can be any type that converts to <see cref="long" />.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg, TWP>(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);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg>(HWND hWnd, TMsg msg, [In, Optional] IntPtr wParam, string lParam)
where TMsg : struct, IConvertible
=> SendMessage(hWnd, Convert.ToUInt32(msg), (IntPtr)Convert.ToInt64(wParam), lParam);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg>(HWND hWnd, TMsg msg, [In, Optional] IntPtr wParam, StringBuilder lParam)
where TMsg : struct, IConvertible
=> SendMessage(hWnd, Convert.ToUInt32(msg), (IntPtr)Convert.ToInt64(wParam), lParam);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <typeparam name="TWP">The type of the <paramref name="wParam"/> parameter. This can be any type that converts to <see cref="long" />.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg, TWP>(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);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <typeparam name="TLP">The type of the <paramref name="lParam"/> parameter. This can be any type that converts to <see cref="long" />.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg, TLP>(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));
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <typeparam name="TLP">The type of the <paramref name="lParam"/> parameter. This must be a type that can be marshaled to memory.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg, TLP>(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);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <typeparam name="TWP">The type of the <paramref name="wParam"/> parameter. This can be any type that converts to <see cref="long" />.</typeparam>
/// <typeparam name="TLP">The type of the <paramref name="lParam"/> parameter. This must be a type that can be marshaled to memory.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg, TWP, TLP>(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);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
/// <typeparam name="TMsg">The type of the message. This can be any type that converts to <see cref="uint"/>.</typeparam>
/// <typeparam name="TWP">The type of the <paramref name="wParam"/> parameter. This must be a type that can be marshaled to memory.</typeparam>
/// <typeparam name="TLP">The type of the <paramref name="lParam"/> parameter. This must be a type that can be marshaled to memory.</typeparam>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>LRESULT</c></para>
/// <para>The return value specifies the result of the message processing; it depends on the message sent.</para>
/// </returns>
/// <remarks>
/// <para>When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).</para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshalling.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// An accessibility application can use <c>SendMessage</c> to send WM_APPCOMMAND messages to the shell to launch applications. This
/// functionality is not guaranteed to work for other types of applications.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Displaying Keyboard Input.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
[PInvokeData("winuser.h", MSDNShortId = "NF:winuser.SendMessage")]
public static IntPtr SendMessage<TMsg, TWP, TLP>(HWND hWnd, TMsg msg, in TWP wParam, ref TLP lParam)
where TMsg : struct, IConvertible where TWP : struct where TLP : struct
{
using var wmem = SafeCoTaskMemHandle.CreateFromStructure(wParam);
return SendMessage(hWnd, Convert.ToUInt32(msg), wmem, ref lParam);
}
private static IntPtr SendMessage<TLP>(HWND hWnd, uint msg, IntPtr wParam, ref TLP lParam) where TLP : struct
{
using var lmem = SafeCoTaskMemHandle.CreateFromStructure(lParam);
var lret = SendMessage(hWnd, msg, wParam, lmem);
lParam = lmem.ToStructure<TLP>();
return lret;
}
/// <summary>
/// Sends the specified message to a window or windows. It calls the window procedure for the specified window and returns
/// immediately if the window belongs to another thread. After the window procedure processes the message, the system calls the
/// specified callback function, passing the result of the message processing and an application-defined value to the callback function.
/// </summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// </param>
/// <param name="Msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lpResultCallBack">
/// <para>Type: <c>SENDASYNCPROC</c></para>
/// <para>
/// A pointer to a callback function that the system calls after the window procedure processes the message. For more information,
/// see SendAsyncProc.
/// </para>
/// <para>
/// If hWnd is <c>HWND_BROADCAST</c> ((HWND)0xffff), the system calls the SendAsyncProc callback function once for each top-level window.
/// </para>
/// </param>
/// <param name="dwData">
/// <para>Type: <c>ULONG_PTR</c></para>
/// <para>An application-defined value to be sent to the callback function pointed to by the lpCallBack parameter.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// If the target window belongs to the same thread as the caller, then the window procedure is called synchronously, and the
/// callback function is called immediately after the window procedure returns. If the target window belongs to a different thread
/// from the caller, then the callback function is called only when the thread that called <c>SendMessageCallback</c> also calls
/// GetMessage, PeekMessage, or WaitMessage.
/// </para>
/// <para>
/// If you send a message in the range below WM_USER to the asynchronous message functions (PostMessage, SendNotifyMessage, and
/// <c>SendMessageCallback</c>), its message parameters cannot include pointers. Otherwise, the operation will fail. The functions
/// will return before the receiving thread has had a chance to process the message and the sender will free the memory before it is used.
/// </para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshaling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshaling.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendmessagecallbacka BOOL SendMessageCallbackA( HWND hWnd,
// UINT Msg, WPARAM wParam, LPARAM lParam, SENDASYNCPROC lpResultCallBack, ULONG_PTR dwData );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SendMessageCallback(HWND hWnd, uint Msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam, Sendasyncproc lpResultCallBack, UIntPtr dwData);
/// <summary>Sends the specified message to one or more windows.</summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>A handle to the window whose window procedure will receive the message.</para>
/// <para>
/// If this parameter is <c>HWND_BROADCAST</c> ((HWND)0xffff), the message is sent to all top-level windows in the system, including
/// disabled or invisible unowned windows. The function does not return until each window has timed out. Therefore, the total wait
/// time can be up to the value of uTimeout multiplied by the number of top-level windows.
/// </para>
/// </param>
/// <param name="Msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Any additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Any additional message-specific information.</para>
/// </param>
/// <param name="fuFlags">
/// <para>Type: <c>UINT</c></para>
/// <para>The behavior of this function. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SMTO_ABORTIFHUNG 0x0002</term>
/// <term>
/// The function returns without waiting for the time-out period to elapse if the receiving thread appears to not respond or "hangs."
/// </term>
/// </item>
/// <item>
/// <term>SMTO_BLOCK 0x0001</term>
/// <term>Prevents the calling thread from processing any other requests until the function returns.</term>
/// </item>
/// <item>
/// <term>SMTO_NORMAL 0x0000</term>
/// <term>The calling thread is not prevented from processing other requests while waiting for the function to return.</term>
/// </item>
/// <item>
/// <term>SMTO_NOTIMEOUTIFNOTHUNG 0x0008</term>
/// <term>The function does not enforce the time-out period as long as the receiving thread is processing messages.</term>
/// </item>
/// <item>
/// <term>SMTO_ERRORONEXIT 0x0020</term>
/// <term>
/// The function should return 0 if the receiving window is destroyed or its owning thread dies while the message is being processed.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="uTimeout">
/// <para>Type: <c>UINT</c></para>
/// <para>
/// The duration of the time-out period, in milliseconds. If the message is a broadcast message, each window can use the full
/// time-out period. For example, if you specify a five second time-out period and there are three top-level windows that fail to
/// process the message, you could have up to a 15 second delay.
/// </para>
/// </param>
/// <param name="lpdwResult">
/// <para>Type: <c>PDWORD_PTR</c></para>
/// <para>The result of the message processing. The value of this parameter depends on the message that is specified.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>LRESULT</c></c></para>
/// <para>
/// If the function succeeds, the return value is nonzero. <c>SendMessageTimeout</c> does not provide information about individual
/// windows timing out if <c>HWND_BROADCAST</c> is used.
/// </para>
/// <para>
/// If the function fails or times out, the return value is 0. To get extended error information, call GetLastError. If
/// <c>GetLastError</c> returns <c>ERROR_TIMEOUT</c>, then the function timed out.
/// </para>
/// <para><c>Windows 2000:</c> If GetLastError returns 0, then the function timed out.</para>
/// </returns>
/// <remarks>
/// <para>
/// The function calls the window procedure for the specified window and, if the specified window belongs to a different thread, does
/// not return until the window procedure has processed the message or the specified time-out period has elapsed. If the window
/// receiving the message belongs to the same queue as the current thread, the window procedure is called directly—the time-out value
/// is ignored.
/// </para>
/// <para>
/// This function considers that a thread is not responding if it has not called GetMessage or a similar function within five seconds.
/// </para>
/// <para>
/// The system only does marshaling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshaling.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendmessagetimeouta LRESULT SendMessageTimeoutA( HWND
// hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD_PTR lpdwResult );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
public static extern IntPtr SendMessageTimeout(HWND hWnd, uint Msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam, SMTO fuFlags, uint uTimeout, ref IntPtr lpdwResult);
/// <summary>
/// <para>
/// Sends the specified message to a window or windows. The <c>SendMessage</c> function calls the window procedure for the specified
/// window and does not return until the window procedure has processed the message.
/// </para>
/// <para>
/// To send a message and return immediately, use the <c>SendMessageCallback</c> or <c>SendNotifyMessage</c> function. To post a
/// message to a thread's message queue and return immediately, use the <c>PostMessage</c> or <c>PostThreadMessage</c> function.
/// </para>
/// </summary>
/// <param name="hWnd">
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </param>
/// <param name="msg">
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">Additional message-specific information.</param>
/// <param name="lParam">Additional message-specific information.</param>
/// <returns>The return value specifies the result of the message processing; it depends on the message sent.</returns>
// 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, EntryPoint = "SendMessage")]
[PInvokeData("Winuser.h", MSDNShortId = "ms644950")]
[System.Security.SecurityCritical]
public static unsafe extern void* SendMessageUnsafe(void* hWnd, uint msg, void* wParam, void* lParam);
/// <summary>
/// Sends the specified message to a window or windows. If the window was created by the calling thread, <c>SendNotifyMessage</c>
/// calls the window procedure for the window and does not return until the window procedure has processed the message. If the window
/// was created by a different thread, <c>SendNotifyMessage</c> passes the message to the window procedure and returns immediately;
/// it does not wait for the window procedure to finish processing the message.
/// </summary>
/// <param name="hWnd">
/// <para>Type: <c>HWND</c></para>
/// <para>
/// A handle to the window whose window procedure will receive the message. If this parameter is <c>HWND_BROADCAST</c>
/// ((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.
/// </para>
/// </param>
/// <param name="Msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The message to be sent.</para>
/// <para>For lists of the system-provided messages, see System-Defined Messages.</para>
/// </param>
/// <param name="wParam">
/// <para>Type: <c>WPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>Additional message-specific information.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// If you send a message in the range below WM_USER to the asynchronous message functions (PostMessage, <c>SendNotifyMessage</c>,
/// and SendMessageCallback), its message parameters cannot include pointers. Otherwise, the operation will fail. The functions will
/// return before the receiving thread has had a chance to process the message and the sender will free the memory before it is used.
/// </para>
/// <para>
/// Applications that need to communicate using <c>HWND_BROADCAST</c> should use the RegisterWindowMessage function to obtain a
/// unique message for inter-application communication.
/// </para>
/// <para>
/// The system only does marshaling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those &gt;=
/// <c>WM_USER</c>) to another process, you must do custom marshaling.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendnotifymessagea BOOL SendNotifyMessageA( HWND hWnd,
// UINT Msg, WPARAM wParam, LPARAM lParam );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SendNotifyMessage(HWND hWnd, uint Msg, [Optional] IntPtr wParam, [Optional] IntPtr lParam);
/// <summary>
/// Sets the extra message information for the current thread. Extra message information is an application- or driver-defined value
/// associated with the current thread's message queue. An application can use the GetMessageExtraInfo function to retrieve a
/// thread's extra message information.
/// </summary>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>The value to be associated with the current thread.</para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>LPARAM</c></c></para>
/// <para>The return value is the previous value associated with the current thread.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setmessageextrainfo LPARAM SetMessageExtraInfo( LPARAM
// lParam );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
public static extern IntPtr SetMessageExtraInfo(IntPtr lParam);
/// <summary>
/// Translates virtual-key messages into character messages. The character messages are posted to the calling thread's message queue,
/// to be read the next time the thread calls the GetMessage or PeekMessage function.
/// </summary>
/// <param name="lpMsg">
/// <para>Type: <c>const MSG*</c></para>
/// <para>
/// A pointer to an MSG structure that contains message information retrieved from the calling thread's message queue by using the
/// GetMessage or PeekMessage function.
/// </para>
/// </param>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>
/// If the message is translated (that is, a character message is posted to the thread's message queue), the return value is nonzero.
/// </para>
/// <para>
/// If the message is WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP, the return value is nonzero, regardless of the translation.
/// </para>
/// <para>
/// If the message is not translated (that is, a character message is not posted to the thread's message queue), the return value is zero.
/// </para>
/// </returns>
/// <remarks>
/// <para>The <c>TranslateMessage</c> function does not modify the message pointed to by the lpMsg parameter.</para>
/// <para>
/// WM_KEYDOWN and WM_KEYUP combinations produce a WM_CHAR or WM_DEADCHAR message. WM_SYSKEYDOWN and WM_SYSKEYUP combinations produce
/// a WM_SYSCHAR or WM_SYSDEADCHAR message.
/// </para>
/// <para><c>TranslateMessage</c> produces WM_CHAR messages only for keys that are mapped to ASCII characters by the keyboard driver.</para>
/// <para>
/// If applications process virtual-key messages for some other purpose, they should not call <c>TranslateMessage</c>. For instance,
/// an application should not call <c>TranslateMessage</c> if the TranslateAccelerator function returns a nonzero value. Note that
/// the application is responsible for retrieving and dispatching input messages to the dialog box. Most applications use the main
/// message loop for this. However, to permit the user to move to and to select controls by using the keyboard, the application must
/// call IsDialogMessage. For more information, see Dialog Box Keyboard Interface.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Creating a Message Loop.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-translatemessage BOOL TranslateMessage( const MSG *lpMsg );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool TranslateMessage(in MSG lpMsg);
/// <summary>Unpacks a Dynamic Data Exchange (DDE)lParam value received from a posted DDE message.</summary>
/// <param name="msg">
/// <para>Type: <c>UINT</c></para>
/// <para>The posted DDE message.</para>
/// </param>
/// <param name="lParam">
/// <para>Type: <c>LPARAM</c></para>
/// <para>
/// The lParam parameter of the posted DDE message that was received. The application must free the memory object specified by the
/// lParam parameter by calling the FreeDDElParam function.
/// </para>
/// </param>
/// <param name="puiLo">
/// <para>Type: <c>PUINT_PTR</c></para>
/// <para>A pointer to a variable that receives the low-order word of lParam.</para>
/// </param>
/// <param name="puiHi">
/// <para>Type: <c>PUINT_PTR</c></para>
/// <para>A pointer to a variable that receives the high-order word of lParam.</para>
/// </param>
/// <returns>
/// <para>Type: <c>BOOL</c></para>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>PackDDElParam eases the porting of 16-bit DDE applications to 32-bit DDE applications.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dde/nf-dde-unpackddelparam BOOL UnpackDDElParam( UINT msg, LPARAM lParam,
// PUINT_PTR puiLo, PUINT_PTR puiHi );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("dde.h", MSDNShortId = "")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnpackDDElParam(uint msg, IntPtr lParam, out IntPtr puiLo, out IntPtr puiHi);
/// <summary>
/// Yields control to other threads when a thread has no other messages in its message queue. The <c>WaitMessage</c> function
/// suspends the thread and does not return until a new message is placed in the thread's message queue.
/// </summary>
/// <returns>
/// <para>Type: <c>Type: <c>BOOL</c></c></para>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// Note that <c>WaitMessage</c> does not return if there is unread input in the message queue after the thread has called a function
/// to check the queue. This is because functions such as PeekMessage, GetMessage, GetQueueStatus, <c>WaitMessage</c>,
/// MsgWaitForMultipleObjects, and MsgWaitForMultipleObjectsEx check the queue and then change the state information for the queue so
/// that the input is no longer considered new. A subsequent call to <c>WaitMessage</c> will not return until new input of the
/// specified type arrives. The existing unread input (received prior to the last time the thread checked the queue) is ignored.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-waitmessage BOOL WaitMessage( );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WaitMessage();
/// <summary>Contains information about a window that denied a request from BroadcastSystemMessageEx.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-__unnamed_struct_2 typedef struct { UINT cbSize; HDESK
// hdesk; HWND hwnd; LUID luid; } BSMINFO, *PBSMINFO;
[PInvokeData("winuser.h")]
[StructLayout(LayoutKind.Sequential)]
public struct BSMINFO
{
/// <summary>
/// <para>Type: <c>UINT</c></para>
/// <para>The size, in bytes, of this structure.</para>
/// </summary>
public uint cbSize;
/// <summary>
/// <para>Type: <c>HDESK</c></para>
/// <para>
/// A desktop handle to the window specified by <c>hwnd</c>. This value is returned only if BroadcastSystemMessageEx specifies
/// <c>BSF_RETURNHDESK</c> and <c>BSF_QUERY</c>.
/// </para>
/// </summary>
public HDESK hdesk;
/// <summary>
/// <para>Type: <c>HWND</c></para>
/// <para>A handle to the window that denied the request. This value is returned if BroadcastSystemMessageEx specifies <c>BSF_QUERY</c>.</para>
/// </summary>
public HWND hwnd;
/// <summary>
/// <para>Type: <c>LUID</c></para>
/// <para>A locally unique identifier (LUID) for the window.</para>
/// </summary>
public uint luid;
}
}
}