using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Runtime.InteropServices;

namespace System
{
/// <summary>
/// Interface to dWinlock core functions,
/// for further information see also dWinlock Programmer's Reference
/// </summary>

	#region implementation of dWinlock core class
	[ToolboxItemAttribute(false)]
	public class dwlcore : Component
	{
	  public const int WM_KEYDOWN       = 0x400 + 200;
	  public const int WM_KEYUP         = 0x400 + 201;
	  public const int MOD_ALT          = 1;
	  public const int MOD_CONTROL      = 2;
	  public const int MOD_SHIFT        = 4;
	  public const int MOD_WIN          = 8;
	  public const int MOD_ALL          = 255;

	  // Constants for disable Desktop items, see also method DisableItem
	  public const int wlTaskBar        = 1;
	  public const int wlDesktop        = 2;
	  public const int wlStartbutton    = 3;
	  public const int wlTaskLinks      = 4;
	  public const int wlTaskTray       = 5;
	  public const int wlTaskRebar      = 6;
	  public const int wlAccessibility  = 7;
	  public const int wlAccHighContrast = 8;
	  public const int wlAccFilterKeys   = 9;
	  public const int wlAccMouseKey     = 10;
	  public const int wlAccStickyKeys   = 11;
	  public const int wlAccToggleKeys   = 12;
	  public const int wlShutdown        = 13;

	  // dwlGinaInstallFlags to use with wlInstallGina and wlUninstallGina
	  public const int giForceInstall   = 1;
	  public const int giForceUninstall = 2;
	  public const int giForceReboot    = 4;
	  public const int giNoReboot       = 8;
	  public const int giNoWarnings     =16;

	  // constants to use with method WinVersion
	  public const int vWinunknown      = 1;
	  public const int vWin95           = 2;
	  public const int vWin98           = 3;
	  public const int vWinMe           = 4;
	  public const int vWinNT           = 5;
	  public const int vWin2000         = 6;
	  public const int vWinXP           = 7;

	  // constants to use with SetKeyCallback
	  public const int kDownEvents      = 1;
	  public const int kUpEvents        = 2;
    
	  private static dwlWindow EventWnd = null;

	  // name of dWinlock gina dll
	  private const string dwldll = "dwlgina3.dll";

	[DllImport(dwldll, EntryPoint = "wlDisableItem")]
	public static extern void wlDisableItem(int Item, int disable);

	[DllImport(dwldll, EntryPoint = "wlIsItemDisabled")]
	public static extern int wlIsItemDisabled(int Item);

	[DllImport(dwldll, EntryPoint = "wlDisableKey")]
	public static extern int wlDisableKey(int window, int vk, int mf, int disable);

	[DllImport(dwldll, EntryPoint = "wlIsKeyDisabled")]
	public static extern int wlIsKeyDisabled(int window, int vk, int mf);

	[DllImport(dwldll, EntryPoint = "wlSetKeySendMessage")]
	public static extern void wlSetKeySendMessage(int window, int KeyDownMessageID, int KeyUpMessageID);

	[DllImport(dwldll, EntryPoint = "wlSetKeyPostMessage")]
	public static extern void wlSetKeyPostMessage(int window, int KeyDownMessageID, int KeyUpMessageID);

	[DllImport(dwldll, EntryPoint = "wlGetDisabledKey")]
	public static extern int wlGetDisabledKey(int index, ref int window, ref int vk, ref int mf, ref int vkout, ref int mfout);

	[DllImport(dwldll, EntryPoint = "wlInstallDwl")]
	public static extern int wlInstallDwl(int Flags);

	[DllImport(dwldll, EntryPoint = "wlUninstallDwl")]
	public static extern int wlUninstallDwl(int Flags);

	[DllImport(dwldll, EntryPoint = "wlIsDwlInstalled")]
	public static extern int wlIsDwlInstalled();

	[DllImport(dwldll, EntryPoint = "wlIsNTSystem")]
	public static extern int wlIsNTSystem();

	[DllImport(dwldll, EntryPoint = "wlNeedDwlInstall")]
	public static extern int wlNeedDwlInstall();

	[DllImport(dwldll, EntryPoint = "wlExitWindows")]
	public static extern int wlExitWindows(int Flags);

	[DllImport(dwldll, EntryPoint = "wlWinVersion")]
	public static extern int wlWinVersion();

	[DllImport(dwldll, EntryPoint = "wlVersion")]
	public static extern int wlVersion(int RequestedVersion);

