MFC学习笔记(1)--对话框

参考:鸡啄米 VS2010/MFC编程入门教程之目录和总结http://www.jizhuomi.com/software/257.html

1 对话框控件常用属性

ID:
对话框ID,唯一标识对话框资源,可以修改。
Caption:
对话框标题。
Border:
边框类型。有四种类型:None、Thin、Resizing和Dialog Frame。
Maximize:
是否使用最大化按钮。
Minimize:
是否使用最小化按钮。
Style:
对话框类型。有三种类型:Overlapped(重叠窗口)、Popup(弹出式窗口)和Child(子窗口)。弹出式窗口比较常见。
System Menu:
是否带有标题栏左上角的系统菜单,包括移动、关闭等菜单项。
Title Bar:
是否带有标题栏。
Font(Size):
字体类型和字体大小。如果将其修改为非系统字体,则Use System自动改为False。而如果Use System原来为False,将其修改为True,则Font(Size)自动设置为系统字体。

2 创建对话框和对话窗类

  • (1)在Resource View的“Dialog”节点上右键,然后在右键菜单中选择“Insert Dialog”创建一个新的对话框模板。
    (2)在中间区域会显示新建的对话框模板,然后选中此对话框模板,点右键,在右键菜单中选择Add Class。
    (3)选择“Add Class”后会弹出一个对话框,在对话框中“Class name”下的编辑框中写入自定义的类名。

    注意,一般类名都以C打头,又比如,CTestDlg。

3 为对话框中的控件添加变量

  1. 在编辑框上点右键,在右键菜单中选择“Add Variable”。弹出添加成员变量的向导对话框。
  2. 为其添加值变量而不是控件变量,所以对话框中“Category”下的组合框中选择Value。
  3. “Variable type”下的组合框此时默认选中的是“CString”,CString是字符串类,可以选择double、float、int等。
  4. 在“Variable name”中写入自定义的变量名。
  5. 点“Finish”完成。

    注意,类的成员变量名一般以m_打头,以标识它是一个成员变量。

4 对话框类的数据交换和检验

控件的属性改变后MFC会相应修改控件关联变量的值。这种同步的改变是通过MFC为对话框类自动生成的成员函数DoDataExchange()来实现的,这也叫做对话框的数据交换和检验机制。
按照3方法添加变量后会自动在DoDataExchange()函数的函数体中增加调用语句。
DoDataExchange()并不是被自动调用的,而是需要我们在程序中调用CDialogEx::UpdateData()函数,由UpdateData()函数再去自动调用DoDataExchange()的。

CDialogEx::UpdateData()函数的原型为:

   BOOL UpdateData(BOOL bSaveAndValidate = TRUE);

   参数:bSaveAndValidate用于指示数据传输的方向,TRUE表示从控件传给变量,FALSE表示从变量传给控件。默认值是TRUE,即从控件传给变量。

   返回值:CDialogEx::UpdateData()函数的返回值表示操作是否成功,成功则返回TRUE,否则返回FALSE。

5 为控件添加消息处理函数

  1. 在按钮的属性视图中添加消息处理函数。
    点属性视图的“Control Events”按钮(类似闪电标志),点击按钮后的消息处理函数(BN_CLICKED)点其右侧空白列表项,会出现一个带下箭头的按钮,再点此按钮会出现“add OnBnClicked****Button”选项,最后选中这个选项就会自动添加BN_CLICKED处理函数了。

  2. 双击按钮添加消息处理函数
    最直接最简单的方法就是,双击按钮控件,MFC会自动为其在C****Dlg类中添加BN_CLICKED消息的处理函数OnBnClicked****Button()。

在加法计算器程序中,我们想要“计算”按钮实现的功能是,获取被加数和加数的数值,然后计算它们的和并显示到和的编辑框里。那么,OnBnClickedAddButton()的函数体就应修改为:

void CAdditionDlg::OnBnClickedAddButton()   
{   
    // TODO: Add your control notification handler code here   
    // 将各控件中的数据保存到相应的变量   
    UpdateData(TRUE);   

    // 将被加数和加数的加和赋值给m_editSum   
    m_editSum = m_editSummand + m_editAddend;   

    // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    UpdateData(FALSE);   
}  

6 设置对话框控件的Tab顺序

在主菜单中选择“Format”->”Tab Order”,或者按快捷键Ctrl+D,对话框模板上就会显示各个控件的Tab顺序数字。
从自己认为Tab顺序应该为1的控件开始依次单击。

