C++打开文件夹对话框-通用文件对话框

本文提供两个C++代码示例,演示如何使用WindowsAPI中的CoCreateInstance和IFileOpenDialog接口来打开本地文件和文件夹对话框。方法一涉及解决编译错误,方法二包含更丰富的ShellHelpers头文件,包含了处理文件和文件夹选择的辅助函数。这两个方法都展示了如何在用户选择文件后进行操作。

此文介绍如何打开本地文本文件、文件夹对话框

方法一:

效果图:

 

 源码

#include <iostream>
#include <objbase.h>
#include <ShObjIdl.h>
using namespace std;
int main()
{
    cout << "start=====" << endl;
    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))
                    {
                        MessageBoxW(NULL, pszFilePath, L"File Path", MB_OK);
                        CoTaskMemFree(pszFilePath);
                    }
                    pItem->Release();
                }
            }
            pFileOpen->Release();
        }
        CoUninitialize();
    }
    return 0;
}

出现错误

1、2、IID_IFileOpenDialog' was not declared in this scope

  hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
            IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));

改为 

 hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileOpen));

2、 error: invalid use of incomplete type 'IFileDialog {aka struct IFileDialog}'

原因:默认情况下,MinGW将NTDDI_VERSION宏的值设置为0x05020000 (NTDDI_WS03),这会禁用shobjidl.h中的IFileDialog定义。宏的值必须至少为0x06000000 (NTDDI_VISTA)才能启用定义。下面列出了这些宏的可能值及其含义:

将以下内容放在源文件的开头(在include之前)应该可以修复编译错误:

#define NTDDI_VERSION 0x0A000006 //NTDDI_WIN10_RS5
#define _WIN32_WINNT 0x0A00 // _WIN32_WINNT_WIN10, the _WIN32_WINNT macro must also be defined when defining NTDDI_VERSION

如果您没有链接所需的库,则可能仍然存在链接错误。你列出的程序需要ole32.dll和uuid.dll,所以编译命令看起来像这样:

 

方法二:

效果图:

选择要尝试的文件对话框类型

 打开对话框效果

 

 

 

源码

ShellHelpers.h

#pragma once
#pragma once

#define STRICT_TYPED_ITEMIDS    // in case you do IDList stuff you want this on for better type saftey
#define UNICODE 1

#include <windows.h>
#include <windowsx.h>           // for WM_COMMAND handling macros
#include <shlobj.h>             // shell stuff
#include <shlwapi.h>            // QISearch, easy way to implement QI
#include <propkey.h>
#include <propvarutil.h>
#include <strsafe.h>
#include <objbase.h>

#pragma comment(lib, "shlwapi.lib")     // link to this
#pragma comment(lib, "comctl32.lib")    // link to this
#pragma comment(lib, "propsys.lib")     // link to this

// set up common controls v6 the easy way
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

__inline HRESULT ResultFromKnownLastError() { const DWORD err = GetLastError(); return err == ERROR_SUCCESS ? E_FAIL : HRESULT_FROM_WIN32(err); }

// map Win32 APIs that follow the return BOOL/set last error protocol
// into HRESULT
//
// example: MoveFileEx()

__inline HRESULT ResultFromWin32Bool(BOOL b)
{
    return b ? S_OK : ResultFromKnownLastError();
}

#if (NTDDI_VERSION >= NTDDI_VISTA)

__inline HRESULT ShellExecuteItem(HWND hwnd, PCWSTR pszVerb, IShellItem* psi)
{
    // how to activate a shell item, use ShellExecute().
    PIDLIST_ABSOLUTE pidl;
    HRESULT hr = SHGetIDListFromObject(psi, &pidl);
    if (SUCCEEDED(hr))
    {
        SHELLEXECUTEINFO ei = { sizeof(ei) };
        ei.fMask = SEE_MASK_INVOKEIDLIST;
        ei.hwnd = hwnd;
        ei.nShow = SW_NORMAL;
        ei.lpIDList = pidl;
        ei.lpVerb = pszVerb;

        hr = ResultFromWin32Bool(ShellExecuteEx(&ei));

        CoTaskMemFree(pidl);
    }
    return hr;
}

__inline HRESULT GetItemFromView(IFolderView2* pfv, int iItem, REFIID riid, void** ppv)
{
    *ppv = NULL;

    HRESULT hr = S_OK;

    if (iItem == -1)
    {
        hr = pfv->GetSelectedItem(-1, &iItem); // Returns S_FALSE if none selected
    }

    if (S_OK == hr)
    {
        hr = pfv->GetItem(iItem, riid, ppv);
    }
    else
    {
        hr = E_FAIL;
    }
    return hr;
}

// set the icon for your window using WM_SETICON from one of the set of stock system icons
// caller must call ClearDialogIcon() to free the HICON that is created
__inline void SetDialogIcon(HWND hdlg, SHSTOCKICONID siid)
{
    SHSTOCKICONINFO sii = { sizeof(sii) };
    if (SUCCEEDED(SHGetStockIconInfo(siid, SHGFI_ICON | SHGFI_SMALLICON, &sii)))
    {
        SendMessage(hdlg, WM_SETICON, ICON_SMALL, (LPARAM)sii.hIcon);
    }
    if (SUCCEEDED(SHGetStockIconInfo(siid, SHGFI_ICON | SHGFI_LARGEICON, &sii)))
    {
        SendMessage(hdlg, WM_SETICON, ICON_BIG, (LPARAM)sii.hIcon);
    }
}
#endif

// free the HICON that was set using SetDialogIcon()
__inline void ClearDialogIcon(HWND hdlg)
{
    DestroyIcon((HICON)SendMessage(hdlg, WM_GETICON, ICON_SMALL, 0));
    DestroyIcon((HICON)SendMessage(hdlg, WM_GETICON, ICON_BIG, 0));
}

__inline HRESULT SetItemImag
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值