Frage

Was muss ich tun, um meine Komponente zu unterstützen. Es ist eine Knopfkomponente, aber ich denke, es ist für jeden Komponenten -Typ das gleiche. Alle Informationen oder wie man hilft.

War es hilfreich?

Lösung

Das hängt davon ab, wie Sie definieren Aktionsunterstützung. Es gibt zwei Arten:

  • Eine möglicherweise angepasste Aktionseigenschaft Ihrer Komponente, die von einer Aktionskomponente zugeordnet werden kann
  • Die Aktionskomponente selbst.

Eine Aktionseigenschaft

Jeder TCONTROL -Nachkommen verfügt über eine Aktionseigenschaft, die ausführlich mit einer linken Maustaste verknüpft ist. Dies Verknüpfung wird von einem ActionLink verwaltet. Der Standard -ActionLink ist vom Typ tcontrolactionLink, der die Synchronisation der Bildunterschrift, des Hinweiss, des aktivierten Zustands usw. sowohl der Aktion als auch der der Kontrolle übernimmt. Wenn diese Grundlage alles ist, was Sie möchten, veröffentlichen Sie einfach die Aktionseigenschaft in Ihrer Komponententyp -Deklaration, und das Delphi -Framework kümmert sich um alle, wie es Serg und Lu rd schon beantwortet.

Wenn Sie möchten, dass Ihre eigene Aktionseigenschaft mit einer anderen Bedingung oder einem anderen Ereignis (dh außer Klick) verknüpft wird oder wenn Sie eine Aktionseigenschaft für ein bestimmtes Subelement Ihrer Komponente implementieren möchten (das ist kein Tontrol -Nachkomme), dann dann Sie können Ihre eigene benutzerdefinierte Aktionseigenschaft implementieren, indem Sie eine benutzerdefinierte ActionLink -Klasse definieren und implementieren.

Angenommen, Ihre Komponente ist eine Art Raster mit Spalten, und Sie möchten, dass jede Spalte eine Aktionseigenschaft hat, die aufgerufen werden sollte, wenn der Benutzer auf den Titel einer Spalte klickt. Da solche Spalten wahrscheinlich einen TCollectionItem -Typ haben, hat der Spaltentyp standardmäßig keine Aktionseigenschaft. Sie müssen also selbst eine implementieren. Betrachten Sie das nächste Beispiel, das die Bildunterschrift der Aktion mit dem Titel der Spalte verknüpft, den aktivierten Status der Aktion umgekehrt mit der Readonly -Eigenschaft der Spalte verknüpft und so weiter ...:

unit Unit1;

interface

uses
  Classes, ActnList, SysUtils;

type
  TColumn = class;

  TColumnActionLink = class(TActionLink)
  protected
    FClient: TColumn;
    procedure AssignClient(AClient: TObject); override;
    function IsCaptionLinked: Boolean; override;
    function IsEnabledLinked: Boolean; override;
    function IsOnExecuteLinked: Boolean; override;
    function IsVisibleLinked: Boolean; override;
    procedure SetCaption(const Value: String); override;
    procedure SetEnabled(Value: Boolean); override;
    procedure SetOnExecute(Value: TNotifyEvent); override;
    procedure SetVisible(Value: Boolean); override;
  end;

  TColumnActionLinkClass = class of TColumnActionLink;

  TColumn = class(TCollectionItem)
  private
    FActionLink: TColumnActionLink;
    FGrid: TComponent;
    FOnTitleClick: TNotifyEvent;
    FReadOnly: Boolean;
    FTitle: String;
    FVisible: Boolean;
    function DefaultTitleCaption: String;
    procedure DoActionChange(Sender: TObject);
    function GetAction: TBasicAction;
    function IsOnTitleClickStored: Boolean;
    function IsReadOnlyStored: Boolean;
    function IsVisibleStored: Boolean;
    procedure SetAction(Value: TBasicAction);
  protected
    procedure ActionChanged(Sender: TObject; CheckDefaults: Boolean); dynamic;
    procedure DoTitleClick; virtual;
    function GetActionLinkClass: TColumnActionLinkClass; virtual;
    property ActionLink: TColumnActionLink read FActionLink write FActionLink;
  public
    destructor Destroy; override;
    procedure InitiateAction; virtual;
  published
    property Action: TBasicAction read GetAction write SetAction;
    property OnTitleClick: TNotifyEvent read FOnTitleClick write FOnTitleClick
      stored IsOnTitleClickStored;
    property ReadOnly: Boolean read FReadOnly write FReadOnly
      stored IsReadOnlyStored;
    property Title: String read FTitle write FTitle;
    property Visible: Boolean read FVisible write FVisible
      stored IsVisibleStored;
  end;

