⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfc12.php

📁 php网页版的mfc教程 不是十分详细 但是很精练 我是新手不是十分会欣赏
💻 PHP
📖 第 1 页 / 共 5 页
字号:
<HTML><HEAD><TITLE>MFC教程_ 对话框和对话框类CDialog</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2800.1458" name=GENERATOR></HEAD>
<BODY bgColor=#ffffff>
<OL start=12>
  <P align=justify>
  <LI><A name=_Toc452640997></A><A name=_Toc457299109></A><B>对话框和对话框类CDialog</B> 

  <P></P>
  <P align=justify>对话框经常被使用,因为对话框可以从模板创建,而对话框模板是可以使用资源编辑器方便地进行编辑的。</P>
  <OL>
    <P align=justify>
    <LI><A name=_Toc452640998></A><A name=_Toc457299110></A><B>模式和无模式对话框</B> 
    <P></P>
    <P align=justify>对话框分两种类型,模式对话框和无模式对话框。</P>
    <OL>
      <P align=justify>
      <LI><A name=_Toc457299111></A><B>模式对话框</B> 
      <P></P>
      <P align=justify>一个模式对话框是一个有系统菜单、标题栏、边线等的弹出式窗口。在创建对话框时指定WS_POPUP, 
      WS_SYSMENU, WS_CAPTION和 DS_MODALFRAME风格。即使没有指定WS_VISIBLE风格,模式对话框也会被显示。</P>
      <P 
      align=justify>创建对话框窗口时,将发送WM_INITDIALOG消息(如果指定对话框的DS_SETFONT风格,还有WM_SETFONT消息)给对话框过程。</P>
      <P align=justify>对话框过程(Dialog box procedure)不是对话框窗口的窗口过程(Window 
      procedure)。在Win32里,对话框的窗口过程由Windows系统提供,用户在创建对话框窗口时提供一个对话框过程由窗口过程调用。</P>
      <P 
      align=justify>对话框窗口被创建之后,Windows使得它成为一个激活的窗口,它保持激活直到对话框过程调用::EndDialog函数结束对话框的运行或者Windows激活另一个应用程序为止,在激活时,用户或者应用程序不可以激活它的所属窗口(Owner 
      window)。</P>
      <P 
      align=justify>从某个窗口创建一个模式对话框时,Windows自动地禁止使用(Disable)这个窗口和它的所有子窗口,直到该模式对话框被关闭和销毁。虽然对话框过程可以Enable所属窗口,但是这样做就失去了模式对话框的作用,所以不鼓励这样做。</P>
      <P 
      align=justify>Windows创建模式对话框时,给当前捕获鼠标输入的窗口(如果有的话)发送消息WM_CANCLEMODE。收到该消息后,应用程序应该终止鼠标捕获(Release 
      the mouse capture)以便于用户能把鼠标移到模式对话框;否则由于Owner窗口被禁止,程序将失去鼠标输入。</P>
      <P 
      align=justify>为了处理模式对话框的消息,Windows开始对话框自身的消息循环,暂时控制整个应用程序的消息队列。如果Windows收到一个非对话框消息时,则它把消息派发给适当的窗口处理;如果收到了WM_QUIT消息,则把该消息放回应用程序的消息队列里,这样应用程序的主消息循环最终能处理这个消息。</P>
      <P 
      align=justify>当应用程序的消息队列为空时,Windows发送WM_ENTERIDLE消息给Owner窗口。在对话框运行时,程序可以使用这个消息进行后台处理,当然应该注意经常让出控制给模式对话框,以便它能接收用户输入。如果不希望模式对话框发送WM_ENTERIDlE消息,则在创建模式对话框时指定DS_NOIDLEMSG风格。</P>
      <P 
      align=justify>一个应用程序通过调用::EndDialog函数来销毁一个模式对话框。一般情况下,当用户从系统菜单里选择了关闭(Close)命令或者按下了确认(OK)或取消(CANCLE)按钮,::EndDialog被对话框过程所调用。调用::EndDialog时,指定其参数nResult的值,Windows将在销毁对话框窗口后返回这个值,一般,程序通过返回值判断对话框窗口是否完成了任务或者被用户取消。</P>
      <P align=justify></P>
      <LI><A name=_Toc457299112></A><B>无模式对话框</B> 
      <P></P></LI></OL>
    <P 
    align=justify>一个无模式对话框是一个有系统菜单、标题栏、边线等的弹出式窗口。在创建对话框模板时指定WS_POPUP、WS_CAPTION、WS_BORDER和WS_SYSMENU风格。如果没有指定WS_VISIBLE风格,无模式对话框不会自动地显示出来。</P>
    <P 
    align=justify>一个无模式对话框既不会禁止所属窗口,也不会给它发送消息。当创建一个模式对话框时,Windows使它成为活动窗口,但用户或者程序可以随时改变和设置活动窗口。如果对话框失去激活,那么即使所属窗口是活动的,在Z轴顺序上,它仍然在所属窗口之上。</P>
    <P 
    align=justify>应用程序负责获取和派发输入消息给对话框。大部分应用程序使用主消息循环来处理,但是为了用户可以使用键盘在控制窗口之间移动或者选择控制窗口,应用程序应该调用::IsDialogMessage函数。</P>
    <P 
    align=justify>这里,顺便解释::IsDialogMessage函数。虽然该函数是为无模式对话框设计的,但是任何包含了控制子窗口的窗口都可以调用它,用来实现类似于对话框的键盘选择操作。</P>
    <P align=justify>当::IsDialogMessage处理一个消息时,它检查键盘消息并把它们转换成相应对话框的选择命令。例如,当Tab 
    键被压下时,下一个或下一组控制被选中,当Down Arrow键按下后,一组控制中的下一个控制被选择。</P>
    <P 
    align=justify>::IsDialogMessage完成了所有必要的消息转换和消息派发,所以该函数处理的消息一定不要传递给TranslateMessage和DispatchMessage处理。</P>
    <P 
    align=justify>一个无模式对话框不能像模式对话框那样返回一个值给应用程序。但是对话框过程可以使用::SendMessage给所属窗口传递信息。</P>
    <P 
    align=justify>在应用程序结束之前,它必须销毁所有的无模式对话框。使用::DestroyWindow销毁一个无模式对话框,不是使用::EndDiaLog。一般来说,对话框过程响应用户输入,如用户选择了“取消”按钮,则调用::DestroyWindow;如果用户没有有关动作,则应用程序必须调用::DestroyWindow。</P>
    <P align=justify></P>
    <LI><A name=_Toc452640999></A><A name=_Toc457299113></A><B>对话框的MFC实现</B> 
    <P></P>
    <P align=justify>在MFC中,对话框窗口的功能主要由CWnd和CDialog两个类实现。</P>
    <OL>
      <P align=justify>
      <LI><A name=_Toc452641000></A><A 
      name=_Toc457299114></A><B>CDialog的设计和实现</B> 
      <P></P>
      <P 
      align=justify>MFC通过CDialog来封装对话框的功能。CDialog从CWnd继承了窗口类的功能(包括CWnd实现的有关功能),并添加了新的成员变量和函数来处理对话框。</P>
      <OL>
        <P align=justify>
        <LI><A name=_Toc457299115></A><B>CDialog的成员变量</B> 
        <P></P>
        <P align=justify>CDialog的成员变量有:</P>
        <P align=justify>protected:</P>
        <P align=justify>UINT m_nIDHelp; // Help ID (0 for none, see 
        HID_BASE_RESOURCE)</P>
        <P align=justify></P>
        <P align=justify>LPCTSTR m_lpszTemplateName; // name or 
        MAKEINTRESOURCE</P>
        <P align=justify>HGLOBAL m_hDialogTemplate; // indirect 
        (m_lpDialogTemplate == NULL)</P>
        <P align=justify>// indirect if (m_lpszTemplateName == NULL)</P>
        <P align=justify>LPCDLGTEMPLATE m_lpDialogTemplate;</P>
        <P align=justify>void* m_lpDialogInit; // DLGINIT resource data</P>
        <P align=justify>CWnd* m_pParentWnd; // parent/owner window</P>
        <P align=justify>HWND m_hWndTop; // top level parent window (may be 
        disabled)</P>
        <P 
        align=justify>成员变量保存了创建对话框的模板资源、对话框父窗口对象、顶层窗口句柄等信息。三个关于模板资源的成员变量m_lpszTemplateName、m_hDialogTemplate、m_lpDialogTemplate对应了三种模板资源,但在创建对话框时,只要一个模板资源就可以了,可以使用其中的任意一类。</P>
        <P align=justify></P>
        <LI><A name=_Toc457299116></A><B>CDialog的成员函数:</B> 
        <P></P></LI></OL></LI></OL></LI></OL></LI></OL>
