MFC与界面应用程序

目录

一、MFC简介... 4

1.MFC的组织结构... 4

(1)根类... 4

(2)应用程序体系结构类... 4

(3)可视对象类... 6

(4)通用类... 7

(5)OLE类... 8

(6)ODBC数据库类... 8

2.全局变量和函数... 9

3应用程序向导Wizard. 9

二、windows标准控件... 9

1.按钮... 9

(1)创建按钮... 10

(2)和按钮有关的消息... 10

(3)可能用到的成员函数... 11

2.滚动条... 11

(1)创建滚动条... 11

(2)和滚动条有关的消息... 12

(3)可能用到的方法... 12

3.静态控件... 13

(1)创建方法... 13

(2)和该控件有关的消息... 13

(3)可能用到的函数... 13

4.列表框... 13

(1)创建列表框... 13

(2)和列表框有关的消息... 14

(3)可能用到的函数... 15

5.编辑框... 17

(1)Cedit的样式... 17

(2)和编辑框有关的消息... 17

(3)可能用到的函数... 18

6.组合框... 19

(1)组合框的样式... 20

(2)和组合框有关的消息... 20

7.对话框通用控件... 22

(1)Picture. 22

(2)Spin. 22

(3)Progress 23

(5)Date Time Picker 25

(6)List Control 25

(7)Tree Control 28

(8)Extended Combo Box. 33

三、资源... 35

1.菜单... 35

(1)程序主菜单... 35

(2)快捷菜单... 37

(3)工具栏菜单... 39

2.加速键... 42

3.字符串... 42

4.对话框... 42

(1)CDialog可能用到的函数... 43

(2)在资源视图中插入新的Dialog,编辑需要的控件... 43

(3)为这个对话框建立关联的类... 43

(4)在对话框类中为需要的控件添加需要的数据变量... 43

(5)在需要的源文件中使用这个对话框类... 43

5.图标... 44

6.位图... 44

四、单文档SDI和多文档MDI界面... 44

1.可能用到的概念... 45

2.消息映射... 46

3.核心类... 47

(1)CWinApp. 47

(2)CDocument 48

(3)CView.. 50

(4)CDocTemplate. 50

(5)CFrameWnd. 51

(6)5个核心类的相互访问... 52

4.在程序向导上创建SDI和MDI程序... 53

(1)SDI 53

(2)MDI 53

5.MFC多线程... 56

五、数据库... 57

1.有关数据库的基础知识... 57

(1)CRecordView.. 57

(2)CRecordSet 57

(3)CDatabase. 59

(4)RFX.. 60

(5)CDBException. 60

2.建立ODBC数据源... 60

3.显示数据库中的数据... 60

4.对记录进行排序... 61

5.增添记录... 62

6.删除记录... 63

7.查询记录... 65

8.修改记录... 66

9.移动到指定的位置... 67

六、多媒体... 68

1.音频播放... 68

(1)使用音频函数的方式... 68

(2)使用MCI的方式... 69

2.视频播放... 77

3.图片显示... 78

(1) 创建SDI工程... 78

(2) 在View类中添加数据成员:... 78

(3) 新数据成员的初始化和销毁:... 78

(4) 通过菜单项打开文件:... 79

(5) 对图片进行绘制:... 81

七、网络编程... 83

1.利用WinInet抓取网页... 83

八、附录... 85

1.Visual Studio 2008的快捷键... 85

正文

一、MFC简介

MFC即Microsoft Foundation Class,封装了很多windows api和windows控件,可以明显的缩短程序设计的周期(填充框架、添加功能即可)

1.MFC的组织结构

按照结构和功能上分类

(1)根类

CObject是MFC中大多数类的基类,这个类有序列化、查询对象运行时信息等功能,序列化是指将对象的数据存储下来;更详细的资料需要查看MSDN文档

Serialize()

 

IsSerializable()

 

IsKindof()

是否是某个类或者派生类

GetRuntimeClass()

包括它的类名、基类名等信息

(2)应用程序体系结构类

CWinApp和程序的结构框架有关,基于MFC的应用程序几乎从它派生而来

①CCmdTarget

功能上是消息映射,当对象收到消息后决定应该调用哪一个函数,其他和CCmdTarget有关的类:窗口类CWnd、文档模板类CDocTemplate、文档类CDocument、视类CView、框架窗口类CFrameWnd

②CWinThread

创建和控制线程

CreateThread()

 

SetThreadPriority()

 

SuspendThread()

 

③CWinApp

即应用程序对象,继承自CWinThread、CWinThread又继承自CCmdTarget、CCmdTarget继承自CObject,CWinApp的对象在每个应用程序中都是唯一的

部分数据成员

m_pszAppName

应用程序的名称

m_hInstance

当前应用程序的实例

m_lpCmdLine

指向命令行参数的指针

m_nCmdShow

窗口开始的显示风格

m_bHelpMode

用户按下shift+f1时是否做出帮助响应

m_pActiveWnd

指向应用程序主窗口的指针

m_pszExeName

应用程序可执行文件的名称

m_pszHelpFilePath

帮助文档的路径

m_pszProfileName

.ini初始化文件名

m_pszRegistryKey

初始化文件存放的位置

部分函数成员

DoMessageBox()

弹出一个对话框

   
   

④文档/视类

CDocument负责管理文档的操作,文档模板对象可以创建不同文档类型的文档对象,并且每个文档对象都有一个指向其文档模板对象的指针

CDocTemplate

文档模板基类

CSingleDocTemplate

单文档界面的文档模板

CMultiDocTemplate

多文档界面的文档模板

CDocument

文档操作

CView

文档数据显示的基类,继承自CWnd

CView的派生类

CScrollView

有滚动条的视图

CCtrlView

有树、列表框等控件的视图

CDaoRecordView

显示数据库记录的视图,多用于DAO的查询结果

CEditView

多行文本编辑器的视图

CFormView

表单模板的视图

CListView

列表框控件的视图

CRecordView

显示数据库记录的视图

CRichEditView

富文本编辑控件的视图

CTreeView

树控件的视图

CPreviewView

支持打印预览

(3)可视对象类

①CWnd

窗口类,它的派生类有:SDI应用程序框架窗口类CFrameWnd、MDI应用程序框架窗口类CMIDFrameWnd、MDI应用程序文档框架窗口类CMDIChildWnd

②CMenu

对基础api对象HMenu的封装,负责和菜单有关的操作

③CDialog

对话框类,它的派生类有:文件标准对话框CFileDialog、颜色标准对话框CColorDialog、字体标准对话框CFontDialog、文件打印标准对话框CPrintDialog、查询替换标准对话框CFindReplaceDialog、用户自定义的对话框CDialog

④控件类

静态控件

CStatic

 

按钮

CButton

 

编辑框

CEdit

 

富文本编辑框

CRichEditCtrl

 

滚动条

CScrollBar

 

进度条

CProgressCtrl

 

游标

CSliderCtrl

 

列表框

CListBox

 

组合框

CComboBox

 

位图按钮

CBitmapButton

 

数值调整框spin

CSpinButtonCtrl

 

动画显示控件

CAnimateCtrl

 

弹出式说明

CToolTipCtrl

 

热键控件窗口

CHotKeyCtrl

用户可以创建“热键”,使某个操作使用更方便

⑤控件条类CControlBar

通常充当工具条、状态条等身份,它的基类有:窗口的基类CStatusBar、工具条上的按钮命令CToolbgar、非模态对话框CDialogBar

⑥绘画对象类CGdiObject

和绘画有关,它的子类有:提供操作GDI位图接口的CBitmap、GDI画刷的CBrush、GDI字体的CFont、GDI调色板的CPalette、GDI画笔的CPen、用于剪裁的GDI域CRgn

⑦设备描述表CDC

和绘画有关,它的子类有:

CPaintDC

简化了BeginPaint和EndPaint的过程,OnPaint、OnDraw对象的成员函数会用到

CClientDC

用户窗口的设备描述表

CWindowDC

整个窗口的设备描述表,包括用户区和框架区

CMetaFileDC

windows元文件的设备描述表,和图形设备接口GDI有关

(4)通用类

①文件类

CFile

提供二进制磁盘文件的总接口,通过CArchive对象被间接访问

CMemFile

提供访问内存文件的总接口

CStdioFile

提供访问缓存磁盘文件的总接口,通常是文本的方式

CArchive

与CFile对象一起实现对象的持久化

②异常类CException

不能直接建立CException对象,通常使用它的派生类;产生异常的描述在异常对象的m_cause成员数据中

CNotSupportedException

不支持服务

CMemoryException

内存异常

CFileException

文件异常

CResourceException

资源异常

COleException

OLE异常

CArchiveException

档案异常

CDaoException

DAO数据库类异常

CDBException

数据库存取异常

CUserException

用户操作异常

③模板收集类

CArray、CMap、CList类使用的是全局帮助函数,可能需要编写特定的帮助函数

CArray

元素存储在数组中

CMap

将键映射到值

CList

元素存储到链表中

CTypedPtrList

将对象指针存储在链表中

CTypedPtrArray

将对象指针存储在数组中

CTypedPtrMap

将键映射到值,键和值都是指针

(5)OLE类

OLE指的是对象连接和嵌入,和复合文档的处理有关(通常见到的word、excel),ActiveX在网络编程方面对OLE做了进一步的扩展

普通类

COleDocument、COleItem、COleException

用户类

COleClientDoc、COleClientItem

服务类

COleServer、COleTemplate、COleServerDoc、COleServerItem

可视编辑容器类

COleClientItem、COleLinkingDOC

数据传输类

COleDropSource、COleDropTarget、COleDataSource、COleDataObject

对话类

COleInsertDialog

其他

CRectTracker为复合文档中的某项建立边框,使之可移动和可调整大小

(6)ODBC数据库类

CDatabase

面向ODBC驱动程序的一种标准界面

CRecordset

面向ODBC驱动程序的一种标准界面

CRecordView

CFormView的子类,将查询集和显示的字段关联起来,便于直观操作

CFieldExchange

提供上下文信息,支持记录字段交换

CLongBinary

用于存储二进制对象,比如位图

CDBException

数据库存取异常

2.全局变量和函数

一般以Afx开头,函数中不包括数据库类的函数和Dialog Data Exchange的内容

AfxMessageBox()

弹出一个对话框

AfxGetApp()

获取一个指向CWinApp对象的指针

AfxGetInstanceHandle()

获取当前实例的句柄

AfxGetResourceHandle()

获取一个应用程序资源的句柄

AfxGetAppName()

获取一个指向应用程序名称的字符串指针

AfxAbort()

无条件终止一个应用程序

AfxBeginThread()

启动一个新线程

AfxEndThread()

终止当前线程

AfxFormatString()

格式化字符串

AfxRegisterWndClass()

注册windows窗口类

3应用程序向导Wizard

使用特定的框架或者添加一些内置的功能

二、windows标准控件

控件几乎都继承了CWnd类具有窗口的属性,因此具有一些通用的方法,比如显示或隐藏控件MoveWindow()、改变控件的位置SetWindowPos()、设置文本内容SetWindowText(),用代码或者在资源视图中拖拽都可以创建控件;在资源视图中右击控件可以添加变量、根据控件的消息添加一些消息处理的代码;格式->Tab键顺序,依次点击可以得到一个想要的tab键切换顺序;项目上右键选择“MFC类”可以扩展出自定义的控件类

1.按钮

(1)创建按钮

BOOL Create(

//按钮上的文本

LPCTSTR lpszCaption,

//按钮的风格

DWORD dwStyle,

//位置和大小

const RECT& rect,

//父窗口的指针

CWnd* pParentWnd,

//按钮的ID

UINT nID);

按钮的风格

BS_AUTOCHECKBOX

同BS_CHECKBOX,只是单击时按钮会自动反转

BS_AUTORADIOBUTTON

同BS_RADIOBUTTON,只是单击时按钮会自动反转

BS_AUTO3STATE

同BS_3STATE,只是单击按钮时会改变状态

BS_DEFPUSHBUTTON

默认的命令按钮,回车可以直接选中该按钮

BS_GROUPBOX

组框

BS_LEFTTEXT

按钮上的文本左对齐

BS_CHECKBOX

矩形的可选择框

BS_RADIOBUTTON

圆形的可选择按钮

BS_3STATE

同BS_CHECKBOX,只是有三种选择的状态

BS_PUSHBUTTON

指定一个命令按钮

BS_OWNERDRAW

指定一个自绘制按钮

(2)和按钮有关的消息

BN_CLICKED

单击

BN_DOUBLECLICKED

双击

(3)可能用到的成员函数

CButton类的成员函数

GetCheck()

获取check类型按钮的选中状态,未选择0、选择1、不确定2

SetCheck()

设置check类型按钮的选中状态

GetBitmap()