implementation

{ TColumnActionLink }

procedure TColumnActionLink.AssignClient(AClient: TObject);
begin
  FClient := TColumn(AClient);
end;

function TColumnActionLink.IsCaptionLinked: Boolean;
begin
  Result := inherited IsCaptionLinked and (Action is TCustomAction) and
    (FClient.Title = TCustomAction(Action).Caption);
end;

function TColumnActionLink.IsEnabledLinked: Boolean;
begin
  Result := inherited IsEnabledLinked and (Action is TCustomAction) and
    (FClient.ReadOnly <> TCustomAction(Action).Enabled);
end;

function TColumnActionLink.IsOnExecuteLinked: Boolean;
begin
  Result := inherited IsOnExecuteLinked and
    (@FClient.OnTitleClick = @Action.OnExecute);
end;

function TColumnActionLink.IsVisibleLinked: Boolean;
begin
  Result := inherited IsVisibleLinked and (Action is TCustomAction) and
    (FClient.Visible = TCustomAction(Action).Visible);
end;

procedure TColumnActionLink.SetCaption(const Value: string);
begin
  if IsCaptionLinked then
    FClient.Title := Value;
end;

procedure TColumnActionLink.SetEnabled(Value: Boolean);
begin
  if IsEnabledLinked then
    FClient.ReadOnly := not Value;
end;

procedure TColumnActionLink.SetOnExecute(Value: TNotifyEvent);
begin
  if IsOnExecuteLinked then
    FClient.OnTitleClick := Value;
end;

procedure TColumnActionLink.SetVisible(Value: Boolean);
begin
  if IsVisibleLinked then
    FClient.Visible := Value;
end;

{ TColumn }

procedure TColumn.ActionChanged(Sender: TObject; CheckDefaults: Boolean);
begin
  if Sender is TCustomAction then
    with TCustomAction(Sender) do
    begin
      if not CheckDefaults or (Caption = DefaultTitleCaption) then
        FTitle := Caption;
      if not CheckDefaults or (not ReadOnly) then
        ReadOnly := not Enabled;
      if not CheckDefaults or not Assigned(FOnTitleClick) then
        FOnTitleClick := OnExecute;
      if not CheckDefaults or (Self.Visible = True) then
        Self.Visible := Visible;
      Changed(False);
    end;
end;

function TColumn.DefaultTitleCaption: String;
begin
  Result := 'Column' + IntToStr(Index);
end;

destructor TColumn.Destroy;
begin
  FreeAndNil(FActionLink);
  inherited Destroy;
end;

procedure TColumn.DoActionChange(Sender: TObject);
begin
  if Sender = Action then
    ActionChanged(Sender, False);
end;

procedure TColumn.DoTitleClick;
begin
  if Assigned(FOnTitleClick) then
    if (Action <> nil) and (@FOnTitleClick <> @Action.OnExecute) then
      FOnTitleClick(Self)
    else if FActionLink = nil then
      FOnTitleClick(Self)
    else if FActionLink <> nil then
      if (FGrid <> nil) and not (csDesigning in FGrid.ComponentState) then
      begin
        if not FActionLink.Execute(FGrid) then
          FOnTitleClick(Self);
      end
      else
        if not FActionLink.Execute(nil) then
          FOnTitleClick(Self);
end;

