关于在主窗口的OnClose关闭子窗口

时间:2021-05-12 19:15:22
我在主窗口的OnClose事件中用一个循环来关闭子窗口:
    //关闭所有子窗口
    for( int iMDIIndex = MDIChildCount-1; iMDIIndex >= 0; iMDIIndex-- )
            this->MDIChildren[iMDIIndex]->Close();
接下来判断是否所有子窗口都已经关闭了,如果是,则关闭,如果不是,则不关闭:
    //如果有子窗口没有被关掉,则不关闭系统
    if( this->MDIChildCount > 0 )
        Action = caNone;
    else
        Action = caFree;

这里的执行结果总是错的,即使子窗口都已经被关闭了,MDIChildCount还是原来的值而不是0。
请问应该用什么方法来替代?

20 个解决方案

#1


你没有在 MDIChild 窗口中写事件OnClose,缺省时只是最小化,或者你没有
在MDIChild 窗口的事件OnClose里将Action赋为caFree。

#2


在每个子窗口的OnClose事件中加上action = cafree

#3


楼上的应该改为:

  Action=caFree;

#4


mark

#5


你在MDIChild 窗口的事件OnClose里将Action赋为caFree试一下。

#6


对于子窗体缺省情况是最小化,你可以自已写代码,最简单的就是加上一句 在子窗体的OnClose事件中加上Action=caFree

#7


用了。

事实上,在OnClose之前有子窗口,OnClose结束后已经没有子窗口了。

请各位试一下,在 OnClose 结束之前 MDIChildCount 确实没变,OnClose结束之后再次进来 MDIChildCount 就是 0 了。

#8


同意

#9


要么这样改吧:
Action = caFree;
for(int num=MDIChildCount-1; num>=0; num--) {
    if (MDIChildren[num]->Visible) {
        Action = caNone;  break;
    }
}

#10


to: jishiping(JSP 季世平)
你的方法似乎不起作用。在执行过
    //关闭所有子窗口
    for( int iMDIIndex = MDIChildCount-1; iMDIIndex >= 0; iMDIIndex-- )
            this->MDIChildren[iMDIIndex]->Close();
以后,所有子窗口的Visible属性都是true

跟踪程序的结果显示,要等到主窗口的OnClose事件结束后才触发子窗口的FormDestroy事件。可见虽然执行过上述语句,实际上并未真正关闭子窗口。
那么究竟应该怎样判断所有子窗口都已经关闭呢?

#11


我的关闭是这样写的:

for( int iMDIIndex = MDIChildCount-1; iMDIIndex >= 0; iMDIIndex-- )
{
           this->MDIChildren[iMDIIndex]->Close();
           ShowMessage(this->MDIChildCount);//加了这一句
}
    if( this->MDIChildCount > 0 )
        Action = caNone;
    else
        Action = caFree;

这样就可以正常关闭,我想是这样的原因,每次当子窗体关闭时都向系统发出消息改变this->MDIChildCount的数值,但是系统还没有来得及处理改变的消息,主窗体的关闭函数就执行了下一步,所以你收到的this->MDIChildCount一直没有变,我在使用ShowMessage()后,产生了等待,系统就有时间进行处理,以致能正常关闭。

#12


难道就没有办法了吗?仍然不行的话,这样好了。如果你没有用到MDIChild
窗口的 Tag 属性,那么 Tag 缺省的值为0,在 MDIChild 的事件 OnClose
里,如果Action=caFree,那么同时将 Tag 设为1。然后在主窗口的OnClose
中,
Action = caFree;
for(int num=MDIChildCount-1; num>=0; num--) {
    if (MDIChildren[num]->Tag == 0) {
        Action = caNone;  break;
    }
}

如果你使用了 Tag ,可以在 MDIChild 里自己定义一个属性,依照上面的
办法做就是了。

#13


事实上,子窗口的关闭需要到下一个Windows消息循环时才真正处理,就像ListBox:删除一项而它的Count不变化。

不妨在关闭主窗口时关闭所有子窗口,然后Post出一个你的关闭的消息DoCloseMsg,然后caAction=不动作,

