搜索
您的当前位置:首页列表控件(排序)

列表控件(排序)

来源:小侦探旅游网


本讲主要介绍组合框(Combo Box)控件和列表框(List Box)控件的的使 用方法。

一.创建一个基于对话框的应用程序模板 1.选择应用程序类型:

选择“File\\New”菜单 → 在弹出的“New”对话框的选择“Projects” 选项卡 → 应用程序类型选择“MFC AppWizard(exe)” → “Project name”编辑框中输入“ListBox” → “Location”编辑框中输入适当的 路径 → 单击“OK” 2.选择项目类型

在“MFC AppWizar – Step 1”对话框中“Dialog based”单选钮 → 单击“Finish”按钮。

二.修改对话框模板

把主对话框模板修改成如下图所示:

图6-1 1.增加“编号”、“姓名”、“出生年月”、“性别”、“职称”和“职工情况列表” 等六个静态文本

2.在“编号”右侧增加一个下沉风格的静态文本,资源符号为:IDC_NUMBER 在“Styles”选项卡的“Center-vertically”复选钮: 选中 3.在“姓名”和“出生年月”右侧,增加二个编辑框,资源符号分别为: IDC_NAME, IDC_BIRTHDAY

4.在“性别”和“职称”右侧,增加二个组合框,资源符号分别命名为:

1

IDC_SEX 在Combo Box Properties对话框的styles选项卡的 type下拉列表框中选择Drop List 注: Drop List选项不允许组合框编辑输入

IDC_TITLE 在Combo Box Properties对话框的styles选项卡的 type下拉列表框中选择Drop List 注: Dropdown选项允许组合框编辑输入 5.增加“添加”、“删除当前选定行”和“在选定行前插入”三个按钮,ID值命 名为: IDC_ADD, IDC_DELETE, IDC_INSERT

6.在“职工情况列表”的下方,增加一个列表控件”List Control”: 在”List Control Properties”对话框中如下设置: A.在General选项卡的ID组合框中输入: IDC_LIST B.在Styles选项卡中选择:

“View:”下拉列表框: Report “Align:”下拉列表框: Top

“Sort:”下拉列表框: Ascending “Single selection”复选框: 选中

三.为控件连接变量

为各控件连接的变量名及其值类型和变量类型如下(连接方法前已述): 控件ID 变量名 变量类别 变量类型 IDC_NUMBER m_nNumber value CString IDC_NAME m_sName value CString IDC_BIRTHDAY m_sBirthday value CString IDC_SEX m_nSex valve int

m_cSex Control CComboBox IDC_TITLE m_sTitle value CString m_cTitle Control CComboBox IDC_LIST m_cList Control CListBox

注:IDC_TITLE组合框控件上各连连接了两个变量,它们值类型分别为value 和Control,连接方法是对同一个控件ID,两次使用“Add Variables…” 即可。

四.组合框控件的初始化

1.在CListBoxDlg类中添加二个成员变量:

变量类型 变量名 作用域 CString strTitle public CString m_sSex public 2.在CListBoxDlg类的构造函数中对变量strTitle初始化: strTitle=\"助教/讲师/副教授/教授/\"; 3.在CListBoxDlg类中添加一个函数:

2

函数类型:void 函数名:InitCombo() 作用域:Protected 4.编写函数InitCombo()成:

void CListBoxDlg::InitCombo() {

int i,n;

CString s1[2] = {\"男\女\

for(i=0;i<2;i++) m_cSex.AddString(s1[i]);

CString s,s2=strTitle; while(s2 != \"\") {

n=s2.Find('/',0); s=s2.Left(n);

m_cTitle.AddString(s); s2.Delete(0,n+1); } }

3.在CListBoxDlg类的OnInitDialog()函数中添加一条语句: // TODO: Add extra initialization here InitCombo();

4.编译并运行程序,观察程序的运行情况

五.组合框内容的获取

经过下拉列表的选择或编辑输入后,组合框中具有了内容,要获取这些 内容可如下操作:

1.为组合框控件IDC_SEX增加一个CBN_SELCHANGE消息响应函数 OnSelchangeSex()如下:

1)选择“View\\ClassWizard…”菜单项