function TColumn.GetAction: TBasicAction;
begin
  if FActionLink <> nil then
    Result := FActionLink.Action
  else
    Result := nil;
end;

function TColumn.GetActionLinkClass: TColumnActionLinkClass;
begin
  Result := TColumnActionLink;
end;

procedure TColumn.InitiateAction;
begin
  if FActionLink <> nil then
    FActionLink.Update;
end;

function TColumn.IsOnTitleClickStored: Boolean;
begin
  Result := (FActionLink = nil) or not ActionLink.IsOnExecuteLinked;
end;

function TColumn.IsReadOnlyStored: Boolean;
begin
  Result := (FActionLink = nil) or not FActionLink.IsEnabledLinked;
  if Result then
    Result := FReadOnly;
end;

function TColumn.IsVisibleStored: Boolean;
begin
  Result := (FActionLink = nil) or not FActionLink.IsVisibleLinked;
  if Result then
    Result := not Visible;
end;

procedure TColumn.SetAction(Value: TBasicAction);
begin
  if Value = nil then
    FreeAndNil(FActionLink)
  else
  begin
    if FActionLink = nil then
      FActionLink := GetActionLinkClass.Create(Self);
    FActionLink.Action := Value;
    FActionLink.OnChange := DoActionChange;
    ActionChanged(Value, csLoading in Value.ComponentState);
    if FGrid <> nil then
      Value.FreeNotification(FGrid);
  end;
  Changed(False);
end;

end.

Beachten Sie, dass dieser Code nur an die entsprechenden Aktionsteile abgezogen wird.

Quelle: www.nldelphi.com.

Eine Aktionskomponente

Eine Aktionskomponente ist der Aktionseigenschaft einer willkürlichen Komponente zugeordnet. Doch da es ziemlich umfassend ist, alles zu erklären, was mit dem Schreiben einer solchen Aktionskomponente beteiligt ist, werde ich es mir leicht machen, das folgende Beispiel anzugeben.

Angenommen, Sie möchten ein Steuerelement erstellen, das Zoomfunktionen bietet und auch die entsprechenden Zoomin- und Zoomout -Aktionen möchten, die den Symbolleistenschaltflächen zugeordnet werden können.

unit Zoomer;

interface

uses
  Classes, Controls, ActnList, Forms, Menus, Windows;

