{-----------------------------------------------------------------------------
This Software is placed into Publlic Domain and distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied.
The Initial Developer is Martin Waldenburg
(Martin.Waldenburg@T-Online.de).
-----------------------------------------------------------------------------}
unit mwCommandProcessor;

interface

uses
  System.Drawing, System.Collections, System.ComponentModel,
  System.Windows.Forms, System.Data, System.Text;

type
  TmwCommand = class
  private
    fKey: string;
  public
    constructor Create(aKey: string);
    procedure Execute(Sender: TObject); virtual;
    function GetHashCode: Integer; override;
    property Key: string read fKey write fKey;
  end;

  TmwEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; EA: EventArgs); reintroduce; virtual;
  end;

  TmwControlEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; EA: ControlEventArgs); reintroduce; virtual;
  end;

  TmwDrawItemEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; DIEA: DrawItemEventArgs); reintroduce; virtual;
  end;

  TmwDragEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; DEA: DragEventArgs); reintroduce; virtual;
  end;

  TmwGiveFeedbackEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; GFEA: GiveFeedbackEventArgs); reintroduce; virtual;
  end;

  TmwInvalidateEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; IEA: InvalidateEventArgs); reintroduce; virtual;
  end;

  TmwKeyEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; KEA: KeyEventArgs); reintroduce; virtual;
  end;

  TmwKeyPressEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; KPEA: KeyPressEventArgs); reintroduce; virtual;
  end;

  TmwLayoutEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; LEA: LayoutEventArgs); reintroduce; virtual;
  end;

  TmwLinkClickedEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; LCEA: LinkClickedEventArgs); reintroduce; virtual;
  end;

  TmwMouseEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; MEA: MouseEventArgs); reintroduce; virtual;
  end;

  TmwPaintEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; PEA: PaintEventArgs); reintroduce; virtual;
  end;

  TmwQueryContinueDragEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; QCDEA: QueryContinueDragEventArgs); reintroduce; virtual;
  end;

  TmwScrollEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; SEA: ScrollEventArgs); reintroduce; virtual;
  end;

  TmwUICuesEventArgsCommand = class(TmwCommand)
  public
    procedure Execute(Sender: TObject; UICEA: UICuesEventArgs); reintroduce; virtual;
  end;

  TmwCommandProcessor = class(System.ComponentModel.Component)
    strict protected
      CommandTable: Hashtable;
    CommandStringBuffer: StringBuilder;
    ModifierStringBuffer: StringBuilder;
    LastModifierKeyValue: Integer;
    ModifierState: set of (msAlt, msCtrl, msShift);
    procedure InitializeCommandProcessor; virtual;
    procedure Dispose(Disposing: Boolean); override;
    procedure RemoveFromModifierString(Value: string);
    function KeyToString(e: KeyEventArgs): string;
    function CommandString: string;
  private
    fMouseEnterHandler: TmwEventArgsCommand;
    fMouseHoverHandler: TmwEventArgsCommand;
    fMouseLeaveHandler: TmwEventArgsCommand;
    fKeyUpHandler: TmwKeyEventArgsCommand;
    fKeyDownHandler: TmwKeyEventArgsCommand;
    fKeyPressHandler: TmwKeyPressEventArgsCommand;
    fLayoutHandler: TmwLayoutEventArgsCommand;
    fMouseDownHandler: TmwMouseEventArgsCommand;
    fMouseMoveHandler: TmwMouseEventArgsCommand;
    fMouseUpHandler: TmwMouseEventArgsCommand;
    fMouseWheelHandler: TmwMouseEventArgsCommand;
    fHScrollHandler: TmwEventArgsCommand;
    fVScrollHandler: TmwEventArgsCommand;
    function AddToCommandStringBuffer(e: KeyEventArgs): Boolean;
    procedure set_KeyDownHandler(const Value: TmwKeyEventArgsCommand);
    procedure set_KeyPressHandler(const Value: TmwKeyPressEventArgsCommand);
    procedure set_KeyUpHandler(const Value: TmwKeyEventArgsCommand);
    procedure set_LayoutHandler(const Value: TmwLayoutEventArgsCommand);
    procedure set_MouseDownHandler(const Value: TmwMouseEventArgsCommand);
    procedure set_MouseEnterHandler(const Value: TmwEventArgsCommand);
    procedure set_MouseHoverHandler(const Value: TmwEventArgsCommand);
    procedure set_MouseLeaveHandler(const Value: TmwEventArgsCommand);
    procedure set_MouseWheelHandler(const Value: TmwMouseEventArgsCommand);
    procedure set_MouseMoveHandler(const Value: TmwMouseEventArgsCommand);
    procedure set_MouseUpHandler(const Value: TmwMouseEventArgsCommand);
    procedure set_HScrollHandler(const Value: TmwEventArgsCommand);
    procedure set_VScrollHandler(const Value: TmwEventArgsCommand);
  public
    constructor Create;
    procedure AddCommand(aCommand: TmwCommand);
    procedure Clear; virtual;
    procedure ExecuteCommand(Sender: TObject; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; EA: EventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; CEA: ControlEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; DEA: DragEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; DIEA: DrawItemEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; GFEA: GiveFeedbackEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; IEA: InvalidateEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; KEA: KeyEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; KPEA: KeyPressEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; LEA: LayoutEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; LCEA: LinkClickedEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; MEA: MouseEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; PEA: PaintEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; QCDEA: QueryContinueDragEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; SEA: ScrollEventArgs; const CommandKey: string); overload;
    procedure ExecuteCommand(Sender: TObject; UICEA: UICuesEventArgs; const CommandKey: string); overload;
    procedure OnHScroll(Sender: TObject; SE: ScrollEventArgs); virtual;
    procedure OnKeyDown(Sender: TObject; KEA: KeyEventArgs); overload; virtual;
    procedure OnKeyPress(Sender: TObject; KPEA: KeyPressEventArgs); overload; virtual;
    procedure OnKeyUp(Sender: TObject; KEA: KeyEventArgs); overload; virtual;
    procedure OnLayout(Sender: TObject; LEA: LayoutEventArgs); overload; virtual;
    procedure OnMouseDown(Sender: TObject; MEA: MouseEventArgs); overload; virtual;
    procedure OnMouseEnter(Sender: TObject; EA: EventArgs); overload; virtual;
    procedure OnMouseHover(Sender: TObject; EA: EventArgs); overload; virtual;
    procedure OnMouseLeave(Sender: TObject; EA: EventArgs); overload; virtual;
    procedure OnMouseMove(Sender: TObject; MEA: MouseEventArgs); overload; virtual;
    procedure OnMouseUp(Sender: TObject; MEA: MouseEventArgs); overload; virtual;
    procedure OnMouseWheel(Sender: TObject; MEA: MouseEventArgs); overload; virtual;
    procedure OnVScroll(Sender: TObject; SE: ScrollEventArgs); virtual;
  published
    property OnHScrollHandler: TmwEventArgsCommand read fHScrollHandler write set_HScrollHandler;
    property OnKeyDownHandler: TmwKeyEventArgsCommand read fKeyDownHandler write set_KeyDownHandler;
    property OnKeyPressHandler: TmwKeyPressEventArgsCommand read fKeyPressHandler write set_KeyPressHandler;
    property OnKeyUpHandler: TmwKeyEventArgsCommand read fKeyUpHandler write set_KeyUpHandler;
    property OnLayoutHandler: TmwLayoutEventArgsCommand read fLayoutHandler write set_LayoutHandler;
    property OnMouseDownHandler: TmwMouseEventArgsCommand read fMouseDownHandler write set_MouseDownHandler;
    property OnMouseEnterHandler: TmwEventArgsCommand read fMouseEnterHandler write set_MouseEnterHandler;
    property OnMouseHoverHandler: TmwEventArgsCommand read fMouseHoverHandler write set_MouseHoverHandler;
    property OnMouseLeaveHandler: TmwEventArgsCommand read fMouseLeaveHandler write set_MouseLeaveHandler;
    property OnMouseMoveHandler: TmwMouseEventArgsCommand read fMouseMoveHandler write set_MouseMoveHandler;
    property OnMouseUpHandler: TmwMouseEventArgsCommand read fMouseUpHandler write set_MouseUpHandler;
    property OnMouseWheelHandler: TmwMouseEventArgsCommand read fMouseWheelHandler write set_MouseWheelHandler;
    property OnVScrollHandler: TmwEventArgsCommand read fVScrollHandler write set_VScrollHandler;
  end;