7 模态对话窗及其弹出过程

http://www.jizhuomi.com/software/160.html
Windows对话框分为两类:模态对话框非模态对话框

  • 模态对话框
    当它弹出后,本应用程序其他窗口将不再接受用户输入,只有该对话框响应用户输入,在对它进行相应操作退出后,其他窗口才能继续与用户交互。
  • 非模态对话框
    它弹出后,本程序其他窗口仍能响应用户输入。非模态对话框一般用来显示提示信息等。

弹出对话框比较关键的一个函数,就是对话框类的DoModal()函数。CDialog::DoModal()函数的原型为:

   virtual INT_PTR DoModal();   

   返回值:整数值,指定了传递给CDialog::EndDialog(该函数用于关闭对话框)的nResult参数值。如果函数不能创建对话框,则返回-1;如果出现其它错误,则返回IDABORT。

   调用了它对话框就会弹出,返回值是退出对话框时所点的按钮的ID,比如,我们点了“退出”按钮,那么DoModal返回值为IDCANCEL。

演示:添加一个新对话框并弹出它

  1. 在对话框模板上点右键选择“Add Class…”,弹出添加类的对话框,设置“Class name”为CTipDlg,点“OK”。在Solution Explorer中可以看到生成了CTipDlg类的头文件TipDlg.h和源文件TipDlg.cpp。
  2. 要在点“计算”按钮之后弹出此提示对话框,那么就要在“计算”按钮的消息处理函数OnBnClickedAddButton()中访问提示对话框类,所以为了访问CTipDlg类,在AdditionDlg.cpp中包含CTipDlg的头文件:#include “TipDlg.h”。
  3. 修改OnBnClickedAddButton()的函数体,在所有代码前,构造CTipDlg类的对象tipDlg,并通过语句tipDlg.DoModal();弹出对话框,最后判断DoModal()函数的返回值是IDOK还是IDCANCEL来确定是否继续进行计算。OnBnClickedAddButton()函数修改后如下:
void CAdditionDlg::OnBnClickedAddButton()   
{   
    // TODO: Add your control notification handler code here   
    INT_PTR nRes;             // 用于保存DoModal函数的返回值   

    CTipDlg tipDlg;           // 构造对话框类CTipDlg的实例   
    nRes = tipDlg.DoModal();  // 弹出对话框   
    if (IDCANCEL == nRes)     // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行   
        return;   

    // 将各控件中的数据保存到相应的变量   
    UpdateData(TRUE);   

    // 将被加数和加数的加和赋值给m_editSum   
    m_editSum = m_editSummand + m_editAddend;   

    // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    UpdateData(FALSE);   
}  

8 非模态对话框的创建及显示

http://www.jizhuomi.com/software/162.html
模态对话框和非模态对话框在创建对话框资源和生成对话框类上是没有区别的,所以上一讲中创建的IDD_TIP_DIALOG对话框资源和CTipDlg类都不需要修改。
需要修改的是,对话框类实例的创建和显示,也就是之前在CAdditionDlg::OnBnClickedAddButton()函数体中添加的对话框显示代码。下面是具体步骤:

  1. 在AdditionDlg.h中包含CTipDlg头文件并定义CTipDlg类型的指针成员变量。详细操作方法是,在AdditionDlg.cpp中删除之前添加的#include “TipDlg.h”,而在AdditionDlg.h中添加#include “TipDlg.h”,这是因为需要在AdditionDlg.h中定义CTipDlg类型的指针变量,所以要先包含它的头文件;然后在AdditionDlg.h中为CAdditionDlg类添加private成员变量CTipDlg *m_pTipDlg;。
  2. 在CAdditionDlg类的构造函数中初始化成员变量m_pTipDlg。如果cpp文件中函数太多,可以在Class View上半个视图中找到CAdditionDlg类,再在下半个视图中找到其构造函数双击,中间客户区域即可马上切到构造函数的实现处。在构造函数体中添加m_pTipDlg = NULL;,这是个好习惯,在任何指针变量使用前都初始化,可以避免因误访问重要内存地址而破坏此地址的数据。
  3. 将上一讲中添加的模态对话框显示代码注释或删除掉,添加非模态对话框的创建和显示代码,修改后的CAdditionDlg::OnBnClickedAddButton()函数如下:
void CAdditionDlg::OnBnClickedAddButton()   
{   
    // TODO: Add your control notification handler code here   
    /*INT_PTR nRes;             // 用于保存DoModal函数的返回值  

    CTipDlg tipDlg;           // 构造对话框类CTipDlg的实例  
    nRes = tipDlg.DoModal();  // 弹出对话框  
    if (IDCANCEL == nRes)     // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行  
        return;*/  

    // 如果指针变量m_pTipDlg的值为NULL,则对话框还未创建,需要动态创建   
    if (NULL == m_pTipDlg)   
    {   
        // 创建非模态对话框实例   
        m_pTipDlg = new CTipDlg();   
        m_pTipDlg->Create(IDD_TIP_DIALOG, this);   
    }   
    // 显示非模态对话框   
    m_pTipDlg->ShowWindow(SW_SHOW);   

    // 将各控件中的数据保存到相应的变量   
    UpdateData(TRUE);   

    // 将被加数和加数的加和赋值给m_editSum   
    m_editSum = m_editSummand + m_editAddend;   

    // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    UpdateData(FALSE);   
}  

因为此非模态对话框实例是动态创建的,所以需要手动删除此动态对象来销毁对话框。在CAdditionDlg类的析构函数中添加删除代码,但是MFC并没有自动给出析构函数,这时需要手动添加,在对话框对象析构时就会调用自定义的析构函数了。在AdditionDlg.h文件中为CAdditionDlg添加析构函数声明:~CAdditionDlg();,然后在AdditionDlg.cpp文件中添加析构函数的实现,函数体如下:

CAdditionDlg::~CAdditionDlg()   
{   
    // 如果非模态对话框已经创建则删除它   
    if (NULL != m_pTipDlg)   
    {   
        // 删除非模态对话框对象   
        delete m_pTipDlg;   
    }   
}  

9 属性页对话框及相关类的介绍

http://www.jizhuomi.com/software/164.html

10 向导对话框的创建及显示

http://www.jizhuomi.com/software/166.html

11 一般属性页对话框的创建及显示

http://www.jizhuomi.com/software/169.html

12 消息对话框

http://www.jizhuomi.com/software/171.html
MFC提供了两个函数可以直接生成指定风格的消息对话框,而不需要在每次使用的时候都要去创建对话框资源和生成对话框类等。这两个函数就是CWnd类的成员函数MessageBox()和全局函数AfxMessageBox()。
1.CWnd::MessageBox()函数

   CWnd::MessageBox()的函数原型如下:

   int MessageBox(
       LPCTSTR lpszText,
       LPCTSTR lpszCaption = NULL,
       UINT nType = MB_OK 
   );

   参数说明:

   lpszText:需要显示的消息字符串。

   lpszCaption:消息对话框的标题字符串。默认值为NULL。取值为NULL时使用默认标题。

   nType:消息对话框的风格和属性。默认为MB_OK风格,即只有“确定”按钮。

   nType的取值可以是下面两个表中任取一个值,也可以是各取一个值的任意组合。即可以指定一个对话框类型,也可以指定一个对话框图标,还可以两者都设定。

nType 取值 参数说明
MB_ABORTRETRY 有“终止”、“重试”和“忽略”按钮
MB_OK 有“确定”按钮
MB_OKCANCEL 有“确定”和“取消”按钮
MB_RETRYCANCEL 有“重试”和“取消”按钮
MB_YESNO 有“是”和“否”按钮
MB_YESNOCANCEL 有“是”、“否”和“取消”按钮
nType 取值 显示图标
MB_ICONEXCLAMTION
MB_ICONWARNING
MB_ICONASTERISK
MB_ICONINFORMATION
MB_ICONQUESTION
MB_ICONHAND
MB_ICONSTOP
MB_ICONERROR
如果想要设置nType的值为类型和图标的组合,可以像这样取值:MB_OKCANCEL | MB_ICONQUESTION。按位取或就可以了。

2.AfxMessageBox()函数

   AfxMessageBox()的函数原型为:

   int AfxMessageBox(
       LPCTSTR lpszText,
       UINT nType = MB_OK,
       UINT nIDHelp = 0 
   );

   参数说明:

   lpszText:同CWnd::MessageBox()函数

   nType:CWnd::MessageBox()函数

   nIDHelp:此消息的帮助的上下文ID。默认值为0,取0时表示要使用应用程序的默认帮助上下文。

