精华内容
下载资源
问答
  • MFC-创建模态对话框和非模态对话框的方法
    2022-01-15 18:48:45

    注意:以下实例中创建模态对话框时没有用create(id号)绑定资源id,而非模态对话框中要用create(id号)绑定对话框资源id。

    在MFC中对话框有两种形式,一个是模态对话框(model dialog box),一个是非模态对话框(modeless dialog box)。本文对此分别简述其创建方法。

    一、模态对话框(model dialog box)

    在程序运行的过程中,若出现了模态对话框,那么主窗口将无法发送消息,直到模态对话框退出才可以发送。
    点击模态对话框中的OK按钮,模态对话框会被销毁。
    创建一个模态对话框的代码如下所示:

     
    
    1. //创建一个模态对话框

    2. CTestDialog td;

    3. td.DoModal();

    其中CTestDialog为我自己所新建的和一个对话框资源相关联的对话框类。
    可以创建一个布局模态对话框类变量,不用担心它会随着所在函数返回而被销毁。因为DoModal()函数的一个功能是,当前只能运行此模态对话框,且停止主窗口的运行,直到模态对话框退出,才允许主窗口运行。
    DoModal()函数也有显示对话框的功能,所以也无需调用其他函数来显示对话框。

    二、非模态对话框(modaless dialog box)

    在程序运行的过程中,若出现了非模态对话框,主窗口还可以发送消息。
    点击非模态对话框中的OK按钮,非模态对话框没有销毁,只是隐藏了。若想点击OK按钮时,非模态对话框也销毁,那么CTestDialog类必须重载其基类CDialog的虚函数OnOK(),在此函数里调用DestroyWindow()来销毁此对话框。

    此处采用和上面一样的方式来创建一个非模态对话框,代码如下:

     
    
    1. CTestDialog td;

    2. td.Create(IDD_DIALOG1); //创建一个非模态对话框

    3. td.ShowWindow(SW_SHOWNORMAL); //显示非模态对话框

    那么,在运行时,你会发现此对话框无法显示。这是因为你声明的对话框变量td是局部变量,但这个函数返回时,td也被析构了,所以无法显示此对话框。

    创建非模态对话框,必须声明一个指向CTestDialog类的指针变量,且需要显示的调用ShowWindow()才能将对话框显示出来。有两种创建方法:

    (1)采用局部变量创建一个非模态对话框

     
    
    1. //采用局部变量创建一个非模态对话框

    2. CTestDialog *pTD = new CTestDialog();

    3. pTD->Create(IDD_DIALOG1); //创建一个非模态对话框

    4. pTD->ShowWindow(SW_SHOWNORMAL); //显示非模态对话框

    因为指针在声明的时候是被放在堆栈中,只有整个应用程序关闭后才会被销毁,所以可以正常显示对话框。
    这种方法虽然不影响程序的运行,可是指针pTD所指向的内存却导致不可用,这样的编程很不好。

    (2)采用成员变量创建一个非模态对话框
    首先在你所要编写的类的头文件中声明一个指针变量:

     
    
    1. private:

    2. CTestDialog *pTD;

    然后再在相应的CPP文件,在你要创建对话框的位置添加如下代码:

     
    
    1. //采用成员变量创建一个非模态对话框

    2. pTD = new CTestDialog(); //给指针分配内存

    3. pTD->Create(IDD_DIALOG1); //创建一个非模态对话框

    4. pTD->ShowWindow(SW_SHOWNORMAL); //显示非模态对话框

    最后在所在类的析构函数中收回pTD所指向的内存:

    delete pTD;

    、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    众所周知的,MFC中非模态对话框在显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换。本文就来给大家讲解一下非模态对话框的实现方法:

    一、非模态对话框的对话框资源和对话框类

    实际上,模态对话框和非模态对话框在创建对话框资源和生成对话框类上是没有区别的,因此,在创建模态对话框时所创建的IDD_TIP_DIALOG对话框资源和CTipDlg类都不需要修改。

    二、创建及显示非模态对话框的步骤

    需要修改的是,对话框类实例的创建和显示,也就是之前在CAdditionDlg::OnBnClickedAddButton()函数体中添加的对话框显示代码。下面是具体步骤:

    1. 在AdditionDlg.h中包含CTipDlg头文件并定义CTipDlg类型的指针成员变量。详细操作方法是,在AdditionDlg.cpp中 删除之前添加的#include "TipDlg.h",而在AdditionDlg.h中添加#include "TipDlg.h",这是因为我们需要在AdditionDlg.h中定义CTipDlg类型的指针变量,所以要先包含它的头文件;然后在 AdditionDlg.h中为CAdditionDlg类添加private成员变量CTipDlg  *m_pTipDlg;。

    2.在CAdditionDlg类的构造函数中初始化成员变量m_pTipDlg。如果cpp文件中函数太多,我们可以在Class View上半个视图中找到CAdditionDlg类,再在下半个视图中找到其构造函数双击,中间客户区域即可马上切到构造函数的实现处。在构造函数体中 添加m_pTipDlg = NULL;,这是个好习惯,在任何指针变量使用前都初始化,可以避免因误访问重要内存地址而 破坏此地址的数据。

    3.添加非模态对话框的创建和显示代 码。VC++中注释单行代码使用“//”,注释多行代码可以在需注释的代码开始处添加“/*”,结束处添加“*/”。修改后的 CAdditionDlg::OnBnClickedAddButton()

    函数如下:

     
    
    1. void CAdditionDlg::OnBnClickedAddButton()

    2. {

    3. // TODO: Add your control notification handler code here

    4. /*INT_PTR nRes; // 用于保存DoModal函数的返回值

    5. CTipDlg tipDlg; // 构造对话框类CTipDlg的实例

    6. nRes = tipDlg.DoModal(); // 弹出对话框

    7. if (IDCANCEL == nRes) // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行

    8. return;*/

    9. // 如果指针变量m_pTipDlg的值为NULL,则对话框还未创建,需要动态创建

    10. if (NULL == m_pTipDlg)

    11. {

    12. // 创建非模态对话框实例

    13. m_pTipDlg = new CTipDlg();

    14. m_pTipDlg->Create(IDD_TIP_DIALOG, this);

    15. }

    16. // 显示非模态对话框

    17. m_pTipDlg->ShowWindow(SW_SHOW);

    18. // 将各控件中的数据保存到相应的变量

    19. UpdateData(TRUE);

    20. // 将被加数和加数的加和赋值给m_editSum

    21. m_editSum = m_editSummand + m_editAddend;

    22. // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值

    23. UpdateData(FALSE);

    24. }

    4.因为此非模态对话框实例是动态创建的,所以需要手动删除此动态对象来销毁对话框。我们在 CAdditionDlg类的析构函数中添加删除代码,但是MFC并没有自动给出析构函数,这时需要我们手动添加,在对话框对象析构时就会调用我们自定义 的析构函数了。在AdditionDlg.h文件中为CAdditionDlg添加析构函数声明:~CAdditionDlg();,然后在 AdditionDlg.cpp文件中添加析构函数的实现,函数体如下:

     
    
    1. CAdditionDlg::~CAdditionDlg()

    2. {

    3. // 如果非模态对话框已经创建则删除它

    4. if (NULL != m_pTipDlg)

    5. {

    6. // 删除非模态对话框对象

    7. delete m_pTipDlg;

    8. }

    9. }

    这样,非模态对话框创建和显示的代码就添加修改完了。

    更多相关内容
  • 在MFC中对话框有两种形式,一个是模态对话框(model dialog box),一个是非模态对话框(modeless dialog box)。本文对此分别简述其创建方法。 一、模态对话框(model dialog box) 在程序运行的过程中,若出现了...
  • 模态窗口 javascript 技巧汇总(传值、打开、刷新) 1、要弹出的页面中,一定要保证<head></head>标签间有<base target=“_self”>,否则会弹出的模态窗口上,点击按钮时,会再次弹出一个新页面。...
  • 弹出子对话框,在子对话框特定位置,显示非模态对话框,对话框之间的数据传递
  • qml自定义模态对话框

    2019-12-06 17:09:39
    不同与Popup,这是自定义样式的模态对话框,是模态的!整个对话框作为一个独立的组件使用.........
  • 谷歌浏览器不支持showModalDialog模态对话框和无法返回returnValue,这个问题,想必很多朋友都有遇到过吧,解决方法很简单,下面的思路,大家可以看看
  • 使用ObjectARX开发CAD制作模态对话框,选自张帆CAD二次开发丛书
  • vc++制作非模态对话框

    2021-11-20 16:16:52
    VC非模式对话框
  • 在项目中,我遇到模态对话框无法弹出的情况。找了很久也咨询了很多人,找到了解决方案,分享给需要的人
  • 基于MFC向导实现的模态对话框和非模态对话框的代码,程序是基于vs2013写的,可以完美运行,适合新手学习,大佬请忽略!
  • VC 创建一个非模态对话框,比较一下模态对话框,与其有何异同。以下是创建对话框的代码:  void CNonModeDlgDlg::Finish()  {   m_pChoice = NULL;   GetDlgItem(IDOK)->EnableWindow();  }  void ...
  • QT主界面调用模态对话框示例程序源码程序,很详细希望可以帮到你
  • 模态对话框失效了? 上个礼拜修改测试一个后台管理项目,在测试与各个浏览器兼容性的时候,发现在chrome浏览器下showModalDialog方法显示的并不是模态对话框,就像新打开一个页面一样,父窗口仍然可以随意获取焦点,...
  • VS2010创建模态对话框模态对话框的方法,给子窗口传值,非模态对话框给父窗口传值,非模态获取父窗口的指针,打开非模态对话框不重复
  • 众所周知的,MFC中非模态对话框在显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换。本文就来给大家讲解一下非模态对话框的实现方法: 一、非模态对话框的对话框资源和对话框类 实际上,模态...
  • 父窗口: 代码如下:<html><head><title>无标题页</title>[removed]function opendialog1() { var someValue=...dialogHeight=500px;status=no;... document.form1.p1t.value=someValue;...body
  • 万能模态对话框 万能模态对话框 万能模态对话框 万能模态对话框 uDialog unity 模态对话框,通用
  • 1、非模态对话框和父窗口共享当前线程的消息循环 2、模态对话框新建一个新的消息循环,并由当前消息循环派发消息,而父窗口。模态对话框屏蔽了用户对它父窗口的操作,但是不是在消息循环里面屏蔽,所以给父窗口发送...

    1、非模态对话框和父窗口共享当前线程的消息循环

    2、模态对话框新建一个新的消息循环,并由当前消息循环派发消息,而父窗口。模态对话框屏蔽了用户对它父窗口的操作,但是不是在消息循环里面屏蔽,所以给父窗口发送消息,父窗口还是可以接收得到。

    3、调用模态对话框的窗口处理函数会被阻塞,但是新的消息循环仍然可以调用父窗口的消息处理函数,所以,发送给父窗口的新消息仍然可以被及时处理。

    /*****************************MFC模态对话框的消息循环***************************/

    MFC模态对话框的消息循环
    单线程程序, 当主窗口响应函数中弹出模态对话框时,为什么主窗口响应函数可能照常工作?

    当弹出模态对话框时,线程的消息循环无法返回,父窗口的事件本应没人处理,应该处于卡死状态,但实事上父窗口是可以正常响应能接收到的消息的,比如计时器传来的WM_TIMER 及系统托盘菜单传回来的WM_COMMAND。

    之前的消息循环无法返回是正确的,但模态对话框并不意味着死循环,实事上,它在做另一个消息循环。


    AfxInternalPumpMessage() 里面就是一个消息泵,包括消息的获取与分发:

     

     


    只要有消息循环存在线程内的所有窗口就会活过来。不管弹出多少个模态对话框,线程内始终有一个消息循环为所以的窗口服务。

    但这种形式带来的那一个问题就是,如何关闭所有模态对话框并退出程序?

    如果简单地有EndDialog来关闭对话框,是无法让所有的消息循环返回的。有一种做法是使用PostQuitMessage,使当前的消息循环退出,消息循环收到WM_QUIT后,不当退出本次循环,还会给线程消息队列Post另一个QUIT 消息,这样消息循环就接二连三挨个退出了。

    int CWnd::RunModalLoop(DWORD dwFlags)中的代码片段可以说明这点:

     /*************************windows 消息队列,消息循环,模态对话框**************/

    Windows的消息队列是基于线程的。


    消息队列,消息循环:

    线程是程序串行执行的最小单位。

    一个典型的Win32项目(不是MFC项目,只有一个窗口的项目),其中的消息循环会使用如下代码实现:


    //代码段1

    MSG msg
    BOOL bRet;

    while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)

        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    }

    GetMessage()是取得消息,如果没有消息,线程阻塞在这里,不占用CPU。

    DispatchMessage()是将消息分发,分发到所有在这个线程中创建的窗口的窗口处理函数中去。 如果不需要分发消息,就不需要调用DispatchMessage(),例如线程中没有窗口的情况。


    线程消息循环:

    实际上,任何线程只要调用了上述代码段1中的代码,就已经实现了消息循环的功能。更进一步,其实只要调用GetMessage()函数就可以了。

    即:

    //代码段2

    BOOL bRet;  MSG msg;
    while( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0)

    if (bRet == -1 || WM_QUIT == msg.message){
    // handle the error and possibly exit
    break;
    }
            }

    在工作线程中,只要有代码段2,就可以实现消息循环的功能了。

    这是一个很方便的线程间异步通信的机制。给线程发消息用PostThreadMessage()。为什么去掉了DispatchMessage()呢,因为一般情况下,在工作线程中是不需要创建窗口的,不需要分发到窗口中去处理,能从线程的消息队列里取得消息就足够了。

    如果设计线程的初衷为:当某条件发生时,让工作线程开始工作,一直将工作完成,之后挂起,等待新条件的发生,等待时不占用CPU资源。 那么代码段2所展示的机制就能很好的完成这样的功能。 而且可以使多个工作线程都用同样的机制实现,彼此间协同工作,加之某种资源共享机制,可以实现一个异步的消息处理链。


    模态对话框:

    消息循环可以有多个,可以在上一级消息循环的某个消息的处理过程中,局部创建一个消息循环,模态对话框就是采用这种机制创建出来的。

    一个线程可以有多个消息循环,并行的消息循环显然没有意义,多个就是在消息循环中嵌套消息循环。

    如代码段1中的DispatchMessage函数,将消息派发到窗口的消息处理函数中,WndProc1()。

    现在假设在WndProc1()中创建一个消息循环,并且只取得这个窗口本身的消息 GetMessage(&msg, hWnd, 0, 0),不必Dispatch了,因为已经找到了目标窗口,然后用这个窗口真正的消息处理函数去处理。 这样模态对话框存在时,处理了所有的窗口消息,创建模态对话框的窗口就一直得不到处理消息的机会,模块对话框就始终处于最上层,直到其主动退出。

    当然,对模态对话框的这种解释是简化了的,实际过程可能复杂的多,取得的窗口消息至少要包含所有的子窗口的消息,也需要Dispatch到相应的子窗口,等等。但是最基本的机制应该就是这样的。
    /*********************模态对话框的消息机制****************************/

    当一个窗口时模态对话框时,它的消息处理过程是有点特殊的。模式对话框都有自己的消息循环,它阻塞的是原始的消息循环,但是被对话框的消息循环接替。消息循环的本

    质是调用窗口过程,进一步调用你的各种消息响应函数,所以无论有多少个消息循环存在,只要有一个消息循环有效,所有的消息响应函数都能被调用,这也是为什么主窗口还能

    响应消息的缘故。多个消息循环的存在会产生某些副作用,比如消息重入,第一次消息响应时弹出一个模式对话框,模式对话框的消息循环2取代原始消息循环1,假设此时主窗口

    消息队列里又有一个同样的消息到来,消息循环2也会调用同样的窗口过程(响应函数),此时就能导致消息重入(因为第一次进入这个处理函数还没有返回,本质上这个响应函数

    被递归调用了),这也是能弹出多个模式对话框的原因。每个模式对话框都有自己的消息循环,只有最后一个弹出对话框的消息循环才是活动的消息循环,其它所有消息循环(包

    括主窗口、之前弹出的模式对话框)全被阻塞。这里的“阻塞”并不是消息被阻塞,而只是DispatchMessage一直没有返回而已,但是其它的消息循环会接替这些工作。

    /**********************MFC模态模式对话框,MessageBox消息循环原理,定时器TIMER消息响应处理函数重入************/

    一、MessageBox和定时器TIMER

    MessageBox是Win32 API全局函数,必须指定标题和样式。共有4个参数。没有父窗口就NULL。返回值是int,看选什么按钮。

    比如:MessageBox( NULL, "选什么?", "标题", MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);

    ::表示全局函数。

    在MFC中,可使用全局API函数::MessageBox(NULL,………),子程序会被暂时中断在这个MessageBox上!其后的代码无法运行,等到MessageBox返回后会继续运行代码。但父窗口可以被点出来,其它程序段可以运行,比如其它按钮。  因为NULL没有指定父窗口,所以不会使父窗口无效!

    MFC中直接使用MessageBox,则是使用CWnd类的MessageBox方法,这时父窗口无法被点出来,等同于::MessageBox(m_hWnd,………)。同时子程序被暂时中断在这个MessageBox上。但关了其中一个消息框,则父窗就可以点出来了。 原理应该是m_hWnd 指定了父窗,MessageBox使父窗口无效,然后进入自己的消息循环,关闭时,使父窗有效。

    在TIMER的响应函数中,有MessageBox的话,则会暂时中断在这个MessageBox上,但当下个时间到时,又会出现一个新的MessageBox,且也是暂时中断在这个MessageBox上...  即出现了多个消息响应函数的例程!!多次重入!!每个例程都中断在MessageBox上,MessageBox返回后,例程会继续执行到结束!  各个消息框都是父窗的子窗,所以是平等的,所以各个消息框都可以点出来,但父窗点不出来。  可以关闭任何一个消息框,但是这个重入例程MessageBox之后的代码不会运行,要按倒序关闭其后的消息框后才会运行。

    二、消息框原理分析:参考《深入探讨MFC消息循环和消息泵》和调试时断点看代码

    注意:

    MFC是单线程运行的。

    MFC内部是有消息循环。

    消息循环的DispatchMessage()会阻塞,需要等窗口消息处理函数处理完了以后,才会返回。

    窗口消息处理函数是由操作系统调用的。

    窗口消息处理函数是可以多次重入的!类似函数自己可以嵌套一样。

    单线程运作:阻塞→重入→阻塞→重入。。。

    时间到→操作系统放WM_TIMER到线程队列→MFC消息循环DispatchMessage()阻塞→系统调用窗口消息处理函数OnTimer()处理完→消息循环继续

    操作系统一到时间就会放WM_TIMER到线程队列。因为是单线程,如果窗口消息处理函数如果一直没处理完,则WM_TIMER会堆积在队列中。

    OnTimer()中有消息框时情况就复杂了。MessageBox内部是一个模态对话框,模态对话框有消息循环。

    时间1到,系统放WM_TIMER到队列

    MFC程序主消息循环DispatchMessage()阻塞

    操作系统调用第1个OnTimer()

    MessageBox生成一个模态对话框对象1,显示出来,运行对话框内的消息循环1

    时间2到,系统放WM_TIMER到队列

    MessageBox1的消息循环1 DispatchMessage()阻塞

    操作系统调用第2个OnTimer() (函数重入了!)

    MessageBox生成一个模态对话框对象2,显示出来,运行对话框内的消息循环2

    时间3到,MessageBox2的消息循环2 DispatchMessage()阻塞,操作系统调用第3个OnTimer() (函数重入了!)。。。

    即一个串一个,只有最后一个消息框的消息循环在起作用,前面的消息循环全部阻塞了。

    OnTimer()是主窗(父窗)函数,所以各个MessageBox都是子窗,各个子窗是都可以点出来,但父窗会被子窗失效掉,所以父窗点不出来。

    当任何一个子窗关掉后,会使父窗有效,这时父窗可以点出来了。

    三、消息框对话框关闭时原理

    关闭时是怎样?为什么关闭时是按倒序在执行代码?

    MessageBox无法调试进入内部看代码,就用模态对话框来代替吧:

    CAboutDlg dlgAbout;

    dlgAbout.DoModal();  // DoModal就会生成模态对话框

    CDialog::DoModal()里面有CreateRunDlgIndirect()。

    CWnd::CreateRunDlgIndirect里面有RunModalLoop()。

    CWnd::RunModalLoop里面有消息循环AfxPumpMessage(),这里一直进行消息循环!循环中还有CWnd::ContinueModal()判断m_nFlags标志看是否需要退出循环。

    当关闭对话框时,如果点“确定”就是触发CAboutDlg::OnOK(),点“X”就是触发CAboutDlg::OnCancel()。 这两个函数进去都是运行EndDialog()。

    CDialog::EndDialog里面先运行EndModalLoop(),然后是运行::EndDialog()。

    CWnd::EndModalLoop()里面有

    m_nFlags &= ~WF_CONTINUEMODAL;  把标志设置成不再继续运行对话框

    PostMessage(WM_NULL);   发送一个空消息以确保消息队列中有消息,这样消息循环不会因为没有消息而阻塞

    ::EndDialog()无法进入看代码,功能是把对话框关了不显示,然后把父窗激活。

    把对话框关了不显示,这样我们就点不到这个对话框,就不会再触发窗口消息处理函数了。

    所以清楚了:

    点击关闭其中一个消息框时(比如消息框1),生成了一个消息(这个消息是关联这个消息框1的),“最后一个”消息框(比如消息框3)的消息循环DispatchMessage()这个消息后,操作系统重入消息框1对象的OnOK()或OnCancel(),设置m_nFlags标志成不再继续运行,发送一个消息框1的消息WM_NULL,以及用::EndDialog()把消息框1销毁了并把父窗激活。  

    这个时候,这个消息框1对象仍存在,它的消息循环仍阻塞在DispatchMessage()中,只有等消息框3、消息框2的消息循环退出、OnTimer()退出后,才会从DispatchMessage()返回,然后发现m_nFlags不需要继续运行消息框了,于是退出消息循环,然后退出消息框对象,然后退出OnTimer(),消息循环就又交还给MFC程序的主循环了。

    四、非模式对话框

    非模对话框没有自己的消息循环,也不会使父窗失效。

    用Create()来显示非模对话框,函数会立刻返回,所以必须要用new,这样对话框对象就保留在内存中。

    如果用CAboutDlg dlgAbout;,则处理函数结束后,对象也被销毁,即对话框一显示就被关掉了。

    CAboutDlg* pdlg = new CAboutDlg;

    pdlg ->Create(IDD_ABOUTBOX);     //非模式对话框,函数立刻返回,无自己的消息循环

    pdlg->ShowWindow(SW_SHOW);

    所以,关键是消息循环、消息处理函数重入。

    /*****************模态对话框和非模态对话框的区别*********************/

    模态对话框 操作模式上来讲 模态对话框在关闭对话框(OnOk,OnCancel,OnClose)这三个消息产生之前不可对此对话框以外的对话框进行操作  当上面3个消息产生后系统负责删除模态对话框资源
    而非模态对话框可以进行其他操作 必须在三个消息发生后自己在析构函数里回收此对话框资源
    比较麻烦
     
    模态对话框用DoModal()可以负责产生,显示,销毁窗口
    非模态对话框需要调用Create()然后在创建的时候WS_VISIBLE或者在创建都调用ShowWindow
    进行显示  最后调用DestroyWindow()  然后自己删除掉对话框对象比较麻烦
    

    按工作方式不同,可将对话框分成两类:
    模式对话框(modal dialog box模态对话框):在关闭模式对话框之前,程序不能进行其他工作(如一般的“打开文件”对话框)
    无模式对话框(modeless dialog box 非模态对话框):模式对话框打开后,程序仍然能够进行其他工作(如一般的“查找与替换”对话框)
    两者的区别:
    一. 非模态对话框的模板必须具有Visible风格(Visible=True),否则对话框将不可见,而模态对话框则无需设置该项风格。在实际编程中更加保险的办法是调用CWnd::ShowWindow(SW_SHOW)来显示对话框,而不管对话框是否具有Visible风格。
    二. 非模态对话框对象是用new操作符来动态创建的,而不是以成员变量的形式嵌入到别的对象中或以局部变量的形式构建的。通常应在对话框的拥有者窗口类内声明一个指向对话框类的指针成员变量,通过该指针可访问对话框对象。
    三. 通过调用CDialog::Create函数来启动对话框,而不是CDialog::DoModal,这是两者之间区别的关键所在。由于Create函数不会启动新的消息循环,对话框与应用程序共用同一个消息循环,这样对话框就不会垄断用户输入。Create在显示了对话框后就立即返回,而DoModal是在对话框被关闭后才返回的。由于在Create返回后,不能确定对话框是否已关闭,这样也就无法确定对话框对象的生存期,因此只好在堆栈中构建对话框对象,而不能以局部变量的形式来构建之。
    四. 必须调用CWnd::DestroyWindow而不是CDialog::EndDialog来关闭非模态对话框。调用CWnd::DestroyWindow是直接删除窗口的一般方法。由于缺省的CDialog::OnOK和CDialog::OnCancel函数均调用EndDialog,故程序员必须编写自己的OnOK和OnCancel函数并且在函数中调用DestroyWindow来关闭对话框。
    五. 因为是用new操作符构建非模态对话框对象,因此必须在对话框关闭后,用delete操作符删除对话框对象。在屏幕上一个窗口被删除后,框架会调用CWnd::PostNcDestroy,这是一个虚拟函数,程序可以在该函数中完成删除窗口对象的工作,具体代码如下
    void CModelessDialog::PostNcDestroy
    {delete this; //删除对象}
    这样,在删除屏幕上的对话框后,对话框对象将被自动删除。拥有者就不必显式地调用delete来删除对话框对象了。
    六. 必须有一个标志表明非模态对话框是否打开的。这样做的原因是用户有可能在打开一个模态对话框的情况下,又一次选择打开命令。程序根据标志来决定是打开一个新的对话框,还是仅仅把原来打开的对话框激活。通常可以用拥有者窗口中的指向对话框对象的指针作为这种标志,当对话框关闭时,给该指针赋NULL值,以表明对话框对象已不存在了。
    例如:
    创建模态对话框
    CTestDlg dlg;
    dlg.DoModal();
    创建非模态对话框
    CTestDlg * dlg = new CTestDlg;
    dlg->Create(IDD_TEST_DLG);
    dlg->ShowWindow(SW_SHOW); 

    展开全文
  • 模态对话框 阻塞同一应用程序中其它可视窗口输入的对话框; 显示模态对话框最常见的方法是调用其exec()函数: #pragma execution_character_set("utf-8") MainWindow *pMainWindow = new MainWindow(); pMainWindow-...

    模态对话框

    阻塞同一应用程序中其它可视窗口输入的对话框;
    显示模态对话框最常见的方法是调用其exec()函数:

    #pragma execution_character_set("utf-8")
    MainWindow *pMainWindow = new MainWindow();
    pMainWindow->setWindowTitle("主界面");
    pMainWindow->show();
    
    CustomWindow *pDialog = new CustomWindow(pMainWindow);
    pDialog->setWindowTitle("模式对话框");
    
    // 关键代码,以模态方法显示对话框
    pDialog->exec();
    
    // 关闭模态对话框以后才会执行下面的代码
    pMainWindow->setWindowTitle("主界面-模式对话框");
    qDebug() << "关闭模态对话框以后,可以继续向下执行";
    

    主界面被阻塞,不能进行点击、拖动等任何操作;
    exec()之后的代码不会执行,直到关闭模态对话框。

    非模态对话框

    和同一个程序中其它窗口操作无关的对话框;
    调用show()来显示非模式对话框,并立即将控制返回给调用者:

    #pragma execution_character_set("utf-8")
    MainWindow *pMainWindow = new MainWindow();
    pMainWindow->setWindowTitle("主界面");
    pMainWindow->show();
    
    CustomWindow *pDialog = new CustomWindow(pMainWindow);
    pDialog->setWindowTitle("非模式对话框");
    
    // 关键代码,以非模态的方式显示对话框
    pDialog->show();
    
    // 下面的代码会立即运行
    pMainWindow->setWindowTitle("主界面-非模式对话框");
    qDebug() << "立即运行";
    

    主界面不会被阻塞,可以进行点击、拖动等任何操作;
    show()之后的代码会立即执行

    半模态对话框(非模态方式,界面阻塞,代码执行)

    调用setModal(true)或者setWindowModality(),然后show();

    #pragma execution_character_set("utf-8")
    MainWindow *pMainWindow = new MainWindow();
    pMainWindow->setWindowTitle("主界面");
    pMainWindow->show();
    
    CustomWindow *pDialog = new CustomWindow(pMainWindow);
    pDialog->setWindowTitle("半模式对话框");
    
    // 关键代码
    pDialog->setModal(true);
    pDialog->show();
    
    // 下面的代码会立即运行
    pMainWindow->setWindowTitle("主界面-半模式对话框");
    qDebug() << "立即运行";
    

    主界面被阻塞,不能进行点击、拖动等任何操作;
    show()之后的代码会立即执行。

    展开全文
  • 本文详细总结了html5各种页面切换效果和模态对话框用法。分享给大家供大家参考。具体分析如下: 页面动画: data-transition 属性可以定义页面切换是的动画效果。例如:<a>I’ll pop</a>data-transition 参数表: ...
  • 这篇文章主要介绍了JavaScript实现模态对话框实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 <!DOCTYPE html> <html lang="en"> <head> ...
  • Qt主界面获取非模态对话框数据的方法。
  • 最近做一个从Access项目向 Asp.net + SqlServer迁移工作,其中遇到了这种情况,在Access窗体的一个按钮事件中,代码大体上是这么个功能:弹出模态对话框,在关闭对话框之后继续走一段数据库操作代码。 在Asp.net...
  • 模态对话框的VC++实现

    2021-03-15 19:09:19
    内容索引:VC/C++源码,界面编程,对话框 VC++实现的模态对话框,通过这个小示例你或许能了解到以下相关的内容:重载虚函数OnOK、非模式对话框不调用基类CDialog的OnCancel函数、模态对话框直接调用基类的OnConcel函数...
  • Qt主界面获取非模态对话框数据的方法
  • 模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在。又有叫法是称为模式对话框,无模式对话框等。所谓模态对话框就是在其没有被关闭之前,用户不能与同...

    模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在。又有叫法是称为模式对话框,无模式对话框等。所谓模态对话框就是在其没有被关闭之前,用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭。对于非模态对话框,当被打开时,用户既可选择和该对话框进行交互,也可以选择同应用程序的其他窗口交互。

    Qt中,显示一个对话框一般有两种方式,一种是使用exec()方法,它总是以模态来显示对话框;另一种是使用show()方法,它使得对话框既可以模态显示,也可以非模态显示,决定它是模态还是非模态的是对话框的modal属性。

    Qt中,Qt模态非模态对话框选择是通过其属性modal来确定的。我们来看看modal属性,其定义如下:

    modal : bool默认情况下,对话框的该属性值是false,这时通过show()方法显示的对话框就是非模态的。而如果将该属性值设置为true,就设置成了模态对话框,其作用于把QWidget::windowModality属性设置为Qt::ApplicationModal。

    而使用exec()方法显示对话框的话,将忽略modal属性值的设置并把对话框设置为模态对话框。

    一般使用setModal()方法来设置对话框的modal属性。

    我们总结一下设置对话框为模态的方法。

    ◆ 如果要设置为模态对话框,最简单的就是使用exec()方法,示例代码如下:

    MyDialog myDlg;    myDlg.exec();也可以使用show()方法,示例代码如下:

    MyDialog myDlg;    myDlg.setModal(true);    myDlg.show();

    ◆  如果要设置为非模态对话框,必须使用show()方法,示例代码如下:

    MyDialog myDlg;    myDlg.setModal(false);
    //或者
    myDlg.setModal();
    myDlg.show();
    再次强调,目前有的朋友对于模态对话框和非模态对话框的认识有误解,认为使用show()方法显示的就是非模态对话框,这是不正确的。

    小贴士:有时候,我们需要一个对话框以非模态的形式显示,但又需要它总在所有窗口的最前面,这时可以通过如下代码设置:

    MyDialog myDlg;    myDlg.setModal(false);
    //或者
    myDlg.setModal();    myDlg.show();
    //关键是下面这行
    myDlg.setWindowFlags(Qt::WindowStaysOnTopHint);

    Qt中创建模态对话框,主要用到了QDialog的exec函数:

    SonDialog dlg(this);

    int res = dlg.exec();

    if (res == QDialog::Accepted)

    {

    QMessageBox::information(this, “INFORMATION”, “You clicked OK button!”);

    }

    if (res == QDialog::Rejected)

    {

    QMessageBox::information(this, “INFORMATION”, “You clicked CANCEL button!”);

    }

    正如上面代码所显示的,可以通过exec函数的返回值来判断用户点击了哪个按钮使得模态对话框退出的,这可以使得我们能够根据用户的不同行为在退出模态对话框之后采取不同的处理方法。

    既然new了,如果不delete,那么内存不就存在了泄露的问题了吗?确实如此!所以,我们希望该Qt窗口在退出时自动能够delete掉自己,因此,我们在SonDialog的构造函数里,添加这样的一句代码:

    setAttribute (Qt::WA_DeleteOnClose);

    这样,我们的SonDialog就能够在它退出时自动的delete掉自己了,不会再造成内存泄漏问题

     

    Qt中存在“窗口”与“部件”的区分,但“窗口”的概念太过浅显,以至于可以忽略不谈。但有时候还是多少有些了解为好。

    很多书上说,Qt中吧没有嵌入到其他部件中的部件成为“窗口”,而这种“窗口”都包含有边框和标题栏。“窗口”就是没有父窗口(或部件)的部件,又称为顶级部件。但在实际开发过Qt程序的工程师看来,这种说法有点欠佳。“窗口是没有嵌入到其他部件的部件“这个好理解,但是“窗口”就是没有父部件的部件?QDialog为窗口是毋庸置疑的吧,但是在使用对话框时为其指定父窗口也是在正常不过了。例如,当我点击主窗口某个按钮时弹出个提示对话框:

    QDialog dlg(this);

    dlg.exec();

    弹出的Dialog一样具有边框和标题栏,难道这种具有父部件的对话框就是不是窗口了?很多人难以接受吧! 所以,一个QWidget是窗体还是窗体上的控件和是否有父类无关,只与窗口标记类型有关,也只有窗口flag才能直接说明此部件是否为窗口!设置或修改部件类型:setWindowFlags(Qt::Window)

    但是也无需怀疑很多书本的可靠性,其实书上说的也没错,只是不够深入。例如:

    QPushButton * pPushBtn = new QPushButton(this);

    //当没有父类时,构造函数就会加上Qt::Window标记

    QPushButton * pPushBtn = new QPushButton;

    因为,当没有指定父窗口(部件)时都是默认设置了Qt::Window标记的。再如:

    //不管有无父类都为窗体,因为向QWidget传参数时传递了Qt::Dialog标记.

    QDialog * dlg = new QDialog(this);

    因此,QDialog是个独特的部件,无论有无指定父部件,其生来就是Window!

     

    总而言之:所以使QWidget变成Window(窗体)只能使用setWindowFlags(Qt::Window); !!!在使用Qt是一般不考虑窗口的概念,较多情况下都直接使用QWidget就行了,对于自定义部件也是如此。对于之前做过VC的选手可能习惯了使用CDialog,但在Qt中QDialog却没那么受待见,熟练使用QWidget才是王道。

     

    对于 QDialog 的模态及非模态是直接可以实现的,很多课本中都会提到,此处总结下。

     

    模态QDialog

    方式一:

    QDialog dlg(this);
    dlg.exec();

    方式二:

    QDialog *pDlg=new QDialog(this);
    pDlg->setModal(true);
    pDlg->show();

    非模态QDialog

    QDialog *pDlg=new QDialog(this);
    pDlg->show();

     

    QDialog实现模态非模态很简单,但是对于QWidget有点迷茫,QWidget中没有exec(),也没有setModal()方式,但是想想看,QWidget作为QDialog的基类,而且QWidget作为“窗口”使用也是在平常不过了,所以会意识到QWidget中是否存在一个相对exec()或setModal()更基本的操作来实现模态和非模态呢?就这样,我找到了setWindowModality(),此函数就是用来设置QWidget运行时的程序阻塞方式的,参数解释如下:

    Qt::NonModal 不阻塞

    Qt::WindowModal 阻塞父窗口,所有祖先窗口及其子窗口

    Qt::ApplicationModal 阻塞整个应用程序

     

    看来,setModal()也就是使用setWindowModality()设置Qt::ApplicationModal参数也实现的模态。

     

    如此,要实现QWidget的模态和非模态,只要调用setWindowModality()设置阻塞类型就好了:

    QWidget *pWid = new QWidget(this);
    pWid->setWindowModality(Qt::ApplicationModal);
    //pWid->setAttribute(Qt::WA_ShowModal, true);
    pWid->show();

    但是运行发现并未实现模态效果。这里需要注意,当希望使用setWindowModality()将QWidget设置为模态时应该保证QWidget父部件为0,这里修改QWidget *pWid = new QWidget(this);为QWidget *pWid = new QWidget(NULL);在运行就好了。

     

    此外,通过setWindowModality()设置模态窗口并不是唯一方式,直接设置部件(或窗口)属性也可以:

    pWid->setAttribute(Qt::WA_ShowModal, true)

    ---------------

    还有很多地方需要注意,当创建QDialog后使用setWindowFlags(Qt::FramelessWindowHint);去掉标题栏时此对话框不再阻塞父窗口,如果需要实现阻塞效果可再次指定Qt::Dialog,即使用:

    setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint); //这样就会阻塞父窗口了!

    但是,这样会影响对话框的半透明(或透明)显示。使用Qt::Dialog之前半透明显示正常:

     

    使用之后却死活不行了:

     

    -- 不知道如何是好! 

    --------------

    总而言之

    是否是模态和QDialog 和QWidget都可以模态和非模态.exec(), show() 等函数无直接关系,只和窗口属性有关,使用以下两种方式都行:

    setAttribute(Qt::WA_ShowModal, true);//属性设置

    setWindowModality(Qt::ApplicationModal);//设置阻塞类型

    -----------------

    QDialog中的成员函数setModal(true)及exec()之所以是模态是因为他先设置了窗口属性:setAttribute()再show()的

    模态对话框:指该对话框关闭之前不可以对其他窗口进行操作,只有等该对话框关闭之后才可以操作其他窗口。
    非模态对话框:该对话框激活的情况下也可以对其他窗口进行操作。

    模态对话框:
    Qdialog dlg;
    dlg.show();
    执行上面的代码,我们会发现窗口一闪而过,其原因是因为dlg被申明为一个局部变量,当用完之后就自动销毁,所以窗口show完之后立马就被释放。为了不让它一闪而过,使用
    dlg.exec();//阻塞
    这个语句起到阻塞程序的作用,当执行到这里的时候停住了,这样也不能对其他窗口进行操作,所以
    Qdialog dlg;
    dlg.exec();
    就是模态对话框的写法。

    非模态对话框:
    Qdialog *dlg=new Qdialog;
    dlg->show();
    dlg->setAttribute(Qt::WA_DelecteOnClose);

    执行上面程序弹出窗口不会一闪而过,因为new创建在堆上,不会自动销毁,需要手动delete。dlg->setAttribute(Qt::WA_DelecteOnClose)的作用是当窗口关闭时,对话框释放。

     

    模态对话框:非阻塞

     

     //方法1
    TestDialog childWindow ;
     childWindow.setModal(false);
     //childWindow.show();//不可行
     childWindow.exec();//可行
    //方法2
        TestDialog * childWindow = new TestDialog();
        childWindow->setModal(false);
        childWindow->show();

    在子窗口初始化中加入

    setAttribute (Qt::WA_DeleteOnClose);

    防止内存泄漏。

     

    非模态对话框:阻塞

     

    //方法1

     

    TestDialog * childWindow = new TestDialog();
    childWindow->setModal(true);
    childWindow->show();

    //方法2

     

     TestDialog* childWindow = new TestDialog();
      childWindow->setWindowModality(Qt::WindowModal);
      childWindow->show();

    qDialog的setmodal,对话框模态、非模态

    对话框模态,关闭当前对话框前,无法操作其他窗口

    非模态,当前对话框打开同时,也可以操作其他对话框

    模态在对话框创建时设定好后,程序运行过程中无法切换!(如:对话框A当前为非模态,弹出后,设置为模态,不起作用)

     

    1.如果使用exec()默认为模态的。如果用show()需要设置setModel(true)才是模态的。

     

    方法1:模态窗口

    A为窗口类,  父类窗口为B

    A *dlg = new A(this,pB)(可确保A显示在B之上)

    dlg->exe();

    注意:此时使用setModal无效果

     

    方法2:

    A *dlg = new A(this,pB)(可确保A显示在B之上)

    dlg-.setModel(true);

    dlg->show();

     

    2、close()会销毁对象嘛。只有当设置了 setAttribute(WA:closeOnDelelte)是才会删除,如果这个标志没有设置,其作用和hide(),setvisible(false)一样,只会隐藏改对象。

     

    A为窗口类,  父类窗口为B

    A *dlg = new A(this,pB)(可确保A显示在B之上)

    dlg->setAttribute(WA:closeOnDelelte);

    dlg->show;

    注意,此时需要使用close();否则dlg指针未被管理。

     

    3、QWidget的模态和非模态;

     

    4、阻塞?

    QDialog模态对话框与非模态对话框 范例

    //模态1

     
    1. MyWidget*w = new MyWidget; //派生于QWidget

    2. w->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);

    3. w->setAttribute(Qt::WA_ShowModal, true);

    4. w->setAttribute(Qt::WA_DeleteOnClose, true);

    5. w->show();

     

    //模态2

     

     
    1. MyDialog _dialog; //派生于QDialog

    2. int ret = _dialog.exec();

    3. if (ret == QDialog::Accepted)

    4. {

    5.  
    6. }

     

    //模态附加

     

     
    1. void on__btnSave_clicked()

    2. {

    3. this->accept();

    4. this->close();

    5. }

     

    if (res == QDialog::Accepted)


     

    //非模态

     

     
    1. MyDialog* _pMyDialog = new MyDialog ;

    2. _pMyDialog->setAttribute(Qt::WA_DeleteOnClose);

    3. _pMyDialog->setModal(false);

    4. _pMyDialog->show();

     

     

     

    展开全文
  • 本文实例讲述了js实现div模拟模态对话框展现URL内容。分享给大家供大家参考,具体如下: [removed] function sAlert(str){ var msgw,msgh,bordercolor; msgw=800;//提示窗口的宽度 msgh=600;//提示窗口...
  • 主要介绍了vue中的模态对话框组件实现过程,通过template定义组件,并添加相应的对话框样式,需要的朋友可以参考下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,056
精华内容 10,422
关键字:

模态对话框