一个定制CFileDialog对话框的实例

2016-01-29 11:52 51 1 收藏

一个定制CFileDialog对话框的实例,一个定制CFileDialog对话框的实例

【 tulaoshi.com - C语言心得技巧 】

一个定制CFileDialog对话框的实例

编译:northtibet

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com) 下载源代码


    很多程序员都喜欢让自己的代码运行效果与众不同。Windows系统的应用程序打开某个文件一般使用的都是默认的CFileDialog。但是这个默认的CFileDialog往往满足不了用户的要求。我就碰到一个这样的用户,他的要求如下: 1、在默认的CFileDialog对话框中加一个预览窗格,以便在选中ASCII文件时能看到所选文件的内容,也就是用*.txt作为文件过滤条件。 2、在默认的CFileDialog对话框中加一个"全部"按钮来选择某个目录中所有的.txt文件。 3、如果选择的目录中没有.txt文件时,要将"全部"按钮disable,也就是置灰这个按钮。    实现上面这些需求必须要改装CFileDialog对话框。当最后写完程序时,功能到是全都实现了,但在Windows2000环境测试中,用户发现了这样一个问题:如果先选中某个文件,然后再去选某个文件夹,预览窗格仍然显示的那个文件的内容。尽管在OnFileNameChange中对CDN_SELCHANGE进行了处理,为了获取所选的文件/路径名,也调用了CFileDialog::GetPathName。但是即使是选中了文件夹,GetPathName仍然返回的是文件的名字。即便尝试用其它的通知消息和函数,比如 CDN_FOLDERCHANGE 和 GetFileName,但仍旧存在同样的问题。必须承认在Windows 2000中,CFileDialog是个不完美的对话框,确实存在上述问题。正是有这些不完美,程序员们才忙得个不亦乐乎......那么到底如何判断用户选中的是文件还是文件夹呢?下面就让我们从用户需求开始,一个一个解决所碰到的问题。
    首先简单介绍下本文引入的三个辅助类:CFileDialogHook;CFileDialogOwnerHook和CFileDlgHelper,这三个类很简单,其功能分别是:子类化文件对话框;子类化文件对话框的父窗口或宿主窗口,这两个类只在CFileDlgHelper类中使用,一些重要的处理都在CFileDlgHelper中。它的使用方法很简单,实例化CFileDlgHelper以后调用Init即可。
class CMyOpenDlg ... {protected:  CFileDlgHelper m_dlghelper;//实例化};BOOL CMyOpenDlg::OnInitDialog(){  m_dlghelper.Init(this)//初始化……}     
    初始化CFileDlgHelper以后,便可以用它来获取列表控制以及判断选项是否有文件夹属性,例如:
CListCtrl* plc = m_dlghelper.GetListCtrl();POSITION pos = plc->GetFirstSelectedItemPosition();while (pos) {  int i = plc->GetNextSelectedItem(pos);  if (fdh.IsItemFolder(i)) {    // 显示"(FOLDER)"……  } else {    // 显示其它内容  }}

    毫无疑问,要改装CFileDialog对话框,必须建立一个它的派生类以及一个新的对话框资源。“全部”按钮的实现代码是这样的:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)
void CMyOpenDlg::OnSelectAll(){  CListCtrl* plc = m_dlghelper.GetListCtrl();  for (int i=0; i<plc->GetItemCount(); i++) {    CString fn = plc->GetItemText(i,0);    if (IsTextFileName(fn)) {      plc->SetItemState(i,LVIS_SELECTED,        LVIS_SELECTED);    }  }  plc->SetFocus();}
    当所选目录中没有.txt文件时,要disable“全部”按钮的处理稍微麻烦一些,要用到ON_UPDATE_COMMAND_UI消息。回顾一下MFC有关UI更新的基本方法,通常是在主消息循环处于空闲状态时候——也就是说在消息队列中没有待处理的消息。但对话框则有所不同,尤其是运行模式对话框时,MFC启动另外一个消息循环。当没有消息等待处理的时候,CWnd::DoModal向对话框发送一个WM_KICKIDLE消息。所以要想让对话框处理UI,常用的方式是这样的:
LRESULT CMyDialog::OnKickIdle(WPARAM wp, LPARAM lp){  UpdateDialogControls(this, TRUE);  return 0;}      
    CWnd::UpdateDialogControls将神奇的CN_UPDATE_COMMAND_UI消息发送到对话框,触发ON_UPDATE_COMMAND_UI处理例程。可惜这个方法对CFileDialog对话框不灵。原因是CFileDialog重写了DoModal,它不会以正常方式运行某个消息循环,而是调用::GetOpenFileName (或::GetSaveFileName)。这些API函数都有自己消息循环,并且你无法钻进去进行消息空闲处理。无论什么时候,每当模式对话框处于等待消息状态时,对话框发送自己的WM_ENTERIDLE消息。从这里进去才可以处理UI更新事宜。但有几个细节需要注意。首先,Windows只发送WM_ENTERIDLE消息到对话框的所有者——此处为主框架

来源:http://www.tulaoshi.com/n/20160129/1483675.html

延伸阅读
前几天领导问我一个问题:就是使用CFileDialog类在设置多选时选中的文件所放的文件缓冲区不知设置多大合适,设置小了DoModal返回为失败, 通过CommDlgExtendedError函数获取错误码为FNERR_BUFFERTOOSMALL(即缓冲区太小),设置大了又浪费内存。(我们 一次要选几百个文件,实在不知设置多大合适)。       我谈了我的思...
1、意图 有时候我们希望将非模态窗口显示为模态窗口。比如在IE的“文件”菜单下选择“打印”,弹出的“打印”对话框就是非模态的(也许我们不太清楚Microsoft的设计意图,一般来说这里的“打印”对话框应该是模态的)。这种情况下如何将“打印”对话框显示为模态的呢(这个对话框对我们来说是Black Box)? 2、简单实现 简单...
基于对话框的程序中,每当用户按下回车键时,程序都会退出,其效果和按下对话框中的默认"OK"按钮是一样的,即使去掉"OK"按钮的 BS_DEFPUSHBUTTON 属性也没用。那么如何定制回车键的行为呢?这个问题在Windows的开发中由来已久,对于初学者来说,这是个恼人的问题,幸运的是,人们找到了很多种解决这个问题的方案。本实例将告诉你实现定制回...
自绘对话框 作者:Alon 下载示例源代码 闲来无事,写了一个简单的对话框界面,希望给需要的朋友有所帮助。 界面如下: 界面很单调,我只是想说明一下如何实现界面的自绘。如果有需要,也可以绘制更复杂漂亮的界面。 程序的实现也不复杂,接下来就跟着我一步一步做。...
标签: PS PS教程
      横轴代表像素本身的两度,竖轴代表新调节的亮度。中间的直线代表目前输入与输出之间的关系。可以单击某个Channels,进行Curves设置,或按Shift键选择两个以上的Channels.     在图像中准备要调节亮度的地方按下鼠标,一个圆出现在Curves对话框中的直线上。拖动这个圆即可调节图...

经验教程

790

收藏

20
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部