implementation

uses
  System.Globalization;

{ TmwCommand }

constructor TmwCommand.Create(aKey: string);
begin
  inherited Create;
  fKey := aKey;
end;

procedure TmwCommand.Execute(Sender: TObject);
begin
  // do nothing;
end;

function TmwCommand.GetHashCode: Integer;
begin
  Result := 0;
  if fKey <> '' then
    Result := fKey.GetHashCode;
end;

{ TmwEventArgsCommand }

procedure TmwEventArgsCommand.Execute(Sender: TObject; EA: EventArgs);
begin
  // do nothing;
end;

{ TmwControlEventArgsCommand }

procedure TmwControlEventArgsCommand.Execute(Sender: TObject;
  EA: ControlEventArgs);
begin
  // do nothing;
end;

{ TmwDragEventArgsCommand }

procedure TmwDragEventArgsCommand.Execute(Sender: TObject;
  DEA: DragEventArgs);
begin
  // do nothing;
end;

{ TmwDrawItemEventArgsCommand }

procedure TmwDrawItemEventArgsCommand.Execute(Sender: TObject;
  DIEA: DrawItemEventArgs);
begin
  // do nothing;
end;

{ TmwGiveFeedbackEventArgsCommand }

procedure TmwGiveFeedbackEventArgsCommand.Execute(Sender: TObject;
  GFEA: GiveFeedbackEventArgs);
