上一页 下一页 返回

6.4 在非对话框窗口中使用控件

  控件并不是对话框独有的,事实上,很多非对话框窗口都可以使用控件.比较典型的应用是在表单视图、工具条和状态栏中使用控件.  

6.4.1 在表单视图中使用控件  

  MFC提供了一个名为CFormView的特殊视图类,我们称其为表单视图.表单视图是指用控件来输入和输出数据的视图,用户可以方便地在表单视图中使用控件.表单视图具有对话框和滚动视图的特性,它使程序看起来象是一个具有滚动条的对话框.在有些情况下,用表单视图比用普通视图更符合用户的需要,例如,在向数据库输入数据时,显然用表单的形式可以更习惯些.  

  用AppWizard可以方便地创建基于表单视图的应用程序,只要在MFC AppWizard对话框的第六步先选择CView,然后在Base class栏中选择CFormView,AppWizard就会创建一个基于CFormView的应用程序.  

  读者可以按上述方法建立一个名为Test的应用程序.在Test工程的资源中,读者会发现一个ID为IDD_TEST_DIALOG的对话框模板,该对话框模板可供用户放置和安排控件.在程序运行时,框架根据该对话框模板创建CFormView对象,并根据模板的信息在表单视图中自动创建控件.与设计对话框类相类似,用户可以用ClassWizard为表单视图类加入与控件对应的成员变量,可以调用UpdateData在控件和成员变量之间交换数据,但对控件的初始化工作是在OnInitialUpdate函数而不是在OnInitDialog函数中进行的.  

  基于表单视图的应用程序与基于对话框的应用程序都是在应用程序中直接使用控件,但二者有很多不同之处.基于对话框的应用程序是用一个对话框来作为程序的主窗口的,因而程序的主窗口的特性与对话框类似,如窗口的大小不能改变,程序没有菜单条、工具条和状态栏等.基于表单视图的应用程序仍然是基于Doc/View框架结构的(见七、八、九章),只是视图被换成了表单视图,也就是说,应用程序的窗口可以改变大小,程序有菜单条、工具条和状态栏,且程序仍然可以Dov/View运行机制来处理文档.  

  表单视图比较简单,这里就不举例说明了.在第十章,读者会看到使用表单视图的例子.  

6.4.2 在工具条和状态栏中使用控件  

  一个专业的程序常常会在工具条和状态栏中加入一些控件以方便用户的使用.例如,在Developer Studio的工具条中就有不少组合框,而在状态栏中则常常会显示一个进度条来表明工作的进度.  

  如果读者想在自己程序的工具条和状态栏中加入控件,则需要掌握一些技巧.在本小节,我们将结合一个具体实例来演示这些技巧.例程的名为CtrlInBar,其界面如图6.8所示.可以看出,该程序在工具条中创建了一个组合框,在状态栏中创建了一个进度条.  

  T6_8.tif (174388 bytes)  

  图6.8 CtrlInBar程序  

  现在让我们开始工作.首先,请读者用AppWizard建立一个名为CtrlInBar的单文挡MFC应用程序,然后,请按清单6.4修改源代码.注意在程序中编写了一个CToolBar类的派生类CMyToolBar,以及一个CStatusBar的派生类CMyStatusBar,这两个类与CMainFrame类在同一模块中.  

