专栏首页MasiMaro 的技术博文windows API实现用户选择文件路径的对话框

windows API实现用户选择文件路径的对话框

在编写应用程序时,有时需要用户选择某个文件,以供应用程序使用,比如在某些管理程序中需要打开某一个进程,这个时候需要弹出一个对话框来将文件路径以树形图的形式表示出来,以图形化的方式供用户选择文件路径,而不是需要用户自己输入文件路径。

  在MFC中能够弹出对话框供用户选择文件路径的类是CFileDialog,但是这个类的主要问题是当用户选择文件路径后,会打开相关的文件,与我们的要求不符,在Windows平台下有两个函数SHBrowseForFolder、SHGetPathFromIDList。这两个函数的说明如下:

LPITEMIDLIST WINAPI SHBrowseForFolder(
  LPBROWSEINFO lpbi
);

该函数的主要作用是弹出一个对话框,便于用户选择文件的路径,传递的参数是一个LPBROWSEINFO的结构体,这个结构体的原型如下:

typedef struct _browseinfo {
  HWND hwndOwner;//该对话框的属主窗口句柄
  LPCITEMIDLIST pidlRoot;//对话框中显示的最上层目录
  LPTSTR pszDisplayName;//指向一个缓冲区,用于返回用户选择的文件名
  LPCTSTR lpszTitle;//文件对话框的标题
  UINT ulFlags;//文件对话框相关标志
  BFFCALLBACK lpfn;//文件对话框对应的回调函数的地址
  LPARAM lParam;//附加参数
  int iImage;//返回用户选中的图片的索引
} BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO;

其中最主要的参数是pszDisplayName,这个参数指向一个缓冲区,用于存储用户选择的文件名(只是文件名不包括具体的路径);lpszTitle这个参数表示的是对话框的具体名称,这两个参数有一个没有给则会造成程序的错误,主要是对话框不能出来。另外的是标志的变量,一般使用的是BIF_BROWSEINCLUDEFILES(允许用户选择文件)、BIF_RETURNONLYFSDIRS(只能选择目录,不能选择文件)

在用户选择了相关的文件并点击对话框中的确定时,会返回一个LPITEMIDLIST的指针,这个结构表示的是文件系统的相关信息,接下来就是利用函数SHGetPathFromIDList来真正获取用户选择的文件路径,该函数的原型如下:

WINSHELLAPI BOOL WINAPI SHGetPathFromIDList( 
  LPCITEMIDLIST pidl, 
  LPSTR pszPath 
);

该函数主要利用pidl对应的文件系统的相关信息,通过第二个参数返回文件的路径,下面是具体的例子:

#include <windows.h>
#include <Shlobj.h>
#include <tchar.h>
#include <Commctrl.h>

#pragma comment(lib, "comctl32.lib")
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    LPITEMIDLIST pil = NULL;
    INITCOMMONCONTROLSEX InitCtrls = {0};
    TCHAR szBuf[4096] = {0};
    BROWSEINFO bi = {0};
    bi.hwndOwner = NULL;
    bi.iImage = 0;
    bi.lParam = NULL;
    bi.lpfn = NULL;
    bi.lpszTitle = _T("请选择文件路径");
    bi.pszDisplayName =  szBuf;
    bi.ulFlags = BIF_BROWSEINCLUDEFILES;

    InitCommonControlsEx(&InitCtrls);//在调用函数SHBrowseForFolder之前需要调用该函数初始化相关环境
    pil = SHBrowseForFolder(&bi);
    if (NULL != pil)//若函数执行成功,并且用户选择问件路径并点击确定
    {
        SHGetPathFromIDList(pil, szBuf);//获取用户选择的文件路径
        wprintf_s(_T("%s"), szBuf);
    }

    return 0;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java 学习笔记(14)—— 文件操作

    java文件操作主要封装在Java.io.File中,而文件读写一般采用的是流的方式,Java流封装在 java.io 包中。Java中流可以理解为一个有序的字...

    Masimaro
  • Windows程序设计学习笔记(一)Windows内存管理初步

    学习Windows程序设计也有一些时间了,为了记录自己的学习成果,以便以后查看,我希望自己能够坚持写下一系列的学习心得,对自己学习的内容进行总结,同时与大家交流...

    Masimaro
  • 如何利用git shell提交代码到github

    在很早之前我根据找到的一些资料以及自己的实践总结了一篇如何将VS2015上的代码上传到GitHub上,后来我发现有小伙伴私信我,说跟我上面写的不一样,但是那段时...

    Masimaro
  • AI框架解释你的社交媒体订阅,提高透明度和可解释性

    如果你像大多数人一样,你每天会花几分钟到几个小时滚动浏览歌曲,剪辑,文章,以及根据你的兴趣和偏好做出的广告。但是,如果支持Feed的算法(及其建议)更加透明就更...

    AiTechYun
  • 数据运营实战(一):细分目标人群,结合用户特征分析的实践

    分群是精细化运营的常用方式。通过用户分群设置,将用户群切割成更细粒度,以推断并定位对关键事件/指标有明显影响的因子。

    腾讯大数据
  • (数据科学学习手札29)KNN分类的原理详解&Python与R实现

      KNN(k-nearst neighbors,KNN)作为机器学习算法中的一种非常基本的算法,也正是因为其原理简单,被广泛应用于电影/音乐推荐等方面,即有些...

    Feffery
  • Golang leetcode 475. Heaters.go

    版权声明:原创勿转 https://blog.csdn.net/anakinsun/article/details/89175256

    anakinsun
  • angularJS配合bootstrap动态加载弹出提示内容

    1.bootstrp的弹出提示   bootstrap已经帮我们封装了非常好用的弹出提示Popover。   http://v3.bootcss.com/jav...

    kklldog
  • 数据库层如何扩展?

    这样看来,似乎只要加几个数据库,共同分担来自应用层的流量就完成了从单库到多库的扩展:

    ayqy贾杰
  • 小米开源soar一款对SQL进行优化和改写的自动化工具

    SOAR(SQL Optimizer And Rewriter)是一个对SQL进行优化和改写的自动化工具。 由小米人工智能与云平台的数据库团队开...

    赵腰静

扫码关注云+社区

领取腾讯云代金券