	[DllImport(dwldll, EntryPoint = "wlGetKeyState")]
	public static extern int wlGetKeyState(int vk);

	[DllImport(dwldll, EntryPoint = "wlSetKeyState")]
	public static extern void wlSetKeyState(int vk, int TurnOn);

	[DllImport(dwldll, EntryPoint = "wlRestoreAll")]
	public static extern void wlRestoreAll();

	[DllImport(dwldll, EntryPoint = "wlEnableAutologin")]
	public static extern int wlEnableAutologin(string defUser, string pass, int enable, string domain);

	[DllImport(dwldll, EntryPoint = "wlWriteReg")]
	public static extern int wlWriteReg(int Key, string SubKey, string Item, string Value);

	[DllImport(dwldll, EntryPoint = "wlMapScancode")]
	public static extern int wlMapScancode(int InputCode, int OutputCode);

	[DllImport(dwldll, EntryPoint = "wlDisableDesktopIcon")]
	public static extern void wlDisableDesktopIcon(int index);

	[DllImport(dwldll, EntryPoint = "wlDesktopIconCount")]
	public static extern int wlDesktopIconCount();

	[DllImport(dwldll, EntryPoint = "wlRestoreDesktopIcons")]
	public static extern void wlRestoreDesktopIcons();

	[DllImport(dwldll, EntryPoint = "wlExit")]
	public static extern void wlExit();

	[DllImport(dwldll, EntryPoint = "wlIsAdmin")]
	public static extern bool wlIsAdmin();

	[DllImport(dwldll, EntryPoint = "wlIsKeyReplaced")]
	public static extern int wlIsKeyReplaced(int window, int vk, int mf);

	[DllImport(dwldll, EntryPoint = "wlReplaceKey")]
	public static extern int wlReplaceKey(int Window, int vk, int mf, int vkout, int mfout);

	[DllImport(dwldll, EntryPoint = "wlGetDisabledMessage")]
	public static extern int wlGetDisabledMessage(int i, ref int window, ref int msgId);

	[DllImport(dwldll, EntryPoint = "wlIsMessageDisabled")]
	public static extern int wlIsMessageDisabled(int window, int msgId);

	[DllImport(dwldll, EntryPoint = "wlDisableMessage")]
	public static extern int wlDisableMessage(int window, int msgId, int disable);

	[DllImport(dwldll, EntryPoint = "wlDisableMouseArea")]
	public static extern int wlDisableMouseArea(int window, int MouseButton, int mf, int x, int y, int h, int w, int id, int disable);

	[DllImport(dwldll, EntryPoint = "wlGetItemHandle")]
	public static extern int wlGetItemHandle(int Item);

	[DllImport(dwldll, EntryPoint = "wlSetStartMenu")]
	public static extern int wlSetStartMenu(int window);

	[DllImport(dwldll, EntryPoint = "wlStrToVk")]
	public static extern void wlStrToVk(string keyStr, string window, int maxCount, ref int vk, ref int mf);

	[DllImport(dwldll, EntryPoint = "wlVkToStr")]
	public static extern void _wlVkToStr(string window, int VK, int MF, StringBuilder KeyStr, int MaxCount);

	[DllImport(dwldll, EntryPoint = "wlSendKeyDown")]
	public static extern void wlSendKeyDown(ushort vk, int mf);

	[DllImport(dwldll, EntryPoint = "wlSendKeyUp")]
	public static extern void wlSendKeyUp(ushort vk, int mf);

	public static void wlVkToStr(string window, int VK, int MF, ref string KeyStr)
	{
		StringBuilder K = new StringBuilder(255);
		_wlVkToStr(window, VK, MF, K, 255);
		KeyStr = K.ToString();
	}

   [DllImport("user32.dll", EntryPoint = "FindWindowExA")]
   private static extern int FindWindowEx(int Parent, int Child, string Classname, string WindowName);

   public static int FindWindowByClassName(int parentwnd, string classname)
   {
	 return FindWindowEx(parentwnd,0,classname,null);
   }

   private class dwlWindow : NativeWindow {

   public dwlOnKeyCallBack Callback;
   private dwlWindow() { }  // Hide the 'empty' constructor
   private Form Parent;

   public dwlWindow(Form parent, dwlOnKeyCallBack callback) {
	if (parent == null)
	  base.CreateHandle(new CreateParams());
	else
	  base.AssignHandle(parent.Handle);
	Parent = parent;
	Callback = callback;
   }