然后在DoCloseMsg消息里再执行主窗口的Close,这时MDIChildCount才会更新过来。

#14


你们说的我认为不妥,你看他的代码:
 if( this->MDIChildCount > 0 )
        Action = caNone;
    else
        Action = caFree;
这个Action的使用我都觉得没有搞清,我只见过书里讲子窗体的关闭时讲到利用它。但对主窗体,是否能这样用呢?值得推敲。如果写成
 if( this->MDIChildCount==0 )
Close();
是不是就可以达到目的了呢?而且前面已经有关闭所有子窗体的句子,再去验证没有必要了。

#15


试试如下:

MYFORM:OnClose()
{
   // to do something

   TMDIFrame::OnClose();
}

TMDIFrame的ONCLOSE会自动关闭所有子窗口,不用手工去关闭。

如果在关闭子窗口时一定要执行一些操作,可以在相应的子窗口的ONCLOSE中进行编写,通过在主窗口的ONCLOSE对子窗口进行操作,违反OOP的封装性。

#16


for( int iMDIIndex = MDIChildCount-1; iMDIIndex >= 0; iMDIIndex-- )
{
            this->MDIChildren[iMDIIndex]->Close();
            ShowMessage(this->MDIChildCount);//加了这个,可以让函数
                                               等一下
}

    if( this->MDIChildCount > 0 )
        Action = caNone;
    else
        Action = caFree;
我加了上面这个语句后就可以完全关闭了,呵呵.其实主要是子窗体关闭时发出的让this->MDIChildCount递减的消息在windows的消息循环中还没有处理完,你就进行了this->MDIChildCount的调用操作,所以this->MDIChildCount 的值不变.看来你要处理一下那些让this->MDIChildCount递减的消息啦!

#17


解释一下为什么在执行循环后还要验证是否所有子窗口都已经关闭。
因为我虽然在循环里面执行了子窗口的关闭操作,但是在子窗口的OnClose事件中做了其他事情,并不一定真的把子窗口关掉了。比如某个子窗口询问用户是否关闭,如果用户说子窗口不关闭,那么主窗口自然也不允许被关闭。

to:magicsnake
利用了一条ShowMessage,这样弹出的一个窗口会被用户看到的,看起来似乎界面不太友好。

看来LoveTide和JiShiPing的比较实用,只是略嫌麻烦些。

#18


鍙戞秷鎭?

#19


???

#20


1.在每个mdichildwindow的close事件中,都应写入Action=caFree;

#1


你没有在 MDIChild 窗口中写事件OnClose,缺省时只是最小化,或者你没有
在MDIChild 窗口的事件OnClose里将Action赋为caFree。

#2


在每个子窗口的OnClose事件中加上action = cafree

#3


楼上的应该改为:

  Action=caFree;

#4


mark

#5


你在MDIChild 窗口的事件OnClose里将Action赋为caFree试一下。

#6


对于子窗体缺省情况是最小化,你可以自已写代码,最简单的就是加上一句 在子窗体的OnClose事件中加上Action=caFree

#7


用了。

事实上,在OnClose之前有子窗口,OnClose结束后已经没有子窗口了。

请各位试一下,在 OnClose 结束之前 MDIChildCount 确实没变,OnClose结束之后再次进来 MDIChildCount 就是 0 了。

#8


同意

#9


要么这样改吧:
Action = caFree;
for(int num=MDIChildCount-1; num>=0; num--) {
    if (MDIChildren[num]->Visible) {
        Action = caNone;  break;
    }
}

#10


to: jishiping(JSP 季世平)
你的方法似乎不起作用。在执行过
    //关闭所有子窗口
    for( int iMDIIndex = MDIChildCount-1; iMDIIndex >= 0; iMDIIndex-- )
            this->MDIChildren[iMDIIndex]->Close();
以后,所有子窗口的Visible属性都是true

跟踪程序的结果显示,要等到主窗口的OnClose事件结束后才触发子窗口的FormDestroy事件。可见虽然执行过上述语句,实际上并未真正关闭子窗口。
那么究竟应该怎样判断所有子窗口都已经关闭呢?

#11


