640 likes | 846 Views
C++ 语言程序设计 第十五章. 山东师范大学管理学院 刘希玉 Email: sdxyliu@beelink.com xyliu@sdnu.edu.cn. 课程目录. 第 1 章 概论 第 2 章 数据类型和表达式 第 3 章 指针和引用 第 4 章 条件、循环及编译预处理 第 5 章 函数 第 6 章 类和对象 第 7 章 继承和派生 第 8 章 多态性和虚函数 第 9 章 字符串和文件 I/O 第 10 章 MFC 应用程序概述 第 11 章 GUI 设计及菜单
E N D
C++语言程序设计第十五章 山东师范大学管理学院刘希玉Email: sdxyliu@beelink.comxyliu@sdnu.edu.cn
课程目录 • 第1章 概论 • 第2章 数据类型和表达式 • 第3章 指针和引用 • 第4章 条件、循环及编译预处理 • 第5章 函数 • 第6章 类和对象 • 第7章 继承和派生 • 第8章 多态性和虚函数 • 第9章 字符串和文件I/O • 第10章 MFC应用程序概述 • 第11章 GUI设计及菜单 • 第12章 创建和使用对话框 • 第13章 应用程序的组成元素 • 第14章 简单的图形和文本输出 • 第15章 Windows 标准控件 • 第16章 Visual C++数据库编程 • 第17章 ACIS的简介与环境配置 • 第18章 ACIS的实例代码 • 第19章 程序调试
第十五章 Windows 标准控件 • 15.1 列表控件 • 15.2 在列表控件中添加项目 • 15.3 进度条控件 • 15.4 滚动条控件 • 15.5 使用滑块控件
15.1 列表控件 • 共有四种类型的列表控件,分别是组合框(Combo box)、列表框(List box)、树(Tree)和列表控件(List controls),每种控件都能达到一种特定的编程目标。在向对话框中添加表控件时,要注意选择控件的正确形式,因为在不同形式下控件的外观和性能有很大的区别。例如,列表框和列表控件都允许多项选定,而组合框在Drop List形式下具有编辑框的功能,而在Dropdown形式下则不然。
添加组合框 • 所以称其为组合框,因为它是多个控件的组合,包括编辑框、列表框和按钮。组合框用来显示选项列表并且只允许用户选择其中的一项。组合框在四种列表控件之中比较独特,因为被选项总是保持可见。 • 表15.1.1显示了组合框的三种形式,它的形式可以通过其属性对话框中的Styles标签来设置。在List示例中,组合框是用来选择目录的,一旦选定某个目录,会在对话框中的其他控件中显示该目录下的子目录和文件。
表15.1.1组合框类型 • 类型 描述 • Simple(简单) 一个编辑框和一个列表框的组合。列表总是可见的, • 被选中的项目显示在编辑框中。 • Dropdown(下拉) 一个有按钮的编辑框和一个列表框的组合。仅当按 • 钮被按下时列表是可见的。 • Drop List 一个有按钮的静态文本和一个列表框的组合。除了 • 用户不能在控件内键入文字外,其余和上一种一样。
在Lists对话框中添加组合框 • 在资源编辑器中打开IDD_LISTS_DIALOG对话框,并删除TODO文本控件。 • 删除对话框中的“Cancel”按钮,将OK按钮移到对话框的右下角。需要在这个对话框中添加多个控件,因此要增加它的宽度和高度。 • 在控件工具栏上选择静态文本控件项,在对话框的左上角添加一个文本控件。 • 在Caption栏中输入Main Directory。 • 在控件工具栏中选择组合框图标,将一个组合框控件添加的Main Directory的右部。 • 将组合框拉伸到对话框的右边界。 • 在ID组合框中输入IDC_MAIN_DIR。 • 选中Styles标签,在Type组合框中选择Drop List项。
用ClassWizard给组合框映射一个CComboBox型变量 • 按Ctrl+W键或者在View菜单中选择ClassWizard来启动ClassWizard。 • 选择Member Variable标签。 • 在Class Name组合框中选择CListDlg。 • 在Control IDs列表框中选择IDC_MAIN_DIR。 • 单击Add Variable按钮,会出现Add Member Variable对话框。 • 确定Category组合框中选中了Control项,Variable Type框中选中了CComboBox项。 • 在Member Variable Name框中输入变量名m_cbMainDir,单击OK按钮。 • 单击OK按钮,关闭ClassWizard。
添加树控件 • 树控件是唯一能显示工程层次关系的列表控件。树控件采用的是从左向右扩展的结构,最左端的项目叫做根节点(root node),最右端的项目叫做叶节点(leaf node),介于最左端和最右端之间的项目叫做枝节点(branch node)。各个项目之间是否用线条连结可以通过样式来设置。在缺省设置下,树控件只允许选定其中一项,如果要让用户在一个树控件中能够同时选中多项,可以通过编辑源代码来实现。 • 在Lists这个示例中,树控件是用来按字母顺序显示目录中的文件。需要为子目标的每一个字母添加一个根节点,然后在相应的节点下面插入代表文件的项目。按下面的步骤为Lists工程添加一个树控件,然后按照用Class Wizard给树控件映射一个CTreeCtrl型变量的步骤为其映射一个变量。
在Lists对话框中添加一个树控件 • 在资源编辑器中打开IDD_LISTS_DLALOG对话框。 • 添加一个静态文本框,标题为Files。 • 在标题工具栏上选择树控件项,在对话框的左边,添加一个树控件。 • 在ID组合框中键入IDC_FILES_TREE。 • 单击Styles标签,选中Has Buttons, Has Lines和Lines at Root几项。
用Class Wizard给树控件映射一个CTreeCtrl型变量 • 按Ctrl+W组合键或者在View菜单中选择ClassWizard项,打开ClassWizard。 • 选择Member Variables标签。 • 在Class Name组合框中选择CListsDlg。 • 在Control IDs列表框中选择IDC_FILES_TREE。 • 单击Add Variable按钮,出现Add Member Variable对话框。 • 确定Category组合框中选中了Control,Variable Type框中选中了CTreeCtrl。 • 在Member Variable Name框中输入变量名m_treeFiles,单击OK。 • 单击OK按钮关闭Class Wizard。
添加列表框控件 • 列表框控件最简单的形式就是直接列出所有项目,不过与组合框和树控件不同,列表框不仅支持单项,而且支持多项选定。表15.1.2所示为列表框的四种形式。
表15.1.2列表框控件选择类型 • 类型 描述 • Single 只有一项可以被选中。选中一项将取消以前的选择 • Multiple 可以在按下Ctrl或Shift键的同时通过鼠标选中多个项目 • Extended 类似Multiple,也可以通过按下鼠标左键并拖动鼠标来选择多个项 • None 所有项都不选
在Lists对话框中添加列表框控件 • 在资源编辑器中打开IDD_LISTS_DIALOG对话框。 • 在对话框右边添加一个标题为Sub Directories的静态文本控件,作为组合框的标题显示。 • 在控件工具栏中选择列表框图标,将其添加到对话框。 • 在ID组合框中键入IDC_SUB_DIRS。 • 在Styles标签下的Selection组合框中选择Extended项。 • 在Seyles标签下不选No Integral Height选项,现在对话框应该如图15.1.1所示。
用ClassWizard给列表框映射CListBox型变量 • .Ctrl+W组合键或者在View菜单中选择ClassWizard选项以打开ClassWizard。 • 2.选择Member Variables标签。 • 3.在Class Name组合框中选择CListsDlg。 • 4.在Control IDs列表框中选择IDC_SUB _DIRS。 • 5.单击Add Variable按钮,会出现Add Member Variable对话框。 • 6.确定Category组合框中选中Control项,Variable Type框中选中CListBox项。 • 7.在Menber Variable Name框中输入变量名m_lbSubDirs,然后单击OK。 • 8.单击OK按钮关闭ClassWizard。
添加列表控件 • 列表控件这个名字有些令人费解,因为本节中介绍的其他三种控件也是列表控件,然而列表控件是四种列表控件中最复杂的一种,在使用中甚至比对话框还常用。它不仅能够显示文本,还能够显示图像,表15.1.3是它的四种显示方式。
在Lists对话框中添加列表控件 • 在资源编辑器中打开IDD_LISTS_DIALOG对话框。 • 2.添加一个标题为Selected Directory Details的静态文本控件,作为列表控件的标题。 • 3.在控件工具栏中选择列表控件图标,在对话框中添加一个列表控件。 • 4.在ID组合框中键入IDC_SELECTED_DIRS。 • 选择Styles标签,在View组合框中选择Report。现在对话框应该如图15.1.2所示。
用ClassWizard给列表框控件映射CListCtrl型变量 • 按Ctrl+W组合键或者在View菜单中选择Class Wizard项,打开ClassWizard。 • 2.选择Member Variables标签。 • 3.在Class name组合框中选择CListsDlg。 • 4.在Control IDs列表框中选择IDC_SELECTED_DIRS。 • 5.单击Add Variable按钮,会出现Add Member Variable对话框。 • 6.确定Category组合框中选中了Control项,Variable Type框中选中了CListCtrl项。 • 7.在Menber Variable Name框中输入变量名m_lcDirDetails,然后单击OK按钮。 • 8.单击OK按钮关闭ClassWizard。
第十五章 Windows 标准控件 • 15.1 列表控件 • 15.2 在列表控件中添加项目 • 15.3 进度条控件 • 15.4 滚动条控件 • 15.5 使用滑块控件
15.2 在列表控件中添加项目 • 因为列表控件是用来显示以及选择多条数据的,所以编程的第一要务就是向控件中添加信息。每一个添加到列表控件的入口都作为一个项目。尽管插入项目使用的机制有相似之处,但是每一种控件类都有其特别的地方。
给组合框添加项目 • 组合框是四种表控件中唯一能够从资源编辑器中添加项目的控件,在组合框属性对话框中选择Data标签即可。每一个项目都可以输入到Enter Listbox Items框中去。每添加完一个工程后按Ctrl+Enter键可再输入一个工程,单独按Enter键则会关闭对话框。这种给组合框添加项目的方法并不常用,在多数情况下组合框中的内容是在程序运行当中通过OnInitDialog( )函数添加的。在第一次打开对话框前,MFC框架会调用此函数。 • 在MFC类中,封装了组合框的是CComboBox类,在该类中有几个与添加或删除组合框中的项目相关的函数,如表15.2.1所示。每一个添加的项目都有一个从零开始的索引号,它是用来访问特殊的项目。
在Lists示例中,通过对话框中的OnInitDialog( )函数给组合框添加了一个主路径的列表,可以确定的是其中调用了Windows的某些全局函数。首先添加一个名为PopulateCombo( )的成员函数,它的返回值为void型。然后编辑OnInitDialog( )函数,如程序清单15.2.1所示。
BOOL CListsDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here PopulateCombo(); m_lcDirDetails.InsertColumn(0,"Directory",LVCFMT_LEFT,70); m_lcDirDetails.InsertColumn(1,"Files",LVCFMT_RIGHT,50); m_lcDirDetails.InsertColumn(2,"Size KB",LVCFMT_RIGHT,60); return TRUE; // return TRUE unless you set the focus to a control } void CListsDlg::PopulateCombo() { TCHAR szBuffer[MAX_PATH]; GetWindowsDirectory(szBuffer,MAX_PATH); m_cbMainDir.AddString(szBuffer);//向组合框中添加Windows目录 szBuffer[2]=0; m_cbMainDir.AddString (szBuffer);//将字符串简化为只包含驱动器符的串,然后 添加到组合框 GetSystemDirectory(szBuffer,MAX_PATH); m_cbMainDir.AddString (szBuffer);//向组合框中添加系统目录 GetCurrentDirectory(MAX_PATH,szBuffer); m_cbMainDir.AddString (szBuffer);//向组合框中添加当前目录 }
使用组合框的目的是允许其中的项目能够被选择,用户一旦选中某项,程序应当立刻对选择进行响应,这个步骤是通过捕捉组合框向对话框传递的CBN_SELCHANGE通知消息来实现的,无论何时改变选项,都会发送该消息的。使用组合框的目的是允许其中的项目能够被选择,用户一旦选中某项,程序应当立刻对选择进行响应,这个步骤是通过捕捉组合框向对话框传递的CBN_SELCHANGE通知消息来实现的,无论何时改变选项,都会发送该消息的。 应该检查AddString( )和InsertString( )函数的返回值,如果出现错误,则它们的返回值是CB_ERR或CB_ERRSPACE。 下面为IDC_MAIN_DIR组合框添加一个名为OnSelchangeMainDir()的消息处理函数和一个用于存放获取的路径的CString型成员变量m_strMainDir。 程序清单15.2.2 获得被选中组合框的文字 void CListsDlg::OnSelchangeMainDir() { // TODO: Add your control notification handler code here CString m_strMainDir; int nIndex=m_cbMainDir.GetCurSel();//得到被选中目录的索引 if(nIndex!=CB_ERR) { m_cbMainDir.GetLBText (nIndex,m_strMainDir);//得到并保存被选中目录的名字 PopulateTree();//向树控件中添加项目 } } 响应组合框的通知消息
给树控件添加项目 • 在向树中添加内容时,需要存放树的结构信息,这样才能确定新增加的项目是以前添加的项目的父项还是子项。 • MFC类库将有关树控件的功能封装在类CTreeCtrl中,此类的成员函数如表15.2.2所示,它们负责处理添加和删除项目。InsertItem( )函数还有很多重载的版本,以满足相关图像和外部数据的需要。每一个新增的工程都有一个HTREEITEM句柄传递给InsertItem( )函数,从而可以创建树中的等级结构。
为了给树Lists添加项目,我们首先创建一个名为PopulateTree( )的成员函数,它的返回值为void型。树控件会按字母顺序显示组合框中选中的目录下的文件。PopulateTree( )函数首先给每一个字母添加一个项目,再为非字母带头的文件名创建一个项目作为第27项。然后它会利用Windows提供的一些函数来获取目录的内容,并将每一个文件名添加到树中合适的位置上。按照程序清单15.2.3所示给PopulateTree( )函数添加源代码。 程序清单15.2.3 给树控件添加项目 void CListsDlg::PopulateTree() { m_treeFiles.DeleteAllItems (); HTREEITEM hLetter[27];//添加根项 for (int nChar='A';nChar<='Z';nChar++) hLetter[nChar-'A']=m_treeFiles.InsertItem((TCHAR*)&nChar); hLetter[26]=m_treeFiles.InsertItem("Other"); HANDLE hFind; WIN32_FIND_DATA dataFind; BOOL bMoreFiles=TRUE; CString strFile; hFind=FindFirstFile(m_strMainDir+"\\*.*",&dataFind); //找到在目录m_strMainDir中的文件 while (hFind!=INVALID_HANDLE_VALUE&&bMoreFiles==TRUE) { if(dataFind.dwFileAttributes==FILE_ATTRIBUTE_ARCHIVE) { int nChar=dataFind.cFileName[0]; if(islower(nChar)) nChar-=32; if(isalpha(nChar)) nChar-='A'; else nChar=26; m_treeFiles.InsertItem(dataFind.cFileName,hLetter[nChar]); //在树中插入文件名 } bMoreFiles=FindNextFile(hFind,&dataFind); } FindClose(hFind); }
DeleteAllItems()会删除现有的所有项目,这是因为每次在组合框中选定不同项目时,树的内容都会更新。FindFirstFile( )函数的参数为m_strMainDir+"\\*.*",是为了找到所选目录的所有文件。FindNextFile( )函数用以跳转到下一个文件。如果没有下一个文件,此函数会返回FALSE值从而中断循环。 • 编译并运行程序,组合框中显示出好几个目录。选择其中的一个,树控件上会显示出该目录下的文件(如图15.2.1所示)。
给列表框添加项目和给组合框添加项目的方法是相同的,因为组合框中的项目列表其实就是一个列表框。它们的主要区别在于外观不同,并且列表框支持多项选定。给列表框添加项目和给组合框添加项目的方法是相同的,因为组合框中的项目列表其实就是一个列表框。它们的主要区别在于外观不同,并且列表框支持多项选定。 MFC类库将有关列表控件的功能封装在CListBox类中,这些成员函数是用来添加和删除项目的,同表15.2.2中列出的是一样的。 在Lists示例中,列表框中要显示组合框中选中的目录下的子目录名。首先添加一个名为PopulateListBox( )的函数,其返回值为void型。然后编辑OnSelchangeMainDir( )函数,在PopulateTree( )函数调用后,添加PopulateListBox();语句调用该函数,并按照程序清单15.4所示,为PopulateListBox()函数添加源代码。 程序清单15.2.2 向列表框添加项目 void CListsDlg::PopulateListBox() { m_lbSubDirs.ResetContent(); HANDLE hFind; WIN32_FIND_DATA dataFind; BOOL bMoreFiles = TRUE; hFind=FindFirstFile(m_strMainDir+"\\*.*",&dataFind); while (hFind!=INVALID_HANDLE_VALUE&&bMoreFiles==TRUE) { if(dataFind.dwFileAttributes==FILE_ATTRIBUTE_ARCHIVE) { if(strcmp(dataFind.cFileName ,".")) if(strcmp(dataFind.cFileName ,"..")) m_lbSubDirs.AddString(dataFind.cFileName); } bMoreFiles=FindNextFile(hFind,&dataFind); } FindClose(hFind); } 给列表框添加项目
用户对列表框进行的操作会向对话框送出一个通知消息,如果选定的项目发生了变化则会送出LBN_SELCHANGE消息。处理选定项目的方式取决于控件是否允许多项选定,CListBox类对不同的类型具有特定的函数。用户对列表框进行的操作会向对话框送出一个通知消息,如果选定的项目发生了变化则会送出LBN_SELCHANGE消息。处理选定项目的方式取决于控件是否允许多项选定,CListBox类对不同的类型具有特定的函数。 在Lists示例中的列表框允许进行多项选定,消息处理函数会在新的成员变量m_strList中记录所选择的目录。m_strList是CStringList型的变量。首先需要用Add MemberVariable对话框来添加此变量。 给IDC_SUB_DIRS列表框创建一个处理 LBN_SELCHANGE消息的函数OnSelchangeSubDirs()。函数必须要知道有多少个项目被选定了,然后将各个项目的文件名提取出来并添加到m_strList变量中去。最后,此函数还要调用PopulateListControl(),实现将m_strList的内容加到列表控件中。OnSelchangeSubDirs()函数如程序清单15.2.5所示。 void CListsDlg::OnSelchangeSubDirs() { // TODO: Add your control notification handler code here int nSelCount=m_lbSubDirs.GetSelCount();//得到列表框中选中的项数 m_strList.RemoveAll(); if(nSelCount) { CString str; LPINT pItems=new int[nSelCount]; m_lbSubDirs.GetSelItems (nSelCount,pItems); for (int i=0;i<nSelCount;i++)//根据控件内容填充数组 { m_lbSubDirs.GetText(pItems[i],str); m_strList.AddTail(str); } delete [] pItems; } PopulateListControl(); } 响应列表框通知消息
给列表控件添加项目 • 给列表控件添加项目的方法和其他几种列表控件不大相同。而且使用的列表控件类型不同,采用的方法也不同。列表控件一共有四种形式,分别是图标、小图标、列表和报表形式。最常用的类型是报表,报表是以分栏的形式显示信息的。例如,Windows Explorer以报表形式显示文件时有名称、大小、类型和修改时间四栏。 • MFC类库中封装列表控件类是ClistCtrl,此类包含了用来添加和删除项目的函数,如表15.2.3所示。
在Lists示例中使用的是报表形式,各栏分别是目录名、目录下的文件数和这些文件的大小总和。要做的第一件事就是添加栏,由于这些不会改变,所以可以调用OnInitDialog()函数来实现,然后调用PopulateListControl();函数来添加项目,现在按程序清单15.2.6所示在OnInitDialog()函数中添加源代码。在Lists示例中使用的是报表形式,各栏分别是目录名、目录下的文件数和这些文件的大小总和。要做的第一件事就是添加栏,由于这些不会改变,所以可以调用OnInitDialog()函数来实现,然后调用PopulateListControl();函数来添加项目,现在按程序清单15.2.6所示在OnInitDialog()函数中添加源代码。 程序清单 15.2.6 初始化列表控件表栏 BOOL CListsDlg::OnInitDialog() { CDialog::OnInitDialog(); . . // TODO: Add extra initialization here PopulateCombo(); m_lcDirDetails.InsertColumn(0,"Directory",LVCFMT_LEFT,70); m_lcDirDetails.InsertColumn(1,"Files",LVCFMT_RIGHT,50); m_lcDirDetails.InsertColumn(2,"Size KB",LVCFMT_RIGHT,60); return TRUE; // return TRUE unless you set the focus to a control }
InsertColumn ( )函数的第一个参数是分栏的索引值,该索引值从零开始。第三个参数设置文本的对齐方式,可以是LVCFMT_LEFT、LVCFMT_RIGHT或LVCFMT_CENTER,最后一个参数是初始化时分栏的宽度,单位是像素,程序运行时列的宽度可以用鼠标来自动调整。 程序清单 15.2.7 void CListsDlg::PopulateListControl() { m_lcDirDetails.DeleteAllItems(); POSITION pos; for (pos=m_strList.GetHeadPosition ();pos!=NULL;) { int nItem; HANDLE hFind; WIN32_FIND_DATA dataFind; BOOL bMoreFiles = TRUE; CString str; CString strFind; str=m_strList.GetAt (pos); nItem=m_lcDirDetails.InsertItem (0,str); strFind=m_strMainDir+"\\"+str+"\\*.*"; hFind=FindFirstFile(strFind,&dataFind); int nFileCount=0; double nFileSize=0; while (hFind!=INVALID_HANDLE_VALUE&&bMoreFiles==TRUE) { if(dataFind.dwFileAttributes==FILE_ATTRIBUTE_ARCHIVE) { nFileCount++; nFileSize+=(dataFind.nFileSizeHigh*MAXDWORD)+dataFind.nFileSizeLow ; } bMoreFiles=FindNextFile(hFind,&dataFind); } FindClose(hFind); str.Format ("%ld",nFileCount); m_lcDirDetails.SetItemText (nItem,1,str); str.Format ("%-1.2f",nFileSize/1024.0); m_lcDirDetails.SetItemText (nItem,2,str); m_strList.GetNext (pos); } }
第十五章 Windows 标准控件 • 15.1 列表控件 • 15.2 在列表控件中添加项目 • 15.3 进度条控件 • 15.4 滚动条控件 • 15.5 使用滑块控件
15.3 进度条控件 • 对一些比较费时的任务,可以使用进度条控件来告诉用户任务当前的进度。进度条控件是通过线条或方块来填充矩形框从而显示当前进度的。另外,进度条控件还能表示在某个范围内的值。 • 在资源编辑器中为对话框添加一个新的进度条控件,只需从控件箱中拖出进度条控件,将它定位在对话框中即可。 • 在进度条属性Styles标签下可以更改如下的有关控件外观的属性: • Border: 选中后会在控件周围出现一个黑色的边框。 • Vertical: 选中后控件纵向大于横向宽度。 • Smooth: 选中后进度条显示是连续的,不是由很多小方块组成的。 • 缺省的进度条设置是选中Border,不选Vertical和Smooth项。
为进度条控件映射变量 • 下面介绍一个进度条应用的实例。首先用AppWizard创建一个基于对话框的工程,然后添加一个按钮和一个进度条控件。按钮的ID为IDC_STEPIT, Caption 为Step It. 进度条控件的ID为IDC_MY_PROGRESS,然后为进度条控件映射成员变量。 • 在资源管理器中单击要映射变量的进度条控件。 • 按Ctrl+W组合键或在View菜单中选择ClassWizard选项以打开ClassWizard并选择Member Variable标签。要确保在Class Name组合框中为新控件了正确的类 (如CProgressDlg类)。 • 双击具有相应控件ID的新进度控件,或者在环境菜单中选择Add Variable选项以弹出新控件的Add Member Variable对话框。 • 在Member Variable Name编辑框中输入新成员的名字(本例使用m_MyProgress). • 注意将Category组合框设为Control,Variable Type设为CProgressCtrl。这是进度条控件唯一可用的选项。 • 单击OK按钮以确认为新控件映射了变量并关闭Add Member Variable对话框。应该可以看到新映射的成员变亮出现在Cortrol Ids列表中相应ID的右侧。 • 单击OK按钮关闭Class Wizard,就将新的变量添加到了所选的类中。 • 给控件映射完变量后,可以通过设置所映射的成员变量的值来更改控件的显示特性,这将在下面的部分中介绍。
操作并更新进度条控件 • 可以通过调用为控件映射的CProgressCtrl变量的方法来操作进度条控件。进度条控件有一个范围,定义了相应于空进度条控件(完成0%)和完成进度条控件(完成100%)的整数值。它还有一个当前值,表示当前的进度相对应的百分比。你还可以设定一个步长值,只要StepIt()函数被调用就增加当前进度。
设计进度条控件的范围 • 设置进度条控件的范围,可以通过调用控件的SetRange()成员函数来实现,直接将范围的低值和高值当作参数传给函数即可。通常设置范围的值是与任务直接相关的,例如当我们计算3000和7000之间的质数时,范围就可以直接设为3000~7000。 • SetRange()只能接受16位的数值,所以它能允许的最大范围是-32768-32767。如果所需的数值范围比这个大,必须使用SetRange32()函数,它接受32位的数值,相应范围是-214783648-214783647。 • 虽然可以在任何时候修改范围的值,但一般都是在进度条控件初始化的时候设定范围的值。程序中通常是在对话框的OnInitDialog()函数的末尾初始化这个控件。 • 在示例程序中,将控件的范围设为0到10。如果设为0,控件为空白。如果设为10,控件充满整个区域。单击工程工作区的ClassView标签,然后单击工程名和类名左侧的加号,如果这个基于对话框的应用程序名为Progress,那么其中的CProgressDig类就是用来处理这个应用程序的主对话框的。找到该类的成员函数OninitDialog(),双击该成员函数就可以在编辑窗口中查看它的代码。要初始化进度条控件的范围,需要在OnInitDialog () 函数的末尾处(恰好在返回语句之前)添加如下的语句: • m_MyProgress.SetRange(0.10); • 现在已将进度条控件的范围设定为0-10。相应的有一个GetRange()函数,同样具有两个整形参数,将返回值存入参数中,前者为范围的最小值,后者为最大值。可以使用该函数获取进度条控件的当前范围。
设置进度条控件的当前值 • 设置了进度条控件的范围后,通过调用其成员函数SetPos()可以更新控件的当前显示。SetPos()函数会用传递给它的参数值更新控件的当前值并显示出来。当前值若高于范围的上限值,则进度条显示为全满状态;若低于范围的下限则进度条显示为空。
设置和使用步长 • 可以设置一个步长值,当每次接收到更新消息时步长值就会自动加入到当前值中,SetStep()函数的参数即是需要设定的步长值。此后可以调用StepIt()函数来更新进度条控件的当前值而无需传给它任何参数。 • 例如,在本例中,可以在OnInitDialog()函数的末尾再加入下面一行源代码将控件的步长设为1: • m_MyProgress.SetStep(1): • 接下来为Step It按钮添加一个处理函数(在资源编辑器中双击该按钮),然后加入下语句: • void CProgressDlg::OnStepit() • { • m_MyProgress.StepIt(): • } • 现在编译并运行程序。你会看到当按下Step It按钮时,进度条中的进度就将前进一格(如图15.3.1所示)。单击10次之后就到达了进度条的末尾,再次调用Stepit()函数,将会清空控件,进度重新开始。
第十五章 Windows 标准控件 • 15.1 列表控件 • 15.2 在列表控件中添加项目 • 15.3 进度条控件 • 15.4 滚动条控件 • 15.5 使用滑块控件
15.4 滚动条控件 • 通常附加在窗口边框上的滚动条使用来滚动窗口中的内容的,它们也能用作控件,用来确定在一个指定范围内的位置。现在,滑块控件已经接替了这一角色。即使这样,仍然需要了解滚动条,因为滑块继承了滚动条的许多基本功能。
在对话框中添加滚动条 • 用资源编辑器从控件工具箱中拖出滚动条控件放置到对话框中。控件工具箱中两个滚动条图表,一个是垂直方向的滚动条,一个是水平方向的滚动条。添加上滚动条后可以根据需要将其位置和大小设置好,然后在其属性对话框的General标签下输入合适的ID,垂直方向滚动条的ID为ScrollBar1,水平方向滚动条的ID为ScrollBar2。 • 滚动条属性对话框中的Styles标签下只有Align一项,这是让设置滚动条的对齐方式,可以将对齐方式设为以下方式中的一种: • ·None:缺省设置,直接采用在对话框模板中添加的滚动框的尺寸。 • ·Top/Left:滚动条具有标准宽度,对齐位置是在对话框模板中添加的滚动框的顶部和底部 • ·Bottom/Right:同Top/Left,但对齐位置是滚动框的底部和右部。
为滚动框映射变量 • 具体方法同15.4.1节中为进度条映射成员变量类似,唯一的区别是第5步中的Category组合框和Varible Type。进度条控件只能选择Control设定,而滚动条可以选择Control项也可以选择Value。 • 如果选择了Value,,则Varible Type就应设为int, 一个映射到滑块控件的整型成员变量就会被插入到所选中的目标类中。新映射的整型成员变量会根据控件的位置进行更新,其更新方式与一个编辑控件更新整数的方式类似。 • 如果选择了Control,则Varible Type会被自动设置为MFC的CScrollBar类。你可以继续“为进度条控件映射成员变量”的步骤,直至关闭Add Member Variable对话框和Class Wizard。
初始化滚动条控件 • 和进度条控件一样,可以在OnInitDialog()函数中初始化滚动条。滚动条也有一个范围,通过调用CScrollBar类中的SetScrollRange()函数可以进行设定,此函数的两个参数分别是范围的下限和上限。还可以选择使用第三个参数来重画滚动条(其缺省值为TRUE)。 • 滚动条范围的最大值和最小值可以使用整数,但是两者之差不能超过32767。 • 例如,OnInitDilog() 函数的末尾添加两行源代码来初始化滚动条: • m__ScrollBar1.SetScrollRange(0,100); • m_ScrollBar2.SetScrollRange(0,200); • 此时,垂直滚动条的范围是0~100,水平滚动条的范围是0~200。因为没有输入第三个参数,所以在缺省情况下,两个滚动条会全部被重画(如果第三个参数为FALSE,则不会被重画)。相应地,GetScrollRange() 函数的参数是指向两个整数的指针,它们会获取当前滚动条的范围,相应的源代码如下: • int nMin,nMax; • m_ScrollBar2.GetScrollRange(&nMin, &nMax): • TRACE(“Range=(%d to %d)\n”, nMin, nMax): • 如果需要使滚动