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

📄 vcc24.htm

📁 vc
💻 HTM
字号:
<html>
<head>
<title>c++系列</title>
 
 
 
 
 
 
 
<meta content="text/html; charset=gb2312" http-equiv=Content-Type>
 
 
</head>
<p align="center"><script src="../../1.js"></script></a>

<body bgcolor="#ffffff" leftmargin="5" topmargin="1" marginheight="5" marginwidth="5">
<div align=center> 
  <table border=0 cellpadding=0 cellspacing=0 width=680 align="center">
    <tbody> 
    <tr> 
      <td width=200 height="59"> 
         
    </tr>
    </tbody> 
  </table>
  <table border=1 bordercolordark=#ffffff bordercolorlight=#ffffff cellpadding=0 
cellspacing=0 width=685 align="center" height="70">
    <tbody> 
    <tr> 
      <td bgcolor=#F9D23C height=14> 
        <div align=center class=H1> <b><font color="#FF0000"><b><font color="#FFFFFF">怎样在一个Pane中显示多种View</font></b></font><font 
      color=#ffa000><b></b></font></b></font></div>
      </td>
    </tr>
    <tr valign=top> 
      <td class=H1 height=212> 
        <p align="center"><font color="#FF0000">   ---- 
          在MS Windows 中,一个窗口可以分割成若干个子窗口,每一个子窗口称作一个窗片(pane),每个窗片可以独立控制,这给界面设计提供了很大的方便。<br>
          <br>
          ---- 利用VC 可以很方便地实现分割窗口。分割的方法有两种:动态和静态。动态分割时可以根据用户的需要分割成数目不同的窗片,但所有窗片的属性和父窗口都是一样的;而静态分割的窗片的数目在程序中指定,运行时是固定的,但每个窗片可以有各自不同类型的视(View),因此其使用范围更为广泛。本文所讨论的问题仅限于静态分割。<br>
          <br>
          ---- 窗片中视的类型大多是在主窗口的创建过程中指定的。这也就意味着,一个窗片虽然可以显示任意类型的视,但是这种类型一旦确定,在程序运行过程中就难以改变。<br>
          <br>
          ---- 一、我要的是这样的!<br>
          <br>
          ---- 但是我们有时确实需要改变一个窗片所显示的视的类型,也就是说,需要让一个窗片显示多种类型的视。例如一个窗口被分割成两部分,一边是命令窗口,另一边是工作窗口,根据命令窗口中发出的不同命令,需要变换不同的工作类型,这就需要工作窗口中能够显示多种类型的视窗,那么,如何做到这一点呢?<br>
          <br>
          ---- 二、你可以这样做!<br>
          <br>
          ---- 从图1 中可以看到,本程序共有三个视类,分别是:<br>
          <br>
          ---- ? 命令视类CCmdView:用来控制右边窗片中不同视的显示;<br>
          <br>
          ---- ? 选项按钮视类CRdiView:显示在右窗片中的选项视类;<br>
          <br>
          ---- ? 检查按钮视类CChkView:显示在右窗片中的检查视类。<br>
          <br>
          ---- 这三个视类都是CFormView 的子类。<br>
          <br>
          ---- 下面我们来看如何在右窗片内进行两类视间的切换。实际上,由视A 切换到视B 的原理很简单,那就是:<br>
          <br>
          ---- 1. 从窗片中删除视A;<br>
          <br>
          ---- 2. 往窗片中添加视B。<br>
          <br>
          ---- 步骤1 的实现非常简单,仅用一条语句即可:<br>
          <br>
          ---- m_wndSplitter.DeleteView(0, 1); <br>
          <br>
          ---- 但它是必不可少的,因为你不能让一个窗片同时包含两个视。我本来希望往一个窗片中添加新的视时,VC 会自动将原来的视删掉,可是它不干。<br>
          <br>
          ---- 我们来看如何实现步骤2,当一个窗片是空的时候,怎样往里面添加一个视呢?其实这样的功能在程序里我们已经用过了,看下面的语句:<br>
          <br>
          BOOL CMainFrame::OnCreateClient<br>
          (LPCREATESTRUCT lpcs, CCreateContext* pContext) <br>
          {<br>
          ……<br>
          if (!m_wndSplitter.CreateView(0, 0, <br>
          pContext-&gt;m_pNewViewClass, <br>
          size, <br>
          pContext))<br>
          ……<br>
          }<br>
          ---- 是的,用的就是CSplitterWnd::CreateView(),要注意的是它共有五个参数,其中前两个用来指定分割窗口的窗片,第三个用来指定视的类型,第四个指定视的大小。最后的一个我们暂时用不上,用空值NULL 
          就可以了。<br>
          <br>
          ---- 这样我们就可以编写视切换的代码了。因为视切换要操纵m_wndSplitter,而它是主窗口的成员,因此切换过程最好设计为主窗口的成员函数。但是切换命令是CCmdView 
          接受的,因而可以让CCmdView 接受到视更改消息后,将消息传给主窗口,由主窗口完成视更改。具体的代码是这样的:<br>
          <br>
          ---- 命令视类中的消息映射:<br>
          <br>
          BEGIN_MESSAGE_MAP(CCmdView, CFormView)<br>
          ……<br>
          ON_BN_CLICKED(IDC_CHECK, OnSwitchToCheckView)<br>
          ON_BN_CLICKED(IDC_RADIO, OnSwitchToRadioView)<br>
          ……<br>
          END_MESSAGE_MAP()<br>
          <br>
          命令视类中的消息响应:<br>
          void CCmdView::OnSwitchToCheckView() <br>
          {<br>
          AfxGetApp()-&gt;m_pMainWnd-&gt;<br>
          SendMessage(WM_COMMAND, ID_CHECK);<br>
          }<br>
          <br>
          void CCmdView::OnSwitchToRadioView() <br>
          {<br>
          AfxGetApp()-&gt;m_pMainWnd-&gt;<br>
          SendMessage(WM_COMMAND, ID_RADIO);<br>
          }<br>
          <br>
          主窗口中的消息映射:<br>
          BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)<br>
          ……<br>
          ON_COMMAND(ID_CHECK, OnSwitchToCheckView)<br>
          ON_COMMAND(ID_RADIO, OnSwitchToRadioView)<br>
          ……<br>
          END_MESSAGE_MAP()<br>
          <br>
          主窗口中的消息响应:<br>
          void CMainFrame::OnSwitchToCheckView() <br>
          {<br>
          m_wndSplitter.DeleteView(0, 1);<br>
          m_wndSplitter.CreateView(0, 1, <br>
          RUNTIME_CLASS(CChkView), <br>
          CSize(0, 0), <br>
          NULL);<br>
          m_wndSplitter.RecalcLayout();<br>
          }<br>
          <br>
          void CMainFrame::OnSwitchToRadioView() <br>
          {<br>
          m_wndSplitter.DeleteView(0, 1);<br>
          m_wndSplitter.CreateView(0, 1,<br>
          RUNTIME_CLASS(CRdiView),<br>
          CSize(0, 0), <br>
          NULL);<br>
          m_wndSplitter.RecalcLayout();<br>
          }<br>
          ---- 好啦,运行一下这个程序,感觉是否不错?看来大功告成了,可是……<br>
          <br>
          ---- 三、还有一个问题<br>
          <br>
          ---- 在运行我们辛辛苦苦编出来的程序时,回头看看VC 的调试窗口,你会发现有很多行这样的话:<br>
          <br>
          ---- Create view without document. <br>
          <br>
          ---- 这是说我们创建了视,可是没有相应的文档。好在这只是警告信息,不是什么错误,如果你不需要相应的文档,就完全不用去管它。可是,VC 
          中一种很重要的结构就是文档- 视结构,利用这种结构,对数据操纵起来非常方便。如果需要建立与视相对应的文档,应该怎么办呢?<br>
          <br>
          ---- 这就涉及到VC 中文档- 视结构的知识,不过不用怕麻烦,与本文有关的就只有这么两点而已:<br>
          <br>
          ---- 1. 利用VC 创建的应用程序一般都会管理一些文档模板(Document Template),文档类和视类的对应关系就是在文档模板里描述的。<br>
          <br>
          ---- 2. 一个文档可以有多个视,创建视的时候,需要根据文档和视的对应关系,给出它所依附的文档。<br>
          <br>
          ---- 怎样实现上述第一点呢?<br>
          <br>
          ---- 首先建立相应的文档类:CRdiDoc 和CChkDoc。<br>
          <br>
          ---- 其次是定义相应的文档模板,这是应用类的成员变量。因为在别的类中要使用它们,我们将之定义为公共类型:<br>
          <br>
          class CViewSwitcherApp : public CWinApp<br>
          {<br>
          ……<br>
          public:<br>
          CSingleDocTemplate* m_pRdiDocTemplate;<br>
          CSingleDocTemplate* m_pChkDocTemplate;<br>
          ……<br>
          }<br>
          然后创建这两个文档模板,并加入到模板列表中:<br>
          BOOL CViewSwitcherApp::InitInstance()<br>
          {<br>
          ……<br>
          m_pRdiDocTemplate = new CSingleDocTemplate(<br>
          IDR_MAINFRAME,<br>
          RUNTIME_CLASS(CRdiDoc),<br>
          RUNTIME_CLASS(CMainFrame),<br>
          RUNTIME_CLASS(CRdiView));<br>
          AddDocTemplate(m_pRdiDocTemplate);<br>
          <br>
          m_pChkDocTemplate = new CSingleDocTemplate(<br>
          IDR_MAINFRAME,<br>
          RUNTIME_CLASS(CChkDoc),<br>
          RUNTIME_CLASS(CMainFrame),<br>
          RUNTIME_CLASS(CChkView));<br>
          AddDocTemplate(m_pChkDocTemplate);<br>
          ……<br>
          }<br>
          ---- 至于第二点,是在创建视时完成的。还记得创建视的情况么?当时有一个叫做pCreateContext 的参数,我们将之置为空,这里就要用到它了。<br>
          <br>
          ---- pCreateContext 是一个指向被称作&quot; 创建上下文&quot;(CreateContext) 结构的指针,这个结构中保存一些与创建视相关的内容。在创建主窗口时,系统会构造这样一个结构,并将它作为参数传递到与创建视有关的函数中。但现在我们不创建主窗口,因此不得不自己构造这样一个结构。实际上,该结构中我们所要使用的字段只有三个:<br>
          <br>
          ---- 1. 新视所属的文档模板m_pNewDocTemplate;<br>
          <br>
          ---- 2. 新视的类型m_pNewViewClass;<br>
          <br>
          ---- 3. 新视所属的文档m_pCurrentDoc;<br>
          <br>
          ---- 其中仅有第三项需要新建,前两项都是已知的,只要指定即可。以切换到选项视为例,修改后的代码是:<br>
          <br>
          void CMainFrame::OnSwitchToRadioView() <br>
          {<br>
          m_wndSplitter.DeleteView(0, 1);<br>
          <br>
          CCreateContext createContext; <br>
          // 定义并初始化CreateContext<br>
          // 获取新视所属的文档模板<br>
          CSingleDocTemplate* pDocTemplate = <br>
          ((CViewSwitcherApp*)AfxGetApp())-&gt; m_pRdiDocTemplate;<br>
          // 创建新文档并初始化<br>
          CDocument* pDoc = pDocTemplate-&gt;CreateNewDocument();<br>
          pDoc-&gt;OnNewDocument();<br>
          <br>
          // 设置CreateContext 相关字段<br>
          createContext.m_pNewViewClass = RUNTIME_CLASS(CChkView);<br>
          createContext.m_pCurrentDoc = pDoc;<br>
          createContext.m_pNewDocTemplate = pDocTemplate;<br>
          <br>
          m_wndSplitter.CreateView(0, 1,<br>
          RUNTIME_CLASS(CRdiView),<br>
          CSize(0, 0),<br>
          &amp;createContext);<br>
          <br>
          m_wndSplitter.RecalcLayout();<br>
          }<br>
          ---- 四、最后的修改<br>
          <br>
          ---- 为了使这个程序更符合要求,我们还要做一些与更换视无关的修改。在这个程序中我们一共定义了三种类型的文档,程序启动时一般要新建一个文档开始工作,可是它不知道要选择哪一种,就弹出一个对话框来询问。而这是我们不希望看到的。修改的方法是不让VC 
          选择新文档类型,而我们指定创建哪一种类型的文档,即把CViewSwitcherApp::CViewSwitcherApp() 中的语句<br>
          <br>
          ---- if (!ProcessShellCommand(cmdInfo)) return FALSE; <br>
          <br>
          ---- 更改为<br>
          <br>
          ---- m_pDocTemplate-&gt;OpenDocumentFile(NULL)。 </font></span></font> 
        </p>
        <p>  转载自CPCW程序方舟 河南大学数学系祁文文 
          </span></font>
         
      </td>
    </tr>
    </tbody> 
  </table>
</div>
<p align="center"><script src="../../2.js"></script></a>
</body>
</html>

⌨️ 快捷键说明

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