begin
  // do nothing;
end;

{ TmwInvalidateEventArgsCommand }

procedure TmwInvalidateEventArgsCommand.Execute(Sender: TObject;
  IEA: InvalidateEventArgs);
begin
  // do nothing;
end;

{ TmwKeyEventArgsCommand }

procedure TmwKeyEventArgsCommand.Execute(Sender: TObject; KEA: KeyEventArgs);
begin
  // do nothing;
end;

{ TmwKeyPressEventArgsCommand }

procedure TmwKeyPressEventArgsCommand.Execute(Sender: TObject;
  KPEA: KeyPressEventArgs);
begin
  // do nothing;
end;

{ TmwLayoutEventArgsCommand }

procedure TmwLayoutEventArgsCommand.Execute(Sender: TObject;
  LEA: LayoutEventArgs);
begin
  // do nothing;
end;

{ TmwLinkClickedEventArgsCommand }

procedure TmwLinkClickedEventArgsCommand.Execute(Sender: TObject;
  LCEA: LinkClickedEventArgs);
begin
  // do nothing;
end;

{ TmwMouseEventArgsCommand }

procedure TmwMouseEventArgsCommand.Execute(Sender: TObject;
  MEA: MouseEventArgs);
begin
  // do nothing;
end;

{ TmwPaintEventArgsCommand }

procedure TmwPaintEventArgsCommand.Execute(Sender: TObject;
  PEA: PaintEventArgs);
begin
  // do nothing;
end;

{ TmwQueryContinueDragEventArgsCommand }

procedure TmwQueryContinueDragEventArgsCommand.Execute(Sender: TObject;
  QCDEA: QueryContinueDragEventArgs);
begin
  // do nothing;
end;

{ TmwScrollEventArgsCommand }

procedure TmwScrollEventArgsCommand.Execute(Sender: TObject;
  SEA: ScrollEventArgs);
begin
  // do nothing;
end;

{ TmwUICuesEventArgsCommand }

procedure TmwUICuesEventArgsCommand.Execute(Sender: TObject;
  UICEA: UICuesEventArgs);
begin
  // do nothing;
end;

/// <summary>
/// </summary>

procedure TmwCommandProcessor.AddCommand(aCommand: TmwCommand);
begin
  CommandTable.Add(aCommand.Key.ToUpper, aCommand);
end;

function TmwCommandProcessor.AddToCommandStringBuffer(e: KeyEventArgs): Boolean;
begin
  Result := LastModifierKeyValue <> e.KeyValue;
  case e.Modifiers of
    Keys.Alt:
      begin
        case msAlt in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Alt');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        ModifierState := [msAlt];
      end;
    Keys.Control:
      begin
        case msCtrl in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Control');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        ModifierState := [msCtrl];
      end;
    Keys.Shift:
      begin
        case msShift in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Shift');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        ModifierState := [msShift];
      end;
    (Keys.Alt or Keys.Control):
      begin
        case msAlt in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Alt');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        case msCtrl in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Control');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        ModifierState := [msAlt, msCtrl];
      end;
    (Keys.Alt or Keys.Shift):
      begin
        case msAlt in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Alt');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        case msShift in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Shift');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        ModifierState := [msAlt, msShift];
      end;
    (Keys.Control or Keys.Shift):
      begin
        case msCtrl in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Control');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        case msShift in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Shift');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        ModifierState := [msCtrl, msShift];
      end;
    (Keys.Alt or Keys.Control or Keys.Shift):
      begin
        case msAlt in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Alt');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        case msCtrl in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Control');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        case msShift in ModifierState of
          False:
            begin
              ModifierStringBuffer.Append('Shift');
              LastModifierKeyValue := e.KeyValue;
              Result := False;
            end;
        end;
        ModifierState := [msAlt, msCtrl, msShift];
      end;
  else
    begin
      ModifierState := [];
      LastModifierKeyValue := 0;
      CommandStringBuffer.set_Length(0);
    end;
  end;
  if Result then
    CommandStringBuffer.Append(KeyToString(e));
