2010-03-02 5 views
4

내 TEdit 필드에 양식이 <number1>..<number2>입니다.TEdit 컨트롤에서 VK_TAB 키를 잡아 내고 포커스를 잃지 않게하려면 어떻게합니까?

내 생각은 다음과 같습니다

사용자가 다른 컨트롤에서 TAB를 사용하여 제어 입력, number1가 선택됩니다. 내은 TEdit 컨트롤이 포커스가 사용자가 다시 TAB을 누르면

, 나는 number2 선택 얻을하고 number1가 해제되고 싶어요.

현재 캐럿 위치가 number2 인 위치에있는 경우 TAB을 누르면 정상적으로 작동하고 양식의 다음 컨트롤로 포커스를 이동해야합니다.

문제점이 2 개 있습니다.

  1. 편집 필드가 이미 활성화되어있는 경우 탭 키를 누를 수 없습니다. 이 컨트롤이 입력/집중 될 때만 나는 그것을 잡을 수 있습니다.

  2. # 0과 비슷한 키가 있는지 알 수 없으므로 키를 NoOP로 바꿀 수 있습니다.

아이디어가 있습니까?

답변

13

WM_GETDLGCODE 메시지를 처리하는 자체 TEdit 자손을 작성하는 것이 좋습니다. 일반적인 생각은 :

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. 

업데이트 :

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. 
+3

'wm_GetDlgCode' 처리가 확실히 진행됩니다. 하지만 자손 클래스를 만들 필요는 없습니다. 모든 컨트롤의'WndProc' 속성을 설정하여 원하는 메시지를 잡을 수 있습니다. –

0
  1. KeyDown 이벤트에서 Tab 키를 잡을 수 있습니다. 당신이 아 # 0

에 키를 설정하고 키를 눌러 이벤트에 당신이 0

편집 에 키를 설정할 수 있습니다에서 KeyDown 이벤트에

  • 을 (KeyPress 이벤트 전에 발생 함) 다음은 정상 키가대로에서 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 
    

    키 TAB에 대한 KeyDown 이벤트를 캡처 호출 스택입니다 대신,416,343를 호출3210

    그래서 당신이 그것을 잡으려고 메시지 포수

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

    이 필요합니다 .... 메시지를 보낼 수 있습니다.

  • +1

    KeyPress 이벤트는 키가 필요합니다하십시오은 TEdit의 하위 클래스를하지 않고 같은 생각 샤아.그러나 Tab 키는 특수 키이며이 메서드에서 인식 할 수 없다는 것을 알고 있습니다. OnKeyDown 및 OnKeyUp 이벤트에는 Key : Word가 필요합니다. 이러한 메서드는 "VK_TAB"이기 때문에 Tab 키를 인식합니다. 이 문제는 Edit 컨트롤이 활성화되어있는 동안 키 다운 이벤트가 전혀 발생하지 않는다는 것입니다. OnKeyUp은 내 편집 컨트롤이 포커스를받는 경우에만 시작됩니다. 편집 컨트롤에 이미 포커스가있는 동안 TAb 키를 눌러야합니다. – user1651105

    +0

    임 꽤 확실한 # 9는 VK_Tab에 대한 문자입니다. –

    0

    JvComCtrls의 TJvIPAddress를보고 싶을 수도 있습니다. 나는 TabThroughFields와 VK_TAB를 찾는 것이 당신을 궤도에 올려 놓아야한다고 생각합니다.

    관련 문제