清单6.4 在工具条和状态栏中创建控件的有关代码  

  // MainFrm.h : interface of the CMainFrame class  

  //  

  /////////////////////////////////////////////////////////////////////////////  

  #define IDC_MYCOMBO 100  

  class CMyToolBar : public CToolBar  

  {  

  public:  

  CComboBox m_ComboBox;  

  BOOL CreateComboBox(int nIndex);  

  };   

     

  #define ID_INDICATOR_PROGRESS 100  

  class CMyStatusBar : public CStatusBar  

  {  

  public:  

  CProgressCtrl m_Progress;  

  int m_nProgressPane;  

  BOOL CreateProgressCtrl(int nPane);  

     

  afx_msg void OnSize(UINT nType, int cx, int cy);  

  DECLARE_MESSAGE_MAP()  

  };  

     

  class CMainFrame : public CFrameWnd  

  {  

     

  . . . . . .  

  protected: // control bar embedded members  

  CMyStatusBar m_wndStatusBar;  

  CMyToolBar m_wndToolBar;  

     

  . . . . . .  

  };  

     

  // MainFrm.cpp : implementation of the CMainFrame class  

  //  

     

  . . . . . .  

  static UINT indicators[] =  

  {  

  ID_SEPARATOR, // status line indicator  

     

  ID_SEPARATOR  

  };  

     

  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)  

  {  

  if (CFrameWnd::OnCreate(lpCreateStruct) == -1)  

  return -1;  

     

  if (!m_wndToolBar.Create(this) ||  

  !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))  

  {  

  TRACE0("Failed to create toolbar\n");  

  return -1; // fail to create  

  }  

     

  if (!m_wndStatusBar.Create(this) ||  

  !m_wndStatusBar.SetIndicators(indicators,  

  sizeof(indicators)/sizeof(UINT)))  

  {  

  TRACE0("Failed to create status bar\n");  

  return -1; // fail to create  

  }  

     

  // TODO: Remove this if you don't want tool tips or a resizeable toolbar  

  m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |  

  CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);  

     

     

  m_wndToolBar.CreateComboBox(0); //在工具条的最左边创建组合框  

  m_wndStatusBar.CreateProgressCtrl(1); //在第二个窗格创建进度条  

     

  m_wndToolBar.m_ComboBox.AddString("Item1");  

  m_wndToolBar.m_ComboBox.AddString("Item2");  

  m_wndToolBar.m_ComboBox.AddString("Item3");  

  m_wndToolBar.m_ComboBox.AddString("Item4");  

  m_wndStatusBar.m_Progress.SetRange(0,200);  

  m_wndStatusBar.m_Progress.SetPos(100);  

     

     

  . . . . . .  

  }  

     

     

  /////////////////////////////////////////////////////////////////////////////  

  //CMyToolBar  

     

  //参数nIndex是按钮的索引,函数将在该按钮的左侧创建组合框  

  BOOL CMyToolBar::CreateComboBox(int nIndex)  

  {  

  if(m_ComboBox.GetSafeHwnd()) //防止重复创建  

  return FALSE;  

     

  CToolBarCtrl &ToolBarCtrl=GetToolBarCtrl();  

  TBBUTTON button;  

  CRect rect;  

  button.fsStyle=TBSTYLE_SEP;  

  ToolBarCtrl.InsertButton(nIndex,&button); //插入空位  

  ToolBarCtrl.InsertButton(nIndex,&button);  

  ToolBarCtrl.InsertButton(nIndex,&button);  

  //设置空位的宽度(处于中间的空位用来容纳组合框)  

  SetButtonInfo(nIndex+1,IDC_MYCOMBO,TBBS_SEPARATOR,100);  

  SetButtonInfo(nIndex, ID_SEPARATOR, TBBS_SEPARATOR, 12);  

  SetButtonInfo(nIndex+2, ID_SEPARATOR, TBBS_SEPARATOR, 12);  

  GetItemRect(nIndex+1, &rect); //获取中间空位的坐标  

  rect.top = 3;  

  rect.bottom = rect.top + 100;  

  if (!m_ComboBox.Create(CBS_DROPDOWNLIST|WS_VISIBLE|WS_TABSTOP,  

  rect, this, IDC_MYCOMBO))  

  return FALSE;  

  m_ComboBox.SetItemHeight(-1,15); //设置编辑框组件的高度  

  return TRUE;  

  }  

     

     

  /////////////////////////////////////////////////////////////////////////////  

  //CMyStatusBar  

     

     

  BEGIN_MESSAGE_MAP(CMyStatusBar, CStatusBar)  

  ON_WM_SIZE()  

  END_MESSAGE_MAP()  

     

  //参数nPane是窗格的索引,函数将在该窗格内创建进度条控件  

  BOOL CMyStatusBar::CreateProgressCtrl(int nPane)  

  {  

  if(m_Progress.GetSafeHwnd()) //防止重复创建  

  return FALSE;  

     

  //设置该窗格的宽度为200  

  SetPaneInfo(nPane,GetItemID(nPane),SBPS_NORMAL,200);  

  CRect rect(0,0,1,1);  

  if(!m_Progress.Create(WS_CHILD|WS_VISIBLE,rect,this,  

  ID_INDICATOR_PROGRESS))  

  return FALSE;  

  m_nProgressPane=nPane;  

  return TRUE;  

  }  

     

  void CMyStatusBar::OnSize(UINT nType, int cx, int cy)   

  {  

  CStatusBar::OnSize(nType, cx, cy);  

  if(m_Progress.GetSafeHwnd()==NULL) return;  

     

  CRect rect;  

  GetItemRect(m_nProgressPane,&rect);  

  m_Progress.MoveWindow(rect); //调整控件的位置和尺寸  

  }  

  CMyToolBar类可以在工具条中指定按钮的左边放置一个下拉列表式组合框,并在组合框的两端留出空位.该类的CreateComboBox成员负责创建组合框,参数nIndex是工具条按钮的索引,需注意的是工具条的一个空位也要占有一个索引.在CreateComboBox中,主要调用了下列函数:  

  

  调用CToolBar::GetTool