end;

procedure TmwCommandProcessor.Clear;
begin
  CommandTable.Clear;
end;

function TmwCommandProcessor.CommandString: string;
begin
  Result:= ModifierStringBuffer.ToString + CommandStringBuffer.ToString;
end;

constructor TmwCommandProcessor.Create;
begin
  inherited Create;
  CommandTable := Hashtable.Create;
  CommandStringBuffer := StringBuilder.Create;
  ModifierStringBuffer := StringBuilder.Create;
  InitializeCommandProcessor;
end;

procedure TmwCommandProcessor.Dispose(Disposing: Boolean);
begin
  if Disposing then
  begin
    CommandTable.Finalize;
    CommandStringBuffer.Finalize;
    ModifierStringBuffer.Finalize;
  end;
  inherited Dispose(Disposing);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwCommand) then
    aCommand.Execute(Sender);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; EA: EventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwEventArgsCommand) then
    TmwEventArgsCommand(aCommand).Execute(Sender, EA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; CEA: ControlEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwControlEventArgsCommand) then
    TmwControlEventArgsCommand(aCommand).Execute(Sender, CEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; DEA: DragEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwDragEventArgsCommand) then
    TmwDragEventArgsCommand(aCommand).Execute(Sender, DEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; DIEA: DrawItemEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwDrawItemEventArgsCommand) then
    TmwDrawItemEventArgsCommand(aCommand).Execute(Sender, DIEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; GFEA: GiveFeedbackEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwGiveFeedbackEventArgsCommand) then
    TmwGiveFeedbackEventArgsCommand(aCommand).Execute(Sender, GFEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; IEA: InvalidateEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwInvalidateEventArgsCommand) then
    TmwInvalidateEventArgsCommand(aCommand).Execute(Sender, IEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; KEA: KeyEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwKeyEventArgsCommand) then
    TmwKeyEventArgsCommand(aCommand).Execute(Sender, KEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; KPEA: KeyPressEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwKeyPressEventArgsCommand) then
    TmwKeyPressEventArgsCommand(aCommand).Execute(Sender, KPEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; LEA: LayoutEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwLayoutEventArgsCommand) then
    TmwLayoutEventArgsCommand(aCommand).Execute(Sender, LEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; LCEA: LinkClickedEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwLinkClickedEventArgsCommand) then
    TmwLinkClickedEventArgsCommand(aCommand).Execute(Sender, LCEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; MEA: MouseEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwMouseEventArgsCommand) then
    TmwMouseEventArgsCommand(aCommand).Execute(Sender, MEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; PEA: PaintEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwPaintEventArgsCommand) then
    TmwPaintEventArgsCommand(aCommand).Execute(Sender, PEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; QCDEA: QueryContinueDragEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwQueryContinueDragEventArgsCommand) then
    TmwQueryContinueDragEventArgsCommand(aCommand).Execute(Sender, QCDEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; SEA: ScrollEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwScrollEventArgsCommand) then
    TmwScrollEventArgsCommand(aCommand).Execute(Sender, SEA);
end;

procedure TmwCommandProcessor.ExecuteCommand(Sender: TObject; UICEA: UICuesEventArgs; const CommandKey: string);
var
  aCommand: TmwCommand;
begin
  aCommand := TmwCommand(CommandTable[CommandKey.ToUpper]);
  if (aCommand <> nil) and (aCommand is TmwUICuesEventArgsCommand) then
    TmwUICuesEventArgsCommand(aCommand).Execute(Sender, UICEA);
end;

procedure TmwCommandProcessor.InitializeCommandProcessor;
begin
  //
end;

function TmwCommandProcessor.KeyToString(e: KeyEventArgs): string;
begin
  Result := '';
  case e.KeyCode of
    Keys.A: Result := 'A';
    Keys.Add: Result := 'Add';
    Keys.Alt: Result := 'Alt';
    Keys.Apps: Result := 'Apps';
    Keys.Attn: Result := 'Attn';
    Keys.B: Result := 'B';
    Keys.Back: Result := 'Back';
    Keys.BrowserBack: Result := 'BrowserBack';
    Keys.BrowserFavorites: Result := 'BrowserFavorites';
    Keys.BrowserForward: Result := 'BrowserForward';
    Keys.BrowserHome: Result := 'BrowserHome';
    Keys.BrowserRefresh: Result := 'BrowserRefresh';
    Keys.BrowserSearch: Result := 'BrowserSearch';
    Keys.BrowserStop: Result := 'BrowserStop';
    Keys.C: Result := 'C';
    Keys.Cancel: Result := 'Cancel';