我的关闭是这样写的:

for( int iMDIIndex = MDIChildCount-1; iMDIIndex >= 0; iMDIIndex-- )
{
           this->MDIChildren[iMDIIndex]->Close();
           ShowMessage(this->MDIChildCount);//加了这一句
}
    if( this->MDIChildCount > 0 )
        Action = caNone;
    else
        Action = caFree;

这样就可以正常关闭,我想是这样的原因,每次当子窗体关闭时都向系统发出消息改变this->MDIChildCount的数值,但是系统还没有来得及处理改变的消息,主窗体的关闭函数就执行了下一步,所以你收到的this->MDIChildCount一直没有变,我在使用ShowMessage()后,产生了等待,系统就有时间进行处理,以致能正常关闭。

#12


难道就没有办法了吗?仍然不行的话,这样好了。如果你没有用到MDIChild
窗口的 Tag 属性,那么 Tag 缺省的值为0,在 MDIChild 的事件 OnClose
里,如果Action=caFree,那么同时将 Tag 设为1。然后在主窗口的OnClose
中,
Action = caFree;
for(int num=MDIChildCount-1; num>=0; num--) {
    if (MDIChildren[num]->Tag == 0) {
        Action = caNone;  break;
    }
}

如果你使用了 Tag ,可以在 MDIChild 里自己定义一个属性,依照上面的
办法做就是了。

#13


事实上,子窗口的关闭需要到下一个Windows消息循环时才真正处理,就像ListBox:删除一项而它的Count不变化。

不妨在关闭主窗口时关闭所有子窗口,然后Post出一个你的关闭的消息DoCloseMsg,然后caAction=不动作,

然后在DoCloseMsg消息里再执行主窗口的Close,这时MDIChildCount才会更新过来。

#14


你们说的我认为不妥,你看他的代码:
 if( this->MDIChildCount > 0 )
        Action = caNone;
    else
        Action = caFree;
这个Action的使用我都觉得没有搞清,我只见过书里讲子窗体的关闭时讲到利用它。但对主窗体,是否能这样用呢?值得推敲。如果写成
 if( this->MDIChildCount==0 )
Close();
是不是就可以达到目的了呢?而且前面已经有关闭所有子窗体的句子,再去验证没有必要了。

#15


试试如下:

MYFORM:OnClose()
{
   // to do something

   TMDIFrame::OnClose();
}

TMDIFrame的ONCLOSE会自动关闭所有子窗口,不用手工去关闭。

如果在关闭子窗口时一定要执行一些操作,可以在相应的子窗口的ONCLOSE中进行编写,通过在主窗口的ONCLOSE对子窗口进行操作,违反OOP的封装性。

#16


for( int iMDIIndex = MDIChildCount-1; iMDIIndex >= 0; iMDIIndex-- )
{
            this->MDIChildren[iMDIIndex]->Close();
            ShowMessage(this->MDIChildCount);//加了这个,可以让函数
                                               等一下
}

    if( this->MDIChildCount > 0 )
        Action = caNone;
    else
        Action = caFree;
我加了上面这个语句后就可以完全关闭了,呵呵.其实主要是子窗体关闭时发出的让this->MDIChildCount递减的消息在windows的消息循环中还没有处理完,你就进行了this->MDIChildCount的调用操作,所以this->MDIChildCount 的值不变.看来你要处理一下那些让this->MDIChildCount递减的消息啦!

#17


解释一下为什么在执行循环后还要验证是否所有子窗口都已经关闭。
因为我虽然在循环里面执行了子窗口的关闭操作,但是在子窗口的OnClose事件中做了其他事情,并不一定真的把子窗口关掉了。比如某个子窗口询问用户是否关闭,如果用户说子窗口不关闭,那么主窗口自然也不允许被关闭。

to:magicsnake
利用了一条ShowMessage,这样弹出的一个窗口会被用户看到的,看起来似乎界面不太友好。

看来LoveTide和JiShiPing的比较实用,只是略嫌麻烦些。

#18


鍙戞秷鎭?

#19


???

#20


1.在每个mdichildwindow的close事件中,都应写入Action=caFree;

#21