Forwarding keyboard events from one Windows control to another

In Delphi XE, I try to implement an “instant search” function that is a bit like Firefox's “type search”, but is better illustrated by a similar function in the open source clipboard expander, Ditto :

Ditto search interface

There is a list of items that handle typical navigation events. However, any alphanumeric keys, as well as navigation and editing commands (right / left arrows, shift + arrows, backspace, delete, etc.) must be redirected to the edit box below the list. The OnChange event of the edit window will cause the list to refresh.

, . ( ) "", . , .

, - ( TcxTreeList) . ?

:

  • TcxTreeList , , , . SQLite . db.

  • , . VK_HOME VK_END, - . , , .

: , , KeyDown, KeyUp KeyPress , :

type
  THackEdit = class( TEdit );

procedure TMainForm.cxTreeList1KeyDown(Sender: TObject; var Key: Word; 
    Shift: TShiftState);
begin
  THackEdit( edit1 ).KeyDown( Key, Shift );
end;

, . , TEdit , . SendMessage (THackEdit (edit1).Handle, WM_KEYDOWN, Key, 0) .

+5
2

VCL . "TcxTreeList", , (, ).

type
  TEdit = class(stdctrls.TEdit)
  private
    FMsgCtrl: TWinControl;
    FRecursing: Boolean;
    procedure WmChar(var Msg: TWMChar); message WM_CHAR;
    procedure WmKeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN;
    procedure WmKeyUp(var Msg: TWMKeyUp); message WM_KEYUP;
  end;

  TMemo = class(stdctrls.TMemo)
  private
    FMsgCtrl: TWinControl;
    FRecursing: Boolean;
    procedure WmChar(var Msg: TWMChar); message WM_CHAR;
    procedure WmKeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN;
    procedure WmKeyUp(var Msg: TWMKeyUp); message WM_KEYUP;
  end;

  TForm1 = class(TForm)
    Edit1: TEdit;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  private
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TEdit }

procedure TEdit.WmChar(var Msg: TWMChar);
begin
  if not FRecursing then begin
    inherited;

    // Insert test here to see if the message will be forwarded
    // exit/modify accordingly.

    if Assigned(FMsgCtrl) then begin
      FRecursing := True;
      try
        FMsgCtrl.Perform(Msg.Msg,
                         MakeWParam(Msg.CharCode, Msg.Unused), Msg.KeyData);
      finally
        FRecursing := False;
      end;
    end;
  end;
end;

procedure TEdit.WmKeyDown(var Msg: TWMKeyDown);
begin
  // exact same contents as in the above procedure
end;

procedure TEdit.WmKeyUp(var Msg: TWMKeyUp);
begin
  // same here
end;

{ TMemo }

procedure TMemo.WmChar(var Msg: TWMChar);
begin
  // same here
end;

procedure TMemo.WmKeyDown(var Msg: TWMKeyDown);
begin
  // same here
end;

procedure TMemo.WmKeyUp(var Msg: TWMKeyUp);
begin
  // same here
end;


{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.FMsgCtrl := Memo1;
  Memo1.FMsgCtrl := Edit1;
end;

, , .

, . , .

+6

, , .

, TEdit Edit1 TListbox Listbox1.

OnEnter Listbox1 focus Edit1

procedure TForm1.ListBox1Enter(Sender: TObject); 
 begin   
  edit1.SetFocus; 
 end;

OnKeyDown Edit1 , .

procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); 
 var k:word; 
 begin   
  if (Shift=[]) and (key=VK_DOWN) then    
   begin
    listbox1.ItemIndex:=listbox1.ItemIndex+1;
    key:=0;    
   end   
  else if (Shift=[]) and (key=VK_UP) then
   begin
    listbox1.ItemIndex:=listbox1.ItemIndex-1;
    key:=0;    
   end   
  else if (Shift=[]) and (key=VK_RETURN) then
   begin
    edit1.text:=listbox1.items[listbox1.itemindex];
   end; 
 end;
+2

All Articles