CWnd::MessageBox()和AfxMessageBox()的返回值
调用了上面两个函数后,都可以弹出模态消息对话框。消息对话框关闭后,我们也都可以得到它们的返回值。两者的返回值就是用户在消息对话框上单击的按钮的ID,可以是以下值:

  IDABORT:单击“终止”按钮。
  IDCANCEL:单击“取消”按钮。
  IDIGNORE:单击“忽略”按钮。
  IDNO:单击“否”按钮。
  IDOK:单击“确定”按钮。
  IDRETRY:单击“重试”按钮。
  IDYES:单击“是”按钮。
    INT_PTR nRes;   
    INT_PTR nRes;   
    // 显示消息对话框   
    nRes = MessageBox(_T("您确定要进行加法计算吗?"), _T("加法计算器"), MB_OKCANCEL | MB_ICONQUESTION);   
    // 判断消息对话框返回值。如果为IDCANCELreturn,否则继续向下执行   
    if (IDCANCEL == nRes)   
        return;   

13 文件对话框

http://www.jizhuomi.com/software/173.html
文件对话框分为打开文件对话框和保存文件对话框,打开文件对话框用于选择要打开的文件的路径,保存文件对话框用来选择要保存的文件的路径。

文件对话框类CFileDialog

  MFC使用文件对话框类CFileDialog封装了对文件对话框的操作。CFileDialog类的构造函数原型如下:

explicit CFileDialog(
BOOL bOpenFileDialog,
LPCTSTR lpszDefExt = NULL,
LPCTSTR lpszFileName = NULL,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL,
CWnd* pParentWnd = NULL,
DWORD dwSize = 0,
BOOL bVistaStyle = TRUE
);

   参数说明:

   bOpenFileDialog:指定要创建的文件对话框的类型。设为TRUE将创建打开文件对话框,否则将创建保存文件对话框。

   lpszDefExt:默认的文件扩展名。如果用户在文件名编辑框中没有输入扩展名,则由lpszDefExt指定的扩展名将被自动添加到文件名后。默认为NULL。

   lpszFileName:文件名编辑框中显示的初始文件名。如果为NULL,则不显示初始文件名。

   dwFlags:文件对话框的属性,可以是一个值也可以是多个值的组合。关于属性值的定义,可以在MSDN中查找结构体OPENFILENAME,元素Flags的说明中包含了所有属性值。默认为OFN_HIDEREADONLY和OFN_OVERWRITEPROMPT的组合,OFN_HIDEREADONLY表示隐藏文件对话框上的“Read Only”复选框,OFN_OVERWRITEPROMPT表示在保存文件对话框中如果你选择的文件存在了,就弹出一个消息对话框,要求确定是否要覆盖此文件。

   lpszFilter:文件过滤器,它是由若干字符串对组成的一个字符串序列。如果指定了文件过滤器,则文件对话框中只有符合过滤条件的文件显示在文件列表中待选择。给大家看看VS2010 MSDN中给出的一个例子:

   static TCHAR BASED_CODE szFilter[] = _T("Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|*.xlc; *.xls|All Files (*.*)|*.*||");

   这样设置过滤器以后,文件对话框的扩展名组合框中将有四个选项:Chart Files (*.xlc)、Worksheet Files (*.xls)、Data Files(*.xlc;*.xls)和All Files (*.*),大家可以看到每种文件的扩展名规定都是一个字符串对,例如Chart Files的过滤字符串是Chart Files(*.xlc)和*.xlc成对出现的。

   pParentWnd:文件对话框的父窗口的指针。

   dwSize:OPENFILENAME结构体的大小。不同的操作系统对应不同的dwSize值。MFC通过此参数决定文件对话框的适当类型(例如,创建Windows 2000文件对话框还是XP文件对话框)。默认为0,表示MFC将根据程序运行的操作系统版本来决定使用哪种文件对话框。

   bVistaStyle:指定文件对话框的风格,设为TRUE则使用Vista风格的文件对话框,否则使用旧版本的文件对话框。此参数仅在Windows Vista中编译时适用。

   文件对话框也是模态对话框,所以在打开时也需要调用CFileDialog类的DoModal()成员函数。在打开文件对话框中点了“打开”或者在保存文件对话框中点了“保存”以后,我们可以使用CFileDialog类的成员函数GetPathName()获取选择的文件路径。

   下面列出几个CFileDialog类的成员函数,我们可以使用它们获得文件对话框中的各种选择。

GetFileExt():获得选定文件的后缀名。
GetFileName():获得选定文件的名称,包括后缀名。
GetFileTitle():获得选定文件的标题,即不包括后缀名。
GetFolderPath():获得选定文件的目录。
GetNextPathName():获得下一个选定的文件的路径全名。
GetPathName():获得选定文件的路径全名。
GetReadOnlyPref():获得是否“以只读方式打开”。

