直接说问题吧:有一个主窗口,点击按钮后用非模式创建并显示一个窗口。
当用户再次点击这个按钮时:
    如果子窗口没有关闭,则将焦点切换到子窗口;
    如果子窗口已关闭,则创建一个新的子窗口;下面是主要代码
....
C c=NULL;//全局变量c,存放子窗口指针,初始为NULL
....
void P::OnClick()//按钮处理函数
{
if(c==NULL||c已关闭)//怎么知道c已关闭?用IsWindow(c->m_hWnd)居然等于TRUE
{
if(c!=NULL)
{
c->DestroyWindow();
delete c;
}
c=new C();
c->Create(IDD_DIALOG_C,CWnd::FromHandle(m_hWnd));
c->ShowWindow(SW_SHOW);
}
else
{
c->SetActiveWindow();
}
}
想到一种变通的方法:在C中声明一个共有成员,当C创建是为TRUE,关闭时为FALSE,然后在主窗口中访问它,我应该重载哪个函数,我试过OnClose,OnDestroy,PostNcDestroy,和析够函数,他们只在主动调用CloseWindow(),DestroyWindow()时才会执行,点击关闭按钮时并没有执行这些函数。
小弟刚从C#转到C++,两种编程思路区别实在太大,还请各位前辈说详细一点。

