procedure TControl.Click;
begin
  { Call OnClick if assigned and not equal to associated action's OnExecute.
    If associated action's OnExecute assigned then call it, otherwise, call
    OnClick. }
  if Assigned(FOnClick) and (Action <> nil) and (@FOnClick <> @Action.OnExecute) then
    FOnClick(Self)
  else if not (csDesigning in ComponentState) and (ActionLink <> nil) then
    ActionLink.Execute
  else if Assigned(FOnClick) then
    FOnClick(Self);
end;
//这段代码是什么意思呀

解决方案 »

  1.   

    csDesigning in ComponentState这又是什么东东?
      

  2.   

    function Assigned(const P): Boolean;DescriptionUse Assigned to determine whether the pointer or procedure referenced by P is nil. P must be a variable reference of a pointer or procedural type. Assigned(P) corresponds to the test P<> nil for a pointer variable, and @P <> nil for a procedural variable.Assigned returns False if P is nil, True otherwise.Note: Assigned can't detect a dangling pointer--that is, one that isn't nil but no longer points to valid data. For example, in the code example for Assigned, Assigned won't detect the fact that P isn't valid.
      

  3.   

    Describes the current state of the component, indicating when a component needs to avoid certain actions.type TComponentState = set of (csLoading, csReading, csWriting, csDestroying, csDesigning, csAncestor, csUpdating, csFixups, csFreeNotification, csInline, csDesignInstance);property ComponentState: TComponentState;DescriptionComponents use the ComponentState property to detect states in which certain kinds of actions are allowed or disallowed. For example, if a component needs to avoid certain behaviors at design time that it performs at runtime, it can check for the csDesigning flag. ComponentState is read-only and its flags are set automatically when appropriate.The TComponentState type defines the set of possible state flags for the ComponentState property. The following table lists the possible values for the TComponentState type and the meaning corresponding to each flag:Flag Component statecsAncestor The component was introduced in an ancestor form. Only set if csDesigning is also set.
    csDesigning The component is in a form being manipulated by the form designer.
    csDestroying The component is about to be destroyed.
    csFixups The component is linked to a component in another form that has not yet been loaded. This flag is cleared when all pending fixups are resolved.
    csFreeNotification One or more other components have requested that this component notify them when it is destroyed. This flag is set when another component calls this component抯 FreeNotification method.csInline The component is a top-level component that can be modified at design time and also embedded in a form. This flag is used to identify nested frames while loading and saving.
    csLoading A filer object is currently loading the component. This flag is set when the component is first created and not cleared until the component and all its children are fully loaded (when the Loaded method is called).
    csReading The component is reading its property values from a stream. Note that the csLoading flag is always set as well when csReading is set. That is, csReading is set for the subinterval of the time when a component is loading that covers reading in property values.csUpdating The component is being updated to reflect changes in an ancestor form. Only set if csAncestor is also set.
    csWriting The component is writing its property values to a stream.
    csDesignInstance The component is the root object in a designer. For example, it is set for a frame when you are designing it, but not on a frame that acts like a component. This flag always appears with csDesigning.
      

  4.   

    标准函数Assigned用于测试变量是否被赋予非空的值。函数声明如下:function Assigned(const P): Boolean;如果P是一个非程序型,那么当表达式P <> nil返回True时,Assigned(P)返回True;当表达式P = nil返回True时,Assigned(P)返回False。如果P是一个程序型,那么当表达式@P <> nil返回True时,Assigned(P)返回True;当表达式@P = nil返回True时,Assigned(P)返回False。可见,Assigned函数测试的是P或@P的值是否是空指针值nil。从另一方面说,Assigned函数不会检查非程序型的P是否指向有效的数据。例如, var P: Pointer;begin  P := nil;  if Assigned(P) then ...{此语句中Assigned(P)返回False}  GetMem(P, 1024);   {执行后,P指向有效的存储空间}  FreeMem(P, 1024);  {执行后,P不再指向有效的存储空间,但其值仍不是空指针值nil}  if Assigned(P) then ...{此语句中Assigned(P)返回True}end;
      

  5.   

    csDesigning in ComponentState这是控件包里才有的代码.判断组件是否在DELPHI中的IDE环境中运行.
      

  6.   

    FOnClick(Self);就是执行存储在其中的过程
      

  7.   

    procedure TControl.Click;
    begin
      { Call OnClick if assigned and not equal to associated action's OnExecute.
        If associated action's OnExecute assigned then call it, otherwise, call
        OnClick. }
      if Assigned(FOnClick) and (Action <> nil) and (@FOnClick <> @Action.OnExecute) then//如果FOnClick已被赋值,并且Action属性不为空,并且FOnClick不等于Action组件的OnExecute,则
        FOnClick(Self)//触发OnClick事件
      else if not (csDesigning in ComponentState) and (ActionLink <> nil) then//否则,如果控件不处在设计时刻,并且ActionLink属性不为空,则
        ActionLink.Execute//触发Action组件的OnExecute事件
      else if Assigned(FOnClick) then//其他情况,只要FOnClick存在,则
        FOnClick(Self);//触发OnClick事件
    end;
      

  8.   

    Assigned(FOnClick) 是判断有没有编写OnClick事件句柄,有就返回真。
    (Action <> nil) 判断有没有挂接一个Action。
    (@FOnClick <> @Action.OnExecute) 判断组件的OnClick是不是挂接了Action的OnExecute事件。
    csDesigning in ComponentState 判断组件是不是处于设计期。由此可以看出事件句柄的执行顺序。说实话,我对这几句也没有理解透彻。
    我来研究一下在接帖。
      

  9.   

    请教一下:stargazer(星空守望者)
    Action.OnExecute和ActionLink.Execute有什么联系和区别?
    我觉得这段代码好乱,是不是应该反过来写?
      

  10.   

    跟了半个多小时,我晕了。
    现在牵涉到四个:
    组件本身的OnClick,
    ActionList的OnExecute,
    Action的OnExecute,
    ActionLink的Execute。我发现组件本身的OnClick,优先级是最高的,然后是ActionList的OnExecute(它和ActionLink的Execute有什么区别?),最后才是Action的OnExecute。还有:当点一下按钮后,delphi会两次调用TControl.Click;
      

  11.   

    not (csDesigning in ComponentState) 
    这表示如果不在设计期以下代码才执行,即运行期才执行
      

  12.   

    一个例子
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ActnList, StdCtrls;type
      TMainForm = class(TForm)
        ActionList1: TActionList;
        Action1: TAction;
        Button1: TButton;
        procedure Action1Execute(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      MainForm: TMainForm;implementation{$R *.dfm}procedure TMainForm.Action1Execute(Sender: TObject);
    begin
      ShowMessage('Action1Execute');
    end;procedure TMainForm.Button1Click(Sender: TObject);
    begin
      ShowMessage('Button1Click');
    end;end.先把Button1.OnClick设为Button1Click,action不设置
    点按钮procedure TControl.Click;
    begin
      { Call OnClick if assigned and not equal to associated action's OnExecute.
        If associated action's OnExecute assigned then call it, otherwise, call
        OnClick. }
      if Assigned(FOnClick) and (Action <> nil) and (@FOnClick <> @Action.OnExecute) then
        FOnClick(Self)
      else if not (csDesigning in ComponentState) and (ActionLink <> nil) then
        ActionLink.Execute(Self)
      else if Assigned(FOnClick) then
        FOnClick(Self);
    end;
    那么执行到
      else if Assigned(FOnClick) then
        FOnClick(Self);
    接着在把action与Action1关联上,Button.OnClick为Button1Click,点按钮
    执行的是  if Assigned(FOnClick) and (Action <> nil) and (@FOnClick <> @Action.OnExecute) then
        FOnClick(Self)
    也就是ylmg说的当一个按钮有OnClick事件句柄和Action,以执行OnClick为先把按扭的OnClick事件删掉,只剩下Action,点按钮,执行的是
     else if not (csDesigning in ComponentState) and (ActionLink <> nil) then
        ActionLink.Execute(Self)
    因为按钮有Action,所以ActionLink不为nil,
    可以从下面看到
    procedure TControl.SetAction(Value: TBasicAction);
    begin
      if Value = nil then
      begin
        ActionLink.Free;
        ActionLink := nil;
        Exclude(FControlStyle, csActionClient);
      end
      else
      begin
        Include(FControlStyle, csActionClient);
        if ActionLink = nil then
          ActionLink := GetActionLinkClass.Create(Self);
        ActionLink.Action := Value;
        ActionLink.OnChange := DoActionChange;
        ActionChange(Value, csLoading in Value.ComponentState);
        Value.FreeNotification(Self);
      end;
    end;
    而且是运行时即 not (csDesigning in ComponentState)
    执行ActionLink.Execute,也就执行Action1.OnExecute,具体可以在跟下去
    这个就是保证当Button的Action设为Action1而OnClick没有事件句柄时
    而执行到Action1.OnExecute