1. 程式人生 > 實用技巧 >delphi – 自定義元件和Tab鍵順序

delphi – 自定義元件和Tab鍵順序

我有一個自定義元件(繼承自TCustomPanel),它由兩個其他元件組成(比方說兩個編輯).如何在使用元件時正確獲取Tab鍵順序?

在Tab鍵順序設計器中,我只能訪問無法獲得焦點的元件本身,因為它是一個面板.在執行時發生的事情是我可以使用tab鍵訪問編輯,但只有在元件下方的兩個按鈕聚焦後才能訪問.

如何在這種情況下更改Tab鍵順序?

解決方法

元件中巢狀控制元件的Tab鍵順序與元件所在表單的Tab鍵順序不同.當您選中巢狀控制元件時,表單的Tab鍵順序列表中元件的Tab鍵順序.一旦所有Tab鍵順序列表合併,它們將導致最終迴圈:

>表單上的控制元件(TabOrder = 0)
>表單上的另一個控制元件(TabOrder = 1)
>您的面板元件(TabOrder = 2)

>編輯1(TabOrder = 0)
>編輯2(TabOrder = 1)

>表單上的另一個控制元件(TabOrder = 3)

為了能夠設定面板元件設計時間的Tab鍵順序:

>使用設計器中的Tab鍵順序編輯器(右鍵單擊元件的父級)並使用編輯器中的箭頭更改Tab鍵順序,或者
>釋出元件的TabOrder屬性並在物件檢查器中設定它:

type 
  TMyPanel = class(TCustomPanel) 
  published 
    property TabOrder; 
  end;

在執行時,始終可以設定元件的Tab鍵順序,因為TabOrder屬性在TWinControl中宣告為public.

… which cannot have focus because it is a panel.

不,一個面板可以很好地聚焦,但預設情況下不會.這是使用TabStop屬性處理的,預設情況下為False.您不希望TabStop為您的元件設定True,因為(1)面板沒有指示它有焦點,(2)它不是(我想象的).

更改巢狀控制元件的Tab鍵順序最好在元件的建構函式中或在執行時完成.

為了能夠在設計時在元件內設定巢狀控制元件的Tab鍵順序,需要更多的工作.我不認為你想要那個,但是因為我之前的回答(刪除)是垃圾(並投票,扼殺)我已經找到了一個例子作為補償.

首先,請注意,使用設計器中的Tab鍵順序編輯器設定這些編輯的Tab鍵順序(右鍵單擊面板元件)將更改Tab鍵順序,但它不會持續.那是因為這些更改沒有流式傳輸到DFM.

為了能夠流式傳輸/儲存控制元件的設計時更改,您需要釋出它們:

type
  TMyPanel = class(TCustomPanel)
  private
    FEdit1: TEdit;
    FEdit2: TEdit;
  public
    constructor Create(AOwner: TComponent); override;
  published 
    property Edit1: TEdit read FEdit1;
    property Edit2: TEdit read FEdit2;
  end;
 
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FEdit1 := TEdit.Create(Self);
  FEdit1.SetBounds(10,10,100,21);
  FEdit1.Name := 'Edit1';
  FEdit1.Parent := Self;
  FEdit1.SetSubComponent(True);
  FEdit2 := TEdit.Create(Self);
  FEdit2.SetBounds(10,41,21);
  FEdit2.Name := 'Edit2';
  FEdit2.Parent := Self;
  FEdit2.SetSubComponent(True);
end;

當然,這會發布這些控制元件的所有屬性,現在使用者可以隨意更改.要防止這種情況,請考慮限制TEdit控制元件的已釋出屬性:

unit MyPanelEdit;
 
interface
 
uses
  DesignEditors,Unit2,DesignIntf,SysUtils,Classes,TypInfo,StdCtrls;
 
type
  TEditProperty = class(TComponentProperty)
  private
    function FilterFunc(const ATestEditor: IProperty): Boolean;
  public
    function GetAttributes: TPropertyAttributes; override;
    procedure GetProperties(Proc: TGetPropProc); override;
  end;
 
procedure Register;
 
implementation
 
procedure Register;
begin
  RegisterPropertyEditor(TypeInfo(TEdit),TMyPanel,'',TEditProperty);
end;
 
{ TEditProperty }
 
function TEditProperty.FilterFunc(const ATestEditor: IProperty): Boolean;
begin
  Result := ATestEditor.GetName = 'TabOrder';
end;
 
function TEditProperty.GetAttributes: TPropertyAttributes;
begin
  Result := [paSubProperties];
end;
 
procedure TEditProperty.GetProperties(Proc: TGetPropProc);
var
  LComponents: IDesignerSelections;
  LDesigner: IDesigner;
begin
  LComponents := GetSelections;
  if LComponents <> nil then
  begin
    if not Supports(
        FindRootDesigner(LComponents[0]),IDesigner,LDesigner) then
      LDesigner := Designer;
    GetComponentProperties(LComponents,[tkInteger],LDesigner,Proc,FilterFunc);
  end;
end;
 
end.

這會將已釋出的TEdit屬性的屬性限制為僅顯示TabOrder.