//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// WFX satellite library | Author: Sergei Y.Kitáev
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.ComponentModel;

using WF = System.Windows.Forms;

using CommonHelpers;

namespace WFX {

//**************************************************************************************************
/// <summary>
/// </summary>
public static partial class MessageHelpers {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[CLSCompliant(false)]
public const uint
   PM_NOREMOVE          = 0x0000,
   PM_REMOVE            = 0x0001,
   PM_NOYIELD           = 0x0002,

   WM_CLOSE             = Win32.WM_CLOSE,
   WM_TIMER             = 0x0113,

   WM_MOUSEMOVE         = 0x0200,
   WM_LBUTTONDOWN       = 0x0201,
   WM_LBUTTONUP         = 0x0202,
   WM_LBUTTONDBLCLK     = 0x0203,
   WM_RBUTTONDOWN       = 0x0204,
   WM_RBUTTONUP         = 0x0205,
   WM_RBUTTONDBLCLK     = 0x0206,
   WM_MBUTTONDOWN       = 0x0207,
   WM_MBUTTONUP         = 0x0208,
   WM_MBUTTONDBLCLK     = 0x0209,
   WM_MOUSEWHEEL        = 0x020A,

   WM_NCMOUSEMOVE       = 0x00A0,
   WM_NCMBUTTONDBLCLK   = 0x00A9,
   WM_NCXBUTTONDOWN     = 0x00AB,
   WM_NCXBUTTONDBLCLK   = 0x00AD,
   WM_NCMOUSEHOVER      = 0x02A0,
   WM_NCMOUSELEAVE      = 0x02A2,

   WM_KEYDOWN           = 0x0100,
   WM_KEYUP             = 0x0101,
   WM_CHAR              = 0x0102,
   WM_DEADCHAR          = 0x0103,
   WM_SYSKEYDOWN        = 0x0104,
   WM_SYSKEYUP          = 0x0105,
   WM_SYSCHAR           = 0x0106,
   WM_SYSDEADCHAR       = 0x0107;

//==================================================================================================

public static Int32 GetMessage( out WF.Message message, IntPtr hWnd,
                                int wMsgFilterMin, int wMsgFilterMax )
{
   return GetMessage( out message, hWnd,
      unchecked( (uint)wMsgFilterMin ),
      unchecked( (uint)wMsgFilterMax ) );
}

public static bool PeekMessage( out WF.Message message, IntPtr hWnd,
                                int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg )
{
   return PeekMessage( out message, hWnd,
      unchecked( (uint)wMsgFilterMin ),
      unchecked( (uint)wMsgFilterMax ),
      unchecked( (uint)wRemoveMsg ) );
}

//--------------------------------------------------------------------------------------------------

[CLSCompliant(false)]
public static Int32 GetMessage( out WF.Message message, IntPtr hWnd,
                                uint wMsgFilterMin, uint wMsgFilterMax )
{
   return Win32.GetMessage( out message, hWnd, wMsgFilterMin, wMsgFilterMax );
}

[CLSCompliant(false)]
public static bool PeekMessage( out WF.Message message, IntPtr hWnd,
                                uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg )
{
   return Win32.PeekMessage( out message, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg );
}

//--------------------------------------------------------------------------------------------------

public static bool TranslateMessage(WF.Message message)
{
   return Win32.TranslateMessage(ref message);
}

public static IntPtr DispatchMessage(WF.Message message)
{
   return Win32.DispatchMessage(ref message);
}

//--------------------------------------------------------------------------------------------------

/// <exception cref="Win32Exception" />
public static void WaitMessage()
{
   if ( !Win32.WaitMessage() )
      throw HWin32Error.CreateExceptionFromLastError();
}

//==================================================================================================

public static void ProcessMessageQueueWithoutUIAccessAndClose()
{
   ProcessMessageQueueWithoutUIAccess
   (
      filterTimerMessage: true,
      filterCloseMessage: true
   );
}

//==================================================================================================

internal static void ProcessMessageQueueWithoutUIAccess( bool filterTimerMessage,
                                                         bool filterCloseMessage )
{
   HProgram.VerifyInMainThread();
   WF.Message message;
   while ( PeekMessage( out message, IntPtr.Zero, 0, 0, PM_REMOVE ) )
   {
      if (!( message.Msg == WM_CLOSE && filterCloseMessage ||
             Input.IsInputMessage( message.Msg ) ))
         try
         {
            AppMessageFilter.FilterTimerMessage = filterTimerMessage;
            DispatchMessage( message );
         }
         finally
         {
            AppMessageFilter.FilterTimerMessage = false;
         }
   }
   Cursor.UpdateWaitCursor( false );
}

//==================================================================================================

static MessageHelpers()
{
   WFX_Library.Access();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // MessageHelpers
//**************************************************************************************************

} // WFX
