Конференция "Компоненты" » Потомок TActionList [D7, Win2k]
 
  • alexnmsk (03.03.08 15:16) [0]
    Для разных приложений потребуется одинаковый набор действий TAction. Хочу создать компонент - потомок TActionList и набор TAction. Можно ли создать такой компонент? То есть как я разумею, он при помещении на форму в Design-time должен создавать набор TAction, которые смогли бы быть доступны свойству Action, например в Button.
  • Семеныч (03.03.08 15:38) [1]
    > Можно ли создать такой компонент?

    А почему нет?

    > То есть как я разумею, он при помещении на форму в Design-time должен
    > создавать набор TAction

    В конструкторе:
    if csDesigning in ComponentState then создать_набор;  

    > которые смогли бы быть доступны свойству Action, например в Button.

    При регистрации своих TAction вызовите еще и RegisterActions.
  • DimaBr © (03.03.08 15:51) [2]

    > В конструкторе:
    > if csDesigning in ComponentState then создать_набор;

    Маленькая неувязочка, сначала создадим, потом считаем из ресурса, что получим в итоге ? (два набора Action)
  • alexnmsk (03.03.08 15:54) [3]

    > В конструкторе:
    > if csDesigning in ComponentState then создать_набор;  

    Вот тут то и проблемы. Все создается, но в Design-time при чтении формы (например, после просмотра View as Text) конструктор вызывается заново и пытается создать уже существующий объект, или если TMyAction.Name='', то плодит их :(
  • DimaBr © (03.03.08 16:02) [4]
    Ну вот, я угадал !!!
  • DimaBr © (03.03.08 16:07) [5]
    Попробуйте так

    TMyAction = class(TAction)
     private
       fLoaded: boolean;
     public
       procedure Loaded;override;
    end;

    TЬнActionList = class(TActionList)
     public
       constructor Create(AOwner: TComponent); override;
       procedure Loaded;override;
    end;

    constructor TЬнActionList.Create(AOwner: TComponent);
    var DefAction: TAction;
    begin
     inherited Create(AOwner);
     if csDesigning in ComponentState then begin
       DefAction := TMyAction.Create(AOwner);
       DefAction.ActionList := self;
     end;
    end;

    procedure TMyActionList.Loaded;
    var i: integer;
    begin
     inherited Loaded;
     for i := 0 to ActionCount-1 do
       if Actions[i] is TMyAction then
         if not TMyAction(Actions[i]).fLoaded then Actions[i].Free;
    end;

    { TMyAction }

    procedure TMyAction.Loaded;
    begin
     inherited Loaded;
     fLoaded := true;
    end;

  • alexnmsk (03.03.08 16:09) [6]
    А есть решение?
    Можно ли как нибудь в конструкторе узнать, например когда компонент помещается на форму или когда читается из ресурса?
  • DimaBr © (03.03.08 16:19) [7]
    В конструкторе  - нет. Остаётся только создавать безимянные Action-ы
  • Семеныч (03.03.08 16:24) [8]
    > alexnmsk   (03.03.08 16:09) [6]

    > Можно ли как нибудь ... узнать... когда компонент ... читается из ресурса?

    if csLoading in ComponentState then компонент_читается_из_ресурса

    То есть, в конструкторе нужна двойная проверка:

    if (csDesigning in ComponentState) and not (csLoading in ComponentState) then
     создать_набор_TAction
  • Семеныч (03.03.08 16:27) [9]
    Или можно так: в конструкторе создаем набор всегда, а в Loaded сначала этот набор грохаем, а потом вызываем inherited.
  • Семеныч (03.03.08 16:35) [10]
    Сорри, фигню сказал в [9].
  • alexnmsk (03.03.08 16:52) [11]

    > Попробуйте так

    Работает!!! с небольшими изменениями. Проблема с именами


    > В конструкторе  - нет. Остаётся только создавать безимянные
    > Action-ы

    К сожалению, тогда их не назначить контролам. Ща подумаю что нибудь.


    > if csLoading in ComponentState then компонент_читается_из_ресурса

    Не появляется csLoading в конструкторе
  • DimaBr © (03.03.08 16:54) [12]
    Проверка на csLoading in ComponentState в кончструкторе бессмысленна
  • DimaBr © (03.03.08 16:59) [13]
    Готово !

    unit MyActionList;

    interface

    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
     Dialogs, StdCtrls, ActnList;

    type
    TMyAction = class(TAction)
     private
       fDesignCreate: boolean;
     public
       procedure SetName(const NewName: TComponentName);override;
    end;

    TMyActionList = class(TActionList)
     public
       constructor Create(AOwner: TComponent); override;
    end;
    procedure Register;

    implementation

    { TActionList }
    procedure Register;
    begin
     RegisterComponents('Standard',[TMyActionList]);
     RegisterNoIcon([TMyAction]);
    end;

    constructor TMyActionList.Create(AOwner: TComponent);
    var DefAction: TMyAction;
       i: integer;
    begin
     inherited Create(AOwner);
     if csDesigning in ComponentState then begin
       DefAction := TMyAction.Create(AOwner);
       DefAction.ActionList := self;
       DefAction.fDesignCreate := true;
       i := 1;
       while 1 = 1 do
         try
           DefAction.Name := 'MyAction'+IntToStr(I);
           Break;
         except
           Inc(i);
         end;
     end;
    end;

    { TMyAction }

    procedure TMyAction.SetName(const NewName: TComponentName);
    var C: TComponent;
    begin
     if not fDesignCreate then begin
        C := Owner.FindComponent(NewName);
        if Assigned(C) then C.Free;
      end;
     inherited
    end;

    initialization
     RegisterClass(TMyAction);
    end.


  • alexnmsk (03.03.08 17:21) [14]

    > DimaBr

    Ура!!! Работает! Огробное спасибо, буду разбираться..
  • DimaBr © (04.03.08 08:41) [15]
    Елементарно, вот дурак, совсем голову запудрили.
    Если вам нужно только добавлять несколько Action и на этом функционал вашего компонента заканчивается, то посмотрите в сторону Create ComponentTemplate...
    Два клика и компонент готов. Причём даже с кодом...
 
Конференция "Компоненты" » Потомок TActionList [D7, Win2k]
Есть новые Нет новых   [134464   +62][b:0][p:0.002]