zoukankan      html  css  js  c++  java
  • 对话框

    /*********************************************************************************************************************
    *   发布日期:
    *   更新日期:2017-11-16 09:22:05
    *   进度:待完善
    *   作者:骆天
    *   备注:
    *********************************************************************************************************************/

    对话框的创建

    一、MFC创建模态对话框

    CMyDialog dlg;
    dlg.DoModal();

    考查模式对话框的创建过程。CDialog::DoModal用来创建模式对话框窗口并执行有关任务,和DoModal相关的是MFC内部使用的成员函数CDialog::PreModal和CDialog::PostModal。下面分别讨论它们的实现。

    HWND CDialog::PreModal()
    {
    // cannot call DoModal on a dialog already constructed as modeless
    ASSERT(m_hWnd == NULL);
    // allow OLE servers to disable themselves
    AfxGetApp()->EnableModeless(FALSE);
    // 得到父窗口
    CWnd* pWnd = CWnd::GetSafeOwner(m_pParentWnd, &m_hWndTop);
    // 如同CWnd处理其他窗口的创建,设置一个窗口创建HOOK
    AfxHookWindowCreate(this);
    //返回父窗口的句柄
    return pWnd->GetSafeHwnd();
    }
    void CDialog::PostModal()
    {
    //取消窗口创建前链接的HOOK
    AfxUnhookWindowCreate(); // just in case
    //MFC对话框对象和对应的Windows对话框窗口分离
    Detach(); // just in case
    // m_hWndTop是当前对话框的父窗口或所属窗口,则恢复它
    if (::IsWindow(m_hWndTop))
        ::EnableWindow(m_hWndTop, TRUE);
    m_hWndTop = NULL;
    AfxGetApp()->EnableModeless(TRUE);
    }
    int CDialog::DoModal()
    {
        // can be constructed with a resource template or InitModalIndirect
        ASSERT(m_lpszTemplateName != NULL ||
            m_hDialogTemplate != NULL || m_lpDialogTemplate != NULL);
    
        //加载对话框资源
        LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
        HGLOBAL hDialogTemplate = m_hDialogTemplate;
        HINSTANCE hInst = AfxGetResourceHandle();
        //查找资源(见9.5.2节),找到了就加载它
        if (m_lpszTemplateName != NULL)
        {
            hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
            HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
            hDialogTemplate = LoadResource(hInst, hResource);
        }
        //锁定加载的资源
        if (hDialogTemplate != NULL)
            lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
        // return -1 in case of failure to load the dialog template resource
        if (lpDialogTemplate == NULL)
            return -1;
        //创建对话框前禁止父窗口,为此要调用PreModal得到父窗口句柄
        HWND hWndParent = PreModal();
        AfxUnhookWindowCreate();
        CWnd* pParentWnd = CWnd::FromHandle(hWndParent);
        BOOL bEnableParent = FALSE;
        if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
        {
            ::EnableWindow(hWndParent, FALSE);
            bEnableParent = TRUE;
        }
        //创建对话框,注意是无模式对话框
        TRY
        {
            //链接一个HOOK到HOOK链以处理窗口创建,
            //如同4.4.1节描述的CWnd类窗口创建一样
            AfxHookWindowCreate(this);
            //CreateDlgIndirect间接调用::CreateDlgIndirect,
            //最终调用了::CreateWindowEX来创建对话框窗口。
            //HOOK过程_AfxCbtFilterHook用子类化的方法
            //取代原来的窗口过程为AfxWndProc。
            if (CreateDlgIndirect(lpDialogTemplate, CWnd::FromHandle(hWndParent), hInst))
            {
                if (m_nFlags & WF_CONTINUEMODAL)
                {
                    // enter modal loop
                    DWORD dwFlags = MLF_SHOWONIDLE;
                    //RunModalLoop接管整个应用程序的消息处理
                    if (GetStyle() & DS_NOIDLEMSG)
                        dwFlags |= MLF_NOIDLEMSG;
                    VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
                }
                // hide the window before enabling the parent, etc.
                if (m_hWnd != NULL)
                    SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW |
                    SWP_NOSIZE | SWP_NOMOVE |
                    SWP_NOACTIVATE | SWP_NOZORDER);
            }
    
        }
        CATCH_ALL(e)
        {
            DELETE_EXCEPTION(e);
            m_nModalResult = -1;
        }
        END_CATCH_ALL
            //Enable并且激活父窗口
        if (bEnableParent)
            ::EnableWindow(hWndParent, TRUE);
        if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
            ::SetActiveWindow(hWndParent);
        //::EndDialog仅仅关闭了窗口,现在销毁窗口
        DestroyWindow();
        PostModal();
        // 必要的话,解锁/释放资源
        if (m_lpszTemplateName != NULL || m_hDialogTemplate != NULL)
            UnlockResource(hDialogTemplate);
        if (m_lpszTemplateName != NULL)
            FreeResource(hDialogTemplate);
        return m_nModalResult;
    
    }

    从DoModal的实现可以看出:
    它首先Disable对话框窗口的父窗口;然后使用::CreateIndrectDialog创建对话框窗口,使用子类化的方法用AfxWndProc(或者AfxBaseProc)替换了原来的窗口过程,并把原来的窗口过程保存在CWnd的成员变量m_pfnSuper中。原来的窗口过程就是::DialogBox等创建对话框窗口时指定的,是Windows内部提供的对话框“窗口类”的窗口过程。取代(Subclass)原来“窗口类”的窗口过程的方法如同 4.4.1节描述的CWnd::Create。

    在::CreateIndirectDialog创建对话框窗口后,会发送WM_INITDIALOG消息给对话框的对话框过程(必要的话,还有WM_SETFONT消息)。但是MFC取代了原来的对话框窗口过程,这两个消息如何送给对话框过程呢?处理方法如下节所描述。

    二、MFC创建非模态对话框

    CMyDialog dlg;//此dlg应在类中作为成员变量;
    dlg.Create(IDD_DIALOG1,this);
    dlg.ShowWindow(SW_SHOW);//显示窗口

    对话框的控制:

    分为几种情况,第一种,直接调用对话框,前提是已经在资源管理器中创建了一个对话框,比如,在菜单中的某个选项中调出对话框,可以直接用CWnd::DialogBox()函数。一旦显示对话框并且操作完成之后,当需要关闭的时候,调用函数EndDialog()函数。调用之后,只关闭这个对话框,而不是是关闭整个窗口。

    BOOL EndDialog(
    HWND hDlg; //该对话框所属的窗口句柄,比如hwnd
    int nResult //返回值
    );

    第二种情况,应用程序就只有一个对话框,只要关闭对话框就意味着整个程序关闭。可以在某个按钮上(比如取消按钮)添加一条消息,PostQuitMessage(0);

    CDialog成员函数一览表

    BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL );
    BOOL Create( UINT nIDTemplate, CWnd* pParentWnd = NULL );

    Create用来根据模板创建无模式对话框

    BOOL CreateIndirect( LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd = NULL );
    BOOL CreateIndirect( HGLOBAL hDialogTemplate, CWnd* pParentWnd = NULL );

    CreateInDirect用来根据内存中的模板创建无模式对话框

    BOOL InitModalIndirect( LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd = NULL );
    BOOL InitModalIndirect( HGLOBAL hDialogTemplate, CWnd* pParentWnd = NULL );

    InitModalIndirect用来根据内存中的模板创建模式对话框。它们都提供了两个重载版本

    /*构造函数*/

    CDialog( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL );
    CDialog( UINT nIDTemplate, CWnd* pParentWnd = NULL );
    CDialog( );

    CDialog重载了三个构造函数。
    其中,第三个是缺省构造函数;
    第一个和第二个构造函数从指定的对话框模板资源创建,pParentWnd指定了父窗口或所属窗口
    若空则设置父窗口为应用程序主窗口。
       
       
       
       
       
       
  • 相关阅读:
    css实现京东顶部导航条
    css盒布局-省份选择盘的实现
    css字体的属性
    css行高
    CSS定位(position)
    CSS-clear属性的作用
    2.b统计字符串长度
    rectangle类。java
    mysql 版本问题之sql-mode 导致 sql 语句报错
    根据一个表中同一字段的不同值进行统计!!!
  • 原文地址:https://www.cnblogs.com/tinaluo/p/5365587.html
Copyright © 2011-2022 走看看