有没有办法通过标准的 OPENFILE 对话框选择向用户显示哪些文件?

2022-01-12 00:00:00 winapi c++ mfc fileopendialog

Vista 引入了一个接口:IFileDialog::SetFilter,它允许我设置一个过滤器,该过滤器将为每个潜在的文件名调用,以查看它是否应该显示给用户.

Vista introduced an interface: IFileDialog::SetFilter, which allows me to setup a filter that will be called for every potential filename to see if it should be shown to the user.

微软在 Windows 7 中删除了它,并且在 XP 中不支持它.

Microsoft removed that in Windows 7, and didn't support it in XP.

我正在尝试自定义我们的打开文件对话框,以便我可以控制向最终用户显示哪些文件.这些文件在内部用产品代码标记 - 文件名本身没有任何要过滤的内容(因此文件扩展名过滤器在这里没有用 - = 我需要实际询问每个文件以查看它是否在额外的过滤器中我们的用户指定的参数).

I am trying to customize the our Open file dialog so that I can control which files are displayed to the end user. These files are marked internally with a product-code - there isn't anything in the filename itself to filter on (hence file extension filters are not useful here -= I need to actually interrogate each one to see if it is within the extra filter parameters that our users specified).

我猜微软删除了 SetFilter 接口,因为它太慢了.我可以想象各种与此类似的想法,但它们不能很好地扩展到网络和云存储以及你有什么.

I would guess that Microsoft removed the SetFilter interface because too often it was too slow. I can imagine all sorts of similar ideas to this one which don't scale well for networks and cloud storage and what have you.

但是,我需要知道是否有实现相同目标的替代界面,或者我是否真的仅限于在文件"对话框中查看文件扩展名以进行过滤?

However, I need to know if there is an alternative interface that accomplishes the same goal, or if I really am restricted to only looking at the file extension for filtering purposes in my File dialogs?

跟进:
在进一步查看 CDN_INCLUDEITEM 后,它需要 OPENFILENAME 的 pre-vista 版本,我发现这是可以想象的最没用的 API.它只过滤非文件系统对象.换句话说,您不能使用它来过滤文件.或文件夹.99.99% 的时间都会过滤文件打开或保存对话框.难以置信!

Follow-up:
After looking further into CDN_INCLUDEITEM, which requires the pre-vista version of OPENFILENAME, I have found that this is the most useless API imaginable. It only filters NON-filesystem objects. In other words, you can't use it to filter files. Or folders. The very things one would filter 99.99% of the time for a file open or save dialog. Unbelievable!

有一篇非常古老的Paul DiLascia 的文章,它提供了每次更新列表视图时从列表视图控件中删除每个有问题的文件名的技术.

There is a very old article by Paul DiLascia which offers the technique of removing each offending filename from the list view control each time the list view is updated.

但是,我从痛苦的经验中知道,列表视图会随着时间的推移而更新.如果您正在查看一个大文件夹(许多项目)或连接速度有点慢(服务器负载过重和/或文件数量很大),那么这些文件将被零散地添加到对话框中.所以必须反复过滤掉有问题的文件名.

However, I know from bitter experience that the list view can update over time. If you're looking at a large folder (many items) or the connection is a bit slow (heavily loaded server and/or large number of files), then the files are added to the dialog piecemeal. So one would have to filter out offending filenames repeatedly.

事实上,我们当前的自定义文件打开对话框使用计时器定期查看视图的文件名列表,以查看是否存在任何给定模式的文件,以启用另一个控件.否则,可以检查这些文件是否存在,但没有找到,但稍后视图会更新以具有更多文件名,并且不会将任何事件发送到您的对话框以指示视图已更改.事实上,多年来我不得不为通用控件文件对话框编写和维护代码的经验是,微软在如何编写这样的东西时并不是很清楚.事件是不完整的,在无用的时间发送,在不必要的时候重复,并且不存在整类有用的通知.

In fact, our current customized file open dialog uses a timer to look at the view's list of filenames periodically to see if any files of a given pattern exist, in order to enable another control. Otherwise it's possible to check for the existence of these files, find none, but a moment later the view updates to have more filenames, and no events are sent to your dialog to indicate that the view has been changed. In fact, my experience with having to write and maintain code for the common controls file dialogs over the years has been that Microsoft is not very cluefull when it comes to how to write such a thing. Events are incomplete, sent at not-useful times, repeated when not necessary, and whole classes of useful notifications don't exist.

可悲的是,我想我可能不得不放弃这个想法.除非有人想到我如何能够在用户尝试与之交互时跟上视图的自发变化(即从列表视图中删除条目并更改用户的视觉位置会很尴尬,或突出显示的文件,或滚动位置等)

Sadly, I think I might have to give up oh this idea. Unless someone has a thought as to how I might be able to keep up with the view spontaneously changing while the user is trying to interact with it (i.e. it would be awkward to go deleting out entries from the list view and changing the user's visual position, or highlighted files, or scroll position, etc.)

推荐答案

您需要初始化 CFileDialog 的回调.然后需要处理CDN_INCLUDEITEM通知码 包括或排除项目.

You need to initialise the callbacks for your CFileDialog. Then you need to process CDN_INCLUDEITEM notification code to include or exclude items.

您也可以查看 这篇很棒的文章.作者除了回调之外还使用了一些其他的方法

You can also check this great article. The author uses some other approaches in addition to callbacks

相关文章