我想在Windows上的 Delphi XE6 中简化以下代码,随着我添加越来越多类型的组件,该代码变得难以维护。
可移植性注意事项:我想稍后在 Linux上的Lazarus 2.0.2 中使用相同的代码,几乎没有更改,因此Windows消息处理已不再可用问题。
问题是,我似乎找不到一种将OnMouseEnter事件处理程序分配给整个Form上所有组件的方法。
我已尽其所能,包括对象树中常见的各种类。 OnMouseEnter事件似乎没有共同点。
事件处理程序本身仅包含一个命令(procedure = void function),并且将不再包含该命令,也许这可以简化整个问题?
正如您在下面看到的那样,此刻,我需要将每种类型的组件(目前仅TLabel,TButton和TEdit)添加到for循环中。
procedure TFormMain.FormCreate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to FormMain.ComponentCount - 1 do
begin
if FormMain.Components[I] is TLabel then
begin
(FormMain.Components[I] as TLabel).OnMouseEnter
:= @CustomGenericMouseEnter;
end;
if FormMain.Components[I] is TButton then
begin
(FormMain.Components[I] as TButton).OnMouseEnter
:= @CustomGenericMouseEnter;
end;
if FormMain.Components[I] is TEdit then
begin
(FormMain.Components[I] as TEdit).OnMouseEnter
:= @CustomGenericMouseEnter;
end;
end;
end;
procedure TFormMain.CustomGenericMouseEnter(Sender: TObject);
begin
SingleCustomProcedure; // no arguments, nor return value
end;
我正在编写颜色选择器应用程序,因此希望向用户显示鼠标坐标。
我那里有一个轮询计时器,我不想添加多余的代码,所以我希望这是不言自明的:
procedure TFormMain.TimerMousePollTimer(Sender: TObject);
begin
if MousePosChanged then
begin
LabelEdit_MousePosX.Text := MousePosX.ToString;
LabelEdit_MousePosY.Text := MousePosY.ToString;
end;
end;
此外,我确实实现了 OnMouseLeave 。
答案 0 :(得分:6)
OnMouseEnter事件似乎没有共同之处。
实际上是。 OnMouseEnter
是TControl
的成员,所有视觉控件都来自于published
,但大多数控件不会将其提升为protected
。但是,由于它被声明为type
TControlAccess = class(TControl)
end;
procedure TFormMain.FormCreate(Sender: TObject);
var
I: Integer;
Comp: TComponent;
begin
for I := 0 to ComponentCount - 1 do
begin
Comp := Components[I];
if Comp is TControl then
TControlAccess(Comp).OnMouseEnter := CustomGenericMouseEnter;
end;
end;
,因此您可以使用访问器类在任何控件上访问它,例如:
TControlAccess
之所以可行,是因为TControl
获得对TControlAccess
的所有受保护成员的访问权,并且声明TControlAccess
的单位可以访问OnMouseEnter
的所有受保护成员。
另一方面,protected
最初是uses
..., TypInfo;
procedure TFormMain.FormCreate(Sender: TObject);
var
I: Integer;
Comp: TComponent;
Prop: PPropInfo;
M: TMethod;
begin
TNotifyEvent(M) := CustomGenericMouseEnter;
for I := 0 to ComponentCount - 1 do
begin
Comp := Components[I];
if not (Comp is TControl) then Continue;
Prop := GetPropInfo(Comp, 'OnMouseEnter', [tkMethod]);
if Prop <> nil then
SetMethodProp(Comp, Prop, M);
end;
end;
,因此控件可以决定是否要公开对其的访问。如果您想遵守该决定,并且仅将其设置为已促进该决定的控件,则可以使用RTTI,例如:
uses
..., System.Rtti;
procedure TFormMain.FormCreate(Sender: TObject);
var
I: Integer;
Ctx: TRttiContext;
Comp: TComponent;
Prop: TRttiProperty;
V: TValue;
begin
V := TValue.From<TNotifyEvent>(CustomGenericMouseEnter);
for I := 0 to ComponentCount - 1 do
begin
Comp := Components[I];
if not (Comp is TControl) then Continue;
Ctx.GetType(Comp.ClassType).GetProperty('OnMouseEnter');
if (Prop <> nil) and (Prop.Visibility in [TMemberVisibility.mvPublic, TMemberVisibility.mvPublished]) then
Prop.SetValue(Comp, V);
end;
end;
或者(仅适用于Delphi 2010 +):
using dbConn