其实这个问题我以前也提过,但总得不到实质性的答案。今天再发一次,希望能够真正解决问题,这个问题对我来说很重要,而且也困扰了我好长时间。问题的核心就是模式对话框与非模式对话框。我做的是一个POS机,就是刷卡消费的那种。当我点击对话框的某个功能按钮时会弹出来一个“请插入会员卡”的提示。这种对话框功能上应该是:用户插入磁卡时对话框关闭或消失,如果没有插卡则一直显示一段时间,到了设定的超时则关闭或隐藏对话框。按照对话框的功能来说,这时选择非模式对话框是再合适不过了。但如果对话框的层数只是一层的话还好办,这时点击那个功能按钮时可以通过ShowWindow来显示或隐藏非模式对话框,但如果点击这个按钮时不光是弹出非模式对话框,弹出后还需要弹出一个模式对话框,而在这个新弹出的模式对话框上还有按钮,点击上面的按钮还有弹出非模式和模式对话框...。因为弹出的非模式对话框总是同一个对话框(这是一个全局变量),当模式对话框弹出时,那个非模式对话框将处于Disable的状态,此时它不接受用户的鼠标和键盘输入,这就是问题之所在。我自己做了一些测试程序,用在弹出子模式对话框时对父对话框GetParent()->EnableWindow( TRUE );则模式对话框可用,但这只是一层,如果是多层DoModal则很难管理,而且我试图在我的代码上使用此方法也没有成功。如果改用模式对话框,弹出的对话框不会处于Disable状态,但调用DoModal后程序无法继续往下执行,就好像插卡对话框,根本无法实现用户插入磁卡后对话框自动消失,除非这个读卡和关闭功能在那个模式对话框内部实现。但是如果功能比较多的话就很麻烦了,因为不可能把功能处理放在这个模式对话框里,这个对话框其实主要起一个提示作用。提示插卡,提示数据处理,仅此而已。说了这么多也不知道大家明不明白我的意思,希望能够得到一些建议!!

