1.12 通用对话框的应用
通用对话框是由操作系统提供的任何应用程序都可获得的对话框,使用这些对话框,可以为用户提供他们所期望的一致性的标准界面。在Visual C++中,这些对话框被封装在CCommonDialog及其派生类中。本节中的实例实现了通用对话框的应用。
实例035 打开位图预览对话框
本实例是一个提高效率的程序
实例位置:光盘\mingrisoft\01\035
实例说明
在使用打开对话框选择图片时,如果能够对图片进行预览就可以让用户更加快捷地选择想要的图片。运行本实例,单击“打开”按钮,在弹出的“打开”对话框中选择一个BMP位图资源,用户可以在“打开”对话框的下方看到该位图的预览图像以及图像尺寸、文件大小和创建时间等信息,效果如图1.45所示。
技术要点
文件对话框CFileDialog有一个数据成员m_ofn,该成员为OPENFILENAME结构变量。OPENFILENAME结构包含了一组成员,其中Flags是初始化对话框的一组标记,lpTemplateName用于提供文件对话框的子对话框窗口,如果Flags中包含OFN_EXPLORER标记,系统将创建一个标准对话框的子对话框。如果用户想要设计自己的文件对话框,可以创建一个新的对话框,在新的对话框中添加控件,然后将其赋给lpTemplateName成员。在这里有一点需要注意,如果文件对话框的子窗口采用了用户提供的对话框,则系统为文件对话框提供的标准控件也将显示在对话框中。因此,用户在向对话框中添加控件时,需要调整控件的位置。可以采用这样一种方式:在对话框中放置一个CStatic控件,将其ID设置为“stc32”。“stc32”是系统预定的标记,它用来确定标准文件对话框中控件显示的位置,用户可以依据它来放置自己添加的控件。
图1.45 半透明窗体
实现过程
(1)新建一个基于对话框的应用程序。
(2)向对话框中添加一个按钮控件,设置其Caption属性为“打开”。
(3)新建一个对话框资源,向新建的对话框中添加1个图片控件和3个静态文本控件。
(4)以CFileDialog类为基类派生一个CNewFileDialog类。
(5)在CNewFileDialog类的头文件中声明变量,代码如下:
CStatic m_Bitmap; //图片控件对应变量 CStatic m_Measure; //图像尺寸控件对应变量 CStatic m_Size; //文件大小控件对应变量 CStatic m_Time; //创建时间控件对应变量
(6)在CNewFileDialog类的构造函数中设置m_ofn成员,代码如下:
CNewFileDialog::CNewFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) { m_ofn.Flags = (OFN_EXPLORER| OFN_ENABLETEMPLATE| OFN_ENABLEHOOK); //将对话框资源赋给lpTemplateName成员 m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_NEWFILE_DIALOG); }
(7)处理CNewFileDialog类的WM_INITDIALOG消息,将声明的成员关联到对话框中的静态文本控件,代码如下:
BOOL CNewFileDialog::OnInitDialog() { CFileDialog::OnInitDialog(); m_Bitmap.SubclassDlgItem(IDC_STATIC1,this); //关联图片控件 m_Measure.SubclassDlgItem(IDC_STATIC2,this); //关联图像尺寸控件 m_Size.SubclassDlgItem(IDC_STATIC3,this); //关联文件大小控件 m_Time.SubclassDlgItem(IDC_STATIC4,this); //关联创建时间控件 return TRUE; }
(8)在CNewFileDialog类中,添加OnFileNameChange虚拟方法,在文件改变时,判断选择的文件是否是位图,如果是,则将其显示在图片控件中,并将其信息显示在静态文本控件中,代码如下:
void CNewFileDialog::OnFileNameChange() { CString exp; exp=GetFileExt(); exp.MakeUpper(); //在比较扩展名时不区分大小写 if(exp=="BMP") //显示位图 { CFile file; //声明CFile类对象 if(!file.Open(GetPathName(),CFile::modeRead)) //打开文件 return; BITMAPFILEHEADER bmfHeader; if(file.Read((LPSTR)&bmfHeader,sizeof(bmfHeader)) != sizeof(bmfHeader)) //读位图文件头信息 return; BITMAPINFOHEADER bmiHeader; if(file.Read((LPSTR)&bmiHeader,sizeof(bmiHeader))!=sizeof(bmiHeader)) //读位图头信息 return ; //获得大小信息,并显示 int bmWidth=bmiHeader.biWidth; //获得位图宽度 int bmHeight=bmiHeader.biHeight; //获得位图高度 file.Close(); //关闭文件 int x=150,y=150; if(bmWidth<150) //如果文件宽度小于150像素 x=bmWidth; //设置其显示宽度 if(bmHeight<150) //如果文件高度小于150像素 y=bmHeight; //设置其显示高度 m_Bitmap.SetBitmap((HBITMAP)LoadImage(NULL,GetPathName(), IMAGE_BITMAP,x,y,LR_LOADFROMFILE)); //显示位图 CFileStatus status; CFile::GetStatus(GetPathName(),status); //获得位图信息 CString measure,size,time; measure.Format("图像尺寸:%d*%d",bmWidth,bmHeight); //格式化图像尺寸 size.Format("文件大小:%dK",status.m_size/1024); //格式化文件大小 time.Format("创建时间:%s",status.m_ctime.Format("%Y年%m月%d日 %H:%M:%S"));//格式化创建时间 m_Measure.SetWindowText(measure); //显示图像尺寸 m_Size.SetWindowText(size); //显示文件大小 m_Time.SetWindowText(time); //显示创建时间 } }
(9)处理主窗口中“打开”按钮的单击事件,在该事件的处理函数中调用“打开”对话框,代码如下:
void CBmpPreviewDlg::OnOpen() { CNewFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT| OFN_EXPLORER|OFN_ENABLETEMPLATE,"All Files(*.BMP)|*.BMP||"); //构造打开对话框 dlg.DoModal(); //显示打开对话框 }
举一反三
根据本实例,读者可以:
隐藏打开对话框中默认的控件。
实例036 打开Windows新型对话框
本实例是一个提高效率、人性化的程序
实例位置:光盘\mingrisoft\01\036
实例说明
在Windows 2000及以后版本的操作系统中提供了新型的打开对话框,在程序中如何调用新型的打开对话框呢?本实例将实现调用Windows新型打开对话框的功能,实例运行结果如图1.46所示。
图1.46 Windows新型打开对话框
技术要点
可以使用GetOpenFileName函数实现Windows新型打开对话框的调用,在使用GetOpenFileName函数时,需要设置OPENFILENAME结构的参数。
实现过程
(1)新建一个基于对话框的应用程序。
(2)向对话框中添加一个按钮控件,设置控件ID和Caption属性。
(3)主要程序代码如下:
void CWindowsDialogDlg::OnButtonopen() { OPENFILENAME fopt ; //声明OPENFILENAME结果 memset(&fopt, 0, sizeof(fopt)); fopt.lStructSize=sizeof(OPENFILENAME); //设置结构大小 fopt.Flags =OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;//设置标记 fopt.hwndOwner =GetSafeHwnd(); //窗口句柄 fopt.lpstrFilter="All Files(*.*)"; //过滤字符串 GetOpenFileName(&fopt); //调用打开对话框 }
举一反三
根据本实例,读者可以:
实现新型保存对话框。
实例037 同时选择多个文件
本实例是人性化的程序
实例位置:光盘\mingrisoft\01\037
实例说明
在使用“打开”对话框时,可以一次性选择多个文件,这样可以方便用户的操作,本实例窗体实现了同时选择多个文件的功能。运行程序,单击“打开”按钮,可以在弹出的“打开”对话框中同时选择多个文件,如图1.47所示。
图1.47 同时选择多个文件
技术要点
使用“打开”对话框同时选择多个文件时,需要在构造“打开”对话框时设置OFN_ ALLOWMULTISELECT属性,构造“打开”对话框通过CFileDialog构造函数来实现,语法如下:
CFileDialog(BOOL bOpenFileDialog,LPCTSTR lpszDefExt=NULL,LPCTSTR lpszFileName=NULL,DWORD dwFlags=OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,LPCTSTR lpszFilter=NULL,CWnd*pParentWnd=NULL);
参数说明:
● bOpenFileDialog:如果值为TRUE,构造“打开”对话框;为FALSE,构造“另存为”对话框。
● lpszDefExt:用于确定文件默认的扩展名,如果为NULL,没有扩展名被插入到文件名中。
● lpszFileName:确定编辑框中初始化时的文件名称,如果为NULL,编辑框中没有文件名称。
● dwFlags:用于自定义文件对话框。
● lpszFilter:用于指定对话框过滤的文件类型。
● pParentWnd:标识文件对话框的父窗口指针。
注意:lpszFilter参数格式,文件类型说明和扩展名间用“|”分隔,每种文件类型间用“|”分隔,末尾用“||”结束。
在获得“打开”对话框选择的文件路径时,需要使用etStartPosition函数和GetNextPathName函数。
GetStartPosition函数用于获取列表中第一个文件路径名的位置,语法如下:
POSITION GetStartPosition( ) const;
GetNextPathName函数用于从对话框所选的组中获取下一个文件名,文件名路径包括文件标题加上整个目录路径,语法如下:
CString GetNextPathName( POSITION& pos ) const;
由前面GetNextPathName或GetStartPosition函数调用返回的一个POSITION值。如果达到列表尾,则为NULL。
实现过程
(1)新建一个基于对话框的应用程序。
(2)在程序中添加一个列表框控件和一个按钮控件。
(3)主要程序代码如下:
void CSelectDlg::OnButselect() { CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |OFN_ALLOWMULTISELECT,"All Files(*.*)|*.*||",AfxGetMainWnd()); //构造文件打开对话框 CString strPath=""; //声明变量 if(dlg.DoModal()==IDOK) //判断是否按下"打开"按钮 { POSITION m_Position=dlg.GetStartPosition(); //获取第一个文件名位置 while(m_Position != NULL) { strPath = dlg.GetNextPathName(m_Position);//获得下一个文件路径 m_List.InsertString(m_List.GetCount(),strPath);//向列表框中插入文件路径 } } }
举一反三
根据本实例,读者可以:
设置文件保存对话框。
实例038 文本替换对话框
本实例是一个提高效率的程序
实例位置:光盘\mingrisoft\01\038
实例说明
使用“查找/替换”对话框可以进行查找和替换操作,CFindReplaceDialog类对“查找/替换”对话框进行了封装,下面通过实例来制作一个文本替换对话框,实例运行结果如图1.48所示。
图1.48 文本替换对话框
技术要点
要使用文本替换对话框,首先要了解CFindReplace Dialog类中封装的各个函数的功能,CFindReplace Dialog类中的常用函数如表1.1所示。
表1.1 CFindReplaceDialog类常用函数表
实现过程
(1)新建一个基于对话框的应用程序。
(2)向对话框中添加一个编辑框控件和一个按钮控件,设置编辑框属性,使其可以多行显示文本,并且具有滚动条。
(3)在对话框头文件中声明变量,代码如下:
CFindReplaceDialog*dlg; //声明“查找/替换”对话框指针 int nindex; //存储查找字符串的起始位置 BOOL degree; //判断是否为第一次替换的变量 BOOL find; //判断是否进行查找的变量
(4)定义一个新消息WM_FINDMESSAGE,代码如下:
static UINT WM_FINDMESSAGE = RegisterWindowMessage(FINDMSGSTRING);
(5)在对话框的头文件和消息映射部分分别添加函数定义和映射宏,代码如下:
afx_msg long OnFindReplace(WPARAM wParam,LPARAM lParam); ON_REGISTERED_MESSAGE(WM_FINDMESSAGE, OnFindReplace )
(6)处理WM_FINDMESSAGE消息,在该消息的响应函数中实现查找和替换操作,代码如下:
long CReplaceDialogDlg::OnFindReplace(WPARAM wParam, LPARAM lParam) { CString strText,repText; //声明字符串变量 strText=dlg->GetFindString(); //获得查找字符串 CString str; //声明字符串变量 m_Edit.GetWindowText(str); //获得编辑框中的文本 if(dlg->ReplaceCurrent()) //判断是否进行替换 find=FALSE; //进行替换 else find=TRUE; //进行查找 int len; //声明整型变量 if(find) //判断是查找还是替换 { len=strText.GetLength(); //获得要查找字符串的长度 } else { if(dlg->ReplaceAll()) //判断是否全部替换 { repText=dlg->GetReplaceString(); //获得替换字符串 len =repText.GetLength(); //获得替换字符串长度 str.Replace(strText,repText); //使用替换字符串替换查找字符串 m_Edit.SetWindowText(str); //将替换后的字符串显示在编辑框中 } else { CString left,right; //声明字符串变量 int num =strText.GetLength(); //获得查找字符串的长度 int strnum=str.GetLength(); //获得编辑框中文本长度 int index; //声明整型变量 if(!degree) //判断是否为第一次替换 index=str.Find(strText,nindex); //获得查找字符串在编辑框文本中的位置 else if(nindex-2>=0) //判断起始查找位置是否小于0 index=str.Find(strText,nindex-2); //获得查找字符串在编辑框文本中的位置 else { nindex=2; //设置起始查找位置 return 1; } degree = TRUE; left=str.Left(index); //获得替换字符串左侧的字符串 right=str.Right(strnum-index-num); //获得替换字符串右侧的字符串 repText=dlg->GetReplaceString(); //获得替换字符串 len=repText.GetLength(); //获得替换字符串长度 str=left+repText+right; //组合成新的字符串 m_Edit.SetWindowText(str); //在编辑框中显示新的字符串 } } int index=str.Find(strText,nindex); //获得查找字符串在编辑框文本中的位置 m_Edit.SetSel(index,index+len); //选中查找或替换的字符串 nindex=index+len; //设置起始查找位置 m_Edit.SetFocus(); //编辑框获得焦点 return 0; }
(7)为“替换”按钮处理单击事件,创建“替换”对话框的代码如下:
void CReplaceDialogDlg::OnReplace() //“替换”按钮单击事件响应函数 { dlg=new CFindReplaceDialog; //为“查找/替换”对话框指针赋值 dlg->Create(FALSE,NULL); //创建“替换”对话框 dlg->ShowWindow(SW_SHOW); //显示“替换”对话框 }
举一反三
根据本实例,读者可以:
设计文件查找对话框。
实例039 字体选择对话框
本实例是一个提高效率的程序
实例位置:光盘\mingrisoft\01\039
实例说明
CFontDialog类封装了Windows字体对话框。用户可以从系统安装的字体列表中选择要用的字体,同时,在“字体”对话框中还可以设置字体大小、颜色、效果、字符集等属性。下面通过实例来演示字体选择对话框,实例运行结果如图1.49所示。
图1.49 字体选择对话框
技术要点
要使用字体对话框就要了解CFontDialog类封装的功能,字体对话框的常用函数如表1.2所示。
表1.2 字体对话框常用函数表
实现过程
(1)新建一个基于对话框的应用程序。
(2)向对话框中添加一个编辑框控件和一个按钮控件,设置编辑框控件属性,使其可以多行显示,并具有滚动条。
(3)在对话框头文件中声明一个CFont对象m_Font。
(4)主要程序代码如下:
void CFontDialogDlg::OnFont() { CFont*TempFont=m_Text.GetFont(); //获取编辑框当前字体 LOGFONT LogFont; TempFont->GetLogFont(&LogFont); CFontDialog dlg(&LogFont); //初始化字体信息 if(dlg.DoModal()==IDOK) { m_Font.Detach(); LOGFONT temp; dlg.GetCurrentFont(&temp); //获取当前字体信息 m_Font.CreateFontIndirect(&temp); //直接创建字体 m_Color=dlg.GetColor(); //获得字体颜色 m_Text.SetFont(&m_Font); //设置字体 } }
举一反三
根据本实例,读者可以:
使用字体对话框为对话框中各个控件设置不同的字体。