对于C语言MFC的详细的解析(5) --深入MFC类库

来源:互联网 发布:mac设置用户头像 编辑:程序博客网 时间:2024/05/22 12:49
 

1 处理用户输入

程序从用户那里得到数据,经过自己的处理,再把计算的结果输出到屏幕、打印机或者其他的输出设备上,这是软件工作的基本模型。消息和键盘消息是最基本的输入信息,除此之外,

 

图3.1

1.1 定义对话框资源

下面我们通过一个例子来介绍如何设计一个基于对话框的界面,接受用户输入的数据,并且将它们以图形化的方式显示出来。我们将制作这样的一个有用的程序。它访问一个保存歌曲曲目的数据库,用户可以通过对话框让用户定义一个曲目表,并选定一张背景图,然后在一个没有系统菜单的窗口客户区上滚动显示曲目的名字。在许多的娱乐场所的大屏幕上我们都可以看到类似的东西。在这部分的内容当中,我们着重介绍如何获得和处理用户输入数据的工作,在后面的处理用户输出的内容当中,我们还将使用这个例子来说明如何在屏幕上进行输出工作。

下面我们来介绍如何定义一个对话框资源。在WORKSPACE窗口当中RESOURCE一页,在DIALOG小图标上面单击鼠标右键,弹出菜单,选择INSERT命令,如图3.2所示:DIALOG,表示添加一个对话框资源。单击NEW按钮。

图3.2

接下来在弹出的资源类型对话框中选择

接下来我们就开始布置这个对话框。对话框上面已经有了两个按钮:OKCANCEL。如下图3.4所示。它们的作用分别是确认用户通过对话框进行的输入和取消前面的输入工作。把它们的标题分别改为确定和取消。布置其它的控件。每一个对话框以及对话框上面的每一个控件都有一个ID号码,它们的定义包括在RESOURCE.H 这个头文件当中。比方说,这个对话框的ID号是IDD_DIALOG2,确认按钮的ID号是IDOK,取消按钮的ID号是IDCANCELMFC将通过ID号来访问这些资源。单击DIALOG工具条上面的TEST按钮可以测试对话框运行的效果。需要注意的是我们这里我们定义的对话框只是一个资源,如果要使这个对话框真正实现它的功能,必须在程序当中定义一个使用这个资源的对话框类。3.4

 

1.2 定义对话框类

下面我们就定义一个对话框类。在

 

 

图3.5

单击图3.5中所示

下面,我们就着手完成实现对话框接受用户输入功能的工作。这里核心的工作就是实现对布置在对话框当中的控件的控制。控制又可以分两种类型:第一种是与界面上的控件交换数据,在对话框中的某些响应函数当中编写取出用户在对话框当中输入的数据。比方说在用户单击了确认输入的按钮,触发了该按钮的单击事件的时候,我们就要从输入新歌的编辑框当中取出曲目字符串保存到数据库当中,并将其显示在曲目列表当中。

我们可以使用

 

图3.6

图3.7

生成一个

VIEW菜单当中选择CLASS WIZARD命令,单击ADD CLASS按钮,在弹出的菜单当中选择NEW命令,在NAME一栏当中输入新类的名字,在BASE CLASS列表框当中选择需要继承MFC当中的哪一个类。在DIALOG ID列表框当中选择对话框资源的ID号码,在这个实例当中,我们不使用OLE AUTOMATION,所以在这个组框当中选择NONE。在FILE NAME一栏显示的是这个类的定义写在哪一个文件当中。CHANGE按钮,在HEADER FILEIMPLEMENTATION FILE当中分别敲入新类的声明和定义分别写在哪个文件当中,单击OK按钮确认,这样我们就完成了对新的对话框类的定义。单击OK 按钮,CLASS WIZARD将按照我们刚才的要求进行对话框类定义的工作。打开WORKSPACE,选择FILE VIEW一页,在SOURCE FILESHEADER FILES组当中到CLASS WIZARD已经新建了两个文件,并将它们加入了工程当中。SongDlg.h当中内容是CSongDlg这个类的声明,SongDlg.cpp这个文件当中的内容是这个类的实现。但是目前的程序只是包含了实现一个对话框的最基本功能的代码,调用这个对话框类的DoModal函数之后可以运行它。但是用户通过对话框进行的所有的输入工作都不会被接受。MFC提供的一种叫做对话框数据交换(DDX)的机制来从编辑控件当中取出数据。在MFC的对话框类CDialog中已经封装了这种机制。它的工作原理就是在对话框资源中的编辑框和对话框类的一个成员变量之间建立连接。然后由MFC自动地完成在成员变量和控件之间的数据交换工作。首先打开CLASSWIZARD,选中MEMBER VARIABLE这一页,在CLASS NAME列表框当中选择CSongDlg,选择曲目编辑框的IDIDC_EDIT1,单击ADD VARIABLE按钮。MEMBER VARIABLE NAME 一栏当中敲入变量的名字,在CATEGORY列表框当中可以选择变量的类型,VALUE表示生成一个数据变量,CONTROL类型的变量可以被用来对控件资源进行另一种类型的控制。它的类型依赖于前面选中的控件资源,比方说如果为一个编辑框控件成一个CONTROL类型的成员变量,那么它只能是CEdit类型的。我们将在后面的内容当中具体地介绍如何使用CONTROL类型的成员变量。VALUE变量,它的数据类型是字符串。单击OK按钮。这时WIZARD就自动地添加了进行对话框数据交换所有的代码。打开对话框类的头文件和实现文件,我们发现当中增加了一个CString类型的成员变量:

// Dialog Data

//{{AFX_DATA(CSongDlg)

enum { IDD = IDD_DIALOG2 };

CString m_songname;

//}}AFX_DATA

并且在建构函数当中对这个变量进行了初始化:

CSongDlg::CSongDlg(CWnd* pParent /*=NULL*/)

: CDialog(CSongDlg::IDD, pParent)

{

//{{AFX_DATA_INIT(CSongDlg)

m_songname = _T("");

//}}AFX_DATA_INIT

}

在新生成的对话框类CSongDlg 中有如下一个虚函数:

virtual void DoDataExchange(CDataExchange* pDX);

//DDX/DDV support

 

DoDataExchange

对控件资源的另外一种类型的控制就是要操纵界面控件的外观。比方说,我们可以通过生成一个C

函数就是对话框类和对话框资源进行DDX数据交换的函数。在对话框初始化的时候或者在程序中调用UpdateData()函数的时候,这个函数将会被调用。DDX_TEXT这个函数可以处理多种类型的数据成员变量与控件资源之间的数据交换。这中间包括int,uint,long,DWORD,CString,float,double等。PDX这个参数是一个指向一个CDataExchange对象的指针通过它我们可以设置进行数据交换的方法。比方说:数据交换的方向。这段代码就可以通过PDX的这个标志志判断数据交换的方向是从变量到控件还是从控件到变量,然后进行不同的处理。进行数据交换之后,程序当中就可以通过成员变量来使用用户输入的数据了。ONTROL类型的成员变量来控制对话框当中的列表控件。和VALUE类型变量的添加方法一样,我们可以使用CLASSWIZARD生成一个CListControl 类型的对象,在DoDataExchange当中增加了这样的代码:

DDX_Control(pDX, IDC_LIST1, m_listCtrl1);

DDX_CONTROL

当对话框开始运行的时候,我们需要从数据库当中取出已经入库的曲目的名字将其显示在曲目列表框当中。这个工作应该在对话框响应

 

图3.8

在响应WM_INITDIALOG消息的处理函数CSongDlg::OnInitDialog中添加如下一段代码:

也是对话框数据交换机制提供的一个函数,它的作用和DDX_TEXT大致一样。使用刚才定义的控件对象m_listCtrl1,就可以对列表框资源进行操纵了。WM_INITDIALOG消息的时候来做。使用CLASS WIZARD来添加这个消息响应函数。在左边的列表框当中选定CSongDlg这个类,在消息列表框当中选定对话框初始化消息,单击ADD FUNCTION按钮,WIZARD就自动地在这个类的声明当中重载了基类的这个成员函数并且在实现文件当中加入了函数体。单击EDIT CODE 按钮,就可以在函数体当中加入我们自己的代码了。

COleVariant var;

LV_ITEM lvitem;

CString Name("song_name");

char str[50];

lvitem.iItem = 0;

if(globalRS_>IsOpen())

globalRS_>Close();

CString strQuery = _T("Select * from ");

strQuery += "SONGS";

globalRS_>Open(dbOpenDynaset,strQuery);

globalRS_>m_bCheckCacheForDirtyFields = FALSE;

 

if(globalRS_>IsOpen())

{

if(!globalRS_>GetRecordCount())

return 0;

globalRS_>MoveFirst();

while(!globalRS_>IsEOF())

{

var =globalRS_>GetFieldValue(_T("[")

+ Name + _T("]"));

 

 

lvitem.iItem++ ;

lvitem.iSubItem = 0;

strcpy(str , (LPCTSTR)CString(V_BSTRT(&var)));

lvitem.pszText = str;

lvitem.iImage = 0;

m_originsonglist.InsertItem(&lvitem);

globalRS_>MoveNext();

}

}

if(globalRS_>IsOpen())

globalRS_>Close();

lvitem.mask = LVIF_TEXT | LVIF_IMAGE| LVIF_DI_SETITEM;

这里使用了

 

lvitem.iItem++ ;

lvitem.iSubItem = 0;

strcpy(str , (LPCTSTR)CString(V_BSTRT(&var)));

lvitem.pszText = str;

lvitem.iImage = 0;

m_originsonglist.InsertItem(&lvitem);

DAO技术来访问数据库并使用读出的字符串向列表控件当中添加条目。关于DAO技术的使用方法,我们在其他的章节当中会有详细地介绍。我们关心的是下面这段代码:lvitem.mask = LVIF_TEXT | LVIF_IMAGE| LVIF_DI_SETITEM;

它执行了对列表控件添加条目的操作。这里需要用到

WIN32提供的一个结构:LV_ITEM。我们可以从VC的HELP中找到其定义:

typedef struct _LV_ITEM {

UINT mask;

int iItem;

int iSubItem;

UINT state;

UINT stateMask;

LPTSTR pszText;

int cchTextMax;

int iImage; // index of the list view item

LPARAM lParam; // 32_bit value to associate with item

} LV_ITEM;

icon

为了添加一个条目,我们首先在在这个结构当中填写条目的信息,然后把它传给列表对象的添加条目函数InsertItem就可以了。

接下来的这段代码位于响应中曲目列表框当中删去选定曲目的按钮单击事件当中。要实现从列表控件当中删去的条目的操作,只要把需要删去的条目的索引号传递给列表对象的删去条目函数DeleteItem就可以了。

 

totalNum = m_selsonglist.GetItemCount();

int step = 0;

LV_ITEM lvitem;

 

int totalNum;

 

lvitem.iSubItem = 0;

lvitem.iImage = 0;

while(step <= totalNum)

{

if(m_selsonglist.GetItemState(step,LVIS_SELECTED))

{

 

m_selsonglist.DeleteItem(step);

}

step++;

}

lvitem.mask = LVIF_TEXT | LVIF_IMAGE| LVIF_DI_SETITEM;

我们在这总结一下对对话框上面的控件进行控制所需的工作:

首先在对话框类当中定义成员变量,然后调用对话框的成员变量的函数来操纵界面控件。

MFC封装了一系列的使用户可以进行可视化的输入的界面对象,比方说对话框以及可以布置在上面的编辑框、按钮、列表控件、树形控件等等。使程序支持用户输入的手段更加丰富。
原创粉丝点击