2)在弹出的MFC Classwizard对话框中如下操作: A.选择Message Maps选项卡

B.在Class name下拉列表框中选择CListBoxDlg类 C.在Object IDs列表框中选择:IDC_SEX D.在Messages列表框中选择CBN_SELCHANGE

E.单击Add Function按钮,在弹出的Add member function对话框中 单击OK按钮

F.再单击MFC Classwizard对话框的“Edit code”按钮,进入函数编 辑

3)编写OnSelchangeSex()如下:

void CListBoxDlg::OnSelchangeSex()

3

{

// TODO: Add your control notification handler code here UpdateData();

int n=m_cSex.GetCurSel();

if(n!=CB_ERR) m_cSex.GetLBText(n,m_sSex); }

2.为组合框控件IDC_TITLE增加一个CBN_SELCHANGE消息响应函数 OnSelchangeTitle(),方法同上,函数程序如下: void CListBoxDlg::OnSelchangeTitle() {

// TODO: Add your control notification handler code here UpdateData();

int n=m_cTitle.GetCurSel();

if(n!=CB_ERR) m_cTitle.GetLBText(n,m_sTitle); }

3.为按钮控件IDC_ADD添加一个BN_CLICKED消息响应函数OnAdd()如下: void CListBoxDlg::OnAdd() {

// TODO: Add your control notification handler code here CString str=\"性别:\"+m_sSex+\"\\n\\n职称:\"+m_sTitle; MessageBox(str); }

4.编译并运动程序,观察程序的运行情况。

由程序的运行情况可见:通过下拉列表选择的内容能正确地获取,但在 IDC_TITLE控件中通过编辑输入的数据无法正确地获取。为解决这一问 题并使编辑输入的内容能增添到下拉列表中,可如下操作:

A.仿上,为控件IDC_TITLE增添一条CBN_KILLFOCUS消息响应函数: OnKillfocusTitle() B.编写函数体如下:

void CListBoxDlg::OnKillfocusTitle() {

// TODO: Add your control notification handler code here //获取编辑输入的内容 UpdateData();

int n=m_cTitle.GetCurSel();

if(n!=CB_ERR) m_cTitle.GetLBText(n,m_sTitle);

//把编辑输入的内容增添到下拉列表中

if(m_sTitle!=\"\" && strTitle.Find(m_sTitle,0)<0) {

4

m_cTitle.AddString(m_sTitle); strTitle=strTitle+m_sTitle+'/'; } }

C.再编译并运行程序,观察运行情况。

六.列表框List Box的初始化

1.在CListBoxDlg类中添加一个函数:

函数类型:void 函数名:InitList() 作用域:Protected 2.编定函数体如下:

void CListBoxDlg::InitList() {

m_cList.InsertColumn(0,\"编号\ m_cList.InsertColumn(1,\"姓名\

m_cList.InsertColumn(2,\"出生年月\ m_cList.InsertColumn(3,\"性别\ m_cList.InsertColumn(4,\"职称\ ① m_cList.SetExtendedStyle(LVS_EX_FULLROWSELECT); }

注:①行设置列表控件的行被选中时整行反白显示

3.在CListBoxDlg类的OnInitDialog()函数中添加几条语句(红色): // TODO: Add extra initialization here InitCombo(); InitList();

4编译并运行程序,观察程序的运行界面

七.在列表控件中增添、删除和插入内容 1.把输入内容增添到列表控件中

A.在CListBoxDlg类中增加一个protected类int型变量:m_nNumber, 并在CListBoxDlg类的构造函数中添加以下赋值语句: m_nNumber=1;

B.在CListBoxDlg类的OnInitDialog()函数中添加四条语句(红色): InitList();

① m_sNumber.Format(\"%d\

② GetDlgItem(IDC_DELETE)->EnableWindow(false); ③ GetDlgItem(IDC_INSERT)->EnableWindow(false); ④ UpdateData(false); 注:①句:给编号赋初值

②③:由于刚开始时列表控件中尚无任何内容,故不能“删除”或 “插入”

5

④句:回显数据。 C.修改OnAdd()函数成:

void CListBoxDlg::OnAdd() {

// TODO: Add your control notification handler code here int m,n;

UpdateData();

m=m_cTitle.GetCurSel(); //获取IDC_TITLE控件内容 if(m!=CB_ERR) m_cTitle.GetLBText(m,m_sTitle);

m=m_cSex.GetCurSel(); //获取IDC_SEX控件内容 if(m!=CB_ERR) m_cSex.GetLBText(m,m_sSex);

if(m_sName==\"\"||m_sBirthday==\"\"||m_sSex==\"\"||m_sTitle==\"\") return;

//把输入内容增添到列表控件中

n=m_cList.InsertItem(0,m_sNumber); m_cList.SetItemText(n,1,m_sName);

m_cList.SetItemText(n,2,m_sBirthday); m_cList.SetItemText(n,3,m_sSex); m_cList.SetItemText(n,4,m_sTitle);

m_nNumber++; // 把职工资料初始化为空 m_sNumber.Format(\"%d\ m_sName=\"\";

m_sBirthday=\"\"; m_sSex=\"\";

m_nSex=-1; // 把性别组合框设置成空 m_sTitle=\"\";

GetDlgItem(IDC_NAME)->SetFocus(); //把输入焦点置于IDC_NAME //控件上 UpdateData(false); }

D.编译并运行程序,观察运行结果。

此时,编辑框和组合框中的输入内容能依次添加到列表控件中,并且, 若输入内容不全,会拒绝添加。 2.删除列表控件中选定行的内容

A.用“MFC CLasswizard”对话框,为控件IDC_LIST添加一个消息响应函 数OnClickList(),并编写该函数如下:

6

void CListBoxDlg::OnClickList(NMHDR* pNMHDR, LRESULT* pResult) {

// TODO: Add your control notification handler code here *pResult = 0;

int n=m_cList.GetNextItem(-1,LVNI_SELECTED);

if(n!=-1) // 若所选行有效,则向对话框回显其内容 {

m_sNumber=m_cList.GetItemText(n,0); m_sName=m_cList.GetItemText(n,1);

m_sBirthday=m_cList.GetItemText(n,2); m_sSex=m_cList.GetItemText(n,3);

m_nSex=(m_sSex==\"男\")?0:1; //把性别回显至性别组合框

m_sTitle=m_cList.GetItemText(n,4);

GetDlgItem(IDC_DELETE)->EnableWindow(true); GetDlgItem(IDC_INSERT)->EnableWindow(true);

GetDlgItem(IDC_ADD)->SetWindowText(\"修 改\"); UpdateData(false); } }

B.用“MFC CLasswizard”对话框,为控件IDC_DELETE添加一个消息响应 函数OnDelete(),并编写该函数如下: void CListBoxDlg::OnDelete() {

// TODO: Add your control notification handler code here int n;

CString s1,s2,s3,s4,str;

n=m_cList.GetNextItem(-1,LVNI_SELECTED); if(n!=-1) {

m_cList.DeleteItem(n); m_nNumber--;

m_sNumber.Format(\"%d\ m_sName=\"\";

m_sBirthday=\"\"; m_nSex=-1; m_sTitle=\"\";

7

UpdateData(false); } }

C.编译并运行程序,可见:

能在列表框中删除选行的内容,但删除内容的编号不再连续,并且按 钮IDC_APPEND的行为不正常,为解决上述问题,应: D.在OnAdd()函数中增添几条语句(红色):

if(m_sName==\"\"||m_sBirthday==\"\"||m_sSex==\"\"||m_sTitle==\"\") return;

bool bState=GetDlgItem(IDC_DELETE)->IsWindowEnabled(); if(bState) // \"删除\"按钮可用时,先删除所选行 {

n=m_cList.GetNextItem(-1,LVNI_SELECTED); m_cList.DeleteItem(n);

GetDlgItem(IDC_DELETE)->EnableWindow(false); GetDlgItem(IDC_INSERT)->EnableWindow(false);

GetDlgItem(IDC_ADD)->SetWindowText(\"添 加\"); m_nNumber--; }

E.函数OnDelete()应如下编写: void CListBoxDlg::OnDelete() {

// TODO: Add your control notification handler code here int i,n,ItemNo; CString s[5]; CString str=\"\";

n=m_cList.GetNextItem(-1,LVNI_SELECTED); m_cList.DeleteItem(n);

ItemNo=m_cList.GetItemCount(); for(n=0;nfor(i=1;i<5;i++) {

s[i]=m_cList.GetItemText(n,i); str=str+s[i]+\"/\"; } }

m_cList.DeleteAllItems(); for(n=0;n8

{

m_sNumber.Format(\"%d\

m_sName=str.Left(i=str.Find(\"/\ str.Delete(0,i+1);

m_sBirthday=str.Left(i=str.Find(\"/\ str.Delete(0,i+1);

m_sSex=str.Left(i=str.Find(\"/\ str.Delete(0,i+1);

m_sTitle=str.Left(i=str.Find(\"/\ str.Delete(0,i+1);

n=m_cList.InsertItem(0,m_sNumber); m_cList.SetItemText(n,1,m_sName);

m_cList.SetItemText(n,2,m_sBirthday); m_cList.SetItemText(n,3,m_sSex); m_cList.SetItemText(n,4,m_sTitle); }

m_nNumber=ItemNo+1; // 把职工资料初始化为空 m_sNumber.Format(\"%d\ m_sName=\"\";

m_sBirthday=\"\"; m_sSex=\"\";

m_cSex.SetCurSel(-1); m_sTitle=\"\";

GetDlgItem(IDC_DELETE)->EnableWindow(false); GetDlgItem(IDC_INSERT)->EnableWindow(false);

GetDlgItem(IDC_APPEND)->SetWindowText(\"添 加\"); GetDlgItem(IDC_NAME)->SetFocus(); //把输入焦点置于IDC_NAME //控件上 UpdateData(false); }

F.上述函数OnDelete()编写得较复杂,当列表框中数据较多时更新速度较 慢,并且可能产生意想不到的问题。为此,函数OnDelete()可在功能不 变的前提下简化如下:

void CListBoxDlg::OnDelete() {

// TODO: Add your control notification handler code here int i,n,ItemNo,m,nc; CString s[5]; CString str=\"\";

n=m_cList.GetNextItem(-1,LVNI_SELECTED);

9

m_cList.DeleteItem(n);

ItemNo=m_cList.GetItemCount(); for(m=n;mfor(i=1;i<5;i++) s[i]=m_cList.GetItemText(m,i); m_cList.DeleteItem(m); s[0].Format(\"%d\

nc=m_cList.InsertItem(0,m_sNumber);

for(i=1;i<5;i++) m_cList.SetItemText(nc,i,s[i]); }

m_nNumber=ItemNo+1; // 把职工资料初始化为空 m_sNumber.Format(\"%d\ m_sName=\"\";

m_sBirthday=\"\"; m_sSex=\"\"; m_nSex=-1; m_sTitle=\"\";

GetDlgItem(IDC_DELETE)->EnableWindow(false); GetDlgItem(IDC_INSERT)->EnableWindow(false);

GetDlgItem(IDC_ADD)->SetWindowText(\"添 加\");

GetDlgItem(IDC_NAME)->SetFocus(); //把输入焦点置于IDC_NAME //控件上 UpdateData(false); }

3.在列表控件的选定行前插入内容

A.为“插入”按钮控件添加一条消息响应函数OnInsert(); B.编写OnInsert()函数如下:

void CListBoxDlg::OnInsert() {

// TODO: Add your control notification handler code here int i,n,ItemNo,m,nc; CString s[5];

n=m_cList.GetNextItem(-1,LVNI_SELECTED); ItemNo=m_cList.GetItemCount(); for(m=ItemNo-1;m>=n;m--) {

for(i=1;i<5;i++) s[i]=m_cList.GetItemText(m,i); m_cList.DeleteItem(m); s[0].Format(\"%d\

nc=m_cList.InsertItem(0,s[0]);

10

for(i=1;i<5;i++) m_cList.SetItemText(nc,i,s[i]); }

UpdateData();

n=m_cList.InsertItem(0,m_sNumber); m_cList.SetItemText(n,1,m_sName);

m_cList.SetItemText(n,2,m_sBirthday); m_cList.SetItemText(n,3,m_sSex); m_cList.SetItemText(n,4,m_sTitle);

m_nNumber=ItemNo+1; // 把职工资料初始化为空 m_sNumber.Format(\"%d\ m_sName=\"\";

m_sBirthday=\"\"; m_sSex=\"\"; m_nSex=-1; m_sTitle=\"\";

GetDlgItem(IDC_DELETE)->EnableWindow(false); GetDlgItem(IDC_INSERT)->EnableWindow(false);

GetDlgItem(IDC_ADD)->SetWindowText(\"添 加\");

GetDlgItem(IDC_NAME)->SetFocus(); //把输入焦点置于IDC_NAME //控件上 UpdateData(false); }

八.把列表框中的数据存盘

1.在对话框模板上再增加一个资源符号为IDC_SAVE的按钮控件,把按钮标题 设置成“把列表框内容存盘”

2.为上述按钮连接一个消息响应函数OnSave(); 3.编写OnSave()函数如下:

void CListBoxDlg::OnSave() {

// TODO: Add your control notification handler code here int i,m,ItemNo,n=0; FILE *fp;

UINT button=IDYES;

CString FileName,s[5];

while(button==IDYES) {

11

CFileDialog SaveCurveDlg(false,\"dat\ OFN_OVERWRITEPROMPT,

\"数据文件(*.dat)|*.dat|所有文件(*.*)|*.*||\ if(button=SaveCurveDlg.DoModal()==IDOK) {

FileName=SaveCurveDlg.GetPathName(); if((fp=fopen(FileName,\"w\"))!=NULL) {

ItemNo=m_cList.GetItemCount(); for(m=0;mfor(i=0;i<5;i++) s[i]=m_cList.GetItemText(m,i); fprintf(fp,\"%-6s%-15s%-15s%-15s%-15s\\n\ s[0],s[1],s[2],s[3],s[4]); }

fclose(fp); button=IDNO; } }

else button=AfxMessageBox(\"驱动器或磁盘没有准备好!\\n\\n\" \"要重试吗?\ } }

九.从数据文件把数据读入列表框

1.在对话框模板上再增加一个资源符号为IDC_READ的按钮控件,把按钮标题 设置成“从数据文件读入数据”

2.为上述按钮连接一个消息响应函数OnRead(); 3.编写OnRead()函数如下: void CAnaSyn::InputRead() {

int m,n=1; FILE *fp;

CString FileName,str; UINT button=IDYES;

while(button==IDYES) {

CFileDialog ReadCurveDlg(true,NULL,NULL,OFN_HIDEREADONLY, \"数据文件(*.dat)|*.dat|所有文件(*.*)|*.*||\

12

if(button=ReadCurveDlg.DoModal()==IDOK) {

FileName=ReadCurveDlg.GetPathName(); if((fp=fopen(FileName,\"r\"))!=NULL) {

while(!feof(fp)) {

fscanf(fp,\"%s\

m=m_cList.InsertItem(0,str); fscanf(fp,\"%s\

m_cList.SetItemText(m,1,str); fscanf(fp,\"%s\

m_cList.SetItemText(m,2,str); fscanf(fp,\"%s\

m_cList.SetItemText(m,3,str); fscanf(fp,\"%s\\n\

m_cList.SetItemText(m,4,str); n++; }

fclose(fp); m_nNumber=n;

m_sNumber.Format(\"%d\ m_sName=m_sBirthday=m_sTitle=\"\"; button=IDNO;

UpdateData(false); }

else button=AfxMessageBox(\" \" } } }

磁盘没准备好或文件没找到!\\n\\n\" 要重试吗?\13

因篇幅问题不能全部显示,请点此查看更多更全内容

Top