自定义组件和制表符顺序 [英] Custom component and tab order
问题描述
我有一个自定义组件(从 TCustomPanel
继承),由两个其他组件组成(比如说两个编辑)。使用组件时如何正确获得制表符顺序?
I have a custom component (inheriting from TCustomPanel
) that consists of two other components (let's say two edits). How do I get the tab order right when using the component?
在制表符顺序设计器中,我只能访问没有焦点的组件本身,因为它是面板。在运行时发生的事情是,我可以使用Tab键来访问编辑,但是只有在组件下方的两个按钮被聚焦之后才可以访问。
In the tab order designer I can only access the component itself which cannot have focus because it is a panel. What happens at runtime is that I can access the edits using the tab key, but only after the two buttons below the component got focused.
如何更改选项卡顺序在这种情况下?
How can I change the tab order in this situation?
推荐答案
组件中这些嵌套控件的制表符顺序与表单上的制表符顺序不同您的组件所在。当您选择嵌套控件时,将在表单的选项卡顺序列表中确定组件的选项卡顺序。一旦所有选项卡顺序列表组合在一起,它们就会进入最后一个循环:
The tab order of those nested controls within your component is distinct from the tab order of the form on which your component resides. The tab order of the component in the tab order list of the form desides when you tab to the nested controls. Once all tab order lists combined, they result in the final cycle:
- 窗体上的控件(
TabOrder = 0
) - 窗体上的另一个控件(
TabOrder = 1
) - 您的面板组件(
TabOrder = 2
)
- 编辑1(
TabOrder = 0
) - 编辑2(
TabOrder = 1
)
- A control on the form (
TabOrder=0
) - Another control on form (
TabOrder=1
) - Your panel component (
TabOrder=2
)- Edit 1 (
TabOrder=0
) - Edit 2 (
TabOrder=1
)
要设置面板组件设计时间的制表顺序:
To be able to set the tab order of the panel component design time:
- 在设计器中使用制表符顺序编辑器(右键单击组件的父级),然后在编辑器中使用箭头更改制表符顺序,或者
-
为您的组件发布
TabOrder
属性,并将其设置在对象检查器中:
- Use the tab order editor in the designer (right click on the parent of the component) and change the tab order with the arrows in the editor, or
Publish the
TabOrder
property for your component and set it in the object inspector:
type TMyPanel = class(TCustomPanel) published property TabOrder; end;
- Edit 1 (
- 编辑1(
在运行时始终可以设置组件的Tab键顺序,因为 TabOrder
属性在 TWinControl
中声明为公共。
At runtime it is always possible to set the tab order of the component since the TabOrder
property is declared public in TWinControl
.
...因为它是一个面板而无法获得焦点。
... which cannot have focus because it is a panel.
否,面板可以使焦点集中起来,但是默认情况下不会。这是通过 TabStop
属性处理的,默认情况下为 False
。您不希望 TabStop
为组件设置 True
,因为(1)面板没有指示器,它没有焦点(2)这是我所不希望的。
No, a panel can aqcuire focus just fine, but will not by default. This is handled with the TabStop
property, which is False
by default. You don't want TabStop
to set True
for your component since (1) a panel has no indicator it has focus and (2) it is not desired (I imagine).
更改嵌套控件的制表符顺序最好
Changing the tab order of the nested controls is preferably done in the constructor of your component, or at runtime.
要在设计时设置组件内嵌套控件的制表顺序,还需要做更多的工作。 我不认为您想要那样,但是由于我先前的答案(已删除)是垃圾(并被强烈投票),因此我提出了一个补偿示例。
To be able to set the tab order of the nested controls within you component at design time requires some more work. I do not think you want that, but since my previous answer (deleted) was rubbish (and voted on, strangly) I have worked out an example as compensation.
首先,请注意,使用设计器中的选项卡顺序编辑器设置这些编辑的选项卡顺序(在面板组件上单击鼠标右键)将更改选项卡顺序,但不会持久。那是因为这些更改没有流式传输到DFM。
First, notice that setting the tab order of those edits with the tab order editor in the designer (right click on the panel component) will change the tab order, but it will not last. That is because those changes are not streamed to the DFM.
要能够流式传输/保存控件的设计时更改,您需要发布它们:
To be able to stream/save the design time changes of the controls, you need to publish them:
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;
当然,这会发布这些控件的所有属性,现在用户可以更改所需的内容。为避免这种情况,请考虑限制 TEdit
控件的发布属性:
Of course this publishes áll properties of those controls and now users can change whatever they want. To prevent this, consider limiting the published properties of the TEdit
controls:
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
。
This limits the properties of the published TEdit
properties to show only TabOrder
.
这篇关于自定义组件和制表符顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!