2012-04-17 17 views
7

Tengo un componente personalizado (que hereda de TCustomPanel) que consta de otros dos componentes (digamos dos ediciones). ¿Cómo obtengo el orden de tabulación correcto cuando uso el componente?Comando personalizado y orden de tabulación

En el diseñador de orden de tabulación solo puedo acceder al componente en sí que no puede tener foco porque es un panel. Lo que sucede en el tiempo de ejecución es que puedo acceder a las ediciones usando la tecla de tabulación, pero solo después de enfocar los dos botones debajo del componente.

¿Cómo puedo cambiar el orden de tabulación en esta situación?

+1

¿No puede simplemente establecer el orden de tabulación en el constructor de su componente? –

+0

@DavidHeffernan no porque el problema es el orden de tabulación en la forma circundante. – jpfollenius

+0

Mi suposición es que los dos controles de edición son hijos del panel. No es ese el caso? –

Respuesta

13

El orden de tabulación de esos controles anidados en su componente es distinto del orden de tabulación del formulario en el que reside su componente. El orden de tabulación del componente en la lista de orden de tabulación del formulario deside cuando se tabula a los controles anidados. Una vez que todas las listas de orden de tabulación combinados, resultan en el ciclo final:

  • un control en el formulario (TabOrder=0)
  • otro control en forma (TabOrder=1)
  • Su componente panel (TabOrder=2)
    • Edición 1 (TabOrder=0)
    • Editar 2 (TabOrder=1)
  • Otro control en el formulario (TabOrder=3)

Para poder establecer el orden de tabulación de las veces el diseño de componentes del panel:

  • Usar el editor de orden de tabulación en el diseñador (botón derecho del ratón en el elemento primario del componente) y cambie el orden de las pestañas con las flechas en el editor, o
  • Publique la propiedad TabOrder para su componente y configúrelo en el inspector de objetos:

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

En tiempo de ejecución, siempre es posible establecer el orden de tabulación de los componentes ya que la propiedad se declara TabOrder pública en TWinControl.

... que no puede tener foco porque es un panel.

No, un panel puede proporcionar un enfoque perfecto, pero no de forma predeterminada. Esto se maneja con la propiedad TabStop, que es False de manera predeterminada. No desea que TabStop configure True para su componente ya que (1) un panel no tiene indicador de que tiene foco y (2) no es deseado (imagino).


Cambiar el orden de tabulación de los controles anidados se realiza preferiblemente en el constructor de su componente, o en tiempo de ejecución.

Para poder establecer el orden de tabulación de los controles anidados dentro de su componente en el momento del diseño, requiere algo más de trabajo. No creo que quiera eso, pero como mi respuesta anterior (eliminada) fue basura (y voté, estranguladamente), he resuelto un ejemplo como compensación.

Primero, observe que establecer el orden de tabulación de esas ediciones con el editor de orden de pestañas en el diseñador (haga clic derecho en el componente del panel) cambiará el orden de las pestañas, pero no durará. Eso es porque esos cambios no se transmiten al DFM.

Para ser capaz de transmitir/guardar los cambios en tiempo de diseño de los controles, lo que necesita para su publicación:

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, 100, 21); 
    FEdit2.Name := 'Edit2'; 
    FEdit2.Parent := Self; 
    FEdit2.SetSubComponent(True); 
end; 

Por supuesto, esto publica todas las propiedades de los controles y ahora los usuarios pueden cambiar lo que quieran. Para evitar esto, tenga en cuenta la limitación de las propiedades publicadas de los controles 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. 

Esto limita las propiedades de las propiedades publicadas TEdit para mostrar solo TabOrder.

+0

Gracias! No estoy seguro de cuál fue exactamente el problema, pero ahora funciona y ¡esta es una muy buena respuesta! +1 y aceptado. – jpfollenius

Cuestiones relacionadas