<OL>
  <P align=justify>
  <LI>构造函数: 
  <P></P>
  <P align=justify>CDialog( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL 
  );</P>
  <P align=justify>CDialog( UINT nIDTemplate, CWnd* pParentWnd = NULL );</P>
  <P align=justify>CDialog( );</P>
  <P 
  align=justify>CDialog重载了三个构造函数。其中,第三个是缺省构造函数;第一个和第二个构造函数从指定的对话框模板资源创建,pParentWnd指定了父窗口或所属窗口,若空则设置父窗口为应用程序主窗口。</P>
  <P align=justify></P>
  <LI>初始化函数 
  <P></P>
  <P align=justify>BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = 
  NULL );</P>
  <P align=justify>BOOL Create( UINT nIDTemplate, CWnd* pParentWnd = NULL );</P>
  <P align=justify>BOOL CreateIndirect( LPCDLGTEMPLATE lpDialogTemplate, CWnd* 
  pParentWnd = NULL );</P>
  <P align=justify>BOOL CreateIndirect( HGLOBAL hDialogTemplate, CWnd* 
  pParentWnd = NULL );</P>
  <P align=justify>BOOL InitModalIndirect( LPCDLGTEMPLATE lpDialogTemplate, 
  CWnd* pParentWnd = NULL );</P>
  <P align=justify>BOOL InitModalIndirect( HGLOBAL hDialogTemplate, CWnd* 
  pParentWnd = NULL );</P>
  <P>Create用来根据模板创建无模式对话框;CreateInDirect用来根据内存中的模板创建无模式对话框;InitModalIndirect用来根据内存中的模板创建模式对话框。它们都提供了两个重载版本。</P>
  <P align=justify></P>
  <LI>对话框操作函数 
  <P></P>
  <P align=justify>void MapDialogRect( LPRECT lpRect ) const;</P>
  <P align=justify>void NextDlgCtrl( ) const;</P>
  <P align=justify>void PrevDlgCtrl( ) const;</P>
  <P align=justify>void GotoDlgCtrl( CWnd* pWndCtrl );</P>
  <P align=justify>void SetDefID( UINT nID );</P>
  <P align=justify>void SetHelpID( UINT nIDR );</P>
  <P align=justify>void EndDialog( int nResult );</P>
  <P align=justify></P>
  <LI>虚拟函数 
  <P></P></LI></OL>
