如何知道我是否引用了正确的组件?

3 delphi custom-component

概观

我正在重写从TXPStyleMenuItem继承的一些过程,这样我可以更改使用TActionMainMenuBar时菜单的显示方式.

例:

  TMyXPStyleMenuItem = class(TXPStyleMenuItem)
  protected
    procedure DrawBackground(var PaintRect: TRect); override;
  end;
Run Code Online (Sandbox Code Playgroud)

我创建了自己的组件,它是从TActionMainMenuBar派生的,而在GetControlClass方法中我设置了var ControlClass: TCustomActionControlClassTMyXPStyleMenuItem.

到目前为止,我的工作做得很好,但显然比上面的例子更完整 - 为了问题的目的,我尽可能地保持简短.

Styler组件

我创建了一个非可视样式组件,它基本上只是一堆已发布的属性,这个样式组件可以分配给我的一些控件,在这种情况下我的下载TActionMainMenuBar.

当我的控件分配了样式器组件时,它会读取属性的值,然后根据值进行绘制.如果未分配样式器组件,那么我只使用默认值来决定如何绘制控件.

一个简单的示例来自我的一个自定义TEdits,我可以根据指定的样式器值更改颜色:

TMyEdit = class(TCustomEdit)
private
  FStyler: TMyStyler;
public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;
end;

if Assigned(FStyler) then
begin
  Color := FStyler.Color;
end;
Run Code Online (Sandbox Code Playgroud)

问题

我面临的问题是中的重写程序TMyXPStyleMenuItem = class(TXPStyleMenuItem).

我需要读取我的样式组件的值,但因为TMyXPStyleMenuItem实际上不是我的菜单组件的一部分,我无法知道从哪里来FStyler,例如我分配给哪个TActionMainMenuBar实例?

通常,我的菜单类中的FStyler设置如下:

private
  FStyler: TMyStyler;
  procedure SetStyler(const Value: TMyStyler);
published
  property Styler: TMyStyler read FStyler write SetStyler;

..

procedure TMyMenu.SetStyler(const Value: TMyStyler);
begin
  if Value <> FStyler  then
  begin
    FStyler := Value;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

但那些程序从TMyXPStyleMenuItem上面不了解.

我不能在重载过程中包含一个新参数,因为它不能正常工作,因为声明与基类不同,例如:

procedure DrawBackground(var PaintRect: TRect; AStyler: TMyStyler); override;
Run Code Online (Sandbox Code Playgroud)

几乎拥有它

我最接近的是在菜单组件的单元中,我在实现部分上方创建了一个全局变量:

var
  FStyler: TMyStyler;

implementation
Run Code Online (Sandbox Code Playgroud)

然后在过度的DrawBackground程序中我这样做了:

procedure TMyXPStyleMenuItem.DrawBackground(var PaintRect: TRect);

  procedure _DrawBackground(AStyler: TMyStyler);
  begin
    // handle all the painting from here
    // using the values from AStyler.
  end;

begin
  if Assigned(FStyler) then
    _DrawBackground(FStyler);
end;
Run Code Online (Sandbox Code Playgroud)

正如我以为我有它工作,我很快发现它不是.只要我有一个二级菜单或另一个表单上的菜单,就会混淆应该使用哪个样式器值绘制哪个菜单.这是因为理论上我的菜单组件的任何实例都将使用全局FStyler变量.

我认为我能做的另一件事是用过载指令标记过程,这会让我添加我的额外参数,但是我仍然不知道我是否引用了正确的菜单组件.

因为我基本上仍然熟悉组件编写等,如果我忽略了一些完全明显的东西,请原谅我.如果它很简单,那么我完全错过了 - 如果我老实,这让我感到很困惑!

jac*_*ate 5

使用Menu属性(声明在TCustomMenuItem,您的类的祖父项)来访问菜单样式器,如下所示:

procedure TMyXPStyleMenuItem.DrawBackground(var PaintRect: TRect);
var
  Styler: TMyStyler;
begin
  if Menu is TMyActionMainMenuBar then
    Styler := TMyActionMainMenuBar(Menu).Styler
  else
    Styler := nil;
  if Assigned(Styler) then
    DrawStyledBackground
  else
    DrawDefaultBackground;
end;
Run Code Online (Sandbox Code Playgroud)

您可以重构代码以添加GetMenuStyler方法:

function TMyXPStyleMenuItem.GetMenuStyler: TMyStyler;
begin
  if Menu is TMyActionMainMenuBar then
    Result := TMyActionMainMenuBar(Menu).Styler
  else
    Result := nil;
end;

procedure TMyXPStyleMenuItem.DrawBackground(var PaintRect: TRect);
var
  Styler: TMyStyler;
begin
  Styler := GetMenuStyler;
  if Assigned(Styler) then
    DrawStyledBackground
  else
    DrawDefaultBackground;
end;

procedure TMyXPStyleMenuItem.OtherDrawMethod(var PaintRect: TRect);
var
  Styler: TMyStyler;
begin
  Styler := GetMenuStyler;
  if Assigned(Styler) then
   ...;
end;
Run Code Online (Sandbox Code Playgroud)