Windows 操作系统内部提供了大量的 COM 接口,为了在程序中打开一对话框,可以使用一个叫做 Common Item Dialog 的 COM 组件。这个组件实现了一个名字叫做 IFileOpenDialog 的接口,该接口被声明在 Shobjidl.h 头文件中。

对话框效果

下面的代码实现了打开对话框的功能,如果用户选择一个文件,程序则会将选中的文件名展示出来:

#include <windows.h>
#include <shobjidl.h>

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
        COINIT_DISABLE_OLE1DDE);
    if (SUCCEEDED(hr))
    {
        IFileOpenDialog *pFileOpen;

        // Create the FileOpenDialog object.
        hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
                IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));

        if (SUCCEEDED(hr))
        {
            // Show the Open dialog box.
            hr = pFileOpen->Show(NULL);

            // Get the file name from the dialog box.
            if (SUCCEEDED(hr))
            {
                IShellItem *pItem;
                hr = pFileOpen->GetResult(&pItem);
                if (SUCCEEDED(hr))
                {
                    PWSTR pszFilePath;
                    hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);

                    // Display the file name to the user.
                    if (SUCCEEDED(hr))
                    {
                        MessageBox(NULL, pszFilePath, L"File Path", MB_OK);
                        CoTaskMemFree(pszFilePath);
                    }
                    pItem->Release();
                }
            }
            pFileOpen->Release();
        }
        CoUninitialize();
    }
    return 0;
}

这段代码中使用了一些其它的概念,如果你不理解也不用担心,以后的文章内容会慢慢介绍,下面介绍代码的基本逻辑:

  1. 调用 CoInitializeEx 初始化 COM 库。
  2. 调用 CoCreateInstance 创建 Common Item Dialog 对象并且获取 IFileOpenDialog 接口指针。
  3. 调用对象的 Show 方法,向用户展示对话框。这个方法堵塞直到用户关闭对话框。
  4. 调用对象的 GetResult 方法。这个方法返回另一个 COM 组件的接口指针,这个接口的名字叫做 IShellItem,实现该接口的对象是 Shell item 对象,代表着用户选择的文件。
  5. 调用 Shell item 对象的 GetDisplayName 接口,这个方法可以获取文件的路径。
  6. 使用 MessageBox 展示文件路径信息。
  7. 调用 CoUninitialize 释放 COM 库的相关资源。

第1、2、7都定义在 COM 库中,它们都是 COM 库中的一般函数。3-5 步调用的方法都在 Common Item Dialog 对象中定义。

这个例子中,有两种创建对象的方式,第一种使用一般的方式,调用 CoCreateInstance 函数获取IFileOpenDialog 接口,第二种方法使用 Common Item Dialog 对象自带的特殊方法 GetResult 获取 IShellItem 接口。

求关注