   public short LoWord(int number) {
	return unchecked((short) (number & 0xFFFF));
   }

   public short HiWord(int number) {
	return (short) (number >> 16);
   }

   private void CallCallback(int down,Message m)
   {
	  int Wnd = m.WParam.ToInt32();
	  int Key = LoWord(m.LParam.ToInt32());
	  int Shift = HiWord(m.LParam.ToInt32());
	  if (Callback != null )
		Callback(0,Wnd,down,Key,Shift);
   }

   [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
   protected override void WndProc(ref Message m)
	{
	  try {
		   switch (m.Msg){
			 case dwl.WM_KEYDOWN: CallCallback(1,m); break;
			 case dwl.WM_KEYUP  : CallCallback(0,m); break;
		   }
		  base.WndProc(ref m);
		 }
		 catch {} // Just ignore it for now...
	  }
	 }

   public static int SetKeyCallback (dwlOnKeyCallBack Callback,int userdata, int Flags)
   {
	  int KDown = 0;
	  int KUp   = 0;
	  if ((Flags & kDownEvents ) > 0) KDown = dwl.WM_KEYDOWN;
	  if ((Flags & kUpEvents ) > 0)   KUp = dwl.WM_KEYUP;
	  if (EventWnd == null)
		EventWnd = new dwlWindow(null,Callback);
	  if (EventWnd != null)
	  {
		wlSetKeyPostMessage((int) EventWnd.Handle,KDown,KUp);
		return 1;
	  } else return 0;

   }
   }

 #endregion

	#region implementation of dWinlock dwl class
	 public class dwlMouseEventArgs : EventArgs
	{
      private MouseButtons fButton;
      private int fWnd;
      private Keys fModifiers;
      public dwlMouseEventArgs(int aWnd, int Buttons, Keys aModifiers)
      {
       fButton = 0;
	     fWnd    = aWnd;
       fModifiers = aModifiers;
       if (Buttons == 1 ) fButton = MouseButtons.Left;
       if (Buttons == 2 ) fButton = MouseButtons.Right;
       if (Buttons == 4 ) fButton = MouseButtons.Middle;
     }

     public int Wnd {get{return fWnd;}}
     public MouseButtons Button {get{ return fButton;}}
     public Keys Modifiers {get{return fModifiers;}}
    }


    public class dwlKeyEventArgs : EventArgs
    {
     private int  fWnd;
     private Keys fKeyCode;
     private Keys fModifiers;

     public dwlKeyEventArgs(int aWnd, Keys aKeyCode, Keys aModifiers)
     {
       fWnd = aWnd;
       fKeyCode = aKeyCode;
       fModifiers = aModifiers;
     }
     public int Wnd {get{return fWnd;}}
     public Keys KeyCode {get{return fKeyCode;}}
     public Keys Modifiers {get{return fModifiers;}}
    }

    public delegate void dwlKeyEventHandler( object sender, dwlKeyEventArgs e);
    public delegate void dwlMouseEventHandler( object sender, dwlMouseEventArgs e);
    public delegate void dwlOnKeyCallBack(int userdata, int hwnd, int Down, int Key, int Shift);


  [Category("Component"),
  ToolboxItemAttribute(true),
	ToolboxBitmap(typeof(dwl),"dwl.bmp"),
	Description("dWinlock component "),
	DefaultEvent ("KeyDown")]

	public class dwl : dwlcore
	{
	    public const Keys ModAll = (Keys) 255;
	    private int KeyDownCount = 0;
      private int KeyUpCount = 0;
      private int MouseDownCount = 0;
      private int MouseUpCount = 0;

      private dwlKeyEventHandler evKeyDown;
      private dwlKeyEventHandler evKeyUp;
	    private dwlMouseEventHandler evMouseDown;
      private dwlMouseEventHandler evMouseUp;

      private dwlOnKeyCallBack KeyCallBack;
      

      public dwl()
      {
         KeyCallBack = new dwlOnKeyCallBack(OnKeyEvent);
      }

       public string Version
      {
        get { return "3.20"; }
      }

      public static int KeysToMF(Keys Key)
      {
        int mf = 0;
        if (Key == ModAll) 
           mf = MOD_ALL;
        else
        {
          if ((Key & Keys.Alt) > 0)     mf |= MOD_ALT;
          if ((Key & Keys.Control) > 0) mf |= MOD_CONTROL;
          if ((Key & Keys.Shift) > 0)   mf |= MOD_SHIFT;
          if (((Key & Keys.LWin) > 0) ||
             ((Key & Keys.RWin) > 0))    mf |= MOD_WIN;
        }
        return mf;
      }