获取位图

SetBitmap()

设置位图

GetButtonStyle()

获取按钮的样式

SetButtonStyle()

设置按钮的样式

GetCursor()

获取光标

SetCursor()

设置按钮上的光标

GetIcon()

获取按钮上的图标

SetIcon()

设置按钮上的图标

GetState()

获取按钮的状态,选中、选择、聚焦

SetState()

设置按钮的状态

继承自CButton类的CBitmapButton

LoadBitmaps()

载入位图

SizeToContent()

改变位图的大小以适应按钮

CWnd类的成员函数

CheckDlgButton()

设置按钮的选中状态

CheckRadioButton()

选择组中的一个按钮

GetCheckedRadioButton()

选择组中的一个已被选中的按钮

IsDlgButtonChecked()

返回按钮的选中状态

GetWindowText()、GetWindowTextLength()、SetWindowText()

和按钮上的文字有关

2.滚动条

(1)创建滚动条

BOOL Create(

DWORD dwStyle,

const RECT& rect,

CWnd* pParentWnd,

UINT nID);

(2)和滚动条有关的消息

SB_TOP

滚动到最顶部

SB_BOTTOM

滚动到最底部

SB_RIGHT

滚动到右边

SB_LEFT

滚动到左边

SB_PAGEUP

向上滚动一页

SB_PAGEDOWN

向下滚动一页

SB_PAGELEFT

向左滚动一页

SB_PAGERIGHT

向右滚动一页

SB_LINEDOWN

向下滚动一行

SB_LINEUP

向上滚动一行

SB_LINELEFT

向左滚动一行

SB_LINERIGHT

向右滚动一行

SB_THUMBPOSITION

滚动框移动到最新位置

SB_THUMBTRACK

滚动框被拖动

SB_ENDSCROLL

滚动到最终位置

(3)可能用到的方法

EnableScrollBar()

使滚动条的一个或两个箭头有效或无效

GetScrollInfo()

获取滚动条的消息

GetScrollLimit()

获取滚动条的范围

GetScrollPos()

获取滚动条的当前位置

GetScrollRange()

获取滚动条的滚动范围

SetScrollInfo()

设置滚动条的消息

SetScrollPos()

设置滚动滑块的位置

SetScrollRange()

设置滚动条的滚动范围

ShowScrollBar()

显示或隐藏滚动条

3.静态控件

一般用在不发送消息也不接收消息的文本或图形上,但是也能想超文本链接那样响应用户的操作,这就要用到SS_NOTIFY样式向父窗口发送WM_COMMAND消息(记事本查看Visual C++ 2008编写的.rc文件可以发现这个问题)

(1)创建方法

Win32的做法或者在资源视图中通过拖拽添加

(2)和该控件有关的消息

STN_CLICKED

单击静态控件

STN_DBLCLK

双击静态控件

STN_ENABLE

激活静态控件

STN_DISABLE

禁用静态控件

(3)可能用到的函数

ModifyStyle(0,SS_BITMAP);

控件是位图风格

SetBitmap();

设置位图

HBITMAP bBmp=LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(位图的ID));

位图资源转换成HBITMAP

GetObject(m_bmp.GetBitmap(),sizeof(BITMAP),&bmp);

位图资源转换成BITMAP

4.列表框

CListBox可以展示像数组一样的数据,允许单选和多选、自带滚动条;

(1)创建列表框

BOOL Create(

DWORD dwStyle,

const Rect& rect,

CWnd* pParentWnd,

UINT nID);

(2)和列表框有关的消息

列表框向应用可能发送的消息

LBN_SELCHANGE

用户的选择发生了改变

LBN_DBCLK

双击

LBN_SELCANCLE

取消选择

LBN_SETFOCUS

获取输入焦点

LBN_KILLFOCUS

失去输入焦点

应用向列表框可能发送的消息

LB_ADDFILE

在文件列表中插入指定文件

LB_ADDSTRING

加入项

LB_DELETESTRING

删除项

LB_DIR

在列表框中列出指定文件

LB_FINDSTRING

在列表框中查找指定项

LB_GETCOUNT

获取多选列表框中项的数目

LB_GETCURSEL

获取当前选中项的索引值

LB_GETSEL

获取指定项的选中状态

LB_GETSELCOUNT

获取多选列表框中选中的项数

LB_GETTEXT

获取指定项的文本

LB_GETTEXTLEN

获取指定项的文本的长度

LB_GETTOPINDEX

获取列表框中第一项的索引值

LB_INSERTSTRING

在指定位置加入项

LB_RESETCONTENT

清空所有项

LB_SETSEL

设置多选列表框中指定项的选中状态

LB_SETCURSEL

设置单选列表框中指定项的选中状态

LB_SETTOPINDEX

设置列表框中第一项的索引值

(3)可能用到的函数

获取当前目录中的所有条目

//tchBuffer是长度为MAX_PAH的TCHAR类型数组

GetCurrentDirectory(MAX_PATH,tchBuffer);

//设置列表框的显示内容

DlgDirList(tchBuffer,列表框的ID,用于显示路径的静态控件ID,0);

通用方法

GetHorizontalExtent()

获取水平滚动的宽度

SetHorizontalExtent()

设置水平滚动的宽度

GetItemData()

获取与列表框项有关的32位数值

SetItemData()

设置与列表框项有关的32位数值

GetItemDataPtr()

获取某一项的指针

SetItemDataPtr()

设置某一项的指针

GetItemHeight()

获取某一项的高度

SetItemHeight()

设置某一项的高度

GetItemRect()

获取列表框的矩形

GetLocale()

获取列表框的位置局部标识LCID

SetLocale()

设置列表框的位置标识LCID

GetSel()

确定某一项的选择状态

GetText()

获取某一项的文本内容

GetTextLen()

返回列表框字符串的长度

GetTopIndex()

获取第一个项的下标,不一定为0

GetCount()

获取项的数目

ItemFromPoint()

获取和某点最近的某一项的下标

SetColumnWidth()

设置多列列表框的列宽度

SetTabStops()

设置列表框的制表位位置

SetTopIndex()

设置第一个可见项的下标

单项选择

GetCurSel()

获取当前选择项的下标

SetCurSel()

设置当前选择项的下标

多项选择

GetAnchorIndex()

获取当前定位项的下标

SetAnchorIndex()

扩充选择设置开始项(定位项)

GetCaretIndex()

获取具有光标矩形的项的下标

SetCaretIndex()

指定下标项设置光标矩形

GetSelCount()

获取当前所选项的数目

GetSelItems()

获取被选项的下标装入数组

SelItemRange()

切换项范围的选择状态

SetSel()

切换项的选择状态

操作字符串

AddString()

向列表框中加入一个字符串

DeleteString()

向列表框中删除一个字符串

Dir()

从当前目录加文件名装入列表框

FindString()

搜索一字符串

FindStringExact()

搜索第一个符合的字符串

InsertString()

在指定下标处插入字符串

ResetContent()

清空所有项

SelectString()

在单选列表框中搜索并选择一字符串

可以自定义的虚方法

CharToItem()

自绘制列表框处理WM_CHAR

CompareItem()

自绘制列表框项的比较方法

DeleteItem()

自绘制列表框删除一项

DrawItem()

自绘制列表框重绘时的方法

MeasureItem()

自绘制列表框创建时,MFC可以获取列表框的维数

VKeyToItem()

处理具有LBS_WANTKEYBOARDINPUT样式的WM_KEYDOWN消息

5.编辑框

可以是多行文本的矩形窗口,比如windows中的记事本;UpdateData()针对含有编辑框部分的代码更新

(1)Cedit的样式

资源视图中根据属性设置后,可以在.rc文件中找到这些样式

ES_AUTOHSCROLL

用户在末尾输入字符时,文本向右滚动

ES_AUTOVSCROLL

用户在末尾输入回车时,光标可以向下移动

ES_CENTER

文本居中

ES_LEFT

文本左对齐

ES_LOWERCASE

编辑框中的字符全部小写

ES_MULTILINE

指定是多行编辑框

ES_NOHIDESEL

失去输入焦点后依然选中文本

ES_NUMBER

Windows95上的编辑框中只能输入数字

ES_OEMCONVERT

字符类型转换

ES_PASSWORD

密码框的形式

ES_READONLY

只读

ES_RIGHT

文本右对齐

ES_UPPERCASE

编辑框中的字符全部大写

ES_WANTRETURN

多行编辑框可以回车换行

(2)和编辑框有关的消息

低字节是控件的标识,高字节是通知码

编辑框向应用程序发送通知码

EN_SETFOCUS

获取输入焦点

EN_KILLFOCUS

失去输入焦点

EN_CHANGE

内容发生改变

EN_UPDATE

内容被更新

EN_MAXTEXT

用户输入已达到最大限度

EN_HSCROLL

内容水平滚动

EN_VSCROLL

内容垂直滚动

应用程序向编辑框发送操作码

EM_GETRECT

获取矩形尺寸

EM_SETRECT

设置矩形尺寸

EM_LINESCROLL

设置滚动条的步长

EM_SETHANDLE

设置输入内容缓冲区句柄

EM_GETHANDLE

获取输入内容缓冲区句柄

EM_LINELENGTH

获取文本的长度

EM_GETFONT

获取编辑框使用的字体

EM_GETLINECOUNT

获取多行文本款的文本行数

EM_REPLACESEL

替换编辑框中选中的文本

EM_SETPASSWORDCHAR

设置密码编辑框中的替代字符

EM_GETPASSWORDCHAR

获取密码编辑框中的替代字符

EM_SETREADONLY

编辑框只读

EM_GETSEL

获取选中的字体

EM_SETSEL

设置选中的字体

(3)可能用到的函数

通用方法

CanUndo()

编辑操作是否可撤销

Clear()

删除当前的选择

Copy()

以CF_TEXT格式复制选择到剪切板中

Cut()

以CF_TEXT格式剪切选择到剪切板中

EmptyUndoBuffer()

消除一个编辑框控件的“撤销”标志

GetFirstVisibleLine()

确定编辑框控件中的最上面的可视行

GetModify()

确定一个编辑框控件的内容是否可修改

GetPasswordChar()

当用户输入文本时,编辑框控件中显示的密码字符

GetRect()

获取编辑框的矩形

GetSel()

获取当前选择的开始和结束字符的位置

LimitText()

限定用户文本输入的长度

LineFromChar()

获取包含指定字符下标的行的行号

LineLength()

获取编辑框控件中一行的长度

LineScroll()

滚动多行编辑框控件的文本

Paste()

将剪切板中的数据粘贴到光标位置

ReplaceSel()

用指定文本替换选中的部分

SetModify()

设置或清除编辑框控件的修改标志

SetPasswordChar()

当用户输入文本时设置或删除一个显示于编辑框控件中的密码字符

SetReadOnly()

只读

SetSel()

选择字符的范围

Undo()

取消最后一个编辑框控件的操作

UpdateData()

更新编辑框及其他控件

多行编辑框支持的方法

FmtLines()

包含软分行符

GetHandle()

获取控件的句柄

GetLine()

获取一行文本

GetLineCount()

获取文本行的数目

LineIndex()

设置一行的字符下标

SetHandle()

设置多行文本框将要用到的句柄

SetRect()

设置多行文本框的矩形并更新控件

SetRectNP()

设置多行文本框的矩形,但是不重绘控件窗口

SetTabStops()

设置制表位tab

6.组合框

CComboBox是一种即可以输入又可以进行选择的控件,看起来像是编辑框和列表框的组合;资源视图上,一组单选按钮的ID值必须连续、第一个按钮选上Group,而且每一组只有第一个按钮能够创建变量

(1)组合框的样式

CBS_DROPDOWN

由列表框和编辑框组成,列表框平时不可见

CBS_DROPDOWNLIST

由列表框和静态文本组成,列表框平时不可见

CBS_AUTOHSCROLL

编辑框自动水平滚动

CBS_SORT

列表框中各项按字母序排列

CBS_SIMPLE

列表框可见

(2)和组合框有关的消息

组合框向应用程序发送消息

CBN_SELCHANGE

列表框中的选中项发生改变

CBN_DBLCLK

双击

CBN_SETFOCUS

组合框获得焦点

CBN_KILLFOCUS

组合框失去焦点

CBN_EDITCHANGE

编辑框中的文本发生改变

CBN_EDITUPDATE

编辑框将显示修改过的文本

CBN_DROPDOWN

列表框将下拉

CBN_CLOSEUP

列表框将隐藏

应用程序向组合框发送消息

CB_SHOWDROPDWON

显示下拉列表框

CB_ADDSTRING

添加新项

CB_DELETESTRING

删除一项

CB_INSERTSTRING

插入新项

CB_FINDSTRING

查询列表项

CB_RESETCONTENT

清空列表框