<P align=justify>virtual int DoModal( );</P>
<P align=justify>virtual BOOL OnInitDialog( );</P>
<P align=justify>virtual void OnSetFont( CFont* pFont );</P>
<P align=justify>virtual void OnOK( );</P>
<P align=justify>virtual void OnCancel( );</P>
<OL>
  <OL>
    <OL>
      <P align=justify>
      <LI><A name=_Toc452641001></A><A name=_Toc457299117></A><B>MFC模式对话框的实现</B> 

      <P></P>
      <P>从前面的介绍可以知道,Win32 
      SDK编程下的模式对话框使用了Windows提供给对话框窗口的窗口过程和自己的对话框过程,对话框过程将被窗口过程调用。但在MFC下,所有的窗口类都使用了同一个窗口过程,CDialog也不例外。CDialog对象在创建Windows对话框时,采用了类似于CWnd的创建函数过程,采用子类化的手段将Windows提供给对话框的窗口过程取代为AfxWndProc或者AfxBaseWndProc,同时提供了对话框过程AfxDlgProc。那么,这些“过程”是如何实现或者协调的呢?下文将予以分析。</P>
      <OL>
        <P align=justify>
        <LI><A name=_Toc457299118></A><B>MFC对话框过程</B> 
        <P></P>
        <P>MFC对话框过程AfxDlgProc的原型和实现如下:</P>
        <P align=justify>BOOL CALLBACK AfxDlgProc(HWND hWnd,</P>
        <P align=justify>UINT message, PARAM, LPARAM)</P>
        <P align=justify>{</P>
        <P align=justify>if (message == WM_INITDIALOG)</P>
        <P align=justify>{</P>
        <P align=justify>//处理WM_INITDIALOG消息</P>
        <P align=justify>CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, </P>
        <P align=justify>CWnd::FromHandlePermanent(hWnd));</P>
        <P align=justify>if (pDlg != NULL)</P>
        <P align=justify>return pDlg-&gt;OnInitDialog();</P>
        <P align=justify>else</P>
        <P align=justify>return 1;</P>
        <P align=justify>}</P>
        <P align=justify>return 0;</P>
        <P align=justify>}</P>
        <P>由上可以看出,MFC的对话框函数AfxDlgProc仅处理消息WM_INITDIALOG,其他都留给对话框窗口过程处理。因此,它不同于SDK编程的对话框过程。程序员在SDK的对话框过程处理消息和事件,实现自己的对话框功能。</P>
        <P>AfxDlgProc处理WM_INITDIALOG消息时调用虚拟函数OnInitDialog,给程序员一个机会处理对话框的初始化。</P>
        <P align=justify></P>
        <LI><A name=_Toc457299119></A><B>模式对话框窗口过程</B> 
        <P></P>
        <P>本小节讨论对话框的窗口过程。</P>
        <P>AfxWndProc是所有的MFC窗口类使用的窗口过程,它取代了模式对话框原来的窗口过程(Windows提供),那么,MFC如何完成Win32下对话框窗口的功能呢?</P>
        <P>考查模式对话框的创建过程。CDialog::DoModal用来创建模式对话框窗口并执行有关任务,和DoModal相关的是MFC内部使用的成员函数CDialog::PreModal和CDialog::PostModal。下面分别讨论它们的实现。</P>
        <P align=justify>HWND CDialog::PreModal()</P>
        <P align=justify>{</P>
        <P align=justify>// cannot call DoModal on a dialog already constructed 
        as modeless</P>
        <P align=justify>ASSERT(m_hWnd == NULL);</P>
        <P align=justify></P>
        <P align=justify>// allow OLE servers to disable themselves</P>
        <P align=justify>AfxGetApp()-&gt;EnableModeless(FALSE);</P>
        <P align=justify></P>
        <P align=justify>// 得到父窗口</P>
        <P align=justify>CWnd* pWnd = CWnd::GetSafeOwner(m_pParentWnd, 
        &amp;m_hWndTop);</P>
        <P align=justify></P>
        <P align=justify>// 如同CWnd处理其他窗口的创建,设置一个窗口创建HOOK</P>
        <P align=justify>AfxHookWindowCreate(this);</P>
        <P align=justify></P>
        <P align=justify>//返回父窗口的句柄</P>
        <P align=justify>return pWnd-&gt;GetSafeHwnd();</P>
        <P align=justify>}</P>
        <P align=justify></P>
        <P align=justify>void CDialog::PostModal()</P>
        <P align=justify>{</P>
        <P align=justify>//取消窗口创建前链接的HOOK</P>
        <P align=justify>AfxUnhookWindowCreate(); // just in case</P>
        <P align=justify>//MFC对话框对象和对应的Windows对话框窗口分离</P>
        <P align=justify>Detach(); // just in case</P>
        <P align=justify></P>
        <P align=justify>// m_hWndTop是当前对话框的父窗口或所属窗口,则恢复它</P>
        <P align=justify>if (::IsWindow(m_hWndTop))</P>
        <P align=justify>::EnableWindow(m_hWndTop, TRUE);</P>
        <P align=justify>m_hWndTop = NULL;</P>
        <P align=justify></P>
        <P align=justify>AfxGetApp()-&gt;EnableModeless(TRUE);</P>
        <P align=justify>}</P>
        <P align=justify></P>
        <P align=justify>int CDialog::DoModal()</P>
        <P align=justify>{</P>
        <P align=justify>// can be constructed with a resource template or 
        InitModalIndirect</P>
        <P align=justify>ASSERT(m_lpszTemplateName != NULL ||</P>
        <P align=justify>m_hDialogTemplate != NULL || m_lpDialogTemplate != 
        NULL);</P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -