null第7章 Visual C++可视化编程基础第7章 Visual C++可视化编程基础7.1 Windows程序设计概述
7.2 API及应用程序基本框架
7.3 MFC及应用程序框架
7.4 对话框与常用控件
7.5 菜单、工具栏与状态栏设计
7.6 文档/视图结构应用程序
7.7 程序举例7.1 Windows程序设计概述7.1.1基于Visual C++的Windows应用程序设计方法 7.1 Windows程序设计概述 用Visual C++编写Windows应用程序主要有两种方法:
1.Application Programming Interface——API
API是Windows系统和Windows应用程序间的
程序接口,应用程序可以通过此接口访问系统。凡是在Windows工作环境下执行的应用程序都可以通过调用API函数来实现各种功能的操作。在Windows程序设计的初期,程序员所能做使用的编程工具就只有使用API函数,通过API函数的调用组合,就可以搭建出各种界面丰富、功能灵活的应用程序。
2.Microsoft Foundation Class——MFC
MFC是Visual C++的核心,是 Microsoft公司提供的用来编写Windows应用程序的C++类库, 集成了大量已经预先定义好的类,大约有200多个,用户可以根据编程的需要调用相应的类或自定义有关的类。这些类可以分成两种:一是CObject类的派生类;二是非CObject派生类,如
示点的CPoint类,表示矩形的CRect类等。nullnull7.1.2 Windows程序设计的基本概念 Windows应用程序的特点:
具有标准的图形用户界面。
具有与硬件无关的特性。
采用“消息传递,事件驱动”的运行机制。 1.窗口与对象
窗口是应用程序与用户之间交互的接口环境。用户可以通过窗口输入数据,控制应用程序的运行;应用程序可以通过窗口显示数据和运行状态。
对象是指Windows的规范部件,包括各种窗口、菜单、按钮、对话框以及程序模块等。
2.常用Windows数据类型
Windows应用程序的源程序中包含种类繁多的数据类型,其中windows.h是用户调用系统功能的关键,文件中定义了Windows系统使用的数据类型。 null 3.句柄
句柄是指系统创建对象后返回的用来代表该对象的一个唯一的4字节长整数值,是整个Windows编程的基础,用于标识应用程序中不同的对象和同类对象中不同的实例。例如,一个窗口、按钮、图标、滚动条、输出设备、控件或者文件等。应用程序通过句柄能够访问相应的对象信息,它代表对对象的引用。
4.事件驱动
Windows应用程序以消息为基础,以事件驱动之。Windows应用程序启动之后将进入一个消息循环,等待系统或应用程序的消息,消息的产生是因为事件发生的结果,Windows程序设计主要围绕编写事件或消息的响应函数上。
5.消息及其在Windows编程中的应用
Windows应用程序的运行是依靠事件来驱动,利用一个while循环实现不断等待,如果有事件发生,操作系统会以消息的形式传递给应用程序,应用程序会捕获相应的消息,然后通过调用相应的函数响应消息。null7.1.3 Windows应用程序中的常见消息 消息在Windows程序设计中是很关键的因素,在API程序设计方法中要求熟练记忆常见消息,但是在MFC程序设计方法中只要求了解这些消息的相关含义即可。
1.鼠标消息
2.键盘消息
3.关闭窗口消息
4.退出程序消息
5.重画消息 7.2 API及应用程序基本框架7.2 API及应用程序基本框架7.2.1 Windows API应用程序实例 共有上千个标准的API函数,调用方法与调用C语言库函数类似
示例:
#include "windows.h"
int APIENTRY WinMain(HINSTANCE hInstance
,HINSTANCE hPrevInstance
,LPSTR lpCmdLine
,int nCmdShow)
{MessageBox(NULL,"简单的Windows应用程序!","API函数示例",MB_OK);
return 0;
}null注意:不是典型的Windows应用程序,典型WinMain具有固定结构,完成三个任务: 注册窗口类、创建并初始化窗口、创建消息循环null7.2.2 Windows API应用程序结构分析 Windows应用程序具有相对固定的基本结构,其中由入口函数WinMain和窗口函数构成基本框架,并包含各种数据类型、数据结构与函数等。
1.WinMain函数
WinMain函数是所有Windows应用程序的入口,类似于C语言中的main函数,其功能是完成一系列的定义和初始化工作,并产生消息循环。
WinMain函数有三个基本的组成部分:函数说明、初始化和消息循环。
2.窗口函数
窗口函数是应用程序处理接收到的消息的函数,其中包含了应用程序对各种可能接收到的消息的处理过程。7.3 MFC及应用程序框架 7.3 MFC及应用程序框架 7.3.1 MFC概述
微软基础类库(MFC)是微软为Windows程序员提供的一个面向对象的Windows编程接口,它封装了大部分Windows API函数,大大简化了Windows编程工作。Microsoft公司的MFC具有以下特点:
1.完全支持所有的Windows函数、控制、消息、GDI(图形设备接口)基本图形函数、菜单以及对话框。
2.使用与传统的Windows API同样的命名规则,因此,一个类所能完成的工作可直接从名字得知。
3.不使用容易产生错误的switch/case语句。
4.通过发送有关对象信息到文件的能力,来提供更好的判断支持。也可以确认成员变量。
5.代码少,速度快,容错处理能力强。
6.在运行时确定数据对象的设计。 null7.3.2 应用程序框架
在Visual C++中,可以创建以下3类典型的Windows 应用程序,它们都是通过MFC AppWizard(exe)(以下简称 AppWizard)向导创建的:
(1)基于对话框的应用程序:这类程序适合于文档较少而交互操作较多的应用场合,如Windows自带的计算器程序。
(2)单文档界面(SDI)应用程序:这类程序一次只能打开一个文档,如Windows自带的记事本程序。
(3)多文档界面(MDI)应用程序:这类程序可以同时打开多个文档并进行处理,处理的过程中很容易地进行切换,如Microsoft Word。7.4 对话框与常用控件7.4 对话框与常用控件 对话框是Windows应用程序中最重要的用户界面元素之一,是与用户交互的重要手段。在Visual C++中,对话框既可以单独组成一个简单的应用程序,又可以成为文档/视图结构程序的资源。
7.4.1创建对话框程序的步骤
1.建立基于对话框的MFC应用程序框架
2.放置控件,设置属性,完成对话框窗口界面设计
3.为控件连接变量,即为控件命名。
4.添加并且编写消息处理函数。
5.编译、链接并运行应用程序 null7.4.2对话框的调用 由于对话框的代码是以类为模块来设计的,使用时需要在程序中加入该类的头文件,并定义一个类对象,然后就可以直接使用该类的相关成员。使用的步骤如下:
1.利用项目工作区ClassView打开相应的.cpp文件,在该源文件的前面加上对话框类的头文件。 假设我们为对话框定义的类名为CMyDlg,则需在源文件的前面加上:#include “MyDlg.h” //注意头文件前比类名少个大写的C
2.在需要调用的位置添加下列代码:
CMyDlg dlg; //定义对话框对象
dlg.DoModal(); //显示对话框7.4.2对话框的调用7.4.3通用对话框与消息对话框 为了方便用户的程序开发,Visual C++提供了一些通用对话框和消息对话框供用户使用。
1.通用对话框
Windows提供了一组标准用户界面的对话框,它们都有相应的MFC库中的类来支持。用来操作这些通用对话框的类就是CCommonDialog类,它从Cdialog类中派生,用户可以与使用其他对话框一样使用通用对话框。
2.消息对话框
消息对话框是最简单的一种对话框,它只是用于显示信息。在Visual C++6.0的MFC类库中就提供相应的函数实现这样的功能,使用时,只要在用户程序任何地方调用它们即可。它们的函数原型如下:7.4.3通用对话框与消息对话框null int AfxMessageBox(LPCTSTR lpszText,UINT nType=MB_OK,UINT nIDHelp=0);
int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption=NULL,UINT nType=MB_OK);
这两个函数都是用于创建和显示消息对话框的,只不过AfxMessageBox是全程函数,可用在任何地方。而MessageBox只能用于控件、对话框、窗口等一些窗口类中。例如:
int n=MessageBox("输入成绩?","系统提示", MB_YESNO| MB_ICONQUESTION);
if (n==IDYES)
{……}7.4.4 控件基本操作1.控件添加的方法
2.控件的选取
3.控件的移动、复制与删除
4.设定控件的Tab键次序
5.控件的布局
6.常用控件的控件
消息 7.4.4 控件基本操作7.4.5 CString 类7.4.5 CString 类 对字符串的存取及有关操作,还可通过标准C++里的字符串类string(定义在string.h头文件中)和MFC中的CString类(定义在afx.h头文件中)。 string是一种用户自定义的数据类型,它由C++标准库来支持,而不是C++语言本身的一部分。在使用string数据类型之前,需要在程序中包含头文件string并声明其所在的名字空间std,如:
#include < string>
using namespace std;
然后在程序中即可定义string类型的变量。如:
string name="张三";
下面主要介绍MFC中CString类的使用。1. 定义CString 类对象 当要使用MFC中的CString 类时,首先必须选择“工程→设置”命令,在“Microsoft Foundation Class”选择除“Not Using MFC”以外的项目。然后源程序的头文件加上:#include "afx.h"形式:
CString 对象名;
CString 对象名="字符串常量";
CString 对象名("字符串常量");
CString 对象名('字符',int n); //重复产生n个相同的字符例如:
CString s1="C++程序设计";
CString s('d',5);cout<
内容复制出来
//复制到CString对象
void GetWindowText( CString& rString ) const;
示例:CString ch;
m_e.GetWindowText(ch);
//复制到数组
int GetWindowText( LPTSTR lpszStringBuf,
int nMaxCount ) const;
示例:char ch[80];
m_e.GetWindowText(ch,80);
(2)设置编辑框中的内容
void SetWindowText( LPCTSTR lpszString );
示例:char ch[20]="abcdefg";
m_e.SetWindowText(ch);null3. 连接变量
Control:只能是CEdit类型
Value:CString
int
double等注意:
若一个编辑框连接了一个Value类别的变量,则该变量就表示这个编辑框,编辑框中显示的内容就是变量的值。但是,改变了编辑框的内容并不会自动更新对应的变量的值,同样,改变了变量的值也不会自动刷新编辑框的内容。若编辑框的内容改变了,则应使用语句UpdateData(TRUE);更新对应的变量的值;若变量的值改变了,则应使用语句UpdateData(FALSE);刷新编辑框的内容。nullvoid CTESTDlg::OnCalc()
{
UpdateData(TRUE);
double a=m_a;
double b=m_b;
double c=m_c;
m_x1=(-b+sqrt(b*b-4*a*c))
/(2*a);
m_x2=(-b-sqrt(b*b-4*a*c))
/(2*a);
UpdateData(FALSE);
}【例7.2】输入一元二次方程ax2+bx+c=0的系数a、b、c,
计算并输出两个根x1、x2 m_x1(double) m_x2(double) m_a
(double) m_b
(double) m_c
(double)void CTESTDlg::OnOk()
{
OnOK();
}ID:OkID:Calc示范操作示范操作null【例7-3】使用静态文本框、组框、编辑框以及按钮等控件设计一个如图7.20所示的程序。当用户在语文、数学、
编辑框输入成绩后,单击“计算平均分”按钮后,将显示这三门课的平均成绩。 null(1)属性设置Selection:选择方式
Single ── 单项选择
Multiple ── 多项选择,但是忽略Ctrl和Alt键。
Extended ── 允许使用Ctrl和Alt进行多项选择
None ── 禁止选择
Sort:排序(2)成员函数
添加:int AddString( LPCTSTR lpszItem );
示列:m_l. AddString(“大学计算机基础");4.列表框控件 null删除:int DeleteString( UINT nIndex );
示例:m_l. DeleteString (4); //删除第5个
说明:下标从0开始
获取当前选定项目的序号
int DeleteString( UINT nIndex );
格式:int GetCurSel( ) const;
示例:int i=m_l.GetCurSel();
获取指定项目
int GetText( int nIndex, LPTSTR lpszBuffer ) const;
void GetText( int nIndex, CString& rString ) const;
示例:
char s1[20];
CString s2;,
m_l. GetText(4, s1); //读入数组
m_l. GetText(4, s2); //读入CString对象null【例7-4】编写一个如图所示的能对列表框进行项目添加、修改和删除操作的应用程序。“添加”按钮的功能是将文本框中的内容添加到列表框,“删除”按钮的功能是删除列表框中选定的选项。如果要修改列表框,则首先选定选项,然后单击“修改”按钮,所选的选项显示在文本框中,当在文本框中修改完之后再单击“修改确定”按钮更新列表框。 null5.组合框控件 Ctrl+Enter键 (1) 属性设置null(2) 成员函数
编辑框和列表框的成员函数
GetText()不能用
int GetLBText( int nIndex, LPTSTR lpszText ) const;
void GetLBText( int nIndex, CString& rString ) const;
(3) 组合框发出的消息
CBN_SELECTCHANGE:选项改变
CBN_EDITCHANGE:编辑框中文本改变【例7-5】设计一个如图7.23所示的对话框。如果单击“确定”按钮,则用MessageBox显示所设置的信息。 null6.滚动条控件 滚动条是CScrollBar类的对象,是Windows应用程序中一个很重要的控件,通常附在对话框上用来协助观察数据或确定位置,也可以用来作为数据输入的工具。滚动条有水平和垂直两种。
主要成员函数的原型如下:
(1)设置最大值和最小值
void SetScrollRange(int nMinPos,int nMaxPos,BOOL bRedraw=TRUE);
最小值 最大值 TRUE时重画
(2)设置滑块的位置
int SetScrollPos(int nPos, BOOL bRedraw=TRUE );
滑块的位置 TRUE时重画 null滚动条没有消息,但对话框却能接收到WM_HScroll(WM_Vscroll)
void CTESTDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
pScrollBar:指向用户正在操作的滚动条。
nPos:滑块当前位置。
nSBCode:用户正在进行的操作null7.进度条控件 进度条除了能表示一个过程的进展情况外,使用进度条还可以表明温度、水平面或类似的测量值。
进度条的风格属性有:进度条是否有边框、水平(默认)还是垂直、用块还是平滑填充进度条。
对进度条的操作都是通过相关的CProgressCtrl类成员函数来实现的。
形式:int SetPos(int nPos);
说明:设置进度条的当前位置。
形式:int GetPos();
说明:获取进度条的当前位置。
形式:int SetStep(int nStep);
说明:获取进度条的当前位置。null8.旋转按钮控件 旋转按钮伙伴窗口 旋转按钮控件也称增减按钮,用户单击它们来增加或减小某个值。旋转按钮控件通常是与一个相拌的控件一起使用。若相伴的的控件的Tab次序刚好在旋转按钮的前面,则这时的旋转按钮控件可以自动定位在它的伙伴窗口的傍边,看起来就像一个单一的控件。一般将一个旋转按钮与一个编辑框一起使用,以提示用户进行数字输入。如图7.24所示。null 默认时旋转按钮控件的最小值是100,最大值是0,看起来好像颠倒一样,需要使用成员函数SetRange来改变。用户单击向上箭头则增加数值,而单击向下箭头则减少数值。使用时,不要忘记在旋转按钮控件的属性对话框中选中“自动结伴”和“设置结伴整数”。
MFC的CSpinButtonCtrl类提供了旋转按钮控件的各种操作函数,常用的函数原型有:
形式:int SetPos(int nPos);
说明:设置旋转按钮控件的当前位置。
形式:void SetRange(int nLower,int nUpper);
说明:设置旋转按钮控件的上下限。
旋转按钮控件的通知消息只有一个:UDN_DELTAPOS,它是当控件的当前数值将要发生改变时向其父窗口发送的。null9.滑块控件 刻度线滑块 滑块控件是由滑块和可选的刻度线组成的。当用户用鼠标或方向键移动滑块时,该控件发送通知消息来表明本次改变。
滑块是按照程序中指定的增量来移动的。例如,如果用户指定此滑块的范围是5,则滑块只能有6个位置:在滑块控件最左边的一个位置和另外5个此范围内每隔一个增量的位置。通常,这些位置都是由相应的刻度线来标识的。 null MFC的CSliderCtrl类提供了滑块控件的各种操作函数,常用的函数原型有:
形式:int SetPos(int nPos);
说明:设置滑块控件的当前位置。
形式:void SetRange(int nMin,int nMax,BOOL bRedraw=FALSE);
说明:设置滑块控件的上下限。
形式:BOOL SetTic(int nTic);
说明:设置滑块控件中的一个刻度线的位置。
形式:void SetTicFreq(int nFreq);
说明:设置滑块控件刻度线的疏密程度。 null【例7-6】设计如图7.27所示的界面,用滚动条、滑块与旋转按钮控件来雕整RGB的三个颜色分量。 7.5 菜单、工具栏与状态栏设计 7.5 菜单、工具栏与状态栏设计 1. 菜单的设计
菜单属于CMenu 类。Windows 应用程序的菜单由两部分组成:一是主菜单,一般位于顶层;二是弹出菜单,它是单击主菜单中的菜单项时弹出的子菜单。
用编辑器设计菜单的主要操作有:
(1)显示菜单——在工作区中选定“ResourceView”,展开Menu ,双击其中的 IDR_MAINFRAME ,可以看到由 AppWizard 生成的标准菜单。
(2)删除菜单项——选定菜单项,然后按 Del 键。
(3)添加菜单项——双击空白菜单框,弹出“Menu Item Properties”,输入菜单项的标题(名称)。若菜单项有一个子菜单(单击会弹出了一子菜单),则选定“弹出”,否则不要选定“弹出”;要输入一条分割线,则选定“分隔符”。null (4)热键字符和快捷键的设置——假定菜单项的标题是:红色 (&R)\tCTRL+F1 ,则R设置为热键字符, CTRL+F1是快捷键,\t 让快捷键右对齐。
打开Accelerator的资源项,双击IDR_MAINFRAME,出现快捷键资源列表。
(5)使用快捷菜单——快捷菜单是一种浮动式的弹出式菜单,当用户按下鼠标右键时,就会相应地弹出一个浮动菜单,其中提供一个或多个与当前操作相关的选项。
用资源编辑器和MFC库的CMenu::TracePopupMenu函数可以很容易地创建这样的菜单,该函数原型如下:
BOOL TracePopupMenu(UNIT nFlags,int x,int y,CWnd *pwnd,LPCRECT lpRect=NULL);
该函数用来显示一个浮动的弹出菜单,其位置由各参数决定。其中,nFlags表示菜单在屏幕显示的位置以及2按钮的标志。null2. 工具栏的设计
工具栏是一系列工具按钮的组合,借助它们可以提高用户的工作效率。Visual C++6.0系统保存了每个工具栏相应的位图,其中包括所有按钮的图像,而所有的按钮图像具有相同的尺寸(16像素宽,15像素高),它们在位图中的排列次序与屏幕上按钮在工具栏上的次序相同。
(1)使用工具栏编辑器——选择Resource View选项卡,双击“Toolbar”项中的IDR_MAINFRAME,打开工具栏编辑器。
(2)工具栏和菜单相结合——工具栏和菜单相结合是指当选择工具按钮或菜单命令时,操作结果是一样的。使它们结合的具体方法是在工具按钮的属性对话框中将按钮的ID号设置为相关联的菜单项ID。7.6 文档/视图结构应用程序 7.6 文档/视图结构应用程序 文档:用于管理应用程序的数据
视图:用户界面,用于显示、打印文档中的数据, 管理与用户的交互。
数据的管理与显示分离的思想简化了开发过程
文档/视图结构应用程序: SDI 与MDI 【例7-7】利用APPWizard创建一个类似Windows记事本程序。null分析:
1. 利用Appwizard创建一个SDI程序框架时,在向导第六步中将视图类的基类由Cview改为CEditView;
2. 在工作区窗口中选定“ResourceView”
1) 展开Menu,双击IDR_MAINFRAME,在“编辑”菜单下按下表添加菜单项,无须编写消息处理函数。 2) 展开Accelerator,双击IDR_MAINFRAME,在其中设置快捷键。
3)展开String Table,双击String Table ,打开字符串编辑窗口,修改默认文件扩展名:
记事本\n\nTest\n文本文件(*.txt)\n.txt\nTest.Document\nTest Document7.7 程序举例【例7.8】选定了“日期”显示日期,选定“时间”显示时间。CTime类封装了日期和时间
静态成员GetCurrentTime()返回系统当前的日期和时间。7.7 程序举例nullvoid CTESTDlg::OnCheck1()
{
UpdateData(TRUE);
if(m_k1==TRUE)
{
CTime time=CTime::GetCurrentTime();
//构造“YYYY.MM.DD”形式的日期字符串
m_e1=time.Format("%Y.%m.%d");
}
else
m_e1="";
UpdateData(FALSE);
}void CTESTDlg::OnCheck2()
{
UpdateData(TRUE);
if(m_k2==TRUE)
{
CTime time=CTime::GetCurrentTime();
//构造“HH.MM.SS”形式的时间字符串
m_e2=time.Format("%I.%M.%S");
}
else
m_e2="";
UpdateData(FALSE);
}null【例7-9】设计如图7.32(a)所示的界面,当单击“确定”按钮后用MessageBox函数显示如图7.32(b) 所示的选择情况。 图7.32(a) 控件综合应用示例 图7.32(b)null UpdateData(TRUE);
CString s,ch;
int m;
s=m_e1;
if (IsDlgButtonChecked(IDC_RADIO1)) s=s+":男";
else s=s+":女";
if (m_L.GetCurSel()!=-1)
{m_L.GetText(m_L.GetCurSel(),ch);
s=s+","+ch;}
ch.Format("%3d",m_e2);
s=s+","+ch;
if (m_e3!="") s=s+","+m_e3+'\n';
for(int i=IDC_CHECK1;i
GetCheck();
if(m==1)
{GetDlgItemText(i,ch);
s=s+","+ch; } }
s=s+","+m_e4;
MessageBox(s,"你的选择:");