CB_DIR

在列表框中显示指定目录及文件

CB_SETCURSEL

设置列表框中选中项的索引值,并在编辑框中显示

CB_GETCURSEL

获取列表框中选中项的索引值

CB_GETCOUNT

获取列表框中项的数目

CB_GETLBTEXT

获取列边框中指定项的文本

CB_GETLBTEXTLEN

获取列边框中指定项的文本长度

CB_LIMITEXT

限制编辑框中的字符串长度

CB_GETEDITSEL

获取编辑框中的选择

CB_SETEDITSEL

设置编辑框中的选择

(3)可能用到的函数

Clear()

删除当前选项,清空编辑框中的内容

Copy()

以CF_TEXT格式将选中内容复制到粘贴板

Cut()

以CF_TEXT格式将选中内容剪切到粘贴板

GetComboBoxInfo()

返回CCombox对象的信息

GetCount()

获取列表框项的数目

GetCurSel()

返回所选列表框条目的顺序号

GetEditSel()

返回DWORD数据,低字节是编辑框中选中文字的开始位置,高字节是结束位置

GetItemHeight()

返回组合框中表示列表条目数

GetLBText()

返回组合框的列表中指定条目的字符串

GetLBTextLen()

返回组合框的列表中指定条目的字符串的长度

Paste()

将粘贴板的内容复制到编辑框

SetCurSel()

选中组合框的指定条目

SetMinVisibleItems()

设置下拉列表中可见条目数

SetTopIndex()

指定下拉列表的第一个可见条目

AddString()

在列表条目中添加一字符串

DeleteString()

从列表项中删除一字符串条目

FindString()

查找第一个和指定字符串匹配的字符串序号

InsertString()

将一字符串插入到指定位置

ResetString()

清空组合空中的所有内容

SelectString()

从列表中查找指定字符串,如果找到将其放到编辑框中

用CTime类获取本地时间

CTime tNow =CTime::GetCurrentTime();

CString sNow=tNow.Format("%y/%m/%d");

获取对话框中的某个对象

GetDlgItem();

//使对象有效或无效,选择TRUE、FALSE

EnableWindow();

//是对象显示或隐藏,选择SW_SHOW、SW_HIDE

ShowWindow();

_tcscpy()、_tcscat()、_tcslen()

单选按钮组的状态

//初始化按钮组的状态

CheckedRadioButton(开始的ID,结束的ID,选中的ID);

//获取单选按钮组的选择状态,得到的值和各单选按钮的ID进行比较即可

iAgeRadio=GetCheckedRadioButton(IDC_AGE1_RADIO, IDC_AGE3_RADIO);

7.对话框通用控件

(1)Picture

分隔线

Color属性选择Etched

图片

Type选择Icon或者Bitmap,设置Image属性为对应资源的ID时可以显示图片

(2)Spin

需要和其他控件组合使用,比如Edit控件;Spin适合在一个范围内选择精确值

设置Edit控件只读,Spin控件的Allignment选择Right Align、Auto buddy为TRUE

初始化

CSpinButtonCtrl* pSpin=(CSpinButtonCtrl*)GetDlgItem(IDC_SPIN1);

pSpin->SetRange(0,100);

pSpin->SetPos(50);

pSpin->GetBuddy()->SetWindowTextW(L"5.0");

事件响应

//响应对话框的VM_VSCROLL消息

if(pScrollBar->GetDlgCtrlID()==IDC_SPIN1)

{

CString strValue;

//Spin上下移动变化只是1,除以10.0表示这个步长是0.1

strValue.Format(L"%3.1f",nPos/10.0);

((CSpinButtonCtrl*)pScrollBar)->GetBuddy()->SetWindowTextW(strValue);

}

(3)Progress

进度条

初始化

CProgressCtrl* pProg=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);

pProg->SetRange(0,100);

pProg->SetPos(50);

启动进度条

//比如某个按钮按下

CProgressCtrl* pProg=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);

pProg->SetPos(0);

SetTimer(2008,100,NULL);

事件响应

//响应对话框的VM_TIMER消息

if(nIDEvent==2008)

{

CProgressCtrl* pProg=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);

pProg->SetPos(pProg->GetPos()+1);

if(pProg->GetPos()>=100)

{

KillTimer(nIDEvent);

AfxMessageBox(L"进行完毕");

}

}

(4)Slider

滑块比较方便在一个范围内选择大致的数值

初始化

CString strText1;

CSliderCtrl* pSlider1=(CSliderCtrl*)GetDlgItem(IDC_SLIDER1);

pSlider1->SetRange(0,100);

pSlider1->SetPos(50);

strText1.Format(L"%d",pSlider1->GetPos());

SetDlgItemText(IDC_STATIC_SLIDER,strText1);

事件响应

//响应对话框的WM_HSCROLL消息

if(pScrollBar->GetDlgCtrlID()==IDC_SLIDER1)

{

CSliderCtrl* pSlide=(CSliderCtrl*)pScrollBar;

CString strText;

strText.Format(L"%d",pSlide->GetPos());

SetDlgItemText(IDC_STATIC_SLIDER,strText);

}

(5)Date Time Picker

用户对时间的输入形式是多样的,这就导致了时间不好解析的问题,这时候选择Date Time Picker是很有意义的

初始化

CDateTimeCtrl* pDT=(CDateTimeCtrl*)GetDlgItem(IDC_DATETIMEPICKER1);

CString str=_T("'今天是:'yyyy'/'MM'/'dd");

pDT->SetFormat(str);

对日期时间的解析

CDateTimeCtrl* pDT=(CDateTimeCtrl*)GetDlgItem(IDC_DATETIMEPICKER1);

CTime t;

pDT->GetTime(t);

CString str=t.Format(L"%Y/%m/%d %A %H:%M:%S");

AfxMessageBox(str);

(6)List Control

类似文件管理器的文件列表;回调项可能会节省程序的存储空间

CListCtrl可能用到的函数

Create()

创建列表控件

SetBkColor()

设置背景颜色

SetImageList()

设置图像列表

SetItem()

设置列表项数据

GetItemRect()

获取列表项的矩形

GetEditControl()

获取正在编辑的列表项的Edit控件

SetTextColor()

设置文本颜色

SetTextBkColor()

设置文本背景颜色

SetItemText()

设置列表项的标签文字

GetHotItem()

获取鼠标指向的列表项

GetSelectionMark()

获取当前选中的列表项

SubItemHitTest()

获取指定点下的列表项

SetBkImage()

设置背景图片

InsertItem()

插入列表项

EditLabel()

启动显示编辑标签文字

CreateDragImage()

创建用于拖放的图片

列表控件的风格

图标:每项显示32*32图标,图标下面显示标签,可以拖动到视图内任意位置;小图标:每项显示16*16图标,图标右边显示标签,可以拖动到视图内任意位置;列表:每项显示16*16图标、按列排列,图标右边显示标签,不能任意拖动图标;报表:每项占一行,第一列显示16*16的图标,图标右边显示标签,再右边的列显示子项由具体程序决定

Windows控件风格

 

hover selection

鼠标在某一项上停留一定时间就自动选择该项

虚拟列表视图

可以使用DWORD类型的项,是管理数据交给具体程序,控件只负责焦点和选择功能

单击和双击激活

允许热点跟踪、单击和双击激活高亮选项

拖放列排序

在报表中允许通过拖放重新排序各项的顺序

列表控件支持的四种图片类型

大图标

图标风格的时候使用

小图标

小图标、列表、报表风格使用

应用程序状态

用于在图标旁边显示应用程序状体的图片

标题栏项

在报表风格中用于标题栏的显示

设置Edit Labels为TRUE,View的属性为Small Icon,在对话框类中添加变量CImageList m_imageList;

初始化

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]);

//创建标签资源

static TCHAR* color[]={L"white",L"black",L"red",L"blue",L"yellow",L"cyan",L"purple",L"green"};

//创建控件

CListCtrl* pList=(CListCtrl*)GetDlgItem(IDC_LIST1);

pList->SetImageList(&m_imageList,LVSIL_SMALL);

for(n=0;n<8;++n)

pList->InsertItem(n,color[n],n);

pList->SetBkColor(RGB(0,255,255));

pList->SetTextBkColor(RGB(255,0,255));

在列表LVN_ITEMCHANGED消息中添加代码,获取选中的内容

CListCtrl* pList=(CListCtrl*)GetDlgItem(IDC_LIST1);

int nSelected=pNMLV->iItem;

if(nSelected>=0)

{

CString strItem=pList->GetItemText(nSelected,0);

SetDlgItemText(IDC_STATIC_LIST,strItem);

}

在列表NM_RCLICK消息中添加代码,编辑右键选中的内容

//LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE>(pNMHDR);

// TODO: 在此添加控件通知处理程序代码

NM_LISTVIEW* pNMListView=(NM_LISTVIEW*)pNMHDR;

CListCtrl* pList=(CListCtrl*)GetDlgItem(IDC_LIST1);

int nSelected=pNMListView->iItem;

if(nSelected>=0)

pList->EditLabel(nSelected);

在列表LVN_ENDLABELEDIT消息中添加代码,更新列表的编辑结果

LVITEM 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);

}

(7)Tree Control

CTreeCtrl可能用到的函数

Create()

创建树控件

GetCount()

获取结点的数目

SetIndent()

设置每层缩进距离

SetIamgeList()

设置图片列表

GetNextItem()

获取指定结点指定方式下的下一个节点

InsertItem()

插入节点

GetChildItem()

获取子节点

GetNextSiblingItem()

获取下一个兄弟节点

GetPrevSiblingItem()

获取上一个兄弟节点

GetParentItem()

获取父节点

GetSelectedItem()

获取选中的节点

GetDropHilightItem()

获取当前释放目标节点

GetRootItem()

获取根节点

GetItem()

获取指定结点的信息

GetEditControl()

获取编辑框控件

SetBkColor()

设置背景颜色

ItemHasChildren()

判断是否有子节点

DeleteItem()

删除节点

DeleteAllItems()

删除所有节点

Expand()

打开或折叠节点

CreateDragImage()

创建用于拖放的图片

SortChildren()

将某节点下的子节点排序

设置Has Buttons为TRUE、这样每个展开项之前就有“+”“-”按钮,设置Has Lines为TRUE、这样每个展开项之前就有虚线连接,设置Lines At Root为TRUE、这样第一层节点之间也有虚线连接,设置Edit Labels为TRUE、是标签可编辑

VERIFY()是个类似assert()的东西

初始化

HICON hIcon[8];

int n;

m_imageList.Create(16,16,0,8,8);

//图标icon资源需要提前制作

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]);

CTreeCtrl* pTree=(CTreeCtrl*)GetDlgItem(IDC_TREE1);

//包含有图片的形式

pTree->SetImageList(&m_imageList,TVSIL_NORMAL);

//建树的一种结构

TV_INSERTSTRUCT tvinsert;

//没有父节点

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;

//创建第一层

tvinsert.item.iImage=1;

tvinsert.item.pszText=L"father";

HTREEITEM hDad=pTree->InsertItem(&tvinsert);

tvinsert.item.iImage=2;

tvinsert.item.pszText=L"mother";

//表示还有子节点

HTREEITEM hMom=pTree->InsertItem(&tvinsert);

//创建第二层

tvinsert.hParent=hDad;

tvinsert.item.iImage=3;

tvinsert.item.pszText=L"son";

//下面没有子节点

pTree->InsertItem(&tvinsert);

tvinsert.item.pszText=L"daughter";

pTree->InsertItem(&tvinsert);

tvinsert.hParent=hMom;

tvinsert.item.iImage=4;

tvinsert.item.pszText=L"son";

pTree->InsertItem(&tvinsert);

tvinsert.item.pszText=L"daughter";

pTree->InsertItem(&tvinsert);

tvinsert.item.pszText=L"cartoon";

HTREEITEM hOther=pTree->InsertItem(&tvinsert);

//创建第三层

tvinsert.hParent=hOther;

tvinsert.item.iImage=7;

tvinsert.item.pszText=L"Tom";

pTree->InsertItem(&tvinsert);

tvinsert.item.pszText=L"Jerry";

pTree->InsertItem(&tvinsert);

在树控件的TVN_SELCHANGED消息中添加代码,实现获取选中的内容

CTreeCtrl* pTree=(CTreeCtrl*)GetDlgItem(IDC_TREE1);

HTREEITEM hSelected=pNMTreeView->itemNew.hItem;

if(hSelected!=NULL)

{

//总长是9个字符,包括最后的'\0'

TCHAR text[9];

TV_ITEM item;

item.mask=TVIF_HANDLE|TVIF_TEXT;

item.hItem=hSelected;

item.pszText=text;

item.cchTextMax=8;

VERIFY(pTree->GetItem(&item));

SetDlgItemText(IDC_STATIC_TREE,item.pszText);

}

