1
第 9章
Windows 标准控件在可视化编
程中的应用
2
控件是 Windows 图形用户界面
的主要组成部分之一,用户通过
操作控件对象完成与应用程序之
间的交互。控件的使用集中体现
了 Windows 系统面向对象的特点
3
9.1概述
控件工
具栏
控件接受的消息
主要有单击、双击
和字符输入等
4
9.2 按钮控件及其应用
按钮
控件
普通按钮
圆按钮
复选框按钮
组框按钮
自绘按钮
5
9.2.1 按钮控件的创建过程
CButton类的成员函数 Create负责创建按
钮控件,该函数的声明为:
BOOL Create
( LPCTSTR lpszCaption,//指定了按钮显示的正文
DWORD dwStyle,//按钮的风格
const RECT& rect,//按钮的位置和大小
CWnd* pParentWnd,//指向父窗口,
UINT nID //按钮的 ID
)
6
按钮控件消息,
ON_BN_CLICKED
ON_BN_DBLCLICKED
ON_COMMAND
两个
类似
按钮
是最
常见
的控
件之
一
复选框
单选按钮
下压式按钮
分组框
常用于只有两种
完全相反状态
的情况下
适用于同一组属性相
同的数据中选一个数据
适用于消息的发送
没有太多的操作
只是在窗口中划
分区域范围
7
GetCheck( )
SetCheck( )
GetBitmap()
SetBitmap()
GetButtonStyle()
SetButtonStyle()
GetCursor()
SetCursor()
GetIcon()
SetIcon()
GetState()
SetState()
CButton
类的 成
员函数
在知道按钮 ID的前
提下,还可使用与
按钮有关的 CWnd
成员函数来设置或
查询按钮状态
CheckDlgButtonCheckRadioButton
GetCheckedRadioButtonIs DlgButtonChecked
GetWindowTexGetWindowTextLength
SetWindowText
8
MFC还提供了一个 CBitmapButton的类,
允许用户以图标的方式显示按钮,它是
在 CButtong下派生的
MFC调用方法 DrawItem()在按钮上 绘制位图,
LoadBitmaps()方法为一个 CBitmapButton对象
附上位图,最多可以有 4个位图
自定义
按钮
9
9.2.2 按钮控件示例
10
IDC_BUTTON1
IDC_BUTTON2
IDC_RADIO1
IDC_RADIO2
IDC_CHECK1
IDC_CHECK2
Group
属性
Auto
属性
主要步骤:
1,创建基于对话框项目
2,设置按钮的属性
11
3,添加成员变量并添加消息响应函数
auto风格控
件不必添加
成员变量
12
void CMy9_1Dlg::OnButton1()
{ m_btn1.SetWindowText(,你 已 按 下 了 按
钮 !, ); }
void CMy9_1Dlg::OnButton2()
{ m_btn2.SetWindowText(“按钮已被按下 !, ); }
void CMy9_1Dlg::OnCheck1()
{ if(m_chk1.GetCheck()>0) m_chk1.SetCheck(0);
else m_chk1.SetCheck(1); }
void CMy9_1Dlg::OnRadio1()
{ m_rad1.SetCheck(1); }
13
9.3 滚动条控件
滚动条是一个交互式的, 高度可视化的控件
它包括一个滑块, 滚动条的两端的按钮等 。
滚动条控件 与 属于窗口的滚动条 是不一样的
处于窗口的滚
动条是由该窗
口创建、管理
和释放的
滚动条控件是由
用户创建、管理
和释放的
14
9.3.1 滚动条类的结构及其方法
滚动条可以通过通知代
码来创建,也可以用对
话框资源模板来创建
CScrollBar 类的方法
方法 说明
EnableScrollBar() 使滚动条的一个或两个箭头有效或无效
GetScrollI nfo() 获得滚动条的消息
GetScrollLi mit() 获得滚动条的范围
GetScrollP os() 获得滚动条当前的位置
GetScrollR ange() 获得制定滚动条的当前最大和最小滚动位置
SetScrollInfo() 设置滚动条的消息
SetScrollPos() 设置滚动块当前的位置
SetScrollRange() 设置制定滚动条的最 大和最小滚动位置
ShowScrollBar() 显示或隐藏滚动条
15
常用滚动条动作标识及其说明
SB_TOP / SB_BOTTOM,滚动到滚动条最顶 /底端
SB_LINEUP / SB_LINEDOWN:向上 / 下滚动一行
SB_LEFT / SB_RIGHT:滚动到左 / 右边
SB_LINELEFT / SB_LINERIGHT:向左 / 右滚动一行
SB_PAGEUP / SB_PAGEDOWN,向上 / 下滚动一页
SB_PAGELEFT / SB_PAGERIGHT,向左 / 右滚动一页
SB_THUMBPOSITION:滚动框移动到新位置
SB_THUMBTRACK:滚动框被拖动
SB_ENDSCROLL:滚动到最终位置
16
9.3.2 创建与初始化滚动条类
创建 CScrollBar
对象的一般步骤
(1) 用 C++关键字 new和构造函数
CScrollBar::CScrollBar()为一个
ScrollBar对象分配一个实例
(2) 初始化 CScrollBar对象,将一
个 Windows滚动条赋予它,并用
CScroll::Create()方法设置参数
和样式
分配一个滚动条控件对象并返回指向该对象的指针
CScrollBar::pMyScroll=new CScrollBar
调用 CScrollBar::Create()方法初始化指针
BOOL Create(DWORD dwStyle,const RECT& rect,CWnd *pParentWnd,UINT nID);
滚动条窗
口的样式
表示控件的
大小和位置
指向控件所属
窗口的指针
父窗口与滚动
条通信的标识
17
在设置滚动条控件时,要通过如下方法设置其范围
CScrollBar::SetScrollRange()
例如,设置滚动范围为 -100到 100的垂直滚动条
pMyScroll->SetScrollRange(SB_VERT,-100,100);
通过 SetScrollPos()设置滚动块当前位置
例如,滚动快的位置在 -100到 100的中间,即为 0
的位置
pMyScroller->SetScrollPos(0);
18
9.3.3滚动条类编程实例
标题为 Application of ScrollBar
滚动条的滚
动范围设为
0到 20
单击滚动块与
箭头之间的区
域。滚动块上
移或下移三格,
编辑框中的数
字加 3或减 3
单击向上或向下的
箭头,滚动块向上
或向下移动一格,
编辑框中的数字加
1或减 1
按住滚动块上
下拖动。编辑
框中的数字随
着随之变化当前值为 10
单击 Up按钮,
滚动块移到最
上边,编辑框
的数字变为 0
单击 Down按钮
,滚动块移到最
下边,编辑框的
数字变为 20
单击 Reset按
钮,滑块移到
中间,编辑框
的数字变为 10
单击 Exit按
钮,退出应
用程序
19
对话框中各个对象的属性
对象 ID
滚动条 IDC _ S CROLLBAR
编辑框 IDC_EDIT1
Up 按钮 IDC_ UP _BUTTON
Down 按钮 IDC_ DOWN _BUTTON
Reset 按钮 IDC_RESET_BUTTON
Exit 按钮 IDC_EXIT_BUTTON
(1) 应用程序的可视化编程部分
20
(2) 应用程序的代码编程部分
(a) 给滚动条连接变量
ID 变量名 类别 类型
IDC_SCROLLBAR m_Scrollbar Control CScrollbar
IDC_EDITl m_Edit Control CEdit
21
BOOL CMy9_2Dlg::OnInitDialog()
{ CDialog::OnInitDialog();
……
// TODO,Add extra initialization here
m_Scrollbar.SetScrollRange(0,20);
m_Scrollbar.SetScrollPos(10);
char sPos[10];
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
UpdateData(FALSE);
return TRUE;
}
10进
制数
(b) 初始化滚动条
22
(3) 给滚动条消息添加代码
void CMy9_2Dlg::OnVScroll(……)
{ // TODO,Add your message handler code here
char sPos[10];
int iNowPos;
switch(nSBCode)
{ if(pScrollBar==&m_Scrollbar)
{ case SB_THUMBTRACK,//拖动滑块
m_Scrollbar.SetScrollPos(nPos);
itoa(nPos,sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
23
case SB_LINEDOWN,//单击滚动条向下的箭头
iNowPos=m_Scrollbar.GetScrollPos();
iNowPos=iNowPos+1;
if(iNowPos>20)
iNowPos=20;
m_Scrollbar.SetScrollPos(iNowPos);
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
break;
24
case SB_LINEUP,//单击滚动条向上的箭头
iNowPos=m_Scrollbar.GetScrollPos();
iNowPos=iNowPos-1;
if(iNowPos<0)
iNowPos=0;
m_Scrollbar.SetScrollPos(iNowPos);
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
break;
25
case SB_PAGEDOWN,//单击箭头与滚块之间的区域
iNowPos=m_Scrollbar.GetScrollPos();
iNowPos=iNowPos+3;
if(iNowPos>20)
iNowPos=20;
m_Scrollbar.SetScrollPos(iNowPos);
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
break;
26
case SB_PAGEUP,//单击箭头与滚块之间的区域
iNowPos=m_Scrollbar.GetScrollPos();
iNowPos=iNowPos-3;
if(iNowPos<0)
iNowPos=0;
m_Scrollbar.SetScrollPos(iNowPos);
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
break;
} }
CDialog::OnVScroll(nSBCode,nPos,pScrollBar); }
27
(4) 给 Exit按钮连接代码
void CMy9_2Dlg::OnExitButton()
{ OnOK(); }
(5) 给 Up按钮添代码
void CMy9_2Dlg::OnUpButton()
{
m_Scrollbar.SetScrollPos(0);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel("0");
}
28
(6) 给 Down按钮添加代码
void CMy9_2Dlg::OnDownButton()
{ m_Scrollbar.SetScrollPos(20);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel("20");
}
(7) 给 Reset按钮添加代码
void CMy9_2Dlg::OnResetButton()
{ m_Scrollbar.SetScrollPos(10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel("10");
}
29
在应用程序中,编辑框只
是有于显示滚动块的位置,
不需要进行编辑,因此必
须将其属性改为只读
30
9.4 静态控件
31
9.4.1 静态控件的特点
一般情况下 静态控件不发送消息。
实际应用中,需要静态文本能够象超文本
那样响应用户的输入,向应用程序发送
控件消息。
要在创建静
态控件时加
入 SS_NOTIFY
样式
该样式允许静态控件向其父
窗口发送 WM_COMMAND消息,
该消息的字参数的低字节中
包含静态控件的 ID,高字节
中包含通知码
32
9.4.2 静态控件应用举例
【 例 9-3】 本例通过演示位图静态控件的使用方
法,说明静态控件消息的强制生成与处理过程,
当单击位图时,就报告该位图的尺寸。
33
主要步骤如下:
(1) 创建基于对话框的应用程序
(2) 导入一张 BMP格式图片。假设位图资源名
称为 IDB_BITMAP1
(3) 向对话框上放上一个 static控件,其 ID为
IDC_STATIC_BMP,并设置控件为 nofity风格,
并添加 CStatic类型成员 m_bmp
无此风格,静
态控件无法响
应鼠标消息
34
(4) 在 OnInitDailog函数中添加如下代码,设置控件为
位图风格,并设置位图
BOOL CMy9_3Dlg::OnInitDialog()
{ ……
// TODO,Add extra initialization here
m_bmp.ModifyStyle(0,SS_BITMAP);
HBITMAP hBmp=LoadBitmap(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP1));
m_bmp.SetBitmap(hBmp);
return TRUE;
}
35
(5) 响应鼠标单击静态控件的消息。为 static控件添加
BN_CLICKED消息的响应
void CMy9_3Dlg::OnStaticBmp()
{ // TODO,Add your control notification handler code here
BITMAP bmp;
GetObject(m_bmp.GetBitmap(),sizeof(BITMAP),&bmp);
CString msg;
msg.Format("Image Size %d*%d",
bmp.bmWidth,bmp.bmHeight);
AfxMessageBox(msg);
}
36
9.5 列表框控件
列表框经常用在对话框里,如用列表
框选择文件名、目录等。列表框有一个
预定义的键盘接口,用户可以用键盘上
的箭头和 PageUp或 PageDown键在列表框
中进行数据的选择,或通过适当的样式
设置,允许与 Shift或 Ctrl键组合使用。
列表框常应用于从众多数据中选某一项
37
9.5.1 列表框控件的类结构
MFC中 CListBox类的层次结构
38
CL i stBo x 消息的消息映像项
消息映像项 说明
O N _ L B N _ D B L C L K
双击,具有 L B S _ N O T I F Y 样式的列表框
向所有者发送此消息
O N _ L B N _ E R R S P A C E 列表框不能分配足够内存以满足要求
O N _ L B N _ K I L L F O C U S 当列表框失去输入焦点时出现此消息
O N _ L B N _ S E L C A N C E L
取消当前选择时,具有 L B S _ N O T I F Y 样
式的列表框向所有者发送此消息
O N _ L B N _ S E L C H A N G E
当列表框中的选择改变时,具有
L B S _ N O T I F Y 样式的 列表框向它的父窗
口 发送此通知
39
消息映像项使用下面的基本格式:
ON_Message( Control ID,ClassMethod)
所有者类声明中的方法原型
afx_msg void ClassMethod();
发送消息的列表框
控件的子窗口标识
处理消息的父
类 方法 的名字
40
9.5.2 列表框类的方法
41
通用 C Li st Box 类方法
方法 描述
G et C ount () 获得列表框中列表项数目
G et H ori zont al Extent () 获得列表框的水平滚动宽度 ( 按像素 )
G et It em D ata( ) 获得列表框项有关的 32 位值
G et It em D ataPtr () 获得指向列表框项的指针
G et It em H ei ght( ) 获得列表框中项的高度
(1) 通用方法
通用方法用来获得和设置列表框数据的
值和属性,所有的 CListBox列表框都有这些
方法,包括单选列表框、多选列表框和自绘
列表框等
42
(2) 单项选择特定方法
列表框的默认模式是单选项模式;
所有的通用方法均适用于单选项列表框
只有 两个类方
法专门处理单
选项列表框
GetCurSel()
SetCurSel()
获得当前选择列表
框项的下标 (基于 0)
选择列表框字符串
43
方法 说明
GetAnchorIndex() 获得多项选择列表框中当前定位项的下标
GetCaretIndex() 获得多项选择列表框中具有光标矩形的项的下标
GetSelCount() 获得多项选择列表框中当前所选的项的数目
GetSelItems() 将所有当前被选列表框项下标放入一整型数组缓冲区
SelItemRange() 切换多选择列表框项范围的选择状态
SetAnchorIndex() 在多项选择列表框中扩充选择设置开始 (定位 )项
SetCaretIndex() 在多项选择列表框中指定下标项设置光标矩形
SetSel() 在多项选择列表框中切换项目的选择状态
(3) 多项选择特定方法
多选项列表框扩展了
标准单项选择列表框
的能力,可以解决在
一个列表框中选择多
项带来的复杂性 特定多项选择列表
框的 CListBox类方法
44
(4) 字符串指定的方法
方法 说明
AddString() 在列表框中加入一个字符串
DeleteString() 从列表框中删除一个字符串
Dir() 从当前目录加文件名放入列表框
FindString() 在列表框中搜索一字符串
FindStringExact() 在列表框中搜索第一个与指定搜索字符串匹配的字符串
InsertString() 在列表框指定下标处插入一字符串
ResetContent() 清除列表框中的所有项
SelectString() 在单选列表框中搜索并选择一字符串
CListBox指定列表
框中字符串的方法
45
(5) 虚拟方法
CListBox类还声明了几个虚拟方法,你可以
从 CListBox类中派生一些类替换到你的类中。
方法 说明
CharToItem() 可以替换此方法来为自绘列表框(没有字符串)处理 WM-CHAR
CompareItem() 由 MFC调用以得到排序的自绘列表框中的新项的位置
DeleteItem() 当用户从自绘列表框中删除一项时 MFC调用此方法
DrawItem() 当确定自绘列表框项必须重绘时 MFC调用此方法
MeasureItem() 当一自绘列表框被创建时 MFC调用此方法来决定列表框的维数
VKeyToItem() 用户可替换此方法,来处理具有 LBS_WANTKEYBOARDINPUT样式
的列表框的 WM_KEYDOWN
能被替换的
CListBox类
的虚拟方法
46
创建和初始化 CListBox对象
(1)用 C++关键字 new和构造函数为 CListBox对象
分配一个实例,
CListBox::CListBox()
(2) 初始化 CListBox对象并赋于它一个 Windows
列表框,通过方法 CListBox::Create()设置列表框
的参数和样式
47
例如,下面代码分配一个 CListBox对象并返回指向该
对象的指针:
CListBox *pMyListBox=new CListBox;
指针 pMyListBox用 CListBox::Create()方法进行初始化
该方法声明如下:
BOOL Create
( DWORD dwStyle,// 列表框控件的窗口样式
const Recy& rect,// 指明控件的大小和位置
CWnd* pParentWnd,// 指向控件所有者的指针
UINT nID // 控件标识
)
48
9.5.3 列表框和应用程序
之间消息传递
49
1,列表框向应用程序发送消息
当用户与列表框交互时, 列表框向应用程序发出
WM_COMMAND消息 。 该消息字参数的高字节为标
识列表框动作的消息通知码 ( 如 LBN_DBLCLK标识
用户双击 ) ;低字节为控件标识值 。
LBN_SELCHANGE,列表框中的用户选择已发生改变
LBN_DBCLK,双击
LBN_SELCANCLE,列表框中的选择被取消
LBN_SETFOCUS,列表框收到输入焦点
LBN_KILLFOCUS,列表框失去输入焦点
50
2.应用程序向列表框发送消息
应用程序对列表框的操作通过调用函数
SendMessage或 SendDlgItemMessage向其发
送各种消息完成。
下面是常用文件属性值及其说明
数值 ( 16进制 ) 说 明
4000 列出驱动器名
0002 列出隐含文件名
0000 列出普通文件名
0004 列出系统文件名
0001 列出只读文件名
0010 列出上述文件及子目录名
51
9.5.4 列表框应用举例
【 例 9-4】 创建一个单选列表框,并在该列表
框中列出当前目录的文件,双击后删除该项
52
主要步骤如下:
(1)在对话框上放置一个 List Box(IDC_LIST_DIR)
控件和一个 Static(IDC_STATIC_DIR )控件。
List Box控件用于显示文件名称,Static控
件用于显示当前显示的文件所在的目录
(2)为 List Box控件添加 CListBox类型成员变
量 —— m_list
53
(3)在 OnInitDialog函数中添加初始化列表框内容的代码
BOOL CMy9_4Dlg::OnInitDialog()
{ CDialog::OnInitDialog();
// TODO,Add extra initialization here
DWORD cchCurDir = MAX_PATH;
LPTSTR lpszCurDir;
CHAR tchBuffer[MAX_PATH];
lpszCurDir = tchBuffer;
GetCurrentDirectory(cchCurDir,lpszCurDir);
DlgDirList(lpszCurDir,IDC_LIST_DIR,IDC_STATIC_DIR,0);
return TRUE;
}
获得当
前目录
设置列表框显示条目为当前目
录下所有文件名
54
(4)为了实现双击条目删除的功能,需要响应列表框的
LBN_DBLCLK消息
void CMy9_4Dlg::OnDblclkListDir()
{
// TODO,Add your control notification handler code here
int i = m_list.GetCurSel();
CString str;
m_list.GetText(i,str);
m_list.DeleteString(i);
CString msg = "Item "+str+" deleted!";
AfxMessageBox(msg);
}
55
9.6 编辑框控件
编辑框控件看起来是个非常简单的矩形
窗口,但它具有许多功能,编辑框控件可以
自带滚动条,显示多行文本。
CEdit是 CWnd
类直接派生来
的,这就意味
着它具有 CWnd
的所有功能编辑框 控件
单行编辑框控件
多行编辑框控件
56
C E d i t 类的通用方法
方法 说明
CanUndo() 决定一个编辑操作是否可以撤销
Clear() 从编辑控件中删除当前的选择 ( 如果有的话 )
Copy() 将编辑控件当前的选择以 C F _T E X T 格式复制到剪贴板中
Cut() 剪下编辑控件中的当前选择并以 C F _T E X T 格式复制到剪贴板中
EmptyUndoBuffe r() 消除一个编辑控件的“撤销”标志
GetFirs tVisible Line() 确定编辑控件中的最上面的可视行
GetM odify() 确定一个编辑控件的内容是否可修改
Get PasswordChar () 当用户输入文本时,获得编辑控件中显示的密码字符
GetRec t() 获得一个编辑控件的格式化矩形
GetSel () 获得编辑控件中当前选择的开始和结束字符位置
LimitText() 限定用户可能输入一编辑控件的文本长度
LineFromChar() 获得包含指定字符下标的行的行号
LineLength() 获得编辑控件中的一行的长度
LineScroll () 滚动多行编辑控件的文本
Paste () 将剪贴板的数据插入到编辑控件作当前的光标位置,只有当前剪贴板
中数 据格式为 C F _T E X T 时方可插入
Replace Sel() 用指定文本替代编辑控件中当前选择的部分
SetM odify() 设置或清除编辑控件的修改标志
SetPa ssword Char() 当用户输入文本时设置或删除一个显示于编辑控件中的密码字符
SetRea dOnly() 将编辑控件设置为只读状态
SetSe l() 在编辑控件中选择字符的范围
Undo() 取消最后一个编辑控件操作
57
多行编辑所支持的 C E di t 法
方法 说明
Fm tLi nes( ) 设置在多行编辑控件中包含软分行符
G etH and l e() 获得当前分配给一个多行编辑控件的内存的句柄
G etLi ne() 从一编辑控件中获得一行文本
G etLi neC oun t( ) 获得多行编辑控件的行数
L i neInd ex() 设置多行编辑控件中一行的字符下标
SetH and l e() 设置多行编辑控件将要用到的句柄内存句柄
SetR ect( ) 设置多行编辑控件的格式化矩形并更新控件
SetR ectN P() 设置多行编辑控件的格式 化矩形并且不重绘控件窗口
SetT abS tops () 在多行编辑控件中设置制表 (t ab) 位
58
9.6.2 编辑框与应用程序间的消
息传递
编辑框通过向其父窗口发关 WM_COMMAND
消息通知应用程序用户的交互信息
应用程序对编辑框的操作通过调用函数
SendMessage或 SendDlgItemMessage
59
9.6.3 编辑类编程实例
单击 Showl,则在 Edit1编辑框中显示,This is the first EditBox.”
?单击 Clear1,则 Edit1编辑框中的内容被清除;
?单击 Show2,则在 Edit2编辑框中显示,This is the second
EditBox!”
?单击 Clear2,则 Edit2编辑框中的内容被清除;
?单击 Transfer,则把 Edit1编辑框的内容复制到 Edit2的编辑框中去
?单击 Undo,则取消上一次操作
?若单击 Exit,则退出程序的运行
60
具体的编程过程
生成了工程文件和
工程工作区文件后
在 EditBox的工作区
中选择 ResourceView
因为本应用程序是基于对话框的,由
向导生成对话框窗口作为应用程序的
主窗口,并且给这个对话框取名为
IDD_EDITBOX_DIALOG,然后 在这个对
话框窗口中进行 界面设计
61
( 1)创建资源,在 ResourceView选项卡中打开 Dialog资
源组,然后双击 IDD_EDITBOX_DIALOG。 VC在工作台中
显示可以进行可视化编辑的 IDD_EDITBOX_DIALOG对话框
把鼠标停在编辑框
控件上,即可显示
该控件的类型
控件工具窗提供
了 VC中所有可建
立的控件类型
62
(2)设置控件 ID
对 象 ID C a pt i o n
编辑框 IDC _EDIT1 无
编辑框 I D C_ E D I T 2 无
命令按钮 IDC _ S H O W 1 _B U T T O N Sh o wl
命令按钮 IDC _ C L E A R 1_ B U T T O N C l ea r l
命令按钮 I D C_ S H O W 2 _B U T T O N S h ow 2
命令按钮 I D C_ C L E A R 2_ B U T T O N C l ea r 2
命令按钮 I D C_ T r a n s fe r _ B U T TO N T r an s f e r
命令按钮 I D C_ EXIT _ BU T T O N & E xi t
命令按钮 I D C_ U N D O _ BU T T O N & U nd o
将鼠标移到 Edit1控键上
--> 单击鼠标右键,选
择 Properties命令,在窗
口中输入控件的 ID标识
值,IDC_EDIT1,用同
样的方法设置其它各个
对象的属性
63
(3) 应用程序的代码编程部分
(a) 给编辑框连接变量
选择 Member
Variables选项卡
在 Control IDs
列表框中单击
IDC_EDIT1
项,使之高亮化
单击 Add Variable
按钮,此时显示
Add Member
Variable窗口
64
(b) 设置成员变量名为 m_Edit1,类别为 Control,变量
类型为 CEdit
注意,不要将 m_Edit1设
为 CString类型,因为只
有设为 CEdit 类型,才
能够调用 CEdit 类中的
一些成员函数,如 Copy,
Paste等,这样才能完成
本应用程序中对 Transfer
按钮要求复制内容的操
作的响应
?
65
用同样的方法给编辑框 EDIT2等其它对象连接各自的变
量,增加变量之后 MFC ClassWizard窗口将变为下图所示
66
若此时运行该程序,在 Edit文本框中
不能进行多行输入,只能单行输入文本,
而且按回车键终止应用程序,同时,文本
框中也没有水平和垂直滚动条。
下面,我们来完善应用程序中编辑框的
特性,使之能够进行多行文本的输入
67
可进行多行输入 增加水平及垂直滚动条
若不选择此项,在编辑框
中按回车键就会终止应用
程序,若选此项,按回车
键就可进行下一行的输入,
实现多行文本的输入
(c) 修改编辑框的特性
68
(4) 添加代码
void CMy9_5Dlg::OnShow1Button()
{
m_Edit1.SetSel(0,-1); // 选中编辑框 IDC_EDIT1中的全部内容
m_Edit1.ReplaceSel("This is the first EditBox.");
}
程序中 SetSel()函数是 CEdit类中的成员函数,因为
m_Edit1是属于 CEdit类的对象,故可以调用该类所有的
成员函数。 ReplaceSel() 函数也是 CEdit类中成员函数。
(a) 给 Showl按钮连接代码
69
(2) 给 Clear1按钮连接代码
void CMy9_5Dlg::OnClear1Button()
{
m_Edit1.SetSel(0,-1); //选中 IDC_EDIT1中的内容
m_Edit1.ReplaceSel("");
//用空串代替所选文本,即把所选的文本删除
}
70
void CMy9_5Dlg::OnShow2Button()
{
m_Edit2.SetSel(0,-1);
m_Edit2.ReplaceSel("This is the second EditBox.");
}
void CMy9_5Dlg::OnClear2Button()
{
m_Edit2.SetSel(0,-1);
m_Edit2.ReplaceSel("");
}
(3) 给 Show2和 Clear2按钮连接代码
71
(4) 给按钮 IDC_Transfer_BUTTON连接代码
void CMy9_5Dlg::OnTransferButton()
{
m_Edit1.SetSel(0,-1);
m_Edit1.Copy();
m_Edit2.SetSel(0,-1);
m_Edit2.ReplaceSel("");
m_Edit2.Paste();
}
72
(5)给 Undo按钮连接代码
void CMy9_5Dlg::OnUndoButton()
{ m_Edit1.Undo();
m_Edit2.Undo();
}
(6)给 Exit按钮连接代码
void CMy9_5Dlg::OnExitButton()
{
OnOK();
}
73
【 例 9-6】,乘法器”
示例程序,使用者
在“乘数”或者
“被乘数”编辑框
中输入数字的时候,
程序可以随时计算
乘法的结果
ID Type Member Read-only Number
IDC_EDIT_MUL1 int m_A √
IDC_EDIT_MUL2 int m_B √
IDC_EDIT_RESULT CStringm_Result √ √
74
(1) 初始化结果编辑框
BOOL CMy9_6Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
……
// TODO,Add extra initialization here
UpdateData(TRUE);
int i=m_A*m_B;
m_Result.Format("%d",i);
UpdateData(FALSE);
return TRUE;
}
75
(2)当编辑框中的内容发生改变时,会产生 EN_CHANGE
消息,需要为乘数与被乘数两个编辑框响应该消息
void CMy9_6Dlg::OnChangeEditMul1( )
{ UpdateData(TRUE);
int i=m_A*m_B;
m_Result.Format("%d",i);
UpdateData(FALSE);
}
void CMy9_6Dlg::OnChangeEditMul2( )
{ UpdateData(TRUE);
int i=m_A*m_B;
m_Result.Format("%d",i);
UpdateData(FALSE);
}
76
(3) 响应 Reset按钮的消息
void CMy9_6Dlg::OnReset()
{ m_A = 0;
m_B = 0;
int i=m_A*m_B;
m_Result.Format("%d",i);
UpdateData(FALSE);
}
77
9.7 组合框控件
78
9.7.1 组合框 (CComboBox)类的
结构及组合框的特点
组合框是两种预定义窗口的组合形式。
在 Windows编程中使用单一控件
往往不能完全满足与用户交互的需要,
最常见的组合框例子是对话框及与其
相联系的静态文本和编辑框。
79
9.7.2 组合框与应用程序间消息
传递
组合框通过向其父窗口发关 WM_COMMAND
消息通知应用程序用户的交互信息。
应用程序对组合框的操作也通过使用函数
SendMessage或 SendDlgItemMessage向组合框
发送消息进行。由于对组合框的操作实际上是
对组合框中各成员的操作。
80
9.7.3 组合框控件应用举例
【 例 9-7】 本例创建组合框控件,当单击向下
按钮时,显示可选文件的名字。当选中某一
项时,显示该项的名称
81
将一个 Combo Box控件放到对话框上。 取消 Sort风
格 。否则插入的内容将按照字母顺序排序,而不是
插入的顺序排序。添加 CComboBox类型的变量 m_cb
BOOL CMy9_7Dlg::OnInitDialog() //初始化对话框
{ CDialog::OnInitDialog();
……
// TODO,Add extra initialization here
m_cb.AddString("Monday");
m_cb.AddString("Tuesday");
m_cb.AddString("Wednesday");
m_cb.AddString("Thursday");
m_cb.AddString("Friday");
m_cb.AddString("Saturday");
m_cb.AddString("Sunday");
return TRUE;
}
82
当用户选择的内容发生改变的时候, 会产
生 CBN_SELCHANGE消息 。 为控件添加该
消息的响应函数:
void CMy9_7Dlg::OnSelchangeCombo()
{
CString msg;
m_cb.GetLBText(m_cb.GetCurSel(),msg);
AfxMessageBox(msg);
}
83
【 例 9-8】 本程序为几种控件的综合应用
84
在设计的过程中,同一组
单选按钮必须一个接一
个地放进对话框中,中
间不能插入其它的控件
对于成组的单选按
钮,只在每组的第
一个按钮的属性中
选中 Group设置
在 Sex Selecting
组中只有 Boy单
选按钮选中
Group属性
在 Age Range组中只
有,>20”单选按钮
选中 Group属性
85
Visual C++按照放入对话框中的先后顺序,给每个控件赋一
个 ID值,所以控件的 ID值是连续的。 Group属性的控件之间
的控件为一组。
可以从 resource.h的资源头文件中得到 ID值
#define IDC_SHOW_BUTTON 1006
#define IDC_HIDE_BUTTON 1007
#define IDC_Boy_RADIO 1008
#define IDC_Girl_RADIO 1009
#define IDC_Age1_RADIO 1010
#define IDC_Age2_RADIO 1011
#define IDC_Age3_RADIO 1012
#define IDC_Show_Sex_Age_BUTTON 1013
#define IDC_Result_EDIT 1014
86
在为相关控件连接变量和方法后,开始编程
(1) 给复选框 IDC_DATE_CHECK添加代码
OnDateCheck()方法的实现代码如下:
void CMy9_8Dlg::OnDataCheck()
{ UpdateData(TRUE);
if(m_DateCheck==TRUE)
{ CTime tNow ;
tNow=CTime::GetCurrentTime();
CString sNow=tNow.Format("%y.%m.%d");
m_DateEdit.SetSel(0,-1);
m_DateEdit.ReplaceSel(sNow);
}
else
{ m_DateEdit.SetSel(0,-1);
m_DateEdit.ReplaceSel("");
}
UpdateData(FALSE);
}
以当前的屏幕
显示内容更新
控件的变量
87
(2)为复选框 IDC_TIME_CHECK添加代码
void CMy9_8Dlg::OnTimeCheck()
{ UpdateData(TRUE);
if(m_TimeCheck==TRUE)
{ CTime tNow;
tNow=CTime::GetCurrentTime();
CString sNow=tNow.Format("%I:%M:%S");
m_TimeEdit.SetSel(0,-1);
m_TimeEdit.ReplaceSel(sNow);
}
else
{ m_TimeEdit.SetSel(0,-1);
m_TimeEdit.ReplaceSel("");
}
UpdateData(FALSE);
}
函数 Format的参
数 %I是时间的小
时表示法( 01~
12),%m是分的
表示法( 00~
59),%d是秒的
表示法( 00~ 59)
88
(3) 给 Enable按钮添加代码
void CMy9_8Dlg::OnEnableButton()
{
GetDlgItem(IDC_DATE_CHECK)->EnableWindow(TRUE);
GetDlgItem(IDC_TIME_CHECK)->EnableWindow(TRUE);
m_DateEdit.EnableWindow(TRUE);
m_TimeEdit.EnableWindow(TRUE);
}
89
(4) 为 Disable按钮连接代码
void CMy9_8Dlg::OnDisableButton()
{
GetDlgItem(IDC_DATE_CHECK)->EnableWindow(FALSE);
GetDlgItem(IDC_TIME_CHECK)->EnableWindow(FALSE);
m_DateEdit.EnableWindow(FALSE);
m_TimeEdit.EnableWindow(FALSE);
}
90
(5) 为 Show Again按钮添加代码
void CMy9_8Dlg::OnShowButton()
{
GetDlgItem(IDC_DATE_CHECK)->EnableWindow(SW_SHOW);
GetDlgItem(IDC_TIME_CHECK)->EnableWindow(SW_SHOW);
GetDlgItem(IDC_DATE_EDIT)->EnableWindow(SW_SHOW);
m_DateEdit.ShowWindow(SW_SHOW);
GetDlgItem(IDC_TIME_EDIT)->EnableWindow(SW_SHOW);
m_TimeEdit.ShowWindow(SW_SHOW);
}
91
(6) 为 Hide the Clock Setting按钮添加实现代码
void CMy9_8Dlg::OnHideButton()
{
GetDlgItem(IDC_DATE_CHECK)->EnableWindow(SW_HIDE);
GetDlgItem(IDC_TIME_CHECK)->EnableWindow(SW_HIDE);
m_DateEdit.ShowWindow(SW_HIDE);
m_TimeEdit.ShowWindow(SW_HIDE);
}
92
(7) 给 Show_the_Sex_and_Age按钮添加代码
void CMy9_8Dlg::OnShowSexAgeBUTTON()
{ char sEdit[50]; int iSexRADIO; int iAgeRADIO;
iSexRADIO=GetCheckedRadioButton(IDC_Boy_RADIO,IDC_Girl_RADIO);
if(iSexRADIO==IDC_Boy_RADIO)
strcpy(sEdit,"The boy's age is");
if(iSexRADIO==IDC_Girl_RADIO)
strcpy(sEdit,"The girl's age is");
iAgeRADIO=GetCheckedRadioButton(IDC_Age1_RADIO,IDC_Age3_RADIO);
if(iAgeRADIO==IDC_Age1_RADIO)
strcat(sEdit," great than 20");
if(iAgeRADIO==IDC_Age2_RADIO)
strcat(sEdit," between 15 and 20");
if(iAgeRADIO==IDC_Age3_RADIO)
strcat(sEdit," less than 15");
m_ResultEdit.SetSel(0,-1); m_ResultEdit.ReplaceSel(sEdit);
}
93
(8) 为 Show_Combo按钮添加代码
void CMy9_8Dlg::OnShowComboButton()
{ UpdateData(TRUE); char sCourseEdit[30];
char sRecordEdit[15]; int iCourseRadio;
iCourseRadio=GetCheckedRadioButton(IDC_ENGLISH_RADIO,IDC_NATURE_RADIO);
if(iCourseRadio==IDC_ENGLISH_RADIO)
strcpy(sCourseEdit,"English record is ");
if(iCourseRadio==IDC_COMPUTER_RADIO)
strcpy(sCourseEdit,"Computer record is ");
if(iCourseRadio==IDC_NATURE_RADIO)
strcpy(sCourseEdit,"Natural record is ");
m_Record.GetWindowText(sRecordEdit,15);
strcat(sCourseEdit,"");
strcat(sCourseEdit,sRecordEdit);
m_ComboEdit=_T(sCourseEdit); UpdateData(FALSE);
}
94
(9) 给 OnExitButton()方法添加代码
void CMy9_8Dlg::OnExitButton()
{
OnOK();
}
95
初始化单选按钮
BOOL CMy9_8Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
……
// TODO,Add extra initialization here
CheckRadioButton(IDC_Boy_RADIO,IDC_Girl_RADIO,IDC_Boy_RADIO);
CheckRadioButton(IDC_Age1_RADIO,IDC_Age3_RADIO,IDC_Age2_RADIO);
UpdateData(FALSE);
m_English=0;
m_Record.AddString("85");
m_Record.AddString("90");
m_Record.AddString("95");
m_Record.SelectString(-1,"95");
UpdateData(FALSE);
return TRUE;
}
96
9.8 对话框通用控件
大部分控件都是在对话框中使用的,
无论是基于对话框的应用程序还是
Doc/View结构的应用程序,控件通常是
放在对话框中的。本节将以一个名为
,Ctrl”的基于对话框的应用程序来介绍
各种 Windows通用控件的使用。
97
9.8.1 Picture控件的使用
(1)分隔线
将 Picture控件拖放
到对话框上,
【 Type】 属性选择
,Frame”,【 Color】
属性选择, Etched”,
将控件拖到最细,
这时,Picture控件
看起来的效果就跟
一条分隔线一样了
98
(2) 图片
将 【 Type】 属性设置为
,Icon”或者,Bitmap”的
时候,可以设置
【 Image】 属性为相应
的资源 ID,来显示图标
或位图。我们在资源中
导入一位图,命名为 IDB_BITMAP_DOT,设置 Picture控件 【 Type】
为,Bitmap”,【 Image】 为,IDB_BITMAP_DOT”
99
9.8.2 Spin控件的使用
Spin按钮控件提供了一
对箭头,用户通过点
击箭头可以微调该控
件所表示的数值。
表示 Spin控件的是
CSpinButtonCtrl类
Spin控件通常和 tab
order位于它之前的
控件成对使用。通
过 CSpinButtonCtrl的
GetBuddy方法可获
得与之配对的控件
100
向对话框拖放一个 Edit控件,置为只读,然后拖放一
个 Spin控件紧挨着刚才拖放的 Edit控件,两个控件的
ID都是用默认值,设置 Spin控件的 【 Allignment】 属
性为,Right”,选中 【 Auto buddy】 属性
BOOL CEx9_9Dlg::OnInitDialog()
{ ……
// TODO,Add extra initialization here
CSpinButtonCtrl* pSpin =(CSpinButtonCtrl*) GetDlgItem(IDC_SPIN1);
pSpin->SetRange(0,100);
pSpin->SetPos(50);
pSpin->GetBuddy()->SetWindowText("5.0");
return TRUE; }
设置 Spin的范围是 0~ 100,当
前位置是 50,同时设置它的
配对控件的显示值
101
在对话框中添加 WM_VSCROLL消息的响应:
void CEx9_9Dlg::OnVScroll(……)
{ if (pScrollBar->GetDlgCtrlID() == IDC_SPIN1)
{CString strValue;
strValue.Format("%3.1f",(double) nPos / 10.0);
((CSpinButtonCtrl*)pScrollBar)->GetBuddy()->SetWindowText(strValue);
}
CDialog::OnVScroll(nSBCode,nPos,pScrollBar);
}
102
9.8.3 Progress控件的使用
进度控件是一个用
来指示长时间操作
的进展程度的控件 。
MFC中表示进度控制
的是 CProgressCtrl类
进度条有一个 范围 和 当前位置 。 范围表示整个
操作的持续时间, 当前位置表示当前进行到的
位置,进度条根据当前位置来判断进行的百分
比,来显示进度
103
添加一个 Progress控件,保持默认 ID,设置
Smooth属性。在旁边添加一个按钮,设置 ID
为,IDC_BUTTON_START”,Caption为“开始”
在 OnInitDialog中添加如下代码:
CProgressCtrl* pProg =(CProgressCtrl*) GetDlgItem(IDC_PROGRESS1);
pProg->SetRange(0,100);
pProg->SetPos(50);
为“开始”按钮添加点击事件实现代码:
void CEx9_9Dlg::OnButtonStar()
{CProgressCtrl* pProg=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
pProg->SetPos(0);
SetTimer(1000,100,NULL);
}
104
在 CCtrlDlg中添加对 WM_TIMER消息的响应函数:
void CEx9_9Dlg::OnTimer(UINT nIDEvent)
{ if(nIDEvent == 1000)
{ CProgressCtrl* pProg = (CProgressCtrl*)
GetDlgItem(IDC_PROGRESS1);
pProg->SetPos(pProg->GetPos()+1);
if(pProg->GetPos() >= 100)
{
KillTimer(nIDEvent);
AfxMessageBox("进行完毕 ");
}
}
CDialog::OnTimer(nIDEvent);
}
每隔 0.1秒,
进度条前
进一步
105
9.8.4 Slider控件的使用
滑块控件可以使用户通过拖动滑块来
快速获得指定的数据 。 当用户滑动滑块的
时候, 控件将发送消息来指示变化 。
滑块控件在你
选择一系列离散
值或者一段连续
范围内的时候十
分有用。
106
在对话框上增加一个 Slider控件,设置 Point
属性为,Bottom/Right”,然后在旁边添加一
个 Static控件,ID设置为 IDC_STATIC_SLIDER。
该控件用来显示滑块的当前位置。
在 OnInitDialog函数中添加如下代码:
CString strText1;
CSliderCtrl* pSlide1 =(CSliderCtrl*) GetDlgItem(IDC_SLIDER1);
pSlide1->SetRange(0,100);
pSlide1->SetPos(50);
strText1.Format("%d",pSlide1->GetPos());
SetDlgItemText(IDC_STATIC_SLIDER,strText1);
107
为了响应滑块移动的消息, 添加 WM_HSCROLL消
息的响应 ( Slider是水平的, 如果是垂直的, 则需
要响应 WM_VSCROLL) 。 实现如下:
void CEx9_9Dlg::OnHScroll(……)
{
if(pScrollBar->GetDlgCtrlID() == IDC_SLIDER1)
{
CSliderCtrl* pSlide = (CSliderCtrl*) pScrollBar;
CString strText;
strText.Format("%d",pSlide->GetPos());
SetDlgItemText(IDC_STATIC_SLIDER,strText);
}
CDialog::OnHScroll(nSBCode,nPos,pScrollBar);
}
108
9.8.5 Date Time Picker控件的使用
Date Timer Picker可以用来接收日期或者
时间输入。用户可以直接按照指定的形
式输入,也可以在弹出的日历控件中选
择日期。
如果让用户以
字符串形式输
入,则由于输
入的多样性,
程序不好解析
109
在对话框上添加一个 Date Time Picker控件,
设置 Format为,Short Date”,选择,Use Spin
Control”,如果不选择使用 Spin控件,则用户
在弹出的日历控件中进行输入。在该控件旁
边添加一个按钮,ID为,IDC_BUTTON_TIME”,
Caption为“报时”。
在 OnInitDialog中添加如下代码:
CDateTimeCtrl* pDT =
(CDateTimeCtrl*) GetDlgItem(IDC_DATETIMEPICKER1);
CString formatStr= _T("'今天是, 'yy'/'MM'/'dd");
pDT->SetFormat(formatStr);
110
添加对 【 报时 】 按钮的点击事件的响应函数:
void CEx9_9Dlg::OnButtonTime()
{
CDateTimeCtrl* pDT =(CDateTimeCtrl*)
GetDlgItem(IDC_DATETIMEPICKER1);
CTime t;
pDT->GetTime(t);
CString s = t.Format( "%A,%B %d,%Y %H:%M:%S" );
AfxMessageBox(s);
}
111
9.8.6 List Control控件的使用
列表控件
112
列表控件是 Windows应用程序中最常用的
控件之一。最常见的用途就是资源管理
器右边的文件列表。
MFC中使用 CListCtrl类来封装列表控件
的功能。
列表控件通常可以包括一个图标和一
个标签。此外,每一项还可以具有其它附
加信息,例如资源管理器中文件的具体信
息就是附加信息。
113
列表控
件的视
图风格
图标视图,每项显示 32× 32图标,在
图标下面显示标签。用户可以将图标
拖放到视图内任何位置
小图标视图,每项显示 16× 16图标,
在图标右边显示标签。用户可以将
图标拖放到视图内任何位置
列表视图,每项显示 16× 16图标,
在图标右边显示标签。每一项按列
排列,不能随意拖动图标
报表视图,每项占一行,第一列是
主项,显示 16× 16图标,在图标右
侧显示标签。右边的列显示子项,
具体由程序来决定
114
为使用列表控件,首先需要创建图标资源,在
ResourceView的 Icon一栏内创建 8个图标资源
在 Cex9_9Dlg类中增加成员如下:
CImageList m_imageList;
在 OnInitDialog函数中添加初始化图片列表的代码:
HICON hIcon[8]; int n;
m_imageList.Create(16,16,0,8,8);
hIcon[0] = AfxGetApp()->LoadIcon(IDI_ICON_WHITE);
hIcon[1] = AfxGetApp()->LoadIcon(IDI_ICON_BLACK);
hIcon[2] = AfxGetApp()->LoadIcon(IDI_ICON_RED);
hIcon[3] = AfxGetApp()->LoadIcon(IDI_ICON_BLUE);
hIcon[4] = AfxGetApp()->LoadIcon(IDI_ICON_YELLOW);
hIcon[5] = AfxGetApp()->LoadIcon(IDI_ICON_CYAN);
hIcon[6] = AfxGetApp()->LoadIcon(IDI_ICON_PURPLE);
hIcon[7] = AfxGetApp()->LoadIcon(IDI_ICON_GREEN);
for (n = 0; n < 8; n++)
m_imageList.Add(hIcon[n]);
115
创建标签资源, 也就是每一项的文字, 在
OnInitDialog函数中添加如下实现代码:
static char* color[] = {"white","black","red","blue",
"yellow","cyan","purple","green"};
有了这些资源,就可以创建列表控件了。
在对话框上添加一个 List Control,其 ID为 IDC_LIST1,
在样式中选择视图风格为 List,并选择 Edit lables选项。
视图风格为列表风格,也就是图标按列排列。设置
【 Edit lables】 属性,允许用于可编辑标签。
116
为了创建控件, 首先在 OnInitDialog中添加如下代码:
CListCtrl* pList = (CListCtrl*) GetDlgItem(IDC_LIST1);
// 获得控件对象
pList->SetImageList(&m_imageList,LVSIL_SMALL);
// 设置小图标图片列表
for (n = 0; n < 8; n++)
{ // 第一个参数为项 id,第二个为 标签文字,第三个为
对应图片列表 id
pList->InsertItem(n,color[n],n);
}
pList->SetBkColor(RGB(0,255,255)); // 设置背景色
pList->SetTextBkColor(RGB(255,0,255));
//设置文字的背景色
现在编译运行已经可以看到列表的运行效果了。
117
在列表控件下添加 static控件, ID为 IDC_STATIC_LIST。
对列表控件添加对 LVN_ITEMCHANGED消息的响应:
void CEx9_9Dlg::OnItemchangedList1(……)
{ NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO,Add your control notification handler code here
CListCtrl* pList = (CListCtrl*) GetDlgItem(IDC_LIST1);
int nSelected = pNMListView->iItem;
if (nSelected >= 0)
{ CString strItem = pList->GetItemText(nSelected,0);
SetDlgItemText(IDC_STATIC_LIST,strItem);
}
*pResult = 0;
}
118
在设置控件属性时, 设置了 Edit labels属性, 下面是
对列表控件的 NM_RCLICK消息的响应:
void CEx9_9Dlg::OnRclickList1(……)
{
// TODO,Add your control notification handler code here
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
CListCtrl* pList = (CListCtrl*) GetDlgItem(IDC_LIST1);
int nSelected = pNMListView->iItem;
if (nSelected >= 0)
pList->EditLabel(nSelected);
*pResult = 0;
}
119
运行程序, 右击某一项, 已可以编辑标签了, 但无
法保存编辑效果 。 若要保存, 需要响应列表控件的
LVN_ENDLABELEDIT消息, 在这里可以判断新输入的
文字是否合法, 然后设置标签为编辑得到的文字:
void CEx9_9Dlg::OnEndlabeleditList1(……)
{ LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO,Add your control notification handler code here
LVITEMA item = pDispInfo->item;
CString str =item.pszText; str.TrimLeft();
str.TrimRight();
if(str.GetLength() > 0)
{ CListCtrl* pList = (CListCtrl*) GetDlgItem(IDC_LIST1);
pList->SetItemText(item.iItem,item.iSubItem,item.pszText);
}
*pResult = 0;
}
120
9.8.7 Tree Control控件的使用
树状视图控件是一种用来显示层次结构的控
件,例如 Windows资源管理器左边的视图。视
图中的每一项包
括一个标签,位
图是可选的,每
项还可以附加若
干子项。点击每
一项,可展开或
合拢当前树节点
121
本例中继续使用 List Control中的图标。接下来在对
话框中添加树状控件,其 ID为 IDC_TREE1,选中 Has
buttons,Has lines,Lines at root和 Edit labels属性
Has buttons:决定可展开项之前是否有, +”,,-, 按钮
Has Lines:决定相关节点之间是否显示虚线连接
Lines at root:决定位于第一层的节点之间是否有虚线连接
Edit labels,表示标签是否可编辑
122
然后在 OnInitDialog函数中添加如下代码:
CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_TREE1);
pTree->SetImageList(&m_imageList,TVSIL_NORMAL); // 设置图片列表
TV_INSERTSTRUCT tvinsert; //创建待插入的 TV_INSERTSTRUCT结构
tvinsert.hParent = NULL; // 无父结点
tvinsert.hInsertAfter = TVI_LAST; // 插入到本层最后
tvinsert.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE| TVIF_TEXT;
//掩码,图标 /选中图标 /文字
tvinsert.item.hItem = NULL; // 句柄为空
tvinsert.item.state = 0; // 状态
tvinsert.item.stateMask = 0; // 状态掩码,不使用这两项
tvinsert.item.cchTextMax = 6; // 最大文字长度,忽略
tvinsert.item.iSelectedImage = 1; // 选中图标索引
tvinsert.item.cChildren = 0; // 没有子节点
tvinsert.item.lParam = 0; // 自定义数据
123
// 创建第一层
tvinsert.item.iImage = 2; // 一般图标
tvinsert.item.pszText = "father"; // 插入第一层第一个节点
HTREEITEM hDad = pTree ->InsertItem(&tvinsert);
tvinsert.item.pszText = "mother"; // 插入第一层第二个节点
HTREEITEM hMom = pTree->InsertItem(&tvinsert);
// 创建第二层
tvinsert.hParent = hDad; // 父节点为 "father"
tvinsert.item.iImage = 3; // 一般图标
tvinsert.item.pszText = "son"; // 插入第二层 "father"的第一个节点
pTree->InsertItem(&tvinsert);
tvinsert.item.pszText = "daughter"; // 插入第二层的第二个节点
pTree->InsertItem(&tvinsert);
tvinsert.hParent = hMom; // 父结点为 "mother"
tvinsert.item.iImage = 4;
124
tvinsert.item.pszText = "son"; // 插入第二层的第一个节点
pTree->InsertItem(&tvinsert);
tvinsert.item.pszText = "daughter"; // 插入第二层的第二个节点
pTree->InsertItem(&tvinsert);
tvinsert.item.pszText = "cartoon"; // 插入第二层的第三个节点
HTREEITEM hOther = pTree->InsertItem(&tvinsert);
// 创建第三层
tvinsert.hParent = hOther; // 父结点为 "cartoon"
tvinsert.item.iImage = 7;
tvinsert.item.pszText = "Tom"; // 插入第三层的第一个节点 Tom
pTree->InsertItem(&tvinsert);
tvinsert.item.pszText = "Jerry"; // 插入第三层的第二个节点 Jerry
pTree->InsertItem(&tvinsert);
125
理解上述代码的关键在于理解关键函数
InsertItem和 TV_INSERTSTRUCT 和 TV_ITEM
数据结构 。
InsertItem的函数执行的功能是向树状控
件中插入一项,至于这一项什么样子,
要插入到什么位置,全部由 InsertItem的
TV_INSERTSTRUCT类型的参数来描述,
126
下面通过添加一些对树状控件常用消息的响应来说
明树状控件的一般使用方法 。 首先在树状控件旁边
添加一个 static控件, ID设置为 IDC_STATIC_TREE。 为
树状控件添加对 TVN_SELCHANGED消息的响应:
void CEx9_9Dlg::OnSelchangedTree1(……)
{ NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO,Add your control notification handler code here
CTreeCtrl* pTree =(CTreeCtrl*) GetDlgItem(IDC_TREE1);
HTREEITEM hSelected = pNMTreeView->itemNew.hItem;
if (hSelected != NULL)
{ char text[31]; TV_ITEM item;
item.mask = TVIF_HANDLE | TVIF_TEXT;
item.hItem = hSelected;
item.pszText = text; item.cchTextMax = 30;
VERIFY(pTree->GetItem(&item));
SetDlgItemText(IDC_STATIC_TREE,text);
}
*pResult = 0;
}
127
在向对话框添加控件时,设置了 Edit labels属性,使得树状控
件可编辑,双击节点文字便进入编辑状态,响应编辑状态结束
消息呢的方法与响应列表控件的编辑结束消息完全一样。对
TVN_ENDLABELEDIT消息的响应函数,实现如下:
void CEx9_9Dlg::OnEndlabeleditTree1(…… )
{ TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
//TODO:Add your control notification handler code here
TVITEMA item = pTVDispInfo->item;
CString str =item.pszText;
str.TrimLeft();
str.TrimRight();
if(str.GetLength() > 0)
{ CTreeCtrl* pTree =(CTreeCtrl*) GetDlgItem(IDC_TREE1);
pTree->SetItemText(item.hItem,item.pszText);
}
*pResult = 0;
}
128
129
9.8.8 Extended Combo Box控件的使用
扩展的复合框继承自普通的复合框 。
MFC提供了 CComboBoxEx来实现扩展
复合框的功能。使用扩展的复合框,
你不再需要自己实现在复合框中绘
制图片的功能了。使用扩展的复合
框可以通过图象列表来访问图象
130
向对话框添加扩展对话框控件,ID为 IDC_COMBOBOXEX1,类型
(Type)为 Dropdown。 在 OnInitDialog函数中添加如下代码:
CComboBoxEx * pComboEx=(CComboBoxEx *)GetDlgItem(IDC_COMBOBOXEX1);
pComboEx->SetImageList(&m_imageList);
COMBOBOXEXITEM comboItem;
comboItem.mask = CBEIF_IMAGE | CBEIF_INDENT |
CBEIF_SELECTEDIMAGE | CBEIF_TEXT ;
for(int i=0; i<3; i++)
{
comboItem.iItem = i;
comboItem.iImage = i;
comboItem.iSelectedImage = i;
comboItem.iIndent = i;
comboItem.pszText = color[i];
pComboEx->InsertItem(&comboItem);
}
131
第 9章
Windows 标准控件在可视化编
程中的应用
2
控件是 Windows 图形用户界面
的主要组成部分之一,用户通过
操作控件对象完成与应用程序之
间的交互。控件的使用集中体现
了 Windows 系统面向对象的特点
3
9.1概述
控件工
具栏
控件接受的消息
主要有单击、双击
和字符输入等
4
9.2 按钮控件及其应用
按钮
控件
普通按钮
圆按钮
复选框按钮
组框按钮
自绘按钮
5
9.2.1 按钮控件的创建过程
CButton类的成员函数 Create负责创建按
钮控件,该函数的声明为:
BOOL Create
( LPCTSTR lpszCaption,//指定了按钮显示的正文
DWORD dwStyle,//按钮的风格
const RECT& rect,//按钮的位置和大小
CWnd* pParentWnd,//指向父窗口,
UINT nID //按钮的 ID
)
6
按钮控件消息,
ON_BN_CLICKED
ON_BN_DBLCLICKED
ON_COMMAND
两个
类似
按钮
是最
常见
的控
件之
一
复选框
单选按钮
下压式按钮
分组框
常用于只有两种
完全相反状态
的情况下
适用于同一组属性相
同的数据中选一个数据
适用于消息的发送
没有太多的操作
只是在窗口中划
分区域范围
7
GetCheck( )
SetCheck( )
GetBitmap()
SetBitmap()
GetButtonStyle()
SetButtonStyle()
GetCursor()
SetCursor()
GetIcon()
SetIcon()
GetState()
SetState()
CButton
类的 成
员函数
在知道按钮 ID的前
提下,还可使用与
按钮有关的 CWnd
成员函数来设置或
查询按钮状态
CheckDlgButtonCheckRadioButton
GetCheckedRadioButtonIs DlgButtonChecked
GetWindowTexGetWindowTextLength
SetWindowText
8
MFC还提供了一个 CBitmapButton的类,
允许用户以图标的方式显示按钮,它是
在 CButtong下派生的
MFC调用方法 DrawItem()在按钮上 绘制位图,
LoadBitmaps()方法为一个 CBitmapButton对象
附上位图,最多可以有 4个位图
自定义
按钮
9
9.2.2 按钮控件示例
10
IDC_BUTTON1
IDC_BUTTON2
IDC_RADIO1
IDC_RADIO2
IDC_CHECK1
IDC_CHECK2
Group
属性
Auto
属性
主要步骤:
1,创建基于对话框项目
2,设置按钮的属性
11
3,添加成员变量并添加消息响应函数
auto风格控
件不必添加
成员变量
12
void CMy9_1Dlg::OnButton1()
{ m_btn1.SetWindowText(,你 已 按 下 了 按
钮 !, ); }
void CMy9_1Dlg::OnButton2()
{ m_btn2.SetWindowText(“按钮已被按下 !, ); }
void CMy9_1Dlg::OnCheck1()
{ if(m_chk1.GetCheck()>0) m_chk1.SetCheck(0);
else m_chk1.SetCheck(1); }
void CMy9_1Dlg::OnRadio1()
{ m_rad1.SetCheck(1); }
13
9.3 滚动条控件
滚动条是一个交互式的, 高度可视化的控件
它包括一个滑块, 滚动条的两端的按钮等 。
滚动条控件 与 属于窗口的滚动条 是不一样的
处于窗口的滚
动条是由该窗
口创建、管理
和释放的
滚动条控件是由
用户创建、管理
和释放的
14
9.3.1 滚动条类的结构及其方法
滚动条可以通过通知代
码来创建,也可以用对
话框资源模板来创建
CScrollBar 类的方法
方法 说明
EnableScrollBar() 使滚动条的一个或两个箭头有效或无效
GetScrollI nfo() 获得滚动条的消息
GetScrollLi mit() 获得滚动条的范围
GetScrollP os() 获得滚动条当前的位置
GetScrollR ange() 获得制定滚动条的当前最大和最小滚动位置
SetScrollInfo() 设置滚动条的消息
SetScrollPos() 设置滚动块当前的位置
SetScrollRange() 设置制定滚动条的最 大和最小滚动位置
ShowScrollBar() 显示或隐藏滚动条
15
常用滚动条动作标识及其说明
SB_TOP / SB_BOTTOM,滚动到滚动条最顶 /底端
SB_LINEUP / SB_LINEDOWN:向上 / 下滚动一行
SB_LEFT / SB_RIGHT:滚动到左 / 右边
SB_LINELEFT / SB_LINERIGHT:向左 / 右滚动一行
SB_PAGEUP / SB_PAGEDOWN,向上 / 下滚动一页
SB_PAGELEFT / SB_PAGERIGHT,向左 / 右滚动一页
SB_THUMBPOSITION:滚动框移动到新位置
SB_THUMBTRACK:滚动框被拖动
SB_ENDSCROLL:滚动到最终位置
16
9.3.2 创建与初始化滚动条类
创建 CScrollBar
对象的一般步骤
(1) 用 C++关键字 new和构造函数
CScrollBar::CScrollBar()为一个
ScrollBar对象分配一个实例
(2) 初始化 CScrollBar对象,将一
个 Windows滚动条赋予它,并用
CScroll::Create()方法设置参数
和样式
分配一个滚动条控件对象并返回指向该对象的指针
CScrollBar::pMyScroll=new CScrollBar
调用 CScrollBar::Create()方法初始化指针
BOOL Create(DWORD dwStyle,const RECT& rect,CWnd *pParentWnd,UINT nID);
滚动条窗
口的样式
表示控件的
大小和位置
指向控件所属
窗口的指针
父窗口与滚动
条通信的标识
17
在设置滚动条控件时,要通过如下方法设置其范围
CScrollBar::SetScrollRange()
例如,设置滚动范围为 -100到 100的垂直滚动条
pMyScroll->SetScrollRange(SB_VERT,-100,100);
通过 SetScrollPos()设置滚动块当前位置
例如,滚动快的位置在 -100到 100的中间,即为 0
的位置
pMyScroller->SetScrollPos(0);
18
9.3.3滚动条类编程实例
标题为 Application of ScrollBar
滚动条的滚
动范围设为
0到 20
单击滚动块与
箭头之间的区
域。滚动块上
移或下移三格,
编辑框中的数
字加 3或减 3
单击向上或向下的
箭头,滚动块向上
或向下移动一格,
编辑框中的数字加
1或减 1
按住滚动块上
下拖动。编辑
框中的数字随
着随之变化当前值为 10
单击 Up按钮,
滚动块移到最
上边,编辑框
的数字变为 0
单击 Down按钮
,滚动块移到最
下边,编辑框的
数字变为 20
单击 Reset按
钮,滑块移到
中间,编辑框
的数字变为 10
单击 Exit按
钮,退出应
用程序
19
对话框中各个对象的属性
对象 ID
滚动条 IDC _ S CROLLBAR
编辑框 IDC_EDIT1
Up 按钮 IDC_ UP _BUTTON
Down 按钮 IDC_ DOWN _BUTTON
Reset 按钮 IDC_RESET_BUTTON
Exit 按钮 IDC_EXIT_BUTTON
(1) 应用程序的可视化编程部分
20
(2) 应用程序的代码编程部分
(a) 给滚动条连接变量
ID 变量名 类别 类型
IDC_SCROLLBAR m_Scrollbar Control CScrollbar
IDC_EDITl m_Edit Control CEdit
21
BOOL CMy9_2Dlg::OnInitDialog()
{ CDialog::OnInitDialog();
……
// TODO,Add extra initialization here
m_Scrollbar.SetScrollRange(0,20);
m_Scrollbar.SetScrollPos(10);
char sPos[10];
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
UpdateData(FALSE);
return TRUE;
}
10进
制数
(b) 初始化滚动条
22
(3) 给滚动条消息添加代码
void CMy9_2Dlg::OnVScroll(……)
{ // TODO,Add your message handler code here
char sPos[10];
int iNowPos;
switch(nSBCode)
{ if(pScrollBar==&m_Scrollbar)
{ case SB_THUMBTRACK,//拖动滑块
m_Scrollbar.SetScrollPos(nPos);
itoa(nPos,sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
23
case SB_LINEDOWN,//单击滚动条向下的箭头
iNowPos=m_Scrollbar.GetScrollPos();
iNowPos=iNowPos+1;
if(iNowPos>20)
iNowPos=20;
m_Scrollbar.SetScrollPos(iNowPos);
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
break;
24
case SB_LINEUP,//单击滚动条向上的箭头
iNowPos=m_Scrollbar.GetScrollPos();
iNowPos=iNowPos-1;
if(iNowPos<0)
iNowPos=0;
m_Scrollbar.SetScrollPos(iNowPos);
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
break;
25
case SB_PAGEDOWN,//单击箭头与滚块之间的区域
iNowPos=m_Scrollbar.GetScrollPos();
iNowPos=iNowPos+3;
if(iNowPos>20)
iNowPos=20;
m_Scrollbar.SetScrollPos(iNowPos);
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
break;
26
case SB_PAGEUP,//单击箭头与滚块之间的区域
iNowPos=m_Scrollbar.GetScrollPos();
iNowPos=iNowPos-3;
if(iNowPos<0)
iNowPos=0;
m_Scrollbar.SetScrollPos(iNowPos);
itoa(m_Scrollbar.GetScrollPos(),sPos,10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel(sPos);
break;
} }
CDialog::OnVScroll(nSBCode,nPos,pScrollBar); }
27
(4) 给 Exit按钮连接代码
void CMy9_2Dlg::OnExitButton()
{ OnOK(); }
(5) 给 Up按钮添代码
void CMy9_2Dlg::OnUpButton()
{
m_Scrollbar.SetScrollPos(0);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel("0");
}
28
(6) 给 Down按钮添加代码
void CMy9_2Dlg::OnDownButton()
{ m_Scrollbar.SetScrollPos(20);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel("20");
}
(7) 给 Reset按钮添加代码
void CMy9_2Dlg::OnResetButton()
{ m_Scrollbar.SetScrollPos(10);
m_Edit.SetSel(0,-1);
m_Edit.ReplaceSel("10");
}
29
在应用程序中,编辑框只
是有于显示滚动块的位置,
不需要进行编辑,因此必
须将其属性改为只读
30
9.4 静态控件
31
9.4.1 静态控件的特点
一般情况下 静态控件不发送消息。
实际应用中,需要静态文本能够象超文本
那样响应用户的输入,向应用程序发送
控件消息。
要在创建静
态控件时加
入 SS_NOTIFY
样式
该样式允许静态控件向其父
窗口发送 WM_COMMAND消息,
该消息的字参数的低字节中
包含静态控件的 ID,高字节
中包含通知码
32
9.4.2 静态控件应用举例
【 例 9-3】 本例通过演示位图静态控件的使用方
法,说明静态控件消息的强制生成与处理过程,
当单击位图时,就报告该位图的尺寸。
33
主要步骤如下:
(1) 创建基于对话框的应用程序
(2) 导入一张 BMP格式图片。假设位图资源名
称为 IDB_BITMAP1
(3) 向对话框上放上一个 static控件,其 ID为
IDC_STATIC_BMP,并设置控件为 nofity风格,
并添加 CStatic类型成员 m_bmp
无此风格,静
态控件无法响
应鼠标消息
34
(4) 在 OnInitDailog函数中添加如下代码,设置控件为
位图风格,并设置位图
BOOL CMy9_3Dlg::OnInitDialog()
{ ……
// TODO,Add extra initialization here
m_bmp.ModifyStyle(0,SS_BITMAP);
HBITMAP hBmp=LoadBitmap(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP1));
m_bmp.SetBitmap(hBmp);
return TRUE;
}
35
(5) 响应鼠标单击静态控件的消息。为 static控件添加
BN_CLICKED消息的响应
void CMy9_3Dlg::OnStaticBmp()
{ // TODO,Add your control notification handler code here
BITMAP bmp;
GetObject(m_bmp.GetBitmap(),sizeof(BITMAP),&bmp);
CString msg;
msg.Format("Image Size %d*%d",
bmp.bmWidth,bmp.bmHeight);
AfxMessageBox(msg);
}
36
9.5 列表框控件
列表框经常用在对话框里,如用列表
框选择文件名、目录等。列表框有一个
预定义的键盘接口,用户可以用键盘上
的箭头和 PageUp或 PageDown键在列表框
中进行数据的选择,或通过适当的样式
设置,允许与 Shift或 Ctrl键组合使用。
列表框常应用于从众多数据中选某一项
37
9.5.1 列表框控件的类结构
MFC中 CListBox类的层次结构
38
CL i stBo x 消息的消息映像项
消息映像项 说明
O N _ L B N _ D B L C L K
双击,具有 L B S _ N O T I F Y 样式的列表框
向所有者发送此消息
O N _ L B N _ E R R S P A C E 列表框不能分配足够内存以满足要求
O N _ L B N _ K I L L F O C U S 当列表框失去输入焦点时出现此消息
O N _ L B N _ S E L C A N C E L
取消当前选择时,具有 L B S _ N O T I F Y 样
式的列表框向所有者发送此消息
O N _ L B N _ S E L C H A N G E
当列表框中的选择改变时,具有
L B S _ N O T I F Y 样式的 列表框向它的父窗
口 发送此通知
39
消息映像项使用下面的基本格式:
ON_Message( Control ID,ClassMethod)
所有者类声明中的方法原型
afx_msg void ClassMethod();
发送消息的列表框
控件的子窗口标识
处理消息的父
类 方法 的名字
40
9.5.2 列表框类的方法
41
通用 C Li st Box 类方法
方法 描述
G et C ount () 获得列表框中列表项数目
G et H ori zont al Extent () 获得列表框的水平滚动宽度 ( 按像素 )
G et It em D ata( ) 获得列表框项有关的 32 位值
G et It em D ataPtr () 获得指向列表框项的指针
G et It em H ei ght( ) 获得列表框中项的高度
(1) 通用方法
通用方法用来获得和设置列表框数据的
值和属性,所有的 CListBox列表框都有这些
方法,包括单选列表框、多选列表框和自绘
列表框等
42
(2) 单项选择特定方法
列表框的默认模式是单选项模式;
所有的通用方法均适用于单选项列表框
只有 两个类方
法专门处理单
选项列表框
GetCurSel()
SetCurSel()
获得当前选择列表
框项的下标 (基于 0)
选择列表框字符串
43
方法 说明
GetAnchorIndex() 获得多项选择列表框中当前定位项的下标
GetCaretIndex() 获得多项选择列表框中具有光标矩形的项的下标
GetSelCount() 获得多项选择列表框中当前所选的项的数目
GetSelItems() 将所有当前被选列表框项下标放入一整型数组缓冲区
SelItemRange() 切换多选择列表框项范围的选择状态
SetAnchorIndex() 在多项选择列表框中扩充选择设置开始 (定位 )项
SetCaretIndex() 在多项选择列表框中指定下标项设置光标矩形
SetSel() 在多项选择列表框中切换项目的选择状态
(3) 多项选择特定方法
多选项列表框扩展了
标准单项选择列表框
的能力,可以解决在
一个列表框中选择多
项带来的复杂性 特定多项选择列表
框的 CListBox类方法
44
(4) 字符串指定的方法
方法 说明
AddString() 在列表框中加入一个字符串
DeleteString() 从列表框中删除一个字符串
Dir() 从当前目录加文件名放入列表框
FindString() 在列表框中搜索一字符串
FindStringExact() 在列表框中搜索第一个与指定搜索字符串匹配的字符串
InsertString() 在列表框指定下标处插入一字符串
ResetContent() 清除列表框中的所有项
SelectString() 在单选列表框中搜索并选择一字符串
CListBox指定列表
框中字符串的方法
45
(5) 虚拟方法
CListBox类还声明了几个虚拟方法,你可以
从 CListBox类中派生一些类替换到你的类中。
方法 说明
CharToItem() 可以替换此方法来为自绘列表框(没有字符串)处理 WM-CHAR
CompareItem() 由 MFC调用以得到排序的自绘列表框中的新项的位置
DeleteItem() 当用户从自绘列表框中删除一项时 MFC调用此方法
DrawItem() 当确定自绘列表框项必须重绘时 MFC调用此方法
MeasureItem() 当一自绘列表框被创建时 MFC调用此方法来决定列表框的维数
VKeyToItem() 用户可替换此方法,来处理具有 LBS_WANTKEYBOARDINPUT样式
的列表框的 WM_KEYDOWN
能被替换的
CListBox类
的虚拟方法
46
创建和初始化 CListBox对象
(1)用 C++关键字 new和构造函数为 CListBox对象
分配一个实例,
CListBox::CListBox()
(2) 初始化 CListBox对象并赋于它一个 Windows
列表框,通过方法 CListBox::Create()设置列表框
的参数和样式
47
例如,下面代码分配一个 CListBox对象并返回指向该
对象的指针:
CListBox *pMyListBox=new CListBox;
指针 pMyListBox用 CListBox::Create()方法进行初始化
该方法声明如下:
BOOL Create
( DWORD dwStyle,// 列表框控件的窗口样式
const Recy& rect,// 指明控件的大小和位置
CWnd* pParentWnd,// 指向控件所有者的指针
UINT nID // 控件标识
)
48
9.5.3 列表框和应用程序
之间消息传递
49
1,列表框向应用程序发送消息
当用户与列表框交互时, 列表框向应用程序发出
WM_COMMAND消息 。 该消息字参数的高字节为标
识列表框动作的消息通知码 ( 如 LBN_DBLCLK标识
用户双击 ) ;低字节为控件标识值 。
LBN_SELCHANGE,列表框中的用户选择已发生改变
LBN_DBCLK,双击
LBN_SELCANCLE,列表框中的选择被取消
LBN_SETFOCUS,列表框收到输入焦点
LBN_KILLFOCUS,列表框失去输入焦点
50
2.应用程序向列表框发送消息
应用程序对列表框的操作通过调用函数
SendMessage或 SendDlgItemMessage向其发
送各种消息完成。
下面是常用文件属性值及其说明
数值 ( 16进制 ) 说 明
4000 列出驱动器名
0002 列出隐含文件名
0000 列出普通文件名
0004 列出系统文件名
0001 列出只读文件名
0010 列出上述文件及子目录名
51
9.5.4 列表框应用举例
【 例 9-4】 创建一个单选列表框,并在该列表
框中列出当前目录的文件,双击后删除该项
52
主要步骤如下:
(1)在对话框上放置一个 List Box(IDC_LIST_DIR)
控件和一个 Static(IDC_STATIC_DIR )控件。
List Box控件用于显示文件名称,Static控
件用于显示当前显示的文件所在的目录
(2)为 List Box控件添加 CListBox类型成员变
量 —— m_list
53
(3)在 OnInitDialog函数中添加初始化列表框内容的代码
BOOL CMy9_4Dlg::OnInitDialog()
{ CDialog::OnInitDialog();
// TODO,Add extra initialization here
DWORD cchCurDir = MAX_PATH;
LPTSTR lpszCurDir;
CHAR tchBuffer[MAX_PATH];
lpszCurDir = tchBuffer;
GetCurrentDirectory(cchCurDir,lpszCurDir);
DlgDirList(lpszCurDir,IDC_LIST_DIR,IDC_STATIC_DIR,0);
return TRUE;
}
获得当
前目录
设置列表框显示条目为当前目
录下所有文件名
54
(4)为了实现双击条目删除的功能,需要响应列表框的
LBN_DBLCLK消息
void CMy9_4Dlg::OnDblclkListDir()
{
// TODO,Add your control notification handler code here
int i = m_list.GetCurSel();
CString str;
m_list.GetText(i,str);
m_list.DeleteString(i);
CString msg = "Item "+str+" deleted!";
AfxMessageBox(msg);
}
55
9.6 编辑框控件
编辑框控件看起来是个非常简单的矩形
窗口,但它具有许多功能,编辑框控件可以
自带滚动条,显示多行文本。
CEdit是 CWnd
类直接派生来
的,这就意味
着它具有 CWnd
的所有功能编辑框 控件
单行编辑框控件
多行编辑框控件
56
C E d i t 类的通用方法
方法 说明
CanUndo() 决定一个编辑操作是否可以撤销
Clear() 从编辑控件中删除当前的选择 ( 如果有的话 )
Copy() 将编辑控件当前的选择以 C F _T E X T 格式复制到剪贴板中
Cut() 剪下编辑控件中的当前选择并以 C F _T E X T 格式复制到剪贴板中
EmptyUndoBuffe r() 消除一个编辑控件的“撤销”标志
GetFirs tVisible Line() 确定编辑控件中的最上面的可视行
GetM odify() 确定一个编辑控件的内容是否可修改
Get PasswordChar () 当用户输入文本时,获得编辑控件中显示的密码字符
GetRec t() 获得一个编辑控件的格式化矩形
GetSel () 获得编辑控件中当前选择的开始和结束字符位置
LimitText() 限定用户可能输入一编辑控件的文本长度
LineFromChar() 获得包含指定字符下标的行的行号
LineLength() 获得编辑控件中的一行的长度
LineScroll () 滚动多行编辑控件的文本
Paste () 将剪贴板的数据插入到编辑控件作当前的光标位置,只有当前剪贴板
中数 据格式为 C F _T E X T 时方可插入
Replace Sel() 用指定文本替代编辑控件中当前选择的部分
SetM odify() 设置或清除编辑控件的修改标志
SetPa ssword Char() 当用户输入文本时设置或删除一个显示于编辑控件中的密码字符
SetRea dOnly() 将编辑控件设置为只读状态
SetSe l() 在编辑控件中选择字符的范围
Undo() 取消最后一个编辑控件操作
57
多行编辑所支持的 C E di t 法
方法 说明
Fm tLi nes( ) 设置在多行编辑控件中包含软分行符
G etH and l e() 获得当前分配给一个多行编辑控件的内存的句柄
G etLi ne() 从一编辑控件中获得一行文本
G etLi neC oun t( ) 获得多行编辑控件的行数
L i neInd ex() 设置多行编辑控件中一行的字符下标
SetH and l e() 设置多行编辑控件将要用到的句柄内存句柄
SetR ect( ) 设置多行编辑控件的格式化矩形并更新控件
SetR ectN P() 设置多行编辑控件的格式 化矩形并且不重绘控件窗口
SetT abS tops () 在多行编辑控件中设置制表 (t ab) 位
58
9.6.2 编辑框与应用程序间的消
息传递
编辑框通过向其父窗口发关 WM_COMMAND
消息通知应用程序用户的交互信息
应用程序对编辑框的操作通过调用函数
SendMessage或 SendDlgItemMessage
59
9.6.3 编辑类编程实例
单击 Showl,则在 Edit1编辑框中显示,This is the first EditBox.”
?单击 Clear1,则 Edit1编辑框中的内容被清除;
?单击 Show2,则在 Edit2编辑框中显示,This is the second
EditBox!”
?单击 Clear2,则 Edit2编辑框中的内容被清除;
?单击 Transfer,则把 Edit1编辑框的内容复制到 Edit2的编辑框中去
?单击 Undo,则取消上一次操作
?若单击 Exit,则退出程序的运行
60
具体的编程过程
生成了工程文件和
工程工作区文件后
在 EditBox的工作区
中选择 ResourceView
因为本应用程序是基于对话框的,由
向导生成对话框窗口作为应用程序的
主窗口,并且给这个对话框取名为
IDD_EDITBOX_DIALOG,然后 在这个对
话框窗口中进行 界面设计
61
( 1)创建资源,在 ResourceView选项卡中打开 Dialog资
源组,然后双击 IDD_EDITBOX_DIALOG。 VC在工作台中
显示可以进行可视化编辑的 IDD_EDITBOX_DIALOG对话框
把鼠标停在编辑框
控件上,即可显示
该控件的类型
控件工具窗提供
了 VC中所有可建
立的控件类型
62
(2)设置控件 ID
对 象 ID C a pt i o n
编辑框 IDC _EDIT1 无
编辑框 I D C_ E D I T 2 无
命令按钮 IDC _ S H O W 1 _B U T T O N Sh o wl
命令按钮 IDC _ C L E A R 1_ B U T T O N C l ea r l
命令按钮 I D C_ S H O W 2 _B U T T O N S h ow 2
命令按钮 I D C_ C L E A R 2_ B U T T O N C l ea r 2
命令按钮 I D C_ T r a n s fe r _ B U T TO N T r an s f e r
命令按钮 I D C_ EXIT _ BU T T O N & E xi t
命令按钮 I D C_ U N D O _ BU T T O N & U nd o
将鼠标移到 Edit1控键上
--> 单击鼠标右键,选
择 Properties命令,在窗
口中输入控件的 ID标识
值,IDC_EDIT1,用同
样的方法设置其它各个
对象的属性
63
(3) 应用程序的代码编程部分
(a) 给编辑框连接变量
选择 Member
Variables选项卡
在 Control IDs
列表框中单击
IDC_EDIT1
项,使之高亮化
单击 Add Variable
按钮,此时显示
Add Member
Variable窗口
64
(b) 设置成员变量名为 m_Edit1,类别为 Control,变量
类型为 CEdit
注意,不要将 m_Edit1设
为 CString类型,因为只
有设为 CEdit 类型,才
能够调用 CEdit 类中的
一些成员函数,如 Copy,
Paste等,这样才能完成
本应用程序中对 Transfer
按钮要求复制内容的操
作的响应
?
65
用同样的方法给编辑框 EDIT2等其它对象连接各自的变
量,增加变量之后 MFC ClassWizard窗口将变为下图所示
66
若此时运行该程序,在 Edit文本框中
不能进行多行输入,只能单行输入文本,
而且按回车键终止应用程序,同时,文本
框中也没有水平和垂直滚动条。
下面,我们来完善应用程序中编辑框的
特性,使之能够进行多行文本的输入
67
可进行多行输入 增加水平及垂直滚动条
若不选择此项,在编辑框
中按回车键就会终止应用
程序,若选此项,按回车
键就可进行下一行的输入,
实现多行文本的输入
(c) 修改编辑框的特性
68
(4) 添加代码
void CMy9_5Dlg::OnShow1Button()
{
m_Edit1.SetSel(0,-1); // 选中编辑框 IDC_EDIT1中的全部内容
m_Edit1.ReplaceSel("This is the first EditBox.");
}
程序中 SetSel()函数是 CEdit类中的成员函数,因为
m_Edit1是属于 CEdit类的对象,故可以调用该类所有的
成员函数。 ReplaceSel() 函数也是 CEdit类中成员函数。
(a) 给 Showl按钮连接代码
69
(2) 给 Clear1按钮连接代码
void CMy9_5Dlg::OnClear1Button()
{
m_Edit1.SetSel(0,-1); //选中 IDC_EDIT1中的内容
m_Edit1.ReplaceSel("");
//用空串代替所选文本,即把所选的文本删除
}
70
void CMy9_5Dlg::OnShow2Button()
{
m_Edit2.SetSel(0,-1);
m_Edit2.ReplaceSel("This is the second EditBox.");
}
void CMy9_5Dlg::OnClear2Button()
{
m_Edit2.SetSel(0,-1);
m_Edit2.ReplaceSel("");
}
(3) 给 Show2和 Clear2按钮连接代码
71
(4) 给按钮 IDC_Transfer_BUTTON连接代码
void CMy9_5Dlg::OnTransferButton()
{
m_Edit1.SetSel(0,-1);
m_Edit1.Copy();
m_Edit2.SetSel(0,-1);
m_Edit2.ReplaceSel("");
m_Edit2.Paste();
}
72
(5)给 Undo按钮连接代码
void CMy9_5Dlg::OnUndoButton()
{ m_Edit1.Undo();
m_Edit2.Undo();
}
(6)给 Exit按钮连接代码
void CMy9_5Dlg::OnExitButton()
{
OnOK();
}
73
【 例 9-6】,乘法器”
示例程序,使用者
在“乘数”或者
“被乘数”编辑框
中输入数字的时候,
程序可以随时计算
乘法的结果
ID Type Member Read-only Number
IDC_EDIT_MUL1 int m_A √
IDC_EDIT_MUL2 int m_B √
IDC_EDIT_RESULT CStringm_Result √ √
74
(1) 初始化结果编辑框
BOOL CMy9_6Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
……
// TODO,Add extra initialization here
UpdateData(TRUE);
int i=m_A*m_B;
m_Result.Format("%d",i);
UpdateData(FALSE);
return TRUE;
}
75
(2)当编辑框中的内容发生改变时,会产生 EN_CHANGE
消息,需要为乘数与被乘数两个编辑框响应该消息
void CMy9_6Dlg::OnChangeEditMul1( )
{ UpdateData(TRUE);
int i=m_A*m_B;
m_Result.Format("%d",i);
UpdateData(FALSE);
}
void CMy9_6Dlg::OnChangeEditMul2( )
{ UpdateData(TRUE);
int i=m_A*m_B;
m_Result.Format("%d",i);
UpdateData(FALSE);
}
76
(3) 响应 Reset按钮的消息
void CMy9_6Dlg::OnReset()
{ m_A = 0;
m_B = 0;
int i=m_A*m_B;
m_Result.Format("%d",i);
UpdateData(FALSE);
}
77
9.7 组合框控件
78
9.7.1 组合框 (CComboBox)类的
结构及组合框的特点
组合框是两种预定义窗口的组合形式。
在 Windows编程中使用单一控件
往往不能完全满足与用户交互的需要,
最常见的组合框例子是对话框及与其
相联系的静态文本和编辑框。
79
9.7.2 组合框与应用程序间消息
传递
组合框通过向其父窗口发关 WM_COMMAND
消息通知应用程序用户的交互信息。
应用程序对组合框的操作也通过使用函数
SendMessage或 SendDlgItemMessage向组合框
发送消息进行。由于对组合框的操作实际上是
对组合框中各成员的操作。
80
9.7.3 组合框控件应用举例
【 例 9-7】 本例创建组合框控件,当单击向下
按钮时,显示可选文件的名字。当选中某一
项时,显示该项的名称
81
将一个 Combo Box控件放到对话框上。 取消 Sort风
格 。否则插入的内容将按照字母顺序排序,而不是
插入的顺序排序。添加 CComboBox类型的变量 m_cb
BOOL CMy9_7Dlg::OnInitDialog() //初始化对话框
{ CDialog::OnInitDialog();
……
// TODO,Add extra initialization here
m_cb.AddString("Monday");
m_cb.AddString("Tuesday");
m_cb.AddString("Wednesday");
m_cb.AddString("Thursday");
m_cb.AddString("Friday");
m_cb.AddString("Saturday");
m_cb.AddString("Sunday");
return TRUE;
}
82
当用户选择的内容发生改变的时候, 会产
生 CBN_SELCHANGE消息 。 为控件添加该
消息的响应函数:
void CMy9_7Dlg::OnSelchangeCombo()
{
CString msg;
m_cb.GetLBText(m_cb.GetCurSel(),msg);
AfxMessageBox(msg);
}
83
【 例 9-8】 本程序为几种控件的综合应用
84
在设计的过程中,同一组
单选按钮必须一个接一
个地放进对话框中,中
间不能插入其它的控件
对于成组的单选按
钮,只在每组的第
一个按钮的属性中
选中 Group设置
在 Sex Selecting
组中只有 Boy单
选按钮选中
Group属性
在 Age Range组中只
有,>20”单选按钮
选中 Group属性
85
Visual C++按照放入对话框中的先后顺序,给每个控件赋一
个 ID值,所以控件的 ID值是连续的。 Group属性的控件之间
的控件为一组。
可以从 resource.h的资源头文件中得到 ID值
#define IDC_SHOW_BUTTON 1006
#define IDC_HIDE_BUTTON 1007
#define IDC_Boy_RADIO 1008
#define IDC_Girl_RADIO 1009
#define IDC_Age1_RADIO 1010
#define IDC_Age2_RADIO 1011
#define IDC_Age3_RADIO 1012
#define IDC_Show_Sex_Age_BUTTON 1013
#define IDC_Result_EDIT 1014
86
在为相关控件连接变量和方法后,开始编程
(1) 给复选框 IDC_DATE_CHECK添加代码
OnDateCheck()方法的实现代码如下:
void CMy9_8Dlg::OnDataCheck()
{ UpdateData(TRUE);
if(m_DateCheck==TRUE)
{ CTime tNow ;
tNow=CTime::GetCurrentTime();
CString sNow=tNow.Format("%y.%m.%d");
m_DateEdit.SetSel(0,-1);
m_DateEdit.ReplaceSel(sNow);
}
else
{ m_DateEdit.SetSel(0,-1);
m_DateEdit.ReplaceSel("");
}
UpdateData(FALSE);
}
以当前的屏幕
显示内容更新
控件的变量
87
(2)为复选框 IDC_TIME_CHECK添加代码
void CMy9_8Dlg::OnTimeCheck()
{ UpdateData(TRUE);
if(m_TimeCheck==TRUE)
{ CTime tNow;
tNow=CTime::GetCurrentTime();
CString sNow=tNow.Format("%I:%M:%S");
m_TimeEdit.SetSel(0,-1);
m_TimeEdit.ReplaceSel(sNow);
}
else
{ m_TimeEdit.SetSel(0,-1);
m_TimeEdit.ReplaceSel("");
}
UpdateData(FALSE);
}
函数 Format的参
数 %I是时间的小
时表示法( 01~
12),%m是分的
表示法( 00~
59),%d是秒的
表示法( 00~ 59)
88
(3) 给 Enable按钮添加代码
void CMy9_8Dlg::OnEnableButton()
{
GetDlgItem(IDC_DATE_CHECK)->EnableWindow(TRUE);
GetDlgItem(IDC_TIME_CHECK)->EnableWindow(TRUE);
m_DateEdit.EnableWindow(TRUE);
m_TimeEdit.EnableWindow(TRUE);
}
89
(4) 为 Disable按钮连接代码
void CMy9_8Dlg::OnDisableButton()
{
GetDlgItem(IDC_DATE_CHECK)->EnableWindow(FALSE);
GetDlgItem(IDC_TIME_CHECK)->EnableWindow(FALSE);
m_DateEdit.EnableWindow(FALSE);
m_TimeEdit.EnableWindow(FALSE);
}
90
(5) 为 Show Again按钮添加代码
void CMy9_8Dlg::OnShowButton()
{
GetDlgItem(IDC_DATE_CHECK)->EnableWindow(SW_SHOW);
GetDlgItem(IDC_TIME_CHECK)->EnableWindow(SW_SHOW);
GetDlgItem(IDC_DATE_EDIT)->EnableWindow(SW_SHOW);
m_DateEdit.ShowWindow(SW_SHOW);
GetDlgItem(IDC_TIME_EDIT)->EnableWindow(SW_SHOW);
m_TimeEdit.ShowWindow(SW_SHOW);
}
91
(6) 为 Hide the Clock Setting按钮添加实现代码
void CMy9_8Dlg::OnHideButton()
{
GetDlgItem(IDC_DATE_CHECK)->EnableWindow(SW_HIDE);
GetDlgItem(IDC_TIME_CHECK)->EnableWindow(SW_HIDE);
m_DateEdit.ShowWindow(SW_HIDE);
m_TimeEdit.ShowWindow(SW_HIDE);
}
92
(7) 给 Show_the_Sex_and_Age按钮添加代码
void CMy9_8Dlg::OnShowSexAgeBUTTON()
{ char sEdit[50]; int iSexRADIO; int iAgeRADIO;
iSexRADIO=GetCheckedRadioButton(IDC_Boy_RADIO,IDC_Girl_RADIO);
if(iSexRADIO==IDC_Boy_RADIO)
strcpy(sEdit,"The boy's age is");
if(iSexRADIO==IDC_Girl_RADIO)
strcpy(sEdit,"The girl's age is");
iAgeRADIO=GetCheckedRadioButton(IDC_Age1_RADIO,IDC_Age3_RADIO);
if(iAgeRADIO==IDC_Age1_RADIO)
strcat(sEdit," great than 20");
if(iAgeRADIO==IDC_Age2_RADIO)
strcat(sEdit," between 15 and 20");
if(iAgeRADIO==IDC_Age3_RADIO)
strcat(sEdit," less than 15");
m_ResultEdit.SetSel(0,-1); m_ResultEdit.ReplaceSel(sEdit);
}
93
(8) 为 Show_Combo按钮添加代码
void CMy9_8Dlg::OnShowComboButton()
{ UpdateData(TRUE); char sCourseEdit[30];
char sRecordEdit[15]; int iCourseRadio;
iCourseRadio=GetCheckedRadioButton(IDC_ENGLISH_RADIO,IDC_NATURE_RADIO);
if(iCourseRadio==IDC_ENGLISH_RADIO)
strcpy(sCourseEdit,"English record is ");
if(iCourseRadio==IDC_COMPUTER_RADIO)
strcpy(sCourseEdit,"Computer record is ");
if(iCourseRadio==IDC_NATURE_RADIO)
strcpy(sCourseEdit,"Natural record is ");
m_Record.GetWindowText(sRecordEdit,15);
strcat(sCourseEdit,"");
strcat(sCourseEdit,sRecordEdit);
m_ComboEdit=_T(sCourseEdit); UpdateData(FALSE);
}
94
(9) 给 OnExitButton()方法添加代码
void CMy9_8Dlg::OnExitButton()
{
OnOK();
}
95
初始化单选按钮
BOOL CMy9_8Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
……
// TODO,Add extra initialization here
CheckRadioButton(IDC_Boy_RADIO,IDC_Girl_RADIO,IDC_Boy_RADIO);
CheckRadioButton(IDC_Age1_RADIO,IDC_Age3_RADIO,IDC_Age2_RADIO);
UpdateData(FALSE);
m_English=0;
m_Record.AddString("85");
m_Record.AddString("90");
m_Record.AddString("95");
m_Record.SelectString(-1,"95");
UpdateData(FALSE);
return TRUE;
}
96
9.8 对话框通用控件
大部分控件都是在对话框中使用的,
无论是基于对话框的应用程序还是
Doc/View结构的应用程序,控件通常是
放在对话框中的。本节将以一个名为
,Ctrl”的基于对话框的应用程序来介绍
各种 Windows通用控件的使用。
97
9.8.1 Picture控件的使用
(1)分隔线
将 Picture控件拖放
到对话框上,
【 Type】 属性选择
,Frame”,【 Color】
属性选择, Etched”,
将控件拖到最细,
这时,Picture控件
看起来的效果就跟
一条分隔线一样了
98
(2) 图片
将 【 Type】 属性设置为
,Icon”或者,Bitmap”的
时候,可以设置
【 Image】 属性为相应
的资源 ID,来显示图标
或位图。我们在资源中
导入一位图,命名为 IDB_BITMAP_DOT,设置 Picture控件 【 Type】
为,Bitmap”,【 Image】 为,IDB_BITMAP_DOT”
99
9.8.2 Spin控件的使用
Spin按钮控件提供了一
对箭头,用户通过点
击箭头可以微调该控
件所表示的数值。
表示 Spin控件的是
CSpinButtonCtrl类
Spin控件通常和 tab
order位于它之前的
控件成对使用。通
过 CSpinButtonCtrl的
GetBuddy方法可获
得与之配对的控件
100
向对话框拖放一个 Edit控件,置为只读,然后拖放一
个 Spin控件紧挨着刚才拖放的 Edit控件,两个控件的
ID都是用默认值,设置 Spin控件的 【 Allignment】 属
性为,Right”,选中 【 Auto buddy】 属性
BOOL CEx9_9Dlg::OnInitDialog()
{ ……
// TODO,Add extra initialization here
CSpinButtonCtrl* pSpin =(CSpinButtonCtrl*) GetDlgItem(IDC_SPIN1);
pSpin->SetRange(0,100);
pSpin->SetPos(50);
pSpin->GetBuddy()->SetWindowText("5.0");
return TRUE; }
设置 Spin的范围是 0~ 100,当
前位置是 50,同时设置它的
配对控件的显示值
101
在对话框中添加 WM_VSCROLL消息的响应:
void CEx9_9Dlg::OnVScroll(……)
{ if (pScrollBar->GetDlgCtrlID() == IDC_SPIN1)
{CString strValue;
strValue.Format("%3.1f",(double) nPos / 10.0);
((CSpinButtonCtrl*)pScrollBar)->GetBuddy()->SetWindowText(strValue);
}
CDialog::OnVScroll(nSBCode,nPos,pScrollBar);
}
102
9.8.3 Progress控件的使用
进度控件是一个用
来指示长时间操作
的进展程度的控件 。
MFC中表示进度控制
的是 CProgressCtrl类
进度条有一个 范围 和 当前位置 。 范围表示整个
操作的持续时间, 当前位置表示当前进行到的
位置,进度条根据当前位置来判断进行的百分
比,来显示进度
103
添加一个 Progress控件,保持默认 ID,设置
Smooth属性。在旁边添加一个按钮,设置 ID
为,IDC_BUTTON_START”,Caption为“开始”
在 OnInitDialog中添加如下代码:
CProgressCtrl* pProg =(CProgressCtrl*) GetDlgItem(IDC_PROGRESS1);
pProg->SetRange(0,100);
pProg->SetPos(50);
为“开始”按钮添加点击事件实现代码:
void CEx9_9Dlg::OnButtonStar()
{CProgressCtrl* pProg=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
pProg->SetPos(0);
SetTimer(1000,100,NULL);
}
104
在 CCtrlDlg中添加对 WM_TIMER消息的响应函数:
void CEx9_9Dlg::OnTimer(UINT nIDEvent)
{ if(nIDEvent == 1000)
{ CProgressCtrl* pProg = (CProgressCtrl*)
GetDlgItem(IDC_PROGRESS1);
pProg->SetPos(pProg->GetPos()+1);
if(pProg->GetPos() >= 100)
{
KillTimer(nIDEvent);
AfxMessageBox("进行完毕 ");
}
}
CDialog::OnTimer(nIDEvent);
}
每隔 0.1秒,
进度条前
进一步
105
9.8.4 Slider控件的使用
滑块控件可以使用户通过拖动滑块来
快速获得指定的数据 。 当用户滑动滑块的
时候, 控件将发送消息来指示变化 。
滑块控件在你
选择一系列离散
值或者一段连续
范围内的时候十
分有用。
106
在对话框上增加一个 Slider控件,设置 Point
属性为,Bottom/Right”,然后在旁边添加一
个 Static控件,ID设置为 IDC_STATIC_SLIDER。
该控件用来显示滑块的当前位置。
在 OnInitDialog函数中添加如下代码:
CString strText1;
CSliderCtrl* pSlide1 =(CSliderCtrl*) GetDlgItem(IDC_SLIDER1);
pSlide1->SetRange(0,100);
pSlide1->SetPos(50);
strText1.Format("%d",pSlide1->GetPos());
SetDlgItemText(IDC_STATIC_SLIDER,strText1);
107
为了响应滑块移动的消息, 添加 WM_HSCROLL消
息的响应 ( Slider是水平的, 如果是垂直的, 则需
要响应 WM_VSCROLL) 。 实现如下:
void CEx9_9Dlg::OnHScroll(……)
{
if(pScrollBar->GetDlgCtrlID() == IDC_SLIDER1)
{
CSliderCtrl* pSlide = (CSliderCtrl*) pScrollBar;
CString strText;
strText.Format("%d",pSlide->GetPos());
SetDlgItemText(IDC_STATIC_SLIDER,strText);
}
CDialog::OnHScroll(nSBCode,nPos,pScrollBar);
}
108
9.8.5 Date Time Picker控件的使用
Date Timer Picker可以用来接收日期或者
时间输入。用户可以直接按照指定的形
式输入,也可以在弹出的日历控件中选
择日期。
如果让用户以
字符串形式输
入,则由于输
入的多样性,
程序不好解析
109
在对话框上添加一个 Date Time Picker控件,
设置 Format为,Short Date”,选择,Use Spin
Control”,如果不选择使用 Spin控件,则用户
在弹出的日历控件中进行输入。在该控件旁
边添加一个按钮,ID为,IDC_BUTTON_TIME”,
Caption为“报时”。
在 OnInitDialog中添加如下代码:
CDateTimeCtrl* pDT =
(CDateTimeCtrl*) GetDlgItem(IDC_DATETIMEPICKER1);
CString formatStr= _T("'今天是, 'yy'/'MM'/'dd");
pDT->SetFormat(formatStr);
110
添加对 【 报时 】 按钮的点击事件的响应函数:
void CEx9_9Dlg::OnButtonTime()
{
CDateTimeCtrl* pDT =(CDateTimeCtrl*)
GetDlgItem(IDC_DATETIMEPICKER1);
CTime t;
pDT->GetTime(t);
CString s = t.Format( "%A,%B %d,%Y %H:%M:%S" );
AfxMessageBox(s);
}
111
9.8.6 List Control控件的使用
列表控件
112
列表控件是 Windows应用程序中最常用的
控件之一。最常见的用途就是资源管理
器右边的文件列表。
MFC中使用 CListCtrl类来封装列表控件
的功能。
列表控件通常可以包括一个图标和一
个标签。此外,每一项还可以具有其它附
加信息,例如资源管理器中文件的具体信
息就是附加信息。
113
列表控
件的视
图风格
图标视图,每项显示 32× 32图标,在
图标下面显示标签。用户可以将图标
拖放到视图内任何位置
小图标视图,每项显示 16× 16图标,
在图标右边显示标签。用户可以将
图标拖放到视图内任何位置
列表视图,每项显示 16× 16图标,
在图标右边显示标签。每一项按列
排列,不能随意拖动图标
报表视图,每项占一行,第一列是
主项,显示 16× 16图标,在图标右
侧显示标签。右边的列显示子项,
具体由程序来决定
114
为使用列表控件,首先需要创建图标资源,在
ResourceView的 Icon一栏内创建 8个图标资源
在 Cex9_9Dlg类中增加成员如下:
CImageList m_imageList;
在 OnInitDialog函数中添加初始化图片列表的代码:
HICON hIcon[8]; int n;
m_imageList.Create(16,16,0,8,8);
hIcon[0] = AfxGetApp()->LoadIcon(IDI_ICON_WHITE);
hIcon[1] = AfxGetApp()->LoadIcon(IDI_ICON_BLACK);
hIcon[2] = AfxGetApp()->LoadIcon(IDI_ICON_RED);
hIcon[3] = AfxGetApp()->LoadIcon(IDI_ICON_BLUE);
hIcon[4] = AfxGetApp()->LoadIcon(IDI_ICON_YELLOW);
hIcon[5] = AfxGetApp()->LoadIcon(IDI_ICON_CYAN);
hIcon[6] = AfxGetApp()->LoadIcon(IDI_ICON_PURPLE);
hIcon[7] = AfxGetApp()->LoadIcon(IDI_ICON_GREEN);
for (n = 0; n < 8; n++)
m_imageList.Add(hIcon[n]);
115
创建标签资源, 也就是每一项的文字, 在
OnInitDialog函数中添加如下实现代码:
static char* color[] = {"white","black","red","blue",
"yellow","cyan","purple","green"};
有了这些资源,就可以创建列表控件了。
在对话框上添加一个 List Control,其 ID为 IDC_LIST1,
在样式中选择视图风格为 List,并选择 Edit lables选项。
视图风格为列表风格,也就是图标按列排列。设置
【 Edit lables】 属性,允许用于可编辑标签。
116
为了创建控件, 首先在 OnInitDialog中添加如下代码:
CListCtrl* pList = (CListCtrl*) GetDlgItem(IDC_LIST1);
// 获得控件对象
pList->SetImageList(&m_imageList,LVSIL_SMALL);
// 设置小图标图片列表
for (n = 0; n < 8; n++)
{ // 第一个参数为项 id,第二个为 标签文字,第三个为
对应图片列表 id
pList->InsertItem(n,color[n],n);
}
pList->SetBkColor(RGB(0,255,255)); // 设置背景色
pList->SetTextBkColor(RGB(255,0,255));
//设置文字的背景色
现在编译运行已经可以看到列表的运行效果了。
117
在列表控件下添加 static控件, ID为 IDC_STATIC_LIST。
对列表控件添加对 LVN_ITEMCHANGED消息的响应:
void CEx9_9Dlg::OnItemchangedList1(……)
{ NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO,Add your control notification handler code here
CListCtrl* pList = (CListCtrl*) GetDlgItem(IDC_LIST1);
int nSelected = pNMListView->iItem;
if (nSelected >= 0)
{ CString strItem = pList->GetItemText(nSelected,0);
SetDlgItemText(IDC_STATIC_LIST,strItem);
}
*pResult = 0;
}
118
在设置控件属性时, 设置了 Edit labels属性, 下面是
对列表控件的 NM_RCLICK消息的响应:
void CEx9_9Dlg::OnRclickList1(……)
{
// TODO,Add your control notification handler code here
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
CListCtrl* pList = (CListCtrl*) GetDlgItem(IDC_LIST1);
int nSelected = pNMListView->iItem;
if (nSelected >= 0)
pList->EditLabel(nSelected);
*pResult = 0;
}
119
运行程序, 右击某一项, 已可以编辑标签了, 但无
法保存编辑效果 。 若要保存, 需要响应列表控件的
LVN_ENDLABELEDIT消息, 在这里可以判断新输入的
文字是否合法, 然后设置标签为编辑得到的文字:
void CEx9_9Dlg::OnEndlabeleditList1(……)
{ LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO,Add your control notification handler code here
LVITEMA item = pDispInfo->item;
CString str =item.pszText; str.TrimLeft();
str.TrimRight();
if(str.GetLength() > 0)
{ CListCtrl* pList = (CListCtrl*) GetDlgItem(IDC_LIST1);
pList->SetItemText(item.iItem,item.iSubItem,item.pszText);
}
*pResult = 0;
}
120
9.8.7 Tree Control控件的使用
树状视图控件是一种用来显示层次结构的控
件,例如 Windows资源管理器左边的视图。视
图中的每一项包
括一个标签,位
图是可选的,每
项还可以附加若
干子项。点击每
一项,可展开或
合拢当前树节点
121
本例中继续使用 List Control中的图标。接下来在对
话框中添加树状控件,其 ID为 IDC_TREE1,选中 Has
buttons,Has lines,Lines at root和 Edit labels属性
Has buttons:决定可展开项之前是否有, +”,,-, 按钮
Has Lines:决定相关节点之间是否显示虚线连接
Lines at root:决定位于第一层的节点之间是否有虚线连接
Edit labels,表示标签是否可编辑
122
然后在 OnInitDialog函数中添加如下代码:
CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_TREE1);
pTree->SetImageList(&m_imageList,TVSIL_NORMAL); // 设置图片列表
TV_INSERTSTRUCT tvinsert; //创建待插入的 TV_INSERTSTRUCT结构
tvinsert.hParent = NULL; // 无父结点
tvinsert.hInsertAfter = TVI_LAST; // 插入到本层最后
tvinsert.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE| TVIF_TEXT;
//掩码,图标 /选中图标 /文字
tvinsert.item.hItem = NULL; // 句柄为空
tvinsert.item.state = 0; // 状态
tvinsert.item.stateMask = 0; // 状态掩码,不使用这两项
tvinsert.item.cchTextMax = 6; // 最大文字长度,忽略
tvinsert.item.iSelectedImage = 1; // 选中图标索引
tvinsert.item.cChildren = 0; // 没有子节点
tvinsert.item.lParam = 0; // 自定义数据
123
// 创建第一层
tvinsert.item.iImage = 2; // 一般图标
tvinsert.item.pszText = "father"; // 插入第一层第一个节点
HTREEITEM hDad = pTree ->InsertItem(&tvinsert);
tvinsert.item.pszText = "mother"; // 插入第一层第二个节点
HTREEITEM hMom = pTree->InsertItem(&tvinsert);
// 创建第二层
tvinsert.hParent = hDad; // 父节点为 "father"
tvinsert.item.iImage = 3; // 一般图标
tvinsert.item.pszText = "son"; // 插入第二层 "father"的第一个节点
pTree->InsertItem(&tvinsert);
tvinsert.item.pszText = "daughter"; // 插入第二层的第二个节点
pTree->InsertItem(&tvinsert);
tvinsert.hParent = hMom; // 父结点为 "mother"
tvinsert.item.iImage = 4;
124
tvinsert.item.pszText = "son"; // 插入第二层的第一个节点
pTree->InsertItem(&tvinsert);
tvinsert.item.pszText = "daughter"; // 插入第二层的第二个节点
pTree->InsertItem(&tvinsert);
tvinsert.item.pszText = "cartoon"; // 插入第二层的第三个节点
HTREEITEM hOther = pTree->InsertItem(&tvinsert);
// 创建第三层
tvinsert.hParent = hOther; // 父结点为 "cartoon"
tvinsert.item.iImage = 7;
tvinsert.item.pszText = "Tom"; // 插入第三层的第一个节点 Tom
pTree->InsertItem(&tvinsert);
tvinsert.item.pszText = "Jerry"; // 插入第三层的第二个节点 Jerry
pTree->InsertItem(&tvinsert);
125
理解上述代码的关键在于理解关键函数
InsertItem和 TV_INSERTSTRUCT 和 TV_ITEM
数据结构 。
InsertItem的函数执行的功能是向树状控
件中插入一项,至于这一项什么样子,
要插入到什么位置,全部由 InsertItem的
TV_INSERTSTRUCT类型的参数来描述,
126
下面通过添加一些对树状控件常用消息的响应来说
明树状控件的一般使用方法 。 首先在树状控件旁边
添加一个 static控件, ID设置为 IDC_STATIC_TREE。 为
树状控件添加对 TVN_SELCHANGED消息的响应:
void CEx9_9Dlg::OnSelchangedTree1(……)
{ NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO,Add your control notification handler code here
CTreeCtrl* pTree =(CTreeCtrl*) GetDlgItem(IDC_TREE1);
HTREEITEM hSelected = pNMTreeView->itemNew.hItem;
if (hSelected != NULL)
{ char text[31]; TV_ITEM item;
item.mask = TVIF_HANDLE | TVIF_TEXT;
item.hItem = hSelected;
item.pszText = text; item.cchTextMax = 30;
VERIFY(pTree->GetItem(&item));
SetDlgItemText(IDC_STATIC_TREE,text);
}
*pResult = 0;
}
127
在向对话框添加控件时,设置了 Edit labels属性,使得树状控
件可编辑,双击节点文字便进入编辑状态,响应编辑状态结束
消息呢的方法与响应列表控件的编辑结束消息完全一样。对
TVN_ENDLABELEDIT消息的响应函数,实现如下:
void CEx9_9Dlg::OnEndlabeleditTree1(…… )
{ TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
//TODO:Add your control notification handler code here
TVITEMA item = pTVDispInfo->item;
CString str =item.pszText;
str.TrimLeft();
str.TrimRight();
if(str.GetLength() > 0)
{ CTreeCtrl* pTree =(CTreeCtrl*) GetDlgItem(IDC_TREE1);
pTree->SetItemText(item.hItem,item.pszText);
}
*pResult = 0;
}
128
129
9.8.8 Extended Combo Box控件的使用
扩展的复合框继承自普通的复合框 。
MFC提供了 CComboBoxEx来实现扩展
复合框的功能。使用扩展的复合框,
你不再需要自己实现在复合框中绘
制图片的功能了。使用扩展的复合
框可以通过图象列表来访问图象
130
向对话框添加扩展对话框控件,ID为 IDC_COMBOBOXEX1,类型
(Type)为 Dropdown。 在 OnInitDialog函数中添加如下代码:
CComboBoxEx * pComboEx=(CComboBoxEx *)GetDlgItem(IDC_COMBOBOXEX1);
pComboEx->SetImageList(&m_imageList);
COMBOBOXEXITEM comboItem;
comboItem.mask = CBEIF_IMAGE | CBEIF_INDENT |
CBEIF_SELECTEDIMAGE | CBEIF_TEXT ;
for(int i=0; i<3; i++)
{
comboItem.iItem = i;
comboItem.iImage = i;
comboItem.iSelectedImage = i;
comboItem.iIndent = i;
comboItem.pszText = color[i];
pComboEx->InsertItem(&comboItem);
}
131