解决方案 »

  1.   

    hello,happyparrot,有看你了。你上次帮我解决了窗口置顶的问题,谢谢你。
    简单点说就是一个对话框程序,在初始化时创建一个非模式对话框,开始是隐藏起来的。每次需要显示一些提示信息时就显示出来,不需要时就隐藏起来。如果说那个对话框为DialogParent,它上面有个按钮,点击时弹出(这里的弹出均是DoModal)一个新对话框为DialogChild1,DialogChild1上有个按钮,点击时弹出一个对话框DialogChild11 -> 再往下就是111,以此类推。
    那个非模式对话框就叫做ModalLessDlg吧,它是在DialogParent窗口中创建的,初始处于隐藏状态ShowWindow( FALSE );请问在DialogChild1111中如何使ModalLessDlg显示并处于Enable状态(可接收鼠标和键盘响应)?不知这样明不明白?
      

  2.   

    请问在DialogChild1111中如何使ModalLessDlg显示并处于Enable状态(可接收鼠标和键盘响应)? 
    ==这还不简单么?给主对话框发消息就行了啊。真是简单的受不了的问题
      

  3.   


    嗯,基本是这个意思,其它理解正确,就是反复无止境这个有点出入,差不多只有三到四层吧。后面的对话框DoModal时会使非模式对话框无效的,我试过直接对那个非模式对话框调用EnableWindow( TRUE );,但没有效果。
      

  4.   

    嗯,我先看看啊。
    这个整体框架是有点问题的,不知上次提没提过,它是用的单文档框架,然后在OnCreate中调用DoModal来显示主对话框,后续则是正常的对话框弹出等了。我是维护和增加新功能的,也没法改变这个框架了,所以好多不是复杂的问题搞得有点麻烦。请问往主对话框发送什么消息呢?是发送WM_ENABLE消息或者EnableWindow吗(这个我当时好像试过,好像不太行,我再试试)?像我目前这种情况是应该往那个单文档的窗口发消息吧?
      

  5.   

    也就是说不可以往那个非模式对话框发消息,只能往Create( IDDxx,这个指针 )主线程发消息是吗?
      

  6.   

    没有必要给这个对话框直接发消息。给主线程发消息就行了。用它的指针对象进行ShowWindow就行了。
      

  7.   

    ??你不是说~把那个共用的非模式对话框设置为全局变量了吗?
    那么任何子地方的对象,,你在程序中都不用再getparent去寻找拉,直接用对话框全局变量的指针,把它showwindow,enablewindows都可以的呀...
    ??
      

  8.   

    全局变量是方便了,可是你的编程水平就没有进步了。现在面向对象编程很重要的一点就是模块化,讲究封装。全局变量,就我的程序来说是禁止的,与goto一样。方便但会让程序可读性和封装性大大降低。要学会消息驱动的好处。
      

  9.   

    呵呵,happyparrot早上好啊。你刚才说的那点我觉得说得很好,我也喜欢你的做法。我早晨试了一下,我发消息那个框架窗口收不到消息啊。我想之所以收不到是不是因为主线程的消息泵被弹出的模式对话框阻塞了?我想,如果说框架能够收到消息的话,说得通俗点也就是主框架是活的,那么这时候的那个非模式对话框也应该可以响应鼠标键盘消息才对,不知我说的对不对?
      

  10.   

    pos机器操作基本上是单流程,还是模式对话框好,你可以用全局变量记录模式对话框的窗口句柄,一般检查用户是否刷卡可以用一个线程去监控,可以在线程里直接发消息将那模式对话框关闭就行;
    我以前就这么做的,虽然笨,但原理简单;
      

  11.   

    模式对话框往主窗口发消息    ::EnableWindow( AfxGetApp()->m_pMainWnd->m_hWnd, true );
        ::PostMessage( AfxGetApp()->m_pMainWnd->m_hWnd, MY_MESSAGE, 0, 0 );
    主框架BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) 
    {
      if( MY_MESSAGE == pMsg->message )
      {
          TRACE( "MainFrame Received MY_MESSAGE message...\n" );
      }
      return CFrameWnd::PreTranslateMessage(pMsg);
    }
    但是Debug窗口没有相应的输出。后来我又改了一下验证方法,证明这时候框架窗口的确是收不到消息的:int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        ...
        SetTimer( 1, 1000, NULL );
        ...
        ...
    }void CMainFrame::OnTimer(UINT nIDEvent) 
    {
    SendMessage( MY_MESSAGE, 0, 0 );
    CFrameWnd::OnTimer(nIDEvent);
    }BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) 
    {
    TRACE( "message loop...\n" );
    return CFrameWnd::PreTranslateMessage(pMsg);
    }当我弹出非模式对话框时,也没有TRACE输出。
      

  12.   

    整个程序的代码相对有点多,而且有些代码是别人写的,风格等更方面都不太好,所以没法帖。
    要是方便的话可以加我QQ:273667359聊或远程我机子(呵呵,不是我拽,要你加我,而是像你这样的牛人可能也不想轻易公布你的QQ,所以方便的话就直接加我吧)。程序运行需要联网、连POS机,不然我就直接把源程序给你发过去了,这样看起来也方便。
      

  13.   

    模式对话框往主窗口发消息 
    肯定收不到消息的,模式对话框有自己的消息循环,回不到主窗口了。除非模式对话框关闭了。SendMessage( MY_MESSAGE, 0, 0 );
    直接调用回调函数,是不会从PreTranslateMessage里执行的。
      

  14.   

    哈哈哈,终于解决了。
    感谢ezhuyin(碧海蓝天)的建议,我采取多线程的方式,果然实现了。实现后对非模式对话框的控制非常灵活,只需要发送消息就可以控制对话框的显示和隐藏。做好后感觉有点像happyparrot说的那样,只不过我是采用多线程来实现。我会把我的具体实现写在我的博客里,感兴趣的朋友可以看看:http://hi.baidu.com/clxye/blog/item/70b747fa629d0314a8d311c0.html最后再次感谢happyparrot、ezhuyin、gotooker。