在树控件的TVN_ENDLABELEDIT消息中添加代码,三击实现编辑选中的内容

TVITEM item=pTVDispInfo->item;

CString str=item.pszText;

//换成Trim()、中间输入些空格到底行不行?

str.TrimLeft();

str.TrimRight();

if(str.GetLength()>0)

{

CTreeCtrl* pTree=(CTreeCtrl*)GetDlgItem(IDC_TREE1);

pTree->SetItemText(item.hItem,item.pszText);

}

(8)Extended Combo Box

扩展出来的组合框,实现列表项图标和标签的组合显示

CComboBoxEx可能用到的函数

Create()

创建扩展组合框控件

DeleteItem()

删除一项

GetItem()

获取指定项信息

InsertItem()

插入一项

SetImageList()

设置图片列表

GetEditCtrl()

获取其中的Edit控件

GetComboBoxCtrl()

获取其中的组合框控件

初始化

HICON hIcon[8];

int n;

//这是对话框添加的CImageList变量

m_imageList.Create(16,16,0,8,8);

//图标icon资源需要提前制作

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]);

static TCHAR* color[]={L"white",L"black",L"red",L"blue",L"yellow",L"cyan",L"purple",L"green"};

CComboBoxEx* pComboEx=(CComboBoxEx*)GetDlgItem(IDC_COMBOBOXEX1);

pComboEx->SetImageList(&m_imageList);

COMBOBOXEXITEM comboItem;

//和下面的操作有关

comboItem.mask=CBEIF_IMAGE|CBEIF_INDENT|CBEIF_SELECTEDIMAGE|CBEIF_TEXT;

for(n=0;n<3;++n)

{

//该项的索引

comboItem.iItem=n;

//项的图标

comboItem.iImage=n;

//选中时候的图标

comboItem.iSelectedImage=n;

//缩进

comboItem.iIndent=n;

comboItem.pszText=color[n];

pComboEx->InsertItem(&comboItem);

}

三、资源

资源和代码是独立的,资源可以是某个.dll、.exe等二进制文件;另存为.res资源文件,在需要的时候可以导入

1.菜单

(1)程序主菜单

出现在界面的最上方,不可以拖动和删除;在View的构造函数和OnDraw函数中填写代码

①菜单编辑器中的属性

Seperator

分割线

Popup

弹出式窗口

Enabled

已激活

Checked

被选中

Grayed

被禁用

Prompt

提示信息

②COMMAND消息

用户点击菜单项的时候会产生该消息

③UPDATE_COMMAND_UI消息

窗口刷新菜单项的时候产生该消息,会用到CCmdUI对象

Enable()

禁止或启动该菜单项

SetCheck()

菜单项或工具条前面是否有√

SetRadio()

菜单项或工具条前面是否有·

SetText()

设置菜单项的显示文字

④ON_COMMAND_RANGE消息

也可以用COMMAND消息一个一个的对菜单项添加代码,但是如果菜单项的ID是连续的话,用ON_COMMAND_RANGE会方便很多;引导程序不支持该消息的自动映射、需要动手写代码完成

a.在View的头文件中填写代码

afx_msg void OnOperColorChange(UINT nID);

b.在View的源文件中填写代码

BEGIN_MESSAGE_MAP(CMy0View, CView)

ON_COMMAND_RANGE(ID_OPER_RED,ID_OPER_BLUE,OnOperColorChange)

END_MESSAGE_MAP()

void CMy0View::OnOperColorChange(UINT nID)

{

m_nColorIndex=nID-ID_OPER_RED;

//强制刷新,会重新调用OnDraw函数

Invalidate();

}

⑤UPDATE_COMMAND_UI_RANGE消息

对ID连续的菜单项进行更新;引导程序不支持该消息的自动映射、也是需要动手写代码完成

a.在View的头文件中填写代码

afx_msg void OnUpdateOperColorChange(CCmdUI* pCmdUI);

b.在View的源文件中填写代码

BEGIN_MESSAGE_MAP(CMy0View, CView)

ON_UPDATE_COMMAND_UI_RANGE(ID_OPER_RED,ID_OPER_BLUE,OnUpdateOperColorChange)

END_MESSAGE_MAP()

void CMy0View::OnUpdateOperColorChange(CCmdUI* pCmdUI)

{

//pCmdUI和之前声明的起始ID、终止ID有关,事件触发的时候将刷新菜单项

pCmdUI->SetRadio(m_nColorIndex==(pCmdUI->m_nID-ID_OPER_RED));

}

(2)快捷菜单

程序主菜单中已经有其中的菜单项,为了方便右键时出现的一组菜单

①CMenu类可能会用到的方法

构造方法

Attach()

把一个菜单句柄附加到CMenu对象上

CreateMenu()

创建一个空菜单并附加到CMenu对象上

CreatePopupMenu()

创建一个弹出式菜单并附加到CMenu对象上

DeleteTempMap()

删除由FromHandle()创建的任何临时CMenu对象

DestroyMenu()

销毁CMenu对象及其下面的菜单

Deatch()

从CMenu对象上拆出一个菜单句柄并返回

FromHandle()

给定菜单句柄时,返回CMenu对象的指针

GetSafeHmenu()

返回由CMenu对象封装的菜单句柄成员

LoadMenu()

从可执行文件中加载菜单资源并附加到CMenu对象上

LoadMenuIndirect()

从内存中加载菜单资源并附加到CMenu对象上

操作菜单

DeleteMenu()

删除某个特定菜单中的菜单项

TrackPopupMenu()

在一个POINT对象指定的地方显示快捷菜单

操作菜单项

AppendMenu()

将新项加到指定的菜单项后面

CheckMenuItem()

弹出式菜单中,菜单项的校验标记或取消下一项的校验标记

CheckMenuRadioItem()

把一个单选按钮放到菜单项旁边或取消一个已存在的单选按钮

EnableMenuItem()

激活/禁用一个菜单项

GetMenuItemCount()

获取菜单项的数目

GetMenuItemID()

获取指定位置的菜单项的标识符

GetMenuState()

获取指定菜单项的状态

GetMenuString()

获取指定菜单项的标记

GetSubMenu()

获取指向弹出式才当的指针

InsertMenu()

在指定位置插入新的菜单项

ModifyMenu()

修改指定位置的菜单项

RemoveMenu()

从指定菜单中删除与弹出式菜单结合的菜单项

②在资源视图中插入新菜单IDR_MENU_POPUP

③在View的头文件中添加新变量

//快捷菜单

CMenu m_PopMenu;

//快捷菜单的子菜单

CMenu* m_pPop;

④在View的源文件中添加代码

CMy0View::CMy0View()

{

//加载菜单资源

m_PopMenu.LoadMenu(IDR_MENU_POPUP);

}

CMy0View::~CMy0View()

{

//销毁菜单资源

m_PopMenu.DestroyMenu();

}

⑤在View的类视图、类的属性面板中选择WM_RBUTTON消息添加处理函数,填写右键后要处理的代码

void CMy0View::OnRButtonDown(UINT nFlags, CPoint point)

{

// TODO: 在此添加消息处理程序代码和/或调用默认值

m_pPop=m_PopMenu.GetSubMenu(0);

UINT nCheck=m_bShow?MF_CHECKED:MF_UNCHECKED;

m_pPop->CheckMenuItem(ID_OPER_SHOW,MF_BYCOMMAND|nCheck);

m_pPop->CheckMenuRadioItem(ID_OPER_RED,ID_OPER_BLUE,ID_OPER_RED+m_nColorIndex,MF_BYCOMMAND);

ClientToScreen(&point);

m_pPop->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);

CView::OnRButtonDown(nFlags, point);

}

(3)工具栏菜单

程序主菜单中也有这些菜单项,通常出现在程序主菜单下方、由一组类似按钮的图标组成,可以拖动和关闭

①CToolBar可能用到的方法

构造方法

Create()

创建工具条并附加到CToolBar对象上

CreateEx()

创建定义了边界的工具条并附加到CToolBar对象上

SetSizes()

设置按钮及位图大小

SetHeight()

设置工具条的高度

LoadToolBar()

加载工具条资源

LoadBitmap()

加载包含工具条按钮图像的位图

SetBitmap()

设置位图图像

SetButtons()

设置按钮并使每个按钮与位图图像相关

操作工具条按钮

CommandToIndex()

返回给定命令的工具条按钮索引

GetItemID()

返回指定索引的按钮或分隔符的ID

GetItemRect()

返回指定索引的按钮矩形

GetButtonStyle()

获取按钮的风格

SetButtonStyle()

设置按钮的风格

GetButtonInfo()

获取按钮的ID、风格、图像号

SetButtonInfo()

设置按钮的ID、风格、图像号

GetButtonText()

获取按钮上的文本内容

SetButtonText()

设置按钮上的文本内容

②CToolBarCtrl也用于操作工具条,CToolBarCtrl可能用到的方法

CToolBarCtrl()

构造函数

Create()

创建工具条,这里与具体的工具条资源绑定

GetState()

获取指定按钮的信息,比如被按下、被禁止等

HitTest()

测试一点是否位于某按钮内

AddButtons()

添加按钮

InsertButton()

插入按钮

AddStrings()

添加按钮文字

③进入资源视图插入Toolbar

④在CMainFrame的头文件中添加工具条对象

protected:

//如果已经有这个对象,还想建立新工具条的话需要另外创建CToolBar对象

CToolBar m_wndToolBar;

⑤在CMainFrame的源文件中编写代码,完成对工具条的加载

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if(!m_wndToolBar.Create(this,WS_VISIBLE|CBRS_TOP)||!m_wndToolBar.LoadToolBar(IDR_TOOLBAR))

{

TRACE0("Fail to create toolbar.");

return -1;

}

