The Windows Shell

Common Item Dialog

文档层级

  • Windows
    • Apps
      • Win32
        • Desktop Technologies
          • Desktop Environment
            • Windows
              • Shell

从Vista开始,Common Item Dialog替换了Common File Dialog。 Common Item Dialog具有Open和Save两种工作方式。

许多文档中Common Item Dialog依然被叫做Command File Dialog。

COM接口

  • IFileDialog
  • IFileOpenDialog
  • IFileSaveDialog

跟之前版本比较得好处:

  • 支持使用IShellItem而不是文件系统路径
  • 无需使用hook即可自定义外观
  • 支持更多通过数据驱动的定制
  • 提供许多事件通知,比如选择变动,或者文件类型变动
  • 新特性,比如调用者可以添加自定义的Place到Places栏
  • Save对话框可以采用Shell提供的新的元数据特性

开发者可以选择实现以下接口:

  • IFileDialogEvents,用于接受事件
  • IFileDialogCustomize,用于自定义对话框
  • IFileDialogControlEvents,用于接受自定义控件的事件

对话框返回的时IShellItem或者IShellItemArray。GetOpenFileName和GetSaveFileName的标记集和OPENFILENAME的标记集OFN类似。

IFileDialog及其后继从IModalWindow派生处理。Show方法只需上级窗口的控把。如果Show返回HRESULT_FROM_WIN32(ERROR_CANCELLED)则表示没有选好。此方法也可能返回E_OUTOFMEMORY。

Sample Usage

本章带有许多例子。

commdlg.h header

旧的API。

文档层级

  • Windows
    • Apps
      • Win32
        • API

参考

https://github.com/microsoft/WindowsAppSDK/issues/491

(本篇完)

2021-07-09更新:WindowsAppSdk对FilePicker的支持

FileOpenPicker, FileSavePicker, and FolderPicker break in WinUI3 Desktop #2716

如何使用IInitializeWithWindow来让FilePicker工作。

FileOpenPicker Constructor记述了对IInitializeWithWindow的使用。

PickSingleFile可以工作,但是PickMultiFile无法工作。

[IUnknown is an ambiguous symbol #5218

C++中如何初始化IInitializeWithWindow。

New File/Folder picker for Reunion #88

新的FilePicker设计。

PickMultipleFilesAsync Crashes Application / Exception Thrown #731

关于PickMultipleFilesAsync 的问题,已关闭。

FileOpenPicker PickMultipleFilesAsync Break in WinUI3 Desktop #467

关于PickMultipleFilesAsync 的问题的跟踪贴。

(更新完)

2022-04-03更新

Display WinRT UI objects that depend on CoreWindow

许多WinRT运行标类实现了IInitializeWithWindow,可以使用如下代码使用对话框:

// pch.h
...
#include <microsoft.ui.xaml.window.h>
#include <Shobjidl.h>
#include <winrt/Windows.Storage.Pickers.h>

// MainWindow.xaml.cpp
winrt::fire_and_forget ShowFolderPickerAsync(HWND hWnd)
{
    // Create a folder picker.
    Windows::Storage::Pickers::FolderPicker folderPicker;

    // Initialize the folder picker with the window handle (HWND).
    auto initializeWithWindow{ folderPicker.as<::IInitializeWithWindow>() };
    initializeWithWindow->Initialize(hWnd);

    // Use the folder picker as usual.
    folderPicker.FileTypeFilter().Append(L"*");
    auto folder{ co_await folderPicker.PickSingleFolderAsync() };
}

(更新完)