在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;