` …

}

⑥可以动态的改变工具条的风格

//使窗口可以移动到用户区的任意位置

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndToolBar);

//改变工具条的风格:Toolbar属性面板中prompt的\n前面的内容显示在状态栏、后面的内容表示鼠标经过时提示的内容

m_wndToolBar.SetBarStyle(CBRS_TOOLTIPS| CBRS_FLYBY| CBRS_SIZE_DYNAMIC);

//使工具条显示或隐藏

ShowControlBar(&m_wndToolBar,TRUE,FALSE);

⑦多列工具栏菜单

if(!m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_FLOAT_MULTI|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

{

TRACE0("Failed to create toolbar");

return -1; // fail to create

}

m_wndToolBar.SetWindowText(_T("标准工具栏"));

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndToolBar);

if(!m_wndExtendBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_FLOAT_MULTI|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||!m_wndExtendBar.LoadToolBar(IDR_TOOLBAR))

{

TRACE0("Failed to create extend toolbar");

return -1;

}

m_wndExtendBar.SetWindowText(_T("扩展工具栏"));

m_wndExtendBar.EnableDocking(CBRS_ALIGN_ANY);

CRect rect;

m_wndExtendBar.GetWindowRect(&rect);

rect.OffsetRect(1,0);

this->RecalcLayout(); //关键的一步,重新排列

DockControlBar(&m_wndExtendBar, AFX_IDW_DOCKBAR_TOP, &rect);

⑧多行工具栏菜单

//默认工具栏已经加载

if(!m_wndToolBarNew.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||

!m_wndToolBarNew.LoadToolBar(IDR_TOOLBAR))

{

TRACE0("Fail to create toolbar.");

return -1;

}

2.加速键

进入资源视图的文件,双击最后一行、设置与该加速键关联的ID、在属性面板中设置加速键,编译执行

3.字符串

使用字符串资源并在需要的时候动态切换,可以设计出跨语言的程序;进入资源视图、打开String Table,双击最下面的空白一行、填写表示该字符串的ID值、填写字符串的内容,编译执行;CTring类.LoadString(字符串的ID值);可以加载需要的字符串资源,CString对象可以直接转换成LPCTSTR而且支持格式化.Format(L“”,…);

//获取字符串的矩形

CSize sizeText=pDC->GetTextExtent(str);

//CString转换为string

CString str = _T("CSDN");

std::string s = (CT2A)str;

//字符串输出

pDC->SetBkColor(RGB(255,0,0));

pDC->SetTextColor(RGB(0,255,0));

CFont a;

a.CreateFont(

//高度和宽度

30,0,

//文本的倾斜度

0,

0,FW_NORMAL,

//斜体、下划线、删除线

0,0,0,

GB2312_CHARSET,OUT_DEFAULT_PRECIS,

CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,

//字体名称

L"华文行楷");

pDC->SelectObject(a);

HDC hdc=pDC->GetSafeHdc();

CString str=L"无边落木萧萧下";

TextOut(hdc,0,80,str,_tcslen(str));

a.DeleteObject();

4.对话框

DDX:对话框数据交换,MFC将控件和数据建立一种绑定关系;重写OnInitDialog()函数可以初始化对话框中组件的状态;改变对话框的位置csDlg->SetWindowPos(NULL,20,10,0,0,SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);;AfxGetMainWnd()->PostMessage(WM_QUIT,0,0);或者使用Dialog::OnOk();都可以退出一个对话窗口

(1)CDialog可能用到的函数

Create()

创建一个对话框,通常用于非模态对话框的创建

Domodal()

显示模态对话框

EndDialog()

关闭模态对话框

GetDlgItem()

获取对话框上的某个控件指针

OnInitDialog()

初始化对话框

OnOk()

OK按钮被点击,可以重载这个函数

OnCancel()

Cancel按钮被点击,可以重载这个函数

(2)在资源视图中插入新的Dialog,编辑需要的控件
(3)为这个对话框建立关联的类
(4)在对话框类中为需要的控件添加需要的数据变量
(5)在需要的源文件中使用这个对话框类

//一个ID为ID_OPER_STRING的菜单项,它的COMMAND消息响应函数OnOperString调用了这个对话框类

//也就是点击这个菜单项的时候会出现这个对话框

#include "InputDlg.h"

void CMy0View::OnOperString()

{

// TODO: 在此添加命令处理程序代码

InputDlg dlgInput;

//这是模态对话框

if(dlgInput.DoModal()==IDOK)

{

m_strShow=dlgInput.m_strInput;

Invalidate();

}

//这是非模态对话框,现在只能用来显示一些消息并不能进行交互

//InputDlg *dlg = new InputDlg;

//dlg->Create(IDD_DIALOG_NEW);

//dlg->ShowWindow(SW_SHOWNORMAL);

}

5.图标

可以在资源视图Icon中可以编辑图标,通常使用的是32*32、16*16的24位图标;也可以添加自己想要的图标,如果把ID值替换成IDR_MAINFRAME,就可以改变应用程序的图标

6.位图

(1)在资源视图中导入.bmp视图并命名ID

(2)在View的OnDraw()中载入位图

//获取窗口的绝对位置,GetClientRect()获取相对位置

CRect rect;

GetWindowRect(&rect);

CDC dcMemory;

dcMemory.CreateCompatibleDC(pDC);

CBitmap bmp1;

bmp1.LoadBitmapW(IDB_BITMAP_24bi);

BITMAP bmpInfo1;

bmp1.GetBitmap(&bmpInfo1);

CBitmap* pOldBitmap=dcMemory.SelectObject(&bmp1);

//pDC->BitBlt(0,0,bmpInfo1.bmWidth,bmpInfo1.bmHeight,&dcMemory,0,0,SRCCOPY);

pDC->StretchBlt(0,0,rect.right-rect.left,rect.bottom-rect.top,&dcMemory,0,0,bmpInfo1.bmWidth,bmpInfo1.bmHeight,SRCCOPY);

dcMemory.SelectObject(pOldBitmap);

四、单文档SDI和多文档MDI界面

SDI只能打开一个类型的一个文档,MDI每次能打开多个类型的多个文档、MDI至少拥有两个主菜单

1.可能用到的概念

和CArchive有关的序列化处理,对象读写字节流的方式还方便了网络、串口传输数据

m_pDocument

使用该档案的文档

Abort()

在不发送异常的情况下关闭档案

Close()

关闭档案

Flush()

将缓冲中的数据强制写入流

operator<<

将基本类型写入流

operator>>

从流中读出基本类型

Read()

读取字节内容

Write()

写入字节内容

ReadString()

读取字符串

WriteClass()

写入类信息

WriteString()

写入字符串

GetFile()

获取底层的CFile对象

GetObjectSchema()

读取对象版本号

SetObjectSchema()

设置对象版本号

IsLoading()

是否处于读取状态

IsStoring()

是否处于保存状态

ReadObject()

读取序列化对象

WriteObject()

写入序列化对象

ReadClass()

读取类信息

和文件打开保存有关的虚函数,可以重载实现对这个过程的具体控制

文档类完整的工作是:显示获取文件名对话框,选择匹配的文件模板,创建关联的框架、文档、视图,打开文件,将文件和档案绑定,调用Serialize

CWinApp::OnFileOpen()

可以完成整个过程

CWinApp::OpenDocumentFile()

MFC帮你获取文件名

CDocTemplate::OpenDocumentFile()

MFC帮你获取文件名并选择一个模板

CDocument::OnOpenDocument()

MFC获取文件名,选择好模板,创建好关联的框架、文档、视图

CDocument::Serialize()

完成序列化即可

CDocument::OnFileSave()/OnFileSaveAs()

可以完成整个过程

CDocument::OnSaveDocument()

MFC帮你获取文件名

2.消息映射

本质是数组,数组中存储了消息传递时的关键信息;某种类型的消息会按照某种顺序从一个对象传递到另一个对象,直到该消息被处理,消息被处理后就不会再传递到后面的对象;这个优先级顺序一般是:文档对象>文档模板>框架窗口>应用程序对象;在BEGIN_MSG_MAP和END_MSG_MAP之间的用宏的方式进行声明

宏/参数

描述

ON_COMMAND

ID

Func

处理WM_COMMAND消息

发出消息的控件的ID

void func();

ON_COMMAND_RANGE

IDFirst

IDLast

func

处理ID连续的WM_COMMAND消息

起始控件的ID

终止控件的ID

void func(WORD id);

ON_UPDATE_COMMAND_UI

ID

func

处理MFC请求更新界面状态

控件ID

void func(CCmdUI* pCmdUI);

ON_UPDATE_COMMAND_UI_RANGE

IDFirst

IDLast

func

处理ID连续的界面更新

起始控件的ID

终止控件的ID

void func(CCmdUI* pCmdUI);

ON_NOTIFY

Code

ID

func

处理来自新风格控件的WM_NOTIFY消息

消息码

控件ID

void func(NMHDR* pNotifyStruct,LRESULT* result);

ON_NOTIFY_RANGE

Code

IDFirst

IDLast

func

处理ID连续的WM_NOTIFY消息

消息码

起始控件的ID

终止控件的ID

void func(UINT id,NMHDR* pNotifyStruct,LRESULT* result);

ON_CONTROL

Code

ID

func

处理WM_COMMAND中的EN_、BN_消息

消息码

控件ID

void func();

ON_CONTROL_RANGE

Code

IDFirst

IDLast

func

要求控件ID连续,功能和上一个一样

消息码

起始控件的ID

终止控件的ID

void func(UINT id);

ON_MESSAGE

Msg

func

处理任意消息,包括用户自定义消息

消息ID

LRESULT func(WPARAM wParam,LPARAM lParam);

ON_REGISTERD_MESSAGE

Msg

func

处理使用RegisterWindowMessage注册的消息

消息ID

LRESULT func(WPARAM wParam,LPARAM lParam);

3.核心类

(1)CWinApp

代表主程序,负责维护进程的启动终止、消息循环、命令行参数、资源管理

常用的成员;调用的方法是使用全局函数AfxGetApp()获取到指针,然后访问

m_pszAppName

应用程序名称

m_lpCmdLine

命令行参数

m_pMainWnd

应用程序主窗口指针

m_pszExeName

可执行文件的名称

m_pszProfileName

配置INI文件的名称

m_pszRegistrKey

配置注册表主键值

LoadCursor

加载光标

LoadIcon

加载图标

GetProfileInt

从配置读取整数

WriteProfileInt

从配置写入整数

GetProfileString

从配置读取字符串

WriteProfileString

从配置写入字符串

AddDocTemplate

添加文档模板

AddToRecentFileList

向“最近打开的文件”菜单项中添加一个文件

InitInstance

MFC程序的入口

Run

事件循环

OnIdle

空闲事件处理

ExitInstance

MFC程序出口

PreTranslateMessage

筛选消息

DoWaitCursor

出现“沙漏”光标

(2)CDocument

提供了文档所需要的最基本功能:打开保存文档、维护文档相关的视图列表、维护文档修改标志、通过电子邮件发送文档,是数据的抽象

可能用到的方法

一般方法

GetTitle()

获取文档标题

SetTitle()

设置文档标题

GetPathName()

获取文档的路径

SetPathName()

设置文档的路径

GetDocTemplate()

获取文档模板的指针

AddView()

对与文档相关的视图列表中添加视图

RemoveView()

从文档视图列表中移除视图

UpdateAllViews()

文档已修改,更新全部相关的视图

DisconnectViews()

使文档与视图相分离

GetFile()

获取指向CFile类型的指针

CDocumnet的虚方法

OnNewDocument()

由MFC调用来创建新文档

OnOpenDocument()

由MFC调用来打开文档

OnSaveDocument()

由MFC调用来保存文档

OnCloseDocument()

由MFC调用来关闭文档

CanCloseDocument()

观察文档的框架窗口是否被允许关闭

DeleteContents()

在未撤销文档对象时删除文档数据

ReleaseFile()

释放文件以允许其他应用程序使用

SaveModified()

查询文档的修改状态并保存修改的文档

IsModified ()

文档是否被修改过

SetModifiedFlag()

设置文档是否被修改过的标记

GetFirstViewPosition()

获取视图列表头的位置

GetNextView()

获取视图列表的下一个视图指针

逐个对视图进行操作

POSITION pos=GetFirstViewPosition();

while(pos!=NULL)

{

CView* pView=GetNextView(pos);

}

(3)CView

继承自CWnd可以接收任何windows消息;OnDraw()除了负责绘制还处理了打印功能、Invalidate()、UpdateWindow()强制视图重绘,都不能在OnDraw()中调用,否则程序会因为递归循环调用而失去响

可能用到的方法

一般方法

GetDocument()

获取与视图相关联的文档指针

DoPreparePrinting()

设置文档标题

虚方法

IsSelected()

文档是否被选中

OnScroll()

当用户滚动时触发

OnInitialUpdate()

类在第一次构造后由MFC调用

OnDraw()

由MFC调用发出文档到设备描述表

OnUpdate()

由MFC调用对修改的文档进行响应

OnPrepareDC()

调用OnDraw()前由MFC修改设备表述表

CView的子类

CEditView

简单的文本编辑器

CListView

列表视图

CTreeView

树状视图

CRichEditView

富文档编辑器

CScrollView

支持滚动条的视图

CFormView

窗体视图,支持在之上使用对话框控件

CRecordView

连接到ODBC数据库的视图

CDaoRecordView

连接到DAO数据库的视图

(4)CDocTemplate

文档模板类将文档、视图和框架窗口对象联系在一起,负责一种文档类型的创建和管理;CSingleDocTemplate、CMultiDocTemplate

可能用到的方法

GetDocString()

获取与文档相关的字符串

LoadTemplate()

加载指定模板

AddDocument()

给文档模板添加指定模板

RemoveDocument()

从文档模板列表中删除文档

GetFirstDocPosition()

获取与文档模板相关的第一个文档的位置

GetNextDoc()

获取文档即下一个文档

CreateNewDocument()

建立文档

CreateNewFrame()

建立包含文档和视图的框架窗口

OpenDocumentFile()

打开有路径名指定的文档

CloseAllDocument()

关闭所有文档

SetDefaultTitle()

显示文档窗口的标题栏内容

SaveAllModified()

查询文档模板的修改状态并存储相关的所有文档

InitialUpdateFrame

触发关联视图的OnInitialUpdate()

CloseAllDocuments

关闭所有关联的文档

CDocTemplate文档模板中的字符串,这些是枚举类型中的数据,通过GetDocString()才能访问到字符串

windowTitle

应用程序的标题栏文字

docName

默认的新文档名

fileNewName

如果有多个模板,先选择模板对话框中显示

filterName

文件对话框中对扩展名的描述

filterExt

文档扩展名

regFileTypeId

该文档类型的注册名

regFileTypeName

该文档类型对应注册表中用户可见的名称

(5)CFrameWnd

框架窗口,维护工具条、菜单、状态栏、视图的显示和刷新等;MDI程序中使用的是它的子类CMDIFrameWnd和CMDIChildWnd

类的成员

m_bAutoMenuEnable

禁用没有消息处理的菜单项

rectDefault

默认尺寸的矩形

Create()

创建窗口,可以重载改变一些窗口属性

LoadFrame()

从资源加载框架

SaveBarState()

保存工具条的状态

LoadBarState()

恢复工具条的状态

ShowControlBar()

显示工具条

EnableDocking()

使一个控制条可以停靠

DockControlBar()

停靠一个控制条

FloatControlBar()

浮动一个控制条

GetControlBar()

获取一个控制条

RecalLayout()

基于当前视图和控制条重新计算显示区域

InitialUpdateFrame()

调用所有关联视图的OnInitialUpdate()

GetActiveFrame()

MDI中获取活动框架

SetActiveView()

激活一个视图

GetActiveView()

获取当前激活的视图

CreateView()

创建一个视图

GetActiveDocument()

获取当前激活的文档

GetMessageString()

获取带有命令ID的消息

GetMessageText()

在状态栏显示一条消息

GetMessageBar()

获取指向状态栏的指针

(6)5个核心类的相互访问

当前对象

要访问的对象

访问方法

文档

视图

GetFirstViewPosition()、GetNextView()

文档

模板

GetDocTemplate()

视图

文档

GetDocment()

视图

框架

GetParentFrame()

框架

视图

GetActiveView()

框架

文档

GetActiveDocument()

MDI主框架

MDI子框架

MDIGetActive()

MDI子框架

MDI主框架

GetParentFrame()

任何位置

应用程序

AfxGetApp()

任何位置

主框架

AfxGetMainWnd()

4.在程序向导上创建SDI和MDI程序

(1)SDI

View类中OnDraw()的填充;

文档序列化

(2)MDI

在类视图中添加类MFC,输入类名和基类

用类似的方法添加视图View类

创建资源

//这个ID要和上一个表示类型的ID数值上连续,如果还有多个类型、可能需要修改#define _APS_NEXT_RESOURCE_VALUE

#define IDR_MYMDITYPE2 135

//在MyMdi.rc文件中IDR_MYMIDTYPE “\n…”后面添加类似的代码

IDR_MYMDITYPE2 “\nMyMdi2\n…”

创建主菜单资源,在MyMdi的资源视图中复制IDR_MYMIDTYPE、修改出ID为IDR_MYMDITYPE2的菜单

创建文档模板类

BOOL CMyMdiApp::InitInstance()

{

CMultiDocTemplate* pDocTemplate2;

pDocTemplate2=new CMulitDocTemplate(

IDR_MYMDITYP2,

RUNTIME_CLASS(CMyMdiDoc2);

RUNTIME_CLASS(CChildFrame);

RUNTIME_CLASS(CMyMdiView2);

AddDocTemplate(pDocTemplate2);

}

扩展CMyMdiDoc2类、菜单处理函数和文档序列化

View视图的输出

void CMyMdiView2::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: 在此添加消息处理程序代码和/或调用默认值

CMyMdiDoc2* pDoc=(CMyMdiDoc2*)GetDocument();

m_drawData=new DrawData;

m_drawData->begin=point;

CView::OnLButtonDown(nFlags, point);

}

void CMyMdiView2::OnLButtonUp(UINT nFlags, CPoint point)

{

// TODO: 在此添加消息处理程序代码和/或调用默认值

CMyMdiDoc2* pDoc=(CMyMdiDoc2*)GetDocument();

pDoc->SetModifiedFlag(TRUE);

m_drawData->end=point;

CClientDC dc(this);

CBrush* brush=CBrush::FromHandle((HBRUSH)GetStockObject(HOLLOW_BRUSH));

dc.SelectObject(brush);

CRect rect(m_drawData->begin,m_drawData->end);

switch(pDoc->m_drawType)

{

case 0:

dc.MoveTo(m_drawData->begin);

dc.LineTo(m_drawData->end);

break;

case 1:

dc.Ellipse(rect);

break;

case 2:

dc.Rectangle(rect);

break;

}

m_drawData->type=pDoc->m_drawType;

pDoc->m_data.Add(m_drawData);

brush->DeleteObject();

Invalidate();

CView::OnLButtonUp(nFlags, point);

}

void CMyMdiView2::OnDraw(CDC* pDC)

{

CMyMdiDoc2* pDoc=(CMyMdiDoc2*)GetDocument();

// TODO: 在此添加绘制代码

CBrush* brush=CBrush::FromHandle((HBRUSH)GetStockObject(HOLLOW_BRUSH));

pDC->SelectObject(brush);

int i;

for(i=0;i<pDoc->m_data.GetCount();++i)

{

m_drawData=(DrawData*)(pDoc->m_data.GetAt(i));

CRect rect(m_drawData->begin,m_drawData->end);

switch(m_drawData->type)

{

case 0:

pDC->MoveTo(m_drawData->begin);

pDC->LineTo(m_drawData->end);

break;

case 1:

pDC->Ellipse(rect);

break;

case 2:

pDC->Rectangle(rect);

break;

}

}

brush->DeleteObject();

}

5.MFC多线程

DWORD ThreadID;

CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&ThreadID);

void ThreadFunc(){…}

五、数据库

1.有关数据库的基础知识

(1)CRecordView

用于显示和操作数据;可能会出现中文乱码的情况,解决的办法是文件->高级保存选项中选择utf8,资源视图中的所有视图的语言都选成简体中文

①可能用到的函数

CRecordView()

构造函数

OnInitialUpdate()

将CRecordView子类中的变量和数据库的数据关联起来

IsOnFirstRecord()

当前记录是否是数据库中的第一个记录

IsOnLastRecord()

当前记录是否是数据库中的最后一个记录

OnGetRecordset()

返回一个CRecordset类型的指针

OnMove()

在数据库中移动游标并将记录显示在视图控件中,有类似BOOL的返回值

②OnMove参数的取值

ID_RECORD_FIRST

移动到数据库的第一个记录

ID_RECORD_LAST

移动到数据库的最后一个记录

ID_RECORD_NEXT

向后移动一个记录

ID_RECORD_PREV

向前移动一个记录

(2)CRecordSet

表示的是数据集,有两种典型的表:动态保持数据库中的数据dynasets、静态的数据库snapshots

①成员

m_hstmt

调用Open()后包含有描述ODBC数据源的句柄

m_nFields

数据库的属性变量,它指示了从数据源读取的记录个数

m_nParams

用来指示CRecordset的派生类的参数个数,默认值是0

m_pDatabase

指向CDatabase的指针、指向当前数据库打开的数据源

m_strFilter

构造CRecordset类后、调用Open函数前,使用这个变量填写一个CString对象,就像SQL语句的WHERE条件部分

m_strSort

构造CRecordset类后、调用Open函数前,使用这个变量填写一个CString对象,就像SQL语句的ORDER BY部分

②成员函数

Open()

打开一个数据源,返回类似BOOL的值

Close()

关闭一个数据集

CanAppend()

判断打开的数据源是否允许加入新记录

CanBookmark()

判断数据源是否支持书签的功能

CanRestart()

判断数据源是否支持重新执行查询语句

CanScroll()

判断数据源是否支持翻阅的功能

CanTransact()

判断数据源是否支持事务

CanUpdate()

判断数据源是否能够更新

GetRecordCount()

获取数据库中记录的数目

GetStatus()

获取数据源的状态,这是一个CRecordsetStatus类型的指针

GetTableName()

获取一张表的名称

GetSQL()

获取一个SQL语句,这是CString类型的指针

IsOpen()

判断数据源是否已经打开

IsBOF()

判断数据库是否为空

IsEOF()

判断是否到了最后一条记录

IsDeleted()

判断指向的记录是否是一个被删除的记录

AddNew()

添加一个新纪录,调用Update()后记录才加入到数据源中去

CancelUpdate()

取消对数据源的修改,在AddNew()、Edit()之后,Update()之前才会有效

Delete()

删除当前指向的记录,游标移走后被删除的记录再无法恢复

Move()

在数据库中移动记录指针,类似的函数有MoveNext()、MovePrev()、MoveFirst()、MoveLast()、SetBookmark()、SetAbsolutePosition()

GetDefaultConnect()

获取一个默认连接的数据源

GetDefaultSQL()

获取相应的默认的SQL语句

Requery()

刷新snapshots数据库,调用前要使用Open()

③virtual BOOL Open(UINT nOpenType,LPCTSTR lpszSQL,DWORD dwOptions);的参数

nOpenType

默认方式AFX_DB_USE_DEFAULT_TYPE 、dynaset、snapshot、dynamic、只能向前翻阅forwardOnly

lpszSQL

表示SQL语句的字符串

dwOptions

选择数据的风格,可以填NULL

④dwOptions数据源的打开方式

openReadOnly

只读

useCursorLib

加载ODBC Cursor Library DLL

noOdbcDialog

不出现ODBC连接对话框

forceOdbcDialog

总要出现ODBC连接对话框

⑤virtual void Move(long nRows,WORD wFetchType);的参数

nRows是要移动的行数、wFetchType是要进行的动作

SQL_FETCH_RELATIVE

默认值,移动到距离第一个记录的指定行上

SQL_FETCH_NEXT

移到下一个记录

SQL_FETCH_PRIOR

移到上一个记录

SQL_FETCH_FIRST

移到第一个记录

SQL_FETCH_LAST

移到最后一个记录

SQL_FETCH_ABSOLUTE

nRows大于0、移到nRows行后,nRows小于0、移到倒数nRows行后,否则返回BOF

SQL_FETCH_BOOKMARK

在指定位置设置标签

(3)CDatabase

用于连接一个数据源

①可能用到的成员函数

Open()

打开一个数据源,返回类似BOOL的值

Close()

关闭一个数据源

ExecuteSQL()

执行SQL语句

CanTransact()

判断数据源是否支持事务处理

SetLoginTimeout()

设置连接超时的时间,单位是s

GetConnect()

返回当前对象的ODBC数据源的名称

Rollback()

事务回滚

GetDatabaseName()

返回当前连接的数据源的名称,这个名称不一定是ODBC控制台登记的名称

IsOpen()

判断当前对象是否连接着数据源

CanUpdate()

判断数据源是否可修改

BeginTrans()

开始一个事务的操作

CommitTrans()

提交一个数据库事务

②virtual BOOL Open(LPCTSTR lpszDSN,BOOL bExclusive,BOOL bReadOnly,LPCTSTR lpszConnect,BOOL bUseCursorLib);的参数

类似的函数是virtual BOOL OpenEX(LPCTSTR lpszConnectString,DWORD dwOptions);

lpszDSN

ODBC控制台中注册的数据源的名称,如果lpszConnect已经有DSN值的话可以取NULL

bExclusive

共享方式打开的数据源取FALSE

bReadOnly

只读

lpszConnect

包含用户和密码的描述字符串

bUseCursorLib

加载ODBC的Cursor Library DLL

lpszConnectString

包含用户和密码的描述字符串

(4)RFX

和DDX类似,RFX用于视图和数据源自动交换数据,有时候需要自定义的代码:带参数的查询、数据库中表之间的连接

(5)CDBException

抛出一个异常void AfxThrowDBException(RETCODE nRetCode,CDatabase* pdb,HSTMT hstmt);

2.建立ODBC数据源

进入Access创建一个空数据库、建立字段、填充数据,这个数据库默认用户名是admin密码为空,如果想要设置用户名和密码可以以独占读取.mdb文件的方式、在工具->安全中设置新的用户名和密码;

控制面板->管理工具-> ODBC 数据源(32 位)->系统DSN->添加.mdb->命名数据源注册的名称、选择数据库文件

3.显示数据库中的数据

如果只是和数据库的记录打交道,在项目向导中选择“不支持文件的数据库视图”;

在资源视图中设计表单的样式、定义各控件的ID;

填充数据到视图的映射代码:

void CMy3View::DoDataExchange(CDataExchange* pDX)

{

CRecordView::DoDataExchange(pDX);

// 可以在此处插入 DDX_Field* 函数以将控件“连接”到数据库字段,例如

// DDX_FieldText(pDX, IDC_MYEDITBOX, m_pSet->m_szColumn1, m_pSet);

// DDX_FieldCheck(pDX, IDC_MYCHECKBOX, m_pSet->m_bColumn2, m_pSet);

// 有关更多信息,请参阅 MSDN 和 ODBC 示例

DDX_FieldText(pDX,IDC_EDIT1,m_pSet->m_Sno,m_pSet);

DDX_FieldText(pDX,IDC_EDIT2,m_pSet->m_Sname,m_pSet);

DDX_FieldText(pDX,IDC_EDIT3,m_pSet->m_Ssex,m_pSet);

DDX_FieldText(pDX,IDC_EDIT4,m_pSet->m_Sage,m_pSet);

DDX_FieldText(pDX,IDC_EDIT5,m_pSet->m_Sdept,m_pSet);

}

4.对记录进行排序

可以在工具栏或菜单项中设计按钮、定义ID,为这个控件的COMMAND消息设计触发事件:

void CMy3View::OnSortPrice()

{

// TODO: 在此添加命令处理程序代码

m_pSet->Close();

m_pSet->m_strSort=L"Sage";

//重新使用成员变量m_strSort

//m_pSet->Open(-1,L"SELECT * FROM Student WHERE Sdept='CS'",NULL);

m_pSet->Open();

//更新表单

UpdateData(FALSE);

}

5.增添记录

清空当前表单,就可以在表单中新添一些数据:

void CMy3View::OnClearRecord()

{

// TODO: ?????í???ü?????í???ò?ú??

m_pSet->SetFieldNull(NULL);

UpdateData(FALSE);

}

在工具栏或菜单项中设计按钮、定义ID,为这个控件的COMMAND消息设计触发事件:

void CMy3View::OnRecordAdd()

{

// TODO: ?????í???ü?????í???ò?ú??

CRecordset* pSet=OnGetRecordset();

if(pSet->CanUpdate() && !pSet->IsDeleted())

{

pSet->Edit();

if(!UpdateData())

return;

pSet->Update();

}

m_pSet->AddNew();

m_pSet->Update();

m_pSet->Requery();

m_pSet->MoveLast();

UpdateData(FALSE);

}

6.删除记录

默认情况下,用户移动一个记录就会对数据库进行修改,所以需要重载View类的OnMove():

BOOL CMy3View::OnMove(UINT nIDMoveCommand)

{

// TODO: ?????í??ר???ú????/?ò?÷???ù?à

switch(nIDMoveCommand)

{

case ID_RECORD_PREV:

m_pSet->MovePrev();

if(!m_pSet->IsBOF())

break;

case ID_RECORD_FIRST:

m_pSet->MoveFirst();

break;

case ID_RECORD_NEXT:

m_pSet->MoveNext();

if(!m_pSet->IsEOF())

break;

if(!m_pSet->CanScroll())

{

m_pSet->SetFieldNull(NULL);

break;

}

case ID_RECORD_LAST:

m_pSet->MoveLast();

break;

default:

ASSERT(FALSE);

}

UpdateData(FALSE);

return TRUE;

//return CRecordView::OnMove(nIDMoveCommand);

}

在工具栏或菜单项中设计按钮、定义ID,为这个控件的COMMAND、UPDATE_COMMAND_UI消息设计触发事件:

void CMy3View::OnDeleteRecord()

{

// TODO: ?????í???ü?????í???ò?ú??

CRecordsetStatus m_cStatus;

try

{

m_pSet->Delete();

}

catch(CDBException* m_pEx)

{

AfxMessageBox(m_pEx->m_strError);

m_pEx->Delete();

m_pSet->MoveFirst();

UpdateData(FALSE);

return;

}

m_pSet->GetStatus(m_cStatus);

if(m_cStatus.m_lCurrentRecord==0)

m_pSet->MoveFirst();

else

m_pSet->MoveNext();

UpdateData(FALSE);

}

void CMy3View::OnUpdateDeleteRecord(CCmdUI *pCmdUI)

{

// TODO: ?????í???ü???ü?????§???????í???ò?ú??

pCmdUI->Enable(!m_pSet->IsEOF());

}

7.查询记录

void CMy3View::OnSearch()

{

// TODO: 在此添加命令处理程序代码

DoFilter(L"Sdept");

}

// 仅供内部重复使用的函数

void CMy3View::DoFilter(CString col)

{

CSearchDlg dlg;

if(dlg.DoModal()==IDOK)

{

CString str=col+L"='"+dlg.m_Edit_Search+L"'";

m_pSet->Close();

m_pSet->m_strFilter=str;

m_pSet->Open();

if(m_pSet->GetRecordCount()==0)

{

MessageBox(L"没有匹配的记录!");

m_pSet->Close();

m_pSet->m_strFilter=L"";

m_pSet->Open();

}

UpdateData(FALSE);

}

}

8.修改记录

默认情况下,用户移动一个记录就会对数据库进行修改,所以需要重载View类的OnMove();

在工具栏或菜单项中设计按钮、定义ID,为这个控件的COMMAND、UPDATE_COMMAND_UI消息设计触发事件:

void CMy3View::OnUpdateRecord()

{

// TODO: ?????í???ü?????í???ò?ú??

m_pSet->Edit();

UpdateData(TRUE);

if(m_pSet->CanUpdate())

{

m_pSet->Update();

}

}

void CMy3View::OnUpdateUpdateRecord(CCmdUI *pCmdUI)

{

// TODO: ?????í???ü???ü?????§???????í???ò?ú??

pCmdUI->Enable(!m_pSet->IsEOF());

}

9.移动到指定的位置

在资源视图中建立对话框和相关的类、编辑框的变量m_RecordID;

在工具栏或菜单项中设计按钮、定义ID,为这个控件的COMMAND消息设计触发事件:

void CMy3View::OnMovetorecord()

{

// TODO: ?????í???ü?????í???ò?ú??

CMoveToRecord dlgMoveTo;

if(dlgMoveTo.DoModal()==IDOK)

{

CRecordset* pSet=OnGetRecordset();

if(pSet->CanUpdate() && !pSet->IsDeleted())

{

pSet->Edit();

if(!UpdateData())

return;

pSet->Update();

}

pSet->SetAbsolutePosition(dlgMoveTo.m_RecordID);

UpdateData(FALSE);

}

}

六、多媒体

1.音频播放

(1)使用音频函数的方式

①BOOL MessageBeep(UINT nType);播放系统提示音

0xFFFFFFFF

系统默认的声音

MB_ICONINFORMATION或MB_ICONASTERISK

出现信息消息框时的声音

MB_ICONEXLAMATION或MB_ICONWARNING

出现警告消息框时的声音

MB_ICONHAND或MB_ICONSTOP或MB_ICONERROR

出现错误提示框时的声音

MB_ICONQUESTION

出现询问对话框时的声音

MB_OK

系统默认声音

②BOOL sndPlaySound(LPCSTR lpszSound,UINT fuSound);播放指定文件名或是注册表中已有的声音

fuSound播放标识

SND_ASYNC

异步播放声音,进入函数后立即返回,终止的办法是sndPlaySound(…,NULL);

SND_LOOP

循环播放声音,但是要和SND_ASYNC一同使用,终止办法和上一个相同

SND_MEMORY

第一个参数是.wav在内存中的映像

SND_NODEFAULT

当无法正常播放声音时不播放系统默认声音

SND_NOSTOP

如果有声音正在播放,则返回FALSE、终止运行

SND_SYNC

同步方式播放声音,只有声音播放结束才返回结果

注册表中已有的声音

SystemAsterisk

出现信息消息框时的声音

SystemExclamation

出现警告消息框时的声音

SystemExit

系统退出时的提示音

SystemHand

出现错误提示框时的声音

SystemQuestion

出现询问对话框时的声音

SystemStart

系统启动提示音

③BOOL PlaySound(LPCSTR pszSound,HMODULE hmod,DWORD fdwSound);

fdwSound指定声音的来源,如果没有指定先到注册表中找、再到文件中找;NULL表示停止当前.wav声音,SND_PURGE表示停止其他声音;hmod是资源文件的句柄。

fdwSound的取值

SND_ALIAS

注册条目

SND_RESOURCE

来自资源

SND_FILENAME

来自文件

SND_NOWAIT

如果设备正使用,立即返回不再播放

SND_APPLICATION

用用应用程序制定的音频

SND_PURGE

停止声音播放

SND_ALIAS_ID

预先确定的声音标识

(2)使用MCI的方式

MCI指的是媒体控制接口类Media Control Interface,可以支持更复杂的音频操作:暂停、向前搜索、向后搜索、对音频文件进行编辑等;对MCI设备进行控制的两个方法,MCI命令串mciSendString()、MCI命令消息mciSendCommand(),但是发送命令消息要比发送命令字串要高效。

①可能用到的函数

MCIERROR mciSendCommand(

//接收命令消息的MCI设备ID,可以通过MCI_OPEN()获得

// MCIERROR的低字节存储错误值、高字节存储设备标识,执行正确的返回结果MCIERROR为0

MCIDEVICEID IDDevice,

//要发送的命令消息

UINT uMsg,

//命令消息的标志集

DWORD fdwCommand,

//包含命令消息参数的结构体地址

DWORD_PTR dwParam);

要发送的命令消息uMsg

MCI_BREAK

为MCI设备设置终止键,默认是ctrl+break

全部设备

MCI_STATUS

获取一个MCI设备的信息

MCI_CLOSE

释放出访问设备的通道

MCI_SYSINFO

获取MCI设备的信息

MCI_GETDEVCAPS

获取一个设备的静态信息

MCI_INFO

获取一个设备的字串信息

MCI_OPEN

初始化一个设备

MCI_CAPTURE

获取缓冲区中每一帧的内容并存入指定文件

数字视频

MCI_CONFIGURE

显示一个对话框用于设置操作

MCI_UNDO

撤销最近一次操作

MCI_LOAD

加载一个文件

MCI_PUT

设置来源、目的和框架矩形

MCI_UPDATE

更新显示矩形

MCI_COPY

拷贝数据到粘贴板

MCI_WHERE

获取视频设备的剪切板模型

MCI_WINDOW

指定窗口和窗口特性用于图形设备

MCI_CUT

剪切数据到粘贴板

MCI_MONITOR

指定陈述的来源

MCI_PASTE

将粘贴板上的数据粘贴到文件中

MCI_QUALITY

指定多媒体的质量

MCI_RESERVE

为下面的记录分配一块磁盘空间

MCI_RESTORE

将一幅位图由文件拷贝到缓冲区中

MCI_SIGNAL

在工作区中设置一个指定位置

MCI_PAUSE

暂停当前播放的位置

CD音频、数字视频、MIDI序列、录像机、影碟机、.wav文件

MCI_PLAY

设备开始输出数据

MCI_SET

设置设备信息

MCI_STOP

停止所有的播放记录并释放缓存

MCI_CUE

提示一个设备、使设备以最小的延迟进行播放或重放

数字视频、录像机、.wav文件

MCI_RESUME

恢复被暂停的操作

MCI_FREEZE

冻结显示中的画面

数字视频、录像机

MCI_LIST

获取可用于输入设备关于数量和类型方面的信息

MCI_SETAUDIO

设置与音频回放、捕捉相关的变量

MCI_SETVIDEO

设置与视频回放相关的变量

MCI_UNFREEZE

恢复执行了MCI_FREEZE命令的设备

MCI_DELETE

删除文件中的数据

数字视频、.wav文件

MCI_ESCAPE

直接发送一个字串到指定设备

影碟机

MCI_SPIN

使设备开始转动或停止

MCI_INDEX

将屏幕上的显示置为on或off

录像机

MCI_SETTIMECODE

使用或禁用VCR设备录音的时间代码

MCI_SETTUNER

设置调制器的当前频道

MCI_MARK

记录或擦除以使MCI_SEEK命令获得更高的寻找速度

MCI_RECORD

从当前位置或指定的起始、终止位置开始记录

录像机、.wav文件

MCI_SAVE

保存当前文件

.wav文件

MCI_SEEK

以最快的速度改变当前内容的输出位置

CD音频、数字视频、MIDI序列、录像机、影碟机

MCI_STEP

跳过一帧或多帧

数字视频、录像机、CAV格式影碟机

检测错误

BOOL mciGetErrorString(

//错误代码

DWORD fdwError,

//用于描述错误内容的字符串

LPTSTR lpszErrorText,

//错误内容的缓冲区容量

UINT cchErrorText);

②环境配置:在stdafx.h中_AFX_NO_AFXCMN_SUPPORT下面添加#include <mmsystem.h>;

右击工程->属性->链接器->输入,在附加依赖项中输入winmm.lib

③对话框类中添加可能用到的数据:

// 判断正在播放的标志

BOOL m_PSign;

// 判断正在暂停的标志

BOOL m_ASign;

// 用来存储错误代码

DWORD dwError;

// 用来存储打开设备的ID值

MCIDEVICEID m_MCIDeviceID;

// 用来存储出错的内容

char szErrorBuf[MAXERRORLENGTH];

④选择要播放的音乐

void CMy0Dlg::OnOpenButton()

{

// TODO: 在此添加控件通知处理程序代码

//文件名

CString fileName;

//文件扩展名

CString fileExt;

MCI_OPEN_PARMS mciOpenParms;

DWORD dwError;

static TCHAR szFilter[]=L"波形音频文件(*.wav)|*.wav|MIDI序列(*.mid)|*.mid||";

CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter);

if(dlg.DoModal()==IDOK)

{

//这个地方可能有问题?

fileName=dlg.GetFolderPath()+L"\\"+dlg.GetFileName();

fileExt=dlg.GetFileExt();

//AfxMessageBox(L"fileName: "+fileName+L"\nfileExt: "+fileExt);

//如果程序正在播放则关闭

if(m_PSign)

{

dwError=mciSendCommand(m_MCIDeviceID,MCI_CLOSE,0,NULL);

if(dwError)

{

if(mciGetErrorString(dwError,(LPTSTR)szErrorBuf,MAXERRORLENGTH))

MessageBox((LPCTSTR)szErrorBuf,L"MCI出错0",MB_ICONWARNING);

else

MessageBox(L"不明错误标识",L"MCI出错0",MB_ICONWARNING);

return;

}

}

if(!_tcscmp(L"wav",fileExt))

mciOpenParms.lpstrDeviceType=L"waveaudio";

else if(!_tcscmp(L"mid",fileExt))

mciOpenParms.lpstrDeviceType=L"sequencer";

mciOpenParms.lpstrElementName=fileName;

//将打开的文件名存入mciOpenParms结构体中

dwError=mciSendCommand(0,MCI_OPEN,MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOpenParms);

if(dwError)

{

if(mciGetErrorString(dwError,(LPTSTR)szErrorBuf,MAXERRORLENGTH))

MessageBox((LPCTSTR)szErrorBuf,L"MCI出错1",MB_ICONWARNING);

else

MessageBox(L"不明错误标识",L"MCI出错1",MB_ICONWARNING);

return;

}

m_MCIDeviceID=mciOpenParms.wDeviceID;

m_PSign=FALSE;

m_ASign=FALSE;

}

}

⑤播放音乐

void CMy0Dlg::OnBnClickedPlayButton()

{

// TODO: 在此添加控件通知处理程序代码

//存储与播放有关的信息

MCI_PLAY_PARMS mciPlayParms;

//如果没有正在播放的声音

if(!m_PSign)

{

//为MM_MCINOTIFY消息指定窗口句柄

mciPlayParms.dwCallback=(long)GetSafeHwnd();

//播放位置从头开始

mciPlayParms.dwFrom=0;

dwError=mciSendCommand(m_MCIDeviceID,MCI_PLAY,MCI_FROM|MCI_NOTIFY,(DWORD)(LPVOID)&mciPlayParms);

if(dwError)

{

if(mciGetErrorString(dwError,(LPTSTR)szErrorBuf,MAXERRORLENGTH))

MessageBox((LPCTSTR)szErrorBuf,L"MCI出错",MB_ICONWARNING);

else

MessageBox(L"不明错误标识",L"MCI出错",MB_ICONWARNING);

return;

}

m_PSign=TRUE;

}

}

⑥暂停/继续

void CMy0Dlg::OnBnClickedPauseButton()

{

// TODO: 在此添加控件通知处理程序代码

//有正在播放的声音

if(m_PSign)

{

//不是暂停状态

if(!m_ASign)

{

dwError=mciSendCommand(m_MCIDeviceID,MCI_PAUSE,0,NULL);

if(dwError)

{

if(mciGetErrorString(dwError,(LPTSTR)szErrorBuf,MAXERRORLENGTH))

MessageBox((LPCTSTR)szErrorBuf,L"MCI出错",MB_ICONWARNING);

else

MessageBox(L"不明错误标识",L"MCI出错",MB_ICONWARNING);

return;

}

m_ASign=TRUE;

}

else

{

dwError=mciSendCommand(m_MCIDeviceID,MCI_RESUME,0,NULL);

if(dwError)

{

if(mciGetErrorString(dwError,(LPTSTR)szErrorBuf,MAXERRORLENGTH))

MessageBox((LPCTSTR)szErrorBuf,L"MCI出错",MB_ICONWARNING);

else

MessageBox(L"不明错误标识",L"MCI出错",MB_ICONWARNING);

return;

}

m_ASign=FALSE;

}

}

}

⑦播放结束后需要响应MM_MCINOTIFY,对类中的标记做修改

对话框的头文件中添加

afx_msg LRESULT MciNotify(WPARAM wParam,LPARAM lParam);

对话框的源文件中添加消息映射

ON_MESSAGE(MM_MCINOTIFY,MciNotify)

定义做出响应的函数

LRESULT CMy0Dlg::MciNotify(WPARAM wParam,LPARAM lParam)

{

if(wParam==MCI_NOTIFY_SUCCESSFUL)

{

AfxMessageBox(L"enter.");

m_PSign=FALSE;

m_ASign=FALSE;

return 0;

}

return -1;

}

2.视频播放

资源视图->右键->插入ActiveX控件->选择Windows Media Player;

项目->添加类->ActiveX控件中的MFC类;

来源选择“文件”,“位置”是C:\windows\system32\wmp.dll,“接口”选择IWMPPlayer4;

对话框类的头文件中加入#include “CWMPPlayer4.h”;

再次进入资源视图,为这个ActiveX控件添加变量m_mediaPlay;

为这个ActiveX控件添加触发事件:

void CMy0Dlg::DoubleClickOcx1(short nButton, short nShiftState, long fX, long fY)

{

// TODO: 在此处添加消息处理程序代码

CFileDialog dlg(TRUE,NULL,L"*.*",OFN_FILEMUSTEXIST,

L"ActiveStreamingFormat(*.asf)|*.asf|"

L"AudioVidesInterleaveFormat(*.avi)|*.avi|"

L"RealAudio/RealVideo(*.rm)|*.rm|"

L"WaveAudio(*wav)|*.wav|"

L"MIDIFile(*.mid)|*.mid|"

L"所有文件(*.*)|*.*||");

if(dlg.DoModal()==IDOK)

m_mediaPlay.put_URL(dlg.GetPathName());

}

3.图片显示

OleLoadPicture支持加载.png、.jpg、.gif等格式的图片

(1) 创建SDI工程
(2) 在View类中添加数据成员:

// 用来装载图片的变量

LPPICTURE m_pPicture;

// 是否压缩显示

BOOL m_bScale;

(3) 新数据成员的初始化和销毁:

CMy4View::CMy4View()

: m_bScale(FALSE)

{

// TODO: 在此处添加构造代码

m_pPicture=NULL;

m_bScale=FALSE;

}

CMy4View::~CMy4View()

{

if(m_pPicture)

{

m_pPicture->Release();

}

}

(4) 通过菜单项打开文件:

void CMy4View::OnOperOpen()

{

// TODO: 在此添加命令处理程序代码

//保存文件名的缓冲,有必要测试下这个对象!

TCHAR szFile[MAX_PATH];

//初始化该缓冲

ZeroMemory(szFile,MAX_PATH);

//用于打开文件的结构体

OPENFILENAME ofn;

//初始化该结构

ZeroMemory(&ofn,sizeof(OPENFILENAME));

//设置结构的大小

ofn.lStructSize=sizeof(OPENFILENAME);

ofn.Flags=OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY;

//文件框的父窗口

ofn.hwndOwner=m_hWnd;

ofn.lpstrFilter=

L"Supported Files Types(*.bmp;*.gif;*.jpg;*.ico;*.emf;*.wmf)\0*.bmp;*.gif;*.jpg;*.ico;*.emf;*.wmf\0"

L"Bitmaps(*.bmp)\0*.bmp\0"

L"GIF Files(*.gif)\0*.gif\0"

L"JPEG Files(*.jpg)\0*.jpg\0"

L"Icons(*.ico)\0*.ico\0"

L"Enhanced Metafiles(*.emf)\0*.emf\0"

L"Windows Metafiles(*.wmf)\0*.wmf\0\0";

//文件框的标题

ofn.lpstrTitle=L"选择图片";

//返回文件名的缓冲

ofn.lpstrFile=szFile;

//设置缓冲的长度

ofn.nMaxFile=MAX_PATH;

if(GetOpenFileName(&ofn)==IDOK)

loadPicture(szFile);

}

void CMy4View::loadPicture(CString strFile)

{

//打开文件

HANDLE hFile=CreateFile(strFile,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);

_ASSERTE(INVALID_HANDLE_VALUE!=hFile);

//获取文件的大小

DWORD dwFileSize=GetFileSize(hFile,NULL);

_ASSERTE(dwFileSize!=-1);

LPVOID pvData=NULL;

//分配全局内存,获取内存句柄

HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE,dwFileSize);

_ASSERTE(hGlobal!=NULL);

//锁定内存,获取内存指针

pvData=GlobalLock(hGlobal);

_ASSERTE(pvData!=NULL);

DWORD dwBytesRead=0;

//读取文件

BOOL hRead=ReadFile(hFile,pvData,dwFileSize,&dwBytesRead,NULL);

_ASSERTE(hRead!=FALSE);

GlobalUnlock(hGlobal);

CloseHandle(hFile);

LPSTREAM pstm=NULL;

//从内存数据创建IStream*

HRESULT hr=CreateStreamOnHGlobal(hGlobal,TRUE,&pstm);

_ASSERTE(pstm&&SUCCEEDED(hr));

if(m_pPicture)

m_pPicture->Release();

//赋值、全局作用域(Windows api),从IStream接口加载图片到IPicture中

hr=::OleLoadPicture(pstm,dwFileSize,FALSE,IID_IPicture,(LPVOID*)&m_pPicture);

_ASSERTE(m_pPicture&&SUCCEEDED(hr));

pstm->Release();

Invalidate();

}

(5) 对图片进行绘制:

void CMy4View::OnDraw(CDC* pDC)

{

CMy4Doc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!pDoc)

return;

// TODO: 在此处为本机数据添加绘制代码

if(m_pPicture)

{

long hmWidth;

long hmHeight;

m_pPicture->get_Width(&hmWidth);

m_pPicture->get_Height(&hmHeight);

int nWidth=MulDiv(hmWidth,GetDeviceCaps(pDC->GetSafeHdc(),LOGPIXELSX),HIMETRIC_INCH);

int nHeight=MulDiv(hmHeight,GetDeviceCaps(pDC->GetSafeHdc(),LOGPIXELSY),HIMETRIC_INCH);

CRect rc;

GetClientRect(&rc);

if(m_bScale)

{

//创建内存DC

CDC memdc;

memdc.CreateCompatibleDC(pDC);

//创建位图

CBitmap bmp;

bmp.CreateCompatibleBitmap(pDC,nWidth,nHeight);

//将位图选入内存DC

memdc.SelectObject(bmp);

//将图片以原始尺寸绘制到内存DC中

m_pPicture->Render(memdc.GetSafeHdc(),0,0,nWidth,nHeight,0,hmHeight,hmWidth,-hmHeight,&rc);

//从内存DC缩放拷贝到显示DC

pDC->StretchBlt(0,0,nWidth/2,nHeight/2,&memdc,0,0,nWidth,nHeight,SRCCOPY);

}

else

m_pPicture->Render(pDC->GetSafeHdc(),0,0,nWidth,nHeight,0,hmHeight,hmWidth,-hmHeight,&rc);

}

}

//通过菜单项控制是否缩放

void CMy4View::OnOperSize()

{

// TODO: 在此添加命令处理程序代码

m_bScale=!m_bScale;

Invalidate();

}

void CMy4View::OnUpdateOperSize(CCmdUI *pCmdUI)

{

// TODO: 在此添加命令更新用户界面处理程序代码

pCmdUI->SetCheck(m_bScale);

}

七、网络编程

1.利用WinInet抓取网页

对基于对话框的MFC工程设置设置属性:

工程->属性->链接器->输入WinInet.lib

为CInternetSession m_session;封装一个类;

从网页获取信息:

CString MyWinInetClass::ConnectHttp(const CString sUrl)

{

CString sResult;

CInternetFile* hHttpFile=NULL;

sResult=L"";

sResult=sResult+L"Trying to connect Http sites: "+sUrl+L"\r\n";

hHttpFile=(CInternetFile*)m_session.OpenURL(sUrl);

if(hHttpFile)

{

sResult=sResult+L"Connection established.\r\n";

CString sLine;

while(hHttpFile->ReadString(sLine))

sResult=sResult+sLine+L"\r\n";

hHttpFile->Close();

}

else

sResult=sResult+L"There are some errors in finding this Http sites";

return sResult;

}

更新界面UI:

void CMy5Dlg::OnBnClickedButtonHttp()

{

// TODO: 在此添加控件通知处理程序代码

UpdateData(TRUE);

m_editResult=L"";

m_editResult=m_editResult+m_WinInetClass.ConnectHttp(m_url);

UpdateData(FALSE);

}

八、附录

1.Visual Studio 2008的快捷键

f9

设置断点

f5

编译

ctrl+f5

运行

ctrl+shift+n

新建项目

ctrl+n

新建文件

ctrl+k+c

注释一行

ctrl+k+u

反注释一行

ctrl+h

快速替换

ctrl+j

对象的成员提示

ctrl+]

括号匹配

ctrl+shift+]

选中括号匹配中的代码

ctrl+c,ctrl+x

可以是行操作,不用选中

ctrl+l

删除一行

ctrl+tab

子窗口切换

alt+右箭头

自动补全、方法提示

ctrl+k

添加书签

shift+f2

到下一个书签

f2

到上一个书签

crl+a,ctrl+k+f

格式化代码

上一篇:python_restframework(认证组件)


下一篇:Java Spring Webflux上传文件MultipartFile问题(415 UnsupportedMediaTypeStatusException)