// Keys.Capital: Result:= 'Capital';
    Keys.CapsLock: Result := 'CapsLock';
    Keys.Clear: Result := 'Clear';
    Keys.Control: Result := 'Control';
    Keys.ControlKey: Result := 'ControlKey';
    Keys.Crsel: Result := 'Crsel';
    Keys.D: Result := 'D';
    Keys.D0: Result := '0';
    Keys.D1: Result := '1';
    Keys.D2: Result := '2';
    Keys.D3: Result := '3';
    Keys.D4: Result := '4';
    Keys.D5: Result := '5';
    Keys.D6: Result := '6';
    Keys.D7: Result := '7';
    Keys.D8: Result := '8';
    Keys.D9: Result := '9';
    Keys.Decimal: Result := 'Decimal';
    Keys.Delete: Result := 'Delete';
    Keys.Divide: Result := 'Divide';
    Keys.Down: Result := 'Down';
    Keys.E: Result := 'E';
    Keys.End: Result := 'End';
    Keys.Enter: Result := 'Enter';
    Keys.EraseEof: Result := 'EraseEof';
    Keys.Escape: Result := 'Escape';
    Keys.Execute: Result := 'Execute';
    Keys.Exsel: Result := 'Exsel';
    Keys.F: Result := 'F';
    Keys.F1: Result := 'F1';
    Keys.F10: Result := 'F10';
    Keys.F11: Result := 'F11';
    Keys.F12: Result := 'F12';
    Keys.F13: Result := 'F13';
    Keys.F14: Result := 'F14';
    Keys.F15: Result := 'F15';
    Keys.F16: Result := 'F16';
    Keys.F17: Result := 'F17';
    Keys.F18: Result := 'F18';
    Keys.F19: Result := 'F19';
    Keys.F2: Result := 'F2';
    Keys.F20: Result := 'F20';
    Keys.F21: Result := 'F21';
    Keys.F22: Result := 'F22';
    Keys.F23: Result := 'F23';
    Keys.F24: Result := 'F24';
    Keys.F3: Result := 'F3';
    Keys.F4: Result := 'F4';
    Keys.F5: Result := 'F5';
    Keys.F6: Result := 'F6';
    Keys.F7: Result := 'F7';
    Keys.F8: Result := 'F8';
    Keys.F9: Result := 'F9';
    Keys.FinalMode: Result := 'FinalMode';
    Keys.G: Result := 'G';
    Keys.H: Result := 'H';
//Keys.HanguelMode: Result:= 'HanguelMode';  // double of HangulMode
    Keys.HangulMode: Result := 'HangulMode';
    Keys.HanjaMode: Result := 'HanjaMode';
    Keys.Help: Result := 'Help';
    Keys.Home: Result := 'Home';
    Keys.I: Result := 'I';
    Keys.IMEAceept: Result := 'IMEAceept';
    Keys.IMEConvert: Result := 'IMEConvert';
    Keys.IMEModeChange: Result := 'IMEModeChange';
    Keys.IMENonconvert: Result := 'IMENonconvert';
    Keys.Insert: Result := 'Insert';
    Keys.J: Result := 'J';
    Keys.JunjaMode: Result := 'JunjaMode';
    Keys.K: Result := 'K';
// Keys.KanaMode: Result:= 'KanaMode';    // double of HangulMode
//Keys.KanjiMode: Result:= 'KanjiMode';   //double of HanjaMode
    Keys.KeyCode: Result := 'KeyCode';
    Keys.L: Result := 'L';
    Keys.LaunchApplication1: Result := 'LaunchApplication1';
    Keys.LaunchApplication2: Result := 'LaunchApplication2';
    Keys.LaunchMail: Result := 'LaunchMail';
    Keys.LButton: Result := 'LButton';
    Keys.LControlKey: Result := 'LControlKey';
    Keys.Left: Result := 'Left';
    Keys.LineFeed: Result := 'LineFeed';
    Keys.LMenu: Result := 'LMenu';
    Keys.LShiftKey: Result := 'LShiftKey';
    Keys.LWin: Result := 'LWin';
    Keys.M: Result := 'M';
    Keys.MButton: Result := 'MButton';
    Keys.MediaNextTrack: Result := 'MediaNextTrack';
    Keys.MediaPlayPause: Result := 'MediaPlayPause';
    Keys.MediaPreviousTrack: Result := 'MediaPreviousTrack';
    Keys.MediaStop: Result := 'MediaStop';
    Keys.Menu: Result := 'Menu';
