如何在我的TEdit控件中捕获VK_TAB键并且不让它失去焦点?

时间:2010-03-02 13:43:07

标签: delphi delphi-2009 keypress

在我的TEdit字段中,我的文字格式为<number1>..<number2>

我的想法是:

当用户使用来自其他控件的 TAB 输入控件时,number1会被选中。

当我的TEdit控件有焦点且用户再次按下 TAB 时,我希望number2被选中并取消选择number1

如果当前插入位置位于number2所在的位置,则按 TAB 应该正常并将焦点移动到表单上的下一个控件。

我有两个问题。

  1. 当“编辑”字段已激活时,我无法按下Tab键。我只能在输入/聚焦此控件时捕获它。

  2. 我不知道是否有类似于#0的键,所以我可以把钥匙变成NoOP。

  3. 任何想法,怎么做?

3 个答案:

答案 0 :(得分:13)

您最好编写自己的TEdit后代来处理WM_GETDLGCODE消息。一般的想法是:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TMyEdit = class(TEdit)
    procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  end;

type
  TForm1 = class(TForm)
    Edit2: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
  private
    { Private declarations }
    FMyEdit: TMyEdit;
    FDone: Boolean;
    procedure MyEditEnter(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyEdit }

procedure TMyEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
  inherited;
  Message.Result:= Message.Result or DLGC_WANTTAB;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FMyEdit:= TMyEdit.Create(Self);
  FMyEdit.Left:= 40;
  FMyEdit.Top:= 40;
  FMyEdit.Parent:= Self;
  FMyEdit.Text:= '45..90';
  FMyEdit.OnEnter:= MyEditEnter;
  KeyPreview:= True;
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if (Key = #9) and (ActiveControl = FMyEdit) then begin
    if FDone then begin
      Perform(CM_DialogKey, VK_TAB, 0);
    end
    else begin
      FMyEdit.SelStart:= 4;
      FMyEdit.SelLength:= 2;
    end;
    FDone:= not FDone;
    Key:= #0;
  end;
end;

procedure TForm1.MyEditEnter(Sender: TObject);
begin
  FDone:= False;
  FMyEdit.SelStart:= 0;
  FMyEdit.SelLength:= 2;
end;

end.

更新:没有制作TEdit后代类的相同想法:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Edit2Enter(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
  private
    { Private declarations }
    FDone: Boolean;
    FOldWndProc: TWndMethod;
    procedure Edit2WindowProc(var Message: TMessage);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Edit2Enter(Sender: TObject);
begin
  FDone:= False;
  Edit2.SelStart:= 0;
  Edit2.SelLength:= 2;
end;

procedure TForm1.Edit2WindowProc(var Message: TMessage);
begin
  if Message.Msg = WM_GETDLGCODE then
    Message.Result:= Message.Result or DLGC_WANTTAB
  else
    if Assigned(FOldWndProc) then FOldWndProc(Message);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  KeyPreview:= True;
  Edit2.Text:= '45..90';
  FOldWndProc:= Edit2.WindowProc;
  Edit2.WindowProc:= Edit2WindowProc;
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if (Key = #9) and (ActiveControl = Edit2) then begin
    if FDone then begin
      Perform(CM_DialogKey, VK_TAB, 0);
    end
    else begin
      Edit2.SelStart:= 4;
      Edit2.SelLength:= 2;
    end;
    FDone:= not FDone;
    Key:= #0;
  end;
end;

end.

答案 1 :(得分:0)

  1. 您可以在KeyDown事件中捕获Tab按钮。 (在KeyPress活动之前发生)
  2. 在KeyDown事件中,您可以将密钥设置为#0
  3. 哦,在按键事件中,您可以将键设置为0

    修改     以下是捕获TAB键的KeyDown事件的调用堆栈

    Form1.TForm1.GetTab((45061, 9, 0, 983041, 0))
    :0101f444 TForm1.GetTab
    :004dca20 TWinControl.WndProc + $500
    :004ef754 TCustomForm.WndProc + $558
    :004d86b3 TControl.Perform + $27
    :004ded6a TWinControl.CNKeyDown + $D6
    :004dca20 TWinControl.WndProc + $500
    :004dc147 TWinControl.MainWndProc + $2F
    :004306ea StdWndProc + $16
    :7e418734 USER32.GetDC + 0x6d
    :7e418816 ; C:\WINDOWS\system32\USER32.dll
    :7e41b4c0 ; C:\WINDOWS\system32\USER32.dll
    :7e41b50c ; C:\WINDOWS\system32\USER32.dll
    :7c90eae3 ntdll.KiUserCallbackDispatcher + 0x13
    :7e42f3cc USER32.SendMessageA + 0x49
    

    正如您所看到的那样,它不像普通键那样通过KeyDown,而是调用BroadCast来发送消息....

    所以你需要一个消息捕手

    Procedure GetTab( var Message: TCMDialogkey ); message CM_DIALOGKEY;
    

    抓住它。

答案 2 :(得分:0)

您可能希望查看JvComCtrls中的TJvIPAddress。我想搜索TabThroughFields和VK_TAB会让你走上正轨。