type
  TZoomer = class;

  TZoomAction = class(TCustomAction)
  private
    FZoomer: TZoomer;
    procedure SetZoomer(Value: TZoomer);
  protected
    function GetZoomer(Target: TObject): TZoomer;
    procedure Notification(AComponent: TComponent; Operation: TOperation);
      override;
  public
    destructor Destroy; override;
    function HandlesTarget(Target: TObject): Boolean; override;
    procedure UpdateTarget(Target: TObject); override;
  published
    property Caption;
    property Enabled;
    property HelpContext;
    property HelpKeyword;
    property HelpType;
    property Hint;
    property ImageIndex;
    property ShortCut;
    property SecondaryShortCuts;
    property Visible;
    property OnExecute; { This property could be omitted. But if you want to be
                          able to override the default behavior of this action
                          (zooming in on a TZoomer component), then you need to
                          assign this event. From within the event handler
                          you could invoke the default behavior manually. }
    property OnHint;
    property OnUpdate;
    property Zoomer: TZoomer read FZoomer write SetZoomer;
  end;

  TZoomInAction = class(TZoomAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TZoomer = class(TCustomControl)
  public
    procedure ZoomIn;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('RoyMKlever', [TZoomer]);
  RegisterActions('Zoomer', [TZoomInAction], nil);
end;

{ TZoomAction }

destructor TZoomAction.Destroy;
begin
  if FZoomer <> nil then
    FZoomer.RemoveFreeNotification(Self);
  inherited Destroy;
end;

function TZoomAction.GetZoomer(Target: TObject): TZoomer;
begin
  if FZoomer <> nil then
    Result := FZoomer
  else if (Target is TZoomer) and TZoomer(Target).Focused then
    Result := TZoomer(Target)
  else if Screen.ActiveControl is TZoomer then
    Result := TZoomer(Screen.ActiveControl)
  else
    { This should not happen! HandlesTarget is called before ExecuteTarget,
      or the action is disabled }
    Result := nil;
end;

function TZoomAction.HandlesTarget(Target: TObject): Boolean;
begin
  Result := ((FZoomer <> nil) and FZoomer.Enabled) or
    ((FZoomer = nil) and (Target is TZoomer) and TZoomer(Target).Focused) or
    ((Screen.ActiveControl is TZoomer) and Screen.ActiveControl.Enabled);
end;

procedure TZoomAction.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (AComponent = FZoomer) then
    FZoomer := nil;
end;

procedure TZoomAction.SetZoomer(Value: TZoomer);
begin
  if FZoomer <> Value then
  begin
    if FZoomer <> nil then
      FZoomer.RemoveFreeNotification(Self);
    FZoomer := Value;
    if FZoomer <> nil then
      FZoomer.FreeNotification(Self);
  end;
end;

procedure TZoomAction.UpdateTarget(Target: TObject);
begin
  Enabled := HandlesTarget(Target);
end;

{ TZoomInAction }

constructor TZoomInAction.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Caption := 'Zoom in';
  Hint := 'Zoom in|Zooms in on the selected zoomer control';
  ShortCut := Menus.ShortCut(VK_ADD, [ssCtrl]);
end;

procedure TZoomInAction.ExecuteTarget(Target: TObject);
begin
  GetZoomer(Target).ZoomIn;
  { For safety, you cóuld check if GetZoomer <> nil. See remark in GetZoomer. }
end;

{ TZoomer }

procedure TZoomer.ZoomIn;
begin
  { implementation of zooming in }
end;

end.

Aktivieren Sie diese Aktion (mit einem Klick auf eine Symbolleistenschaltfläche oder Auswählen eines Menüelements).

  1. Die Zoomer -Steuerung, die Sie manuell in der inhaltlichen Eigenschaft der Aktion eingestellt haben, wenn dies ausgeführt wird und wenn die Aktion aktiviert ist, sonst:
  2. die von der von der Bewerbung angeforderten Antrag Ziel, aber nur, wenn dieses Ziel eine fokussierte Zoomer -Kontrolle ist oder auf andere Weise:
  3. Die aktive Steuerung in der gesamten Anwendung, jedoch nur dann, wenn dies eine fähige Zoomer -Steuerung ist.

Anschließend wird die Zoomout -Aktion einfach hinzugefügt:

type
  TZoomOutAction = class(TZoomAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

{ TZoomOutAction }

constructor TZoomOutAction.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Caption := 'Zoom out';
  Hint := 'Zoom out|Zooms out on the selected zoomer control';
  ShortCut := Menus.ShortCut(VK_SUBTRACT, [ssCtrl]);
end;

procedure TZoomOutAction.ExecuteTarget(Target: TObject);
begin
  GetZoomer(Target).ZoomOut;
end;

Beachten Sie, dass Aktionskomponenten eine Registrierung in der IDE erfordern, damit sie die Entwurfszeit verwenden können.

Lesen Sie Lebensmittel in der Delphi -Hilfe:

Quelle: www.nldelphi.com.

Andere Tipps

Grundlegende Aktionsunterstützung wird in der TControl -Klasse implementiert. Im einfachsten Fall müssen Sie Ihre Komponente von TControl Nachkommen und Deklary erben Action Eigentum wie veröffentlicht, z.

type
  TMyGraphicControl = class(TGraphicControl)
  published
    property Action;
  end;

Wenn Ihre Komponente über zusätzliche Eigenschaften verfügt, die mit Taction -Eigenschaften verknüpft werden sollten, sollten Sie auch überschreiben ActionChange Methode.

Wenn Ihre Komponente bereits ein Nachkomme von Tbutton ist, wird die Aktionsunterstützung vererbt. Alles, was Sie tun müssen, ist die Aktionseigenschaft wie veröffentlicht zu deklarieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top