// Keys.Modifiers: Result:= 'Modifiers';    // out of case Range
    Keys.Multiply: Result := 'Multiply';
    Keys.N: Result := 'N';
// Keys.Next: Result:= 'Next';      // double of PageDown
    Keys.NoName: Result := 'NoName';
    Keys.None: Result := 'None';
    Keys.NumLock: Result := 'NumLock';
    Keys.NumPad0: Result := 'NumPad0';
    Keys.NumPad1: Result := 'NumPad1';
    Keys.NumPad2: Result := 'NumPad2';
    Keys.NumPad3: Result := 'NumPad3';
    Keys.NumPad4: Result := 'NumPad4';
    Keys.NumPad5: Result := 'NumPad5';
    Keys.NumPad6: Result := 'NumPad6';
    Keys.NumPad7: Result := 'NumPad7';
    Keys.NumPad8: Result := 'NumPad8';
    Keys.NumPad9: Result := 'NumPad9';
    Keys.O: Result := 'O';
    Keys.Oem8: Result := 'Oem8';
    Keys.OemBackslash: Result := 'OemBackslash';
    Keys.OemClear: Result := 'OemClear';
    Keys.OemCloseBrackets: Result := 'OemCloseBrackets';
    Keys.Oemcomma: Result := 'Oemcomma';
    Keys.OemMinus: Result := 'OemMinus';
    Keys.OemOpenBrackets: Result := 'OemOpenBrackets';
    Keys.OemPeriod: Result := 'OemPeriod';
    Keys.OemPipe: Result := 'OemPipe';
    Keys.Oemplus: Result := 'Oemplus';
    Keys.OemQuestion: Result := 'OemQuestion';
    Keys.OemQuotes: Result := 'OemQuotes';
    Keys.OemSemicolon: Result := 'OemSemicolon';
    Keys.Oemtilde: Result := 'Oemtilde';
    Keys.P: Result := 'P';
    Keys.Pa1: Result := 'Pa1';
    Keys.PageDown: Result := 'PageDown';
    Keys.PageUp: Result := 'PageUp';
    Keys.Pause: Result := 'Pause';
    Keys.Play: Result := 'Play';
    Keys.Print: Result := 'Print';
    Keys.PrintScreen: Result := 'PrintScreen';
// Keys.Prior: Result:= 'Prior';    // double of PageUp
    Keys.ProcessKey: Result := 'ProcessKey';
    Keys.Q: Result := 'Q';
    Keys.R: Result := 'R';
    Keys.RButton: Result := 'RButton';
    Keys.RControlKey: Result := 'RControlKey';
// Keys.Return: Result:= 'Return';   // double of Enter
    Keys.Right: Result := 'Right';
    Keys.RMenu: Result := 'RMenu';
    Keys.RShiftKey: Result := 'RShiftKey';
    Keys.RWin: Result := 'RWin';
    Keys.S: Result := 'S';
    Keys.Scroll: Result := 'Scroll';
    Keys.Select: Result := 'Select';
    Keys.SelectMedia: Result := 'SelectMedia';
    Keys.Separator: Result := 'Separator';
    Keys.Shift: Result := 'Shift';
    Keys.ShiftKey: Result := 'ShiftKey';
// Keys.Snapshot: Result:= 'Snapshot';   // double of PrintScreen
    Keys.Space: Result := 'Space';
    Keys.Subtract: Result := 'Subtract';
    Keys.T: Result := 'T';
    Keys.Tab: Result := 'Tab';
    Keys.U: Result := 'U';
    Keys.Up: Result := 'Up';
    Keys.V: Result := 'V';
    Keys.VolumeDown: Result := 'VolumeDown';
    Keys.VolumeMute: Result := 'VolumeMute';
    Keys.VolumeUp: Result := 'VolumeUp';
    Keys.W: Result := 'W';
    Keys.X: Result := 'X';
    Keys.XButton1: Result := 'XButton1';
    Keys.XButton2: Result := 'XButton2';
    Keys.Y: Result := 'Y';
    Keys.Z: Result := 'Z';
    Keys.Zoom: Result := 'Zoom';
  end;
end;