14 字体对话窗

http://www.jizhuomi.com/software/175.html
MFC使用CFontDialog类封装了字体对话框的所有操作。字体对话框也是一种模态对话框。
CFontDialog类的构造函数

   我们先来了解CFontDialog类。它的常用构造函数原型如下:

CFontDialog(
LPLOGFONT lplfInitial = NULL,
DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
CDC* pdcPrinter = NULL,
CWnd* pParentWnd = NULL
);

   参数说明:

   lplfInitial:指向LOGFONT结构体数据的指针,可以通过它设置字体的一些特征。

   dwFlags:指定选择字体的一个或多个属性,详情可在MSDN中查阅。

   pdcPrinter:指向一个打印设备上下文的指针。

   pParentWnd:指向字体对话框父窗口的指针。

   上面的构造函数中第一个参数为LOGFONT指针,LOGFONT结构体中包含了字体的大部分特征,包括字体高度、宽度、方向、名称等等。下面是此结构体的定义:

typedef struct tagLOGFONT {
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
TCHAR lfFaceName[LF_FACESIZE];
} LOGFONT;

   获取字体对话框中所选字体

   我们在字体对话框中选择了字体后,如何获取选定的字体呢?我们可以通过CFontDialog类的成员变量m_cf间接获得选定字体的CFont对象。m_cf是CHOOSEFONT类型的变量,CHOOSEFONT结构体定义如下:

typedef struct {
DWORD lStructSize;
HWND hwndOwner;
HDC hDC;
LPLOGFONT lpLogFont;
INT iPointSize;
DWORD Flags;
COLORREF rgbColors;
LPARAM lCustData;
LPCFHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
HINSTANCE hInstance;
LPTSTR lpszStyle;
WORD nFontType;
INT nSizeMin;
INT nSizeMax;
} CHOOSEFONT, *LPCHOOSEFONT;

   CHOOSEFON结构体中有个成员lpLogFont,它是指向LOGFONT结构体变量的指针,就像上面所说,LOGFONT中包含了字体特征,例如,我们可以通过LOGFONT的lfFaceName得知字体名。

   我们最终要获得的是所选择字体的CFont对象,有了字体的LOGFONT怎样获得对应的CFont对象呢?使用CFont类的成员函数CreateFontIndirect可以达到此目的。函数原型如下:

   BOOL CreateFontIndirect(const LOGFONT* lpLogFont );

   参数是LOGFONT指针类型,我们可以传入CFontDialog类成员变量m_cf的lpLogFont成员,就可以得到所选字体的CFont对象了。

15 颜色对话框

http://www.jizhuomi.com/software/177.html
MFC中提供了CColorDialog类封装了颜色对话框的所有操作,我们可以通过它显示颜色对话框,并获取颜色对话框中选择的颜色。颜色对话框跟字体对话框一样,也是一种模态对话框。
CColorDialog类的构造函数

CColorDialog(
COLORREF clrInit = 0,
DWORD dwFlags = 0,
CWnd* pParentWnd = NULL
);

   参数说明:

   clrInit:默认选择颜色的颜色值,类型为COLORREF,实际上就是unsigned long类型。如果没有设置它的值,则默认为RGB(0,0,0),即黑色。

   注:RGB(r,g,b)是宏,可以计算颜色值。括号中的三个值分别为红、绿、蓝分量的值。

   dwFlags:自定义颜色对话框功能和外观的属性值。详情可在MSDN中查阅。

   pParentWnd:颜色对话框的父窗口的指针。

   获取颜色对话框中所选颜色值

   我们使用颜色对话框的最终目的还是要获得在颜色对话框中选择的颜色值。为此CColorDialog类的成员函数GetColor()能够很好的实现我们的要求。GetColor()函数的原型为:

   COLORREF GetColor( ) const;

   它返回所选颜色的COLORREF值。

   如果我们想获得R、G、B各分量的值呢?可以根据GetColor得到的COLORREF颜色值,通过使用GetRValue、GetGValue和GetBValue三个宏获得。GetRValue的语法形式为:

   BYTE GetRValue(DWORD rgb);

   参数rgb就是COLORREF颜色值,返回值即是R分量值。其他两个宏的形式与之类似。例如,GetColor()函数返回的COLORREF为10000,则R分量值就是GetRValue(10000)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值