我想实现如下的功能MDI主窗体中的工具栏的可用性控制
当Child窗体中的DBGridEH处于活动状态是,工具栏可用,否则不可以
因为有很多的CHild,所以不可能在每个窗体中的DBGridEH中的事件中写入代码我现在的实现方法是:
在MDI窗体中用自定义消息处理代码。
在每个窗体中向主窗体中SENDMESSAGE(),这样还要在每个窗体中加入部分代码不能像系统的复制,剪切等action那样,是自动接收消息的,我就像实现这种效果。
 谢谢了先

解决方案 »

  1.   

    老冯 你有没有MSN的啊 交个朋友 加我一个 [email protected]
      

  2.   

    zuoansuifeng 把你的方法举个例子说说来吧
    我学习下先
      

  3.   

    刚刚米西米西完,比较长:  IObserver = interface
      ['{D6E975DE-338D-4558-8C00-8F6FB608CC49}']
        procedure Update(const Subject: IInterface);
      end;  ISubject = interface
      ['{13BF13FC-09A5-4321-888C-9A29BD0AE893}']
        procedure Attach(const Observer: IObserver);
        procedure Detach(const Observer: IObserver);
        procedure BeginUpdate;
        procedure EndUpdate;
        procedure Notify;
        function GetHasFocused: Boolean;
        procedure SetHasFocused(const Value: Boolean);
        property HasFocused: Boolean read GetHasFocused write SetHasFocused;
      end;  TSubject = class(TInterfacedObject, ISubject)
      private
        FObservers: IInterfaceList;
        FController: Pointer;
        FUpdateCount: Integer;
        FHasFocused: Boolean;
        function GetController: IInterface;
      protected
        //ISubject
        procedure Attach(const Observer: IObserver);
        procedure Detach(const Observer: IObserver);
        procedure BeginUpdate;
        procedure EndUpdate;
        procedure Notify;
        function GetHasFocused: Boolean;
        procedure SetHasFocused(const Value: Boolean);
      public
        constructor Create(const Controller: IInterface); virtual;
        destructor Destroy; override;
      end;implementation{ TSubject }procedure TSubject.Attach(const Observer: IObserver);
    begin
      if FObservers = nil then
        FObservers := TInterfaceList.Create;
      if FObservers.IndexOf(Observer) < 0 then
        FObservers.Add(Observer);
    end;procedure TSubject.BeginUpdate;
    begin
      Inc(FUpdateCount);
    end;constructor TSubject.Create(const Controller: IInterface);
    begin
      inherited Create;
      FController := Pointer(Controller);
      FUpdateCount := 0;
    end;destructor TSubject.Destroy;
    begin
      inherited;
    end;procedure TSubject.Detach(const Observer: IObserver);
    begin
      if FObservers <> nil then
      begin
        if FObservers.IndexOf(Observer) >= 0 then
        begin
          FObservers.Remove(Observer);
          if FObservers.Count = 0 then
            FObservers := nil;
        end;
      end;
    end;procedure TSubject.EndUpdate;
    begin
      Dec(FUpdateCount);
      if FUpdateCount = 0 then
        Notify;
    end;function TSubject.GetController: IInterface;
    begin
      Result := IInterface(FController);
    end;function TSubject.GetHasFocused: Boolean;
    begin
      Result := FHasFocused;
    end;procedure TSubject.Notify;
    var
      Idx: Integer;
    begin
      if FObservers <> nil then
        for Idx := 0 to Pred(FObservers.Count) do
          if FObservers[Idx] <> nil then
            (FObservers[Idx] as IObserver).Update(GetController);
    end;procedure TSubject.SetHasFocused(const Value: Boolean);
    begin
      FHasFocused := Value;
    end;  IObserverRegister = interface
      ['{CFDDEC69-A8FC-4C41-92E2-8F223AFAC88F}']
        procedure RegisterObserver(const Subject: ISubject);
        procedure UnRegisterObserver(const Subject: ISubject);
      end;TObserverRegister = class(TInterfacedObject, IObserverRegister)
      private
      protected
        //IObserverRegister
        procedure RegisterObserver(const Subject: ISubject);
        procedure UnRegisterObserver(const Subject: ISubject);
        //SingleTon
        constructor CreateInstance;
        class function GetInstance(Request: Integer): TObserverRegister;
      public
        constructor Create;
        destructor Destroy; override;
        //SingleTon
        class procedure ReleaseInstance;
        class function Instance: TObserverRegister;
      end;implementationuses Sysutils, Observer.Mainform, Observer.ObserverIntf;{$J+}{ TObserverRegister }constructor TObserverRegister.Create;
    begin
      inherited Create;
      raise Exception.CreateFmt('只能通过Instance方法来创建和访问%s的实例', [ClassName]);
    end;constructor TObserverRegister.CreateInstance;
    begin
      inherited Create;
      _AddRef;
    end;destructor TObserverRegister.Destroy;
    begin
      if GetInstance(0) = Self then Getinstance(2);
      inherited;
    end;class function TObserverRegister.GetInstance(
      Request: Integer): TObserverRegister;
    const
      FInstance: TObserverRegister = nil;
    begin
      case Request of
        0:;
        1: if not assigned(FInstance) then Finstance := CreateInstance;
        2: Finstance := nil;
      else
        raise Exception.CreateFmt('%d是GetInstance()中的非法参数', [Request]);
      end;
      Result := FInstance;
    end;class function TObserverRegister.Instance: TObserverRegister;
    begin
      Result := GetInstance(1);
    end;procedure TObserverRegister.RegisterObserver(const Subject: ISubject);
    begin
      Subject.Attach(IObserver(MainForm));
    end;class procedure TObserverRegister.ReleaseInstance;
    begin
      GetInstance(0).Free;
    end;procedure TObserverRegister.UnRegisterObserver(const Subject: ISubject);
    begin
      Subject.Detach(IObserver(MainForm));
    end;  TBaseChildform = class(TForm, ISubject)
        DBGrid: TDBGrid;
        Edit: TEdit;
        procedure FormCreate(Sender: TObject);
        procedure DBGridEnter(Sender: TObject);
        procedure DBGridExit(Sender: TObject);
        procedure FormDeactivate(Sender: TObject);
      private
        FSubject: ISubject;
      protected
        property Subject: ISubject read FSubject implements ISubject;
      public
      end;implementationuses Observer.ObserverRegisterImpl, Observer.ObserverRegisterIntf,
      Observer.SubjectImpl;{$R *.dfm}procedure TBaseChildform.FormCreate(Sender: TObject);
    begin
      FSubject := TSubject.Create(Self);
      (TObserverRegister.Instance as IObserverRegister).RegisterObserver(Self);
      //FSubject.HasFocused := False;
      //FSubject.Notify;
    end;procedure TBaseChildform.DBGridEnter(Sender: TObject);
    begin
      FSubject.HasFocused := True;
      FSubject.Notify;
    end;procedure TBaseChildform.DBGridExit(Sender: TObject);
    begin
      FSubject.HasFocused := False;
      FSubject.Notify;
    end;procedure TBaseChildform.FormDeactivate(Sender: TObject);
    begin
      FSubject.HasFocused := False;
      FSubject.Notify;
    end;  TMainform = class(TForm, IObserver)
        ToolBar: TToolBar;
        ToolButton1: TToolButton;
        procedure ToolButton1Click(Sender: TObject);
      private
        procedure IObserver.Update = ObserverUpdate;
        procedure ObserverUpdate(const Subject: IInterface);
      public
        { Public declarations }
      end;var
      Mainform: TMainform;implementationuses Observer.BaseChildform, Observer.SubjectIntf;{$R *.dfm}{ TMainform }procedure TMainform.ObserverUpdate(const Subject: IInterface);
    var
      Obj: ISubject;
    begin
      Subject.QueryInterface(ISubject, Obj);
      if Obj <> nil then
        ToolBar.Enabled := Obj.HasFocused;
    end;procedure TMainform.ToolButton1Click(Sender: TObject);
    begin
      TBaseChildform.Create(nil);
    end;
      

  4.   

    其实对于此类问题,如何获取消息不是很重要的。(各类消息API都有详尽说明),关键是如何协调消息发送者和接收者之间的关系。
      

  5.   

    晕到, 这么麻烦, 不是每个窗口都要实现那个接口Screen->ActiveControl 就是了, 在任何地方都可以用这段代码if Screen.ActiveControl is TDBGridEh then
    begin
    end;比方你放在 Action Update 里(Sender as TAction).Enabled := Screen.ActiveControl is TDBGridEh;在 ActionExecute 里if Screen.ActiveControl is TDBGridEh then
    begin
      Grid := Screen.ActiveControl as TDBGridEh;
      Grid...
    end;
      

  6.   

    老冯,我不知道把这段代码防盗锁什么地方,
    另外,我看这个代码也要每次在child窗体加入代码是不是?
    请再说明一下吧,看的吃力的很。
    我做Delphi不久,以前是做Flash的。呵呵
      

  7.   

    他这段可用作的地方比较多, 相当于定义一个通用接口, 说个比方, 你现在有几十个同类窗口, 内存不见得一样, 但行为一样, 比方说都有打开, 保存, 关闭, 这下由 MainForm 调度打开时, 是不是得 if Form is XXXForm then 
    else if 
    else if
    ...定义好调用调用方法后就没必要了
    (Form as IObserver).Save
    这只是好处之一这只是多态的一种用法, 一般 C++ 用户不这么说, C++ 可以定义一个基类(delphi 也行), 作 TObserver 的功能, 所有子窗体从 TObserverForm 中派生, 或是用多重基类也行(delphi 就不行了)delphi 没法定义这样一个基类, 因为 TMainForm 是 ide 管理的, 你也可以去改 TMainForm=class(TForm) 定义成 TMainForm=class(TObserverForm), 不过一般不这样, 而是用上面这种办法
      

  8.   

    今天长见识了,我用的 comanche 的方法,我完成了功能的设置
    但是对观察模式,很赶兴趣,决定学习下先,相信老冯的方法一定可以的,只是我还没有搞明白。
    谢谢各位!