MDIForm的罪恶

来源:互联网 发布:幼儿园主题网络图片 编辑:程序博客网 时间:2024/04/28 18:50

在MDI应用程序中有个奇怪的问题, 当你执行以下代码时你会看到一个奇怪的结果

 

假设目前你已开了3个MDI子窗口

 

Procedure Button1Click(Sender: TObject)

Begin

       ShowMessage(IntToStr(MDIChildCount)); // 很显然结果等于3

      

    If Assigned(ActiveMDIChild) then ActiveMDIChild.Close;

 

ShowMessage(IntToStr(MDIChildCount));  // 这个时候结果应该是几?

End;

 

很奇怪结果并不象想像当中的那样因该是2, 而是依然是3, 为什么?

如何解释这个现象呢? 因为它还没有真正的被释放。那么什么它才会被释放呢。

procedure TCustomForm.Close;

var

  CloseAction: TCloseAction;

begin

  if fsModal in FFormState then

    ModalResult := mrCancel

  else

    if CloseQuery then

    begin

      if FormStyle = fsMDIChild then

        if biMinimize in BorderIcons then

          CloseAction := caMinimize else

          CloseAction := caNone

      else

        CloseAction := caHide;

      DoClose(CloseAction);

      if CloseAction <> caNone then

        if Application.MainForm = Self then Application.Terminate

        else if CloseAction = caHide then Hide

        else if CloseAction = caMinimize then WindowState := wsMinimized

        else Release; // 看看Release 中是什么?

    end;

end;

{ 很简单的发了个消息 }

procedure TCustomForm.Release;

begin

  PostMessage(Handle, CM_RELEASE, 0, 0);

end;

 

 

    procedure CMRelease(var Message: TMessage); message CM_RELEASE;

    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;

    procedure CMUIActivate(var Message); message CM_UIACTIVATE;

 

 

procedure TCustomForm.CMRelease;

begin

  Free;// 原来真正的Free在这里。

end;

 

从上面这些代码就可以基本猜出为什么会有上面的现象了。

ActiveMDIChild.Close

   SendMessage(Handle, CMRelease); // 消息进入到消息队列没有马上实行

 

  ShowMessage(IntToStr(MDIChindCount)); // 这个时候还没有真正的Free.

   //所以我门得到的是错误的结果, 好了知道了原因事情就好办多了。接下来我们来解决它。

 

 

Procedure Button1Click(Sender: TObject)

Var

       Ret: Boolean;

    Msg: tagMsg;

Begin

       ShowMessage(IntToStr(MDIChildCount)); // 很显然结果等于3

      

    If Assigned(ActiveMDIChild) then

    Begin

ActiveMDIChild.Close;

Ret:= GetMessage(msg, ActiveMDIChild.Handle, 0, 0);

If Ret then

  If msg.message = CMRelease then

       ActiveMDIChild.Destroy; // 提前宣判死刑, 省得麻烦。

    End;

   

 

ShowMessage(IntToStr(MDIChildCount));  // 这个时候的结果就正确了。

End;

 

原创粉丝点击