procedure TmwCommandProcessor.OnHScroll(Sender: TObject; SE: ScrollEventArgs);
begin
  if fHScrollHandler <> nil then
    fHScrollHandler.Execute(Self, se);
end;

procedure TmwCommandProcessor.OnKeyDown(Sender: TObject; KEA: KeyEventArgs);
var
  aCommand: TmwCommand;
begin
  case KEA.Modifiers of
    Keys.Alt:;
    Keys.Control:;
    Keys.Shift:;
    (Keys.Alt or Keys.Control):;
    (Keys.Alt or Keys.Shift):;
    (Keys.Control or Keys.Shift):;
    (Keys.Alt or Keys.Control or Keys.Shift):;
  else
    begin
      ModifierState := [];
      LastModifierKeyValue:= 0;
      ModifierStringBuffer.set_Length(0);
      CommandStringBuffer.set_Length(0);
    end;
  end;
  case fKeyDownHandler <> nil of
    True: fKeyDownHandler.Execute(Sender, KEA);
    False:
      if AddToCommandStringBuffer(KEA) then
      begin
        aCommand := TmwCommand(CommandTable[CommandString.ToUpper]);
        if aCommand <> nil then
        begin
          aCommand.Execute(Sender);
          CommandStringBuffer.set_Length(0);
        end;
      end;
  end;
end;

procedure TmwCommandProcessor.OnKeyPress(Sender: TObject; KPEA: KeyPressEventArgs);
begin
  case fKeyPressHandler <> nil of
    True:
      case ModifierState = [] of
        True:
          begin
            CommandStringBuffer.set_Length(0);
            fKeyPressHandler.Execute(Sender, KPEA);
          end;
      end;
    False:
      case ModifierState = [] of
        True: CommandStringBuffer.set_Length(0);
      end;
  end;
end;

procedure TmwCommandProcessor.OnKeyUp(Sender: TObject; KEA: KeyEventArgs);
begin
  case KEA.Modifiers of
    Keys.Alt:
      begin
        ModifierState := [msAlt];
        LastModifierKeyValue:= 0;
        RemoveFromModifierString('Control');
        RemoveFromModifierString('Shift');
      end;
    Keys.Control:
      begin
        ModifierState := [msCtrl];
        LastModifierKeyValue:= 0;
        RemoveFromModifierString('Alt');
        RemoveFromModifierString('Shift');
      end;
    Keys.Shift:
      begin
        ModifierState := [msShift];
        LastModifierKeyValue:= 0;
        RemoveFromModifierString('Alt');
        RemoveFromModifierString('Control');
      end;
    (Keys.Alt or Keys.Control):
      begin
        ModifierState := [msAlt, msCtrl];
        LastModifierKeyValue:= 0;
        RemoveFromModifierString('Shift');
      end;
    (Keys.Alt or Keys.Shift):
      begin
        ModifierState := [msAlt, msShift];
        LastModifierKeyValue:= 0;
        RemoveFromModifierString('Control');
      end;
    (Keys.Control or Keys.Shift):
      begin
        ModifierState := [msCtrl, msShift];
        LastModifierKeyValue:= 0;
        RemoveFromModifierString('Alt');
      end;
    (Keys.Alt or Keys.Control or Keys.Shift):;
  else
    begin
      ModifierState := [];
      LastModifierKeyValue:= 0;
      ModifierStringBuffer.set_Length(0);
    end;
  end;
  if fKeyUpHandler <> nil then
    fKeyUpHandler.Execute(Sender, KEA);
end;

procedure TmwCommandProcessor.OnLayout(Sender: TObject; LEA: LayoutEventArgs);
begin
  if fLayoutHandler <> nil then
    fLayoutHandler.Execute(Sender, LEA);
end;

procedure TmwCommandProcessor.OnMouseDown(Sender: TObject; MEA: MouseEventArgs);
begin
  if fMouseDownHandler <> nil then
    fMouseDownHandler.Execute(Sender, MEA);
end;

procedure TmwCommandProcessor.OnMouseEnter(Sender: TObject; EA: EventArgs);
begin
  if fMouseEnterHandler <> nil then
    fMouseEnterHandler.Execute(Sender, EA);
end;

procedure TmwCommandProcessor.OnMouseHover(Sender: TObject; EA: EventArgs);
begin
  if fMouseHoverHandler <> nil then
    fMouseHoverHandler.Execute(Sender, EA);
end;

procedure TmwCommandProcessor.OnMouseLeave(Sender: TObject; EA: EventArgs);
begin
  if fMouseLeaveHandler <> nil then
    fMouseLeaveHandler.Execute(Sender, EA);