      public static Keys MFToKeys(int mf)
      {
          Keys k = (Keys) mf;
          if ( mf == MOD_ALL)
            k = ModAll;
          else
          {
            if ( (mf & MOD_ALT) > 0)     k |= Keys.Alt;
            if ( (mf & MOD_CONTROL) > 0) k |= Keys.Control;
            if ( (mf & MOD_SHIFT) > 0)   k |= Keys.Shift;
            if ( (mf & MOD_WIN) > 0)     k |= Keys.RWin;
          }
          return k;
      }


      public static void DisableKey(int Wnd, Keys Key, Keys Modifier, bool disable)
      {
        int mf =  KeysToMF(Modifier);
        if (disable)
          dwlcore.wlDisableKey(Wnd,(int) Key, mf,1);
        else
          dwlcore.wlDisableKey(Wnd, (int)Key, mf, 0);
      }

      private void OnKeyEvent(int userdata, int hwnd, int down, int vk, int mf)
      {
          Keys k = (Keys) vk;
          Keys modifiers = 0;
		  if ( (mf & MOD_ALT) > 0)     modifiers |= Keys.Alt;
          if ( (mf & MOD_CONTROL) > 0) modifiers |= Keys.Control;
          if ( (mf & MOD_SHIFT) > 0)   modifiers |= Keys.Shift;
          if ( (mf & MOD_WIN) > 0)     modifiers |= Keys.RWin;

          if (down == 1)
          {
            if (vk == 1 || vk == 2 || vk == 4)  // then it's a mouse button
            {
              dwlMouseEventArgs e = new dwlMouseEventArgs(hwnd,vk,modifiers);
              evMouseDown(this,e);
            }
            else
            {
              dwlKeyEventArgs e = new dwlKeyEventArgs(hwnd,k,modifiers);
              evKeyDown(this,e);
            }
          }
          else
          {
            if (vk == 1 || vk == 2 || vk == 4)  // then it's a mouse button
            {
              dwlMouseEventArgs e = new dwlMouseEventArgs(hwnd,vk,modifiers);
              evMouseUp(this,e);
            }
            else
            {
              dwlKeyEventArgs e = new dwlKeyEventArgs(hwnd,k,modifiers);
              evKeyUp(this,e);
            }
          }
      }

      protected virtual void SetKeyEvent()
      {
        int Flags = 0;
        if (DesignMode) return;
        if (KeyDownCount > 0)   Flags |= kDownEvents;
        if (KeyUpCount > 0)     Flags |= kUpEvents;
        if (MouseDownCount > 0) Flags |= kDownEvents;
        if (MouseUpCount > 0)   Flags |= kUpEvents;
        if (Flags > 0)
          SetKeyCallback(KeyCallBack,0,Flags);
		else
          SetKeyCallback(null,0,0);  // no key and mouse events
      }

      [Category("Key"),
      Description("System wide key down event.")]
      public event dwlKeyEventHandler KeyDown
	  {
        add{ KeyDownCount++;
             evKeyDown += value;
             SetKeyEvent();
           }
        remove {KeyDownCount--;
                evKeyDown -= value;
                SetKeyEvent(); }
        }

        [Category("Key"),
        Description("System wide key up event.")
        ]
        public event dwlKeyEventHandler KeyUp
        {
          add{ KeyUpCount++;
               evKeyUp += value;
               SetKeyEvent();}
          remove {KeyUpCount--;
                  SetKeyEvent();
                  evKeyUp -= value; }
        }
        [Category("Mouse"),
        Description("System wide mouse down event.")]
        public event dwlMouseEventHandler MouseDown
        {
            add{ MouseDownCount++;
                 evMouseDown += value;
                 SetKeyEvent();
               }
            remove {KeyDownCount--;
                    evMouseDown -= value;
                   SetKeyEvent(); }
        }

        [Category("Mouse"),
        Description("System wide mouse up event.")
        ]
        public event dwlMouseEventHandler MouseUp
        {
            add{    MouseUpCount++;
                    evMouseUp += value;
                    SetKeyEvent(); }
			remove { MouseUpCount--;
                     SetKeyEvent();
                     evMouseUp -= value; }
        }
    }
    #endregion
}