解决方案 »

  1.   

    用IsWindow或者GetSafeHandle来判断窗口是否已经存在
      

  2.   

    当关闭该子窗口的时候,使用SendMessage向父窗口发送消息,通知父窗口子窗口已销毁。
    父窗口可记录该操作。
      

  3.   

    子对话框类的对象必定是父对话框的成员变量.判断一下就行了:
    CChild dlg;
    if(dlg.m_hWhd)
    关闭了;
    else
    没有.
      

  4.   

    为父窗口及时知道
    还是在子窗口关闭的时候postmessage给父窗口
      

  5.   

    在OnDestroy() 里设置
    在OnCancel和OnOK里加上 DestroyWindow();
      

  6.   

    试下if( dlg.GetSafeHWnd() == 0 )
      

  7.   

    在关闭子窗口的时候是否销毁,如果销毁的话那就在OnDestroy()中令c=NULL;
    在按钮单击中判断是否为空来决定是否显示还是重建显示
      

  8.   

    当关闭该子窗口的时候,使用SendMessage向父窗口发送消息,通知父窗口子窗口已销毁。 
    父窗口可记录该操作。----------------------------------------------------------
    子对话框类的对象必定是父对话框的成员变量.判断一下就行了: 
    CChild dlg; 
    if(dlg.m_hWhd) 
    关闭了; 
    else 
    没有.
    -------------------------------------------------------------
    为父窗口及时知道 
    还是在子窗口关闭的时候postmessage给父窗口
    -------------------------------------------------------------
    在OnDestroy() 里设置 
    在OnCancel和OnOK里加上 DestroyWindow();
    ------------------------------------------------------------
    在关闭子窗口的时候是否销毁,如果销毁的话那就在OnDestroy()中令c=NULL; 
    在按钮单击中判断是否为空来决定是否显示还是重建显示说来说去还是我问的两个问题: 
    1、在主窗口中声明子窗口的变量,我该访问哪个属性才能知道这个窗口是否已关闭。
           关闭c后IsWindow(c->m_hWnd)依然为TRUE。
    2、若使用子窗口“关闭时”通知主窗口的办法,子窗口怎样才知道自己正在被关闭。
           我试过重载OnClose,OnDestroy,PostNcDestroy,但是关闭时他们都没有执行to dulvtianya:
    GetSafeHandle是做什么用的,关闭后我测试过c.GetSafeHandle()不等于NULL,IsWindow(c.GetSafeHandle())也仍然等于TRUE,或者是我的用法不对?
      

  9.   

    LZ的子窗口似乎只是隐藏了而已,没有真正关闭。可以用SPY++来看一下子窗口是否真的关闭了。
      

  10.   

    我是点的关闭按钮啊,是不是我ShowWindows有问题c=new C();
    c->Create(IDD_DIALOG_C,CWnd::FromHandle(m_hWnd));
    c->ShowWindow(SW_SHOW);这个子窗口也挺奇怪,他始终在主窗口的前面,但不是TOPMost,因为其他窗口可以覆盖他,C#中称为Owner,怎么去掉这个属性,是不是跟这个有关?我关闭子窗口后再关闭主窗口,这时执行了DestroyWindow(),感觉是和隐藏差不多,可能是退出程序后窗口才真正被销毁了。我再用SPY++查一下
      

  11.   

    SPY++确实能查到那个子窗口,这是什么原因???难道点关闭按钮不会销毁他吗?
      

  12.   

    非模式的对话框点关闭按钮不会销毁子窗口,要发一个消息到主窗口进行销毁处理:
    例如:子窗口:ChildDlg在消息处理函数中:
    if(ChildDlg.GetSafeHwnd())
    {
        ChildDlg.DestroyWindow();
    }
    这样才可以销毁子窗口。在按钮处理函数判断的时候用:if(ChildDlg.GetSafeHwnd()) 就可以判断子窗口是否还存在。
      

  13.   

    处理WM_PARENTNOTIFY
    lo=LOWORD(wParam);
    switch(lo)
    {
    case WM_DESTROY:
       if((HWND)lParam==hChild) ...
    }
      

  14.   

    非模态对话框要显示的实现WM_DESTROY;不记得是不是这个名字了。反正就是那个退出窗口的消息;
    然后你要在里面调用DestroyWindow();
    这是模态对话框和非模态对话框的一个重要区别饿。
      

  15.   

    下面是我的测试代码
    BEGIN_MESSAGE_MAP(FormSeach, CDialog)
    ....
    ON_MESSAGE(DM_GETDEFID, OnGetDefID)
    ON_MESSAGE(WM_QUIT, OnQuit)
    ON_MESSAGE(WM_CLOSE,OnClose2)
    ON_MESSAGE(WM_PARENTNOTIFY,ParentNotify)
    ON_MESSAGE(WM_DESTROY,Destroy)
    END_MESSAGE_MAP()
    LRESULT C::ParentNotify(WPARAM wp, LPARAM lp) 
    {
    MessageBox("ParentNotify");
    return true;

    LRESULT C::OnQuit(WPARAM wp, LPARAM lp) 
    {
    MessageBox("OnQuit");
    return true;

    LRESULT C::Destroy(WPARAM wp, LPARAM lp) 
    {
    MessageBox("Destroy");
    return true;

    void C::OnClose()//这个是重载
    {
    MessageBox("OnClosing");
    CDialog::OnClose();
    MessageBox("OnClosed");

    LRESULT C::OnClose2(WPARAM wp, LPARAM lp)// 这个是订阅
    {
    MessageBox("OnClose2");
    return true;
    } 只有OnClose2()会执行,为什么我重载OnClose()没有执行,而直拦截WM_CLOSE却会执行呢?
      

  16.   

    无模态的对话框不能直接调用CDialog::OnOk 和 CDialog::OnCancel函数析构,
    这些只对模态对话框有用。
    所以你在按下退出按钮时,根本就没有调用到OnClose();
    销毁无模态的对话框应该在父窗口中进行。
      

  17.   

    非模态对话框关闭需要调用DestroyWindow来关闭的要判断的窗口是否存在的话判断GetSafeHandle是否为空来判断
      

  18.   

    我没有说OnOk()和OnCancel()啊,而且我点的是又上角的叉叉,没有点退出按钮。
      

  19.   

    先不讨论怎样销毁,我说的是用户点击关闭按钮,不可能叫用户调用DestroyWindow吧,我要先判断他点了关闭才能去销毁啊
      

  20.   

    答案已经有了,WM_CLOSE 可以捕捉到关闭事件,但是问题好像越来越多,
    其它消息为什么没有执行?
    我拦截WM_CLOSE和重载OnClose()有什么区别
    在OnClose2()中调用CDialog::OnClose()为什么不从C::OnClose()开始执行
      

  21.   

    WM_CLOSE是窗口发送的关闭消息啊。接到了这个消息之后才会调用这个消息的响应函数OnClose();
    但是非模态对话框是不会发送这条消息的。除非你显式调用DestroyWindow();回去看了下。非模态对话框是要在ok和cancel两个按钮中实现DestroyWinodw();....