end;

procedure TmwCommandProcessor.OnMouseMove(Sender: TObject; MEA: MouseEventArgs);
begin
  if fMouseMoveHandler <> nil then
    fMouseMoveHandler.Execute(Sender, MEA);
end;

procedure TmwCommandProcessor.OnMouseUp(Sender: TObject; MEA: MouseEventArgs);
begin
  if fMouseUpHandler <> nil then
    fMouseUpHandler.Execute(Sender, MEA);
end;

procedure TmwCommandProcessor.OnMouseWheel(Sender: TObject; MEA: MouseEventArgs);
begin
  if fMouseWheelHandler <> nil then
    fMouseWheelHandler.Execute(Sender, MEA);
end;

procedure TmwCommandProcessor.OnVScroll(Sender: TObject; SE: ScrollEventArgs);
begin
  if fVScrollHandler <> nil then
    fVScrollHandler.Execute(Self, se);
end;

procedure TmwCommandProcessor.RemoveFromModifierString(Value: string);
begin
  ModifierStringBuffer.Replace(Value, '');
end;

procedure TmwCommandProcessor.set_HScrollHandler(const Value: TmwEventArgsCommand);
begin
  case fHScrollHandler <> nil of
    True:
      begin
        CommandTable.Remove(fHScrollHandler);
        fHScrollHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fHScrollHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_KeyDownHandler(const Value: TmwKeyEventArgsCommand);
begin
  case fKeyDownHandler <> nil of
    True:
      begin
        CommandTable.Remove(fKeyDownHandler);
        fKeyDownHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fKeyDownHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_KeyPressHandler(const Value: TmwKeyPressEventArgsCommand);
begin
  case fKeyPressHandler <> nil of
    True:
      begin
        CommandTable.Remove(fKeyPressHandler);
        fKeyPressHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fKeyPressHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_KeyUpHandler(const Value: TmwKeyEventArgsCommand);
begin
  case fKeyUpHandler <> nil of
    True:
      begin
        CommandTable.Remove(fKeyUpHandler);
        fKeyUpHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fKeyUpHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_LayoutHandler(const Value: TmwLayoutEventArgsCommand);
begin
  case fLayoutHandler <> nil of
    True:
      begin
        CommandTable.Remove(fLayoutHandler);
        fLayoutHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fLayoutHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_MouseDownHandler(const Value: TmwMouseEventArgsCommand);
begin
  case fMouseDownHandler <> nil of
    True:
      begin
        CommandTable.Remove(fMouseDownHandler);
        fMouseDownHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fMouseDownHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_MouseEnterHandler(const Value: TmwEventArgsCommand);
begin
  case fMouseEnterHandler <> nil of
    True:
      begin
        CommandTable.Remove(fMouseEnterHandler);
        fMouseEnterHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fMouseEnterHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_MouseHoverHandler(const Value: TmwEventArgsCommand);
begin
  case fMouseHoverHandler <> nil of
    True:
      begin
        CommandTable.Remove(fMouseHoverHandler);
        fMouseHoverHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fMouseHoverHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_MouseLeaveHandler(const Value: TmwEventArgsCommand);
begin
  case fMouseLeaveHandler <> nil of
    True:
      begin
        CommandTable.Remove(fMouseLeaveHandler);
        fMouseLeaveHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fMouseLeaveHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_MouseMoveHandler(const Value: TmwMouseEventArgsCommand);
begin
  case fMouseMoveHandler <> nil of
    True:
      begin
        CommandTable.Remove(fMouseMoveHandler);
        fMouseMoveHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fMouseMoveHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_MouseUpHandler(const Value: TmwMouseEventArgsCommand);
begin
  case fMouseUpHandler <> nil of
    True:
      begin
        CommandTable.Remove(fMouseUpHandler);
        fMouseUpHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fMouseUpHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_MouseWheelHandler(const Value: TmwMouseEventArgsCommand);
begin
  case fMouseWheelHandler <> nil of
    True:
      begin
        CommandTable.Remove(fMouseWheelHandler);
        fMouseWheelHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fMouseWheelHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

procedure TmwCommandProcessor.set_VScrollHandler(const Value: TmwEventArgsCommand);
begin
  case fVScrollHandler <> nil of
    True:
      begin
        CommandTable.Remove(fVScrollHandler);
        fVScrollHandler := Value;
        AddCommand(Value);
      end;
    False:
      begin
        fVScrollHandler := Value;
        AddCommand(Value);
      end;
  end;
end;

end.

