今天完成一个需求,就是记住用户选择的文件路径,先是熟悉代码,然后在网上找解决方法,一开始感觉没什么,网上的方法差不多,应该很容易做出来,结果真是卡了一半天,到晚上自己才慢慢的搞清楚了。

遇到的问题真不少,记录一下好多细节,真是不写不知道。

2016-08-18 21:35:36补充:

1.基本方法

http://blog.csdn.net/shuilan0066/article/details/7302904

http://www.cnblogs.com/Hisin/archive/2012/02/27/2370614.html

这两篇是比较清楚的。

先认识了

SHBrowseForFolder打开文件夹时,每次都是从根目录打开。要记住上次的路径或者设置默认路径,需要写个回掉函数。

CFileDialog会自动记住上次路径

int CALLBACK BrowseCallBackFun(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
switch(uMsg)
{
case BFFM_INITIALIZED: //选择文件夹对话框初始化
     //设置默认路径为lpData即'D:\'
::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
//在STATUSTEXT区域显示当前路径
::SendMessage(hwnd, BFFM_SETSTATUSTEXT, , lpData);
//设置选择文件夹对话框的标题
::SetWindowText(hwnd, TEXT("请先设置个工作目录"));
break;
case BFFM_SELCHANGED: //选择文件夹变更时
{
TCHAR pszPath[MAX_PATH];
//获取当前选择路径
SHGetPathFromIDList((LPCITEMIDLIST)lParam, pszPath);
//在STATUSTEXT区域显示当前路径
::SendMessage(hwnd, BFFM_SETSTATUSTEXT, TRUE, (LPARAM)pszPath);
}
break;
}
return ;
}

回掉函数首先搞清楚参数的意义

2.SHBrowseForFolder函数

打开文件目录对话框,我找到的方法就是使用SHBrowseForFolder函数,这个函数的原型是LPITEMIDLIST SHBrowseForFolder(LPBROWSEINFO lpbi)。函数很简单,就一个返回值和一个参数。参数简单罗列如下

typedef struct _browseinfo {

HWND hwndOwner;            // 父窗口句柄

LPCITEMIDLIST pidlRoot;    // 要显示的文件目录对话框的根(Root)

LPTSTR pszDisplayName;     // 保存被选取的文件夹路径的缓冲区

LPCTSTR lpszTitle;         // 显示位于对话框左上部的标题

UINT ulFlags;              // 指定对话框的外观和功能的标志

BFFCALLBACK lpfn;          // 处理事件的回调函数

LPARAM lParam;             // 应用程序传给回调函数的参数

int iImage;                // 文件夹对话框的图片索引

} BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO

一般而言父窗口句柄(hwndOwner)和根(pidlRoot)设置为Null就可以了,pszDisplayName设定一块MAX_PATH大小的缓冲区,跟显示相关的参数就是对话框提示标题(lpszTitle)、对话框样式(ulFlags)、设定对话框的缺省路径的操作(lpfn和lParam)以及对话框任务栏上显示的图标(iImage)。

由于返回值LPITEMIDLIST是一个指向ITEMIDLIST的指针,这个ITEMIDLIST涉及到Windows Shell中关于管理诸如文件、网络上的计算机、控制面板程序、回收站等等对象的知识点,Windows Shell为了识别具体的每一个对象,就使用了ITEMID来唯一识别和区分,而ITEMIDLIST就是一个完整的对象路径。显然这个函数可以用来浏览非文件对象,比如局域网内的电脑等等,在这里这个LPITEMIDLIST返回的对象路径是一个文件夹的路径,Windows提供了一个函数BOOL SHGetPathFromIDList(LPCITEMIDLIST pidl, LPSTR pszPath)来实现从对象路径转化为文件夹路径。

弄清楚每个参数的意义,然后才能按需求设定初值。先太盲目了,只知道套别人的,根本就没有理解。

                LPCITEMIDLIST pidl = NULL;
BROWSEINFO bi;
bi.hwndOwner = AfxGetMainWnd()->GetSafeHwnd();
bi.pidlRoot = NULL;
bi.pszDisplayName = folderName;
bi.lpszTitle = _T("请选择用于保存的文件夹");
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;;
bi.lpfn = BrowseCallbackProc; //回调函数
bi.iImage = ;
bi.lParam = long(&szPath); //设置默认路径,传给回掉函数的参数 pidl = SHBrowseForFolder(&bi);
if (pidl)
{
SHGetPathFromIDList(pidl, szPath);
}

3.回掉函数

     先看别人说设置全局的静态变量,然后设置静态变量和静态函数,开始编译通不过,要搞清楚类里面怎么写这种特殊的静态变量和函数。

      静态变量初始化,在cpp中,回掉函数的定义.h中static,cpp不需要了。

     感觉回掉函数只是发送了一些消息,根本就没有什么其他的用处,然后有人用lpData设置初始化路径,每次将选中的路径赋值给IpData也可以完成功能。

4.记住路径

在软件开启的时候,设置全局变量,每个更新默认的路径即可,但是重新开启软件的时候,采用先写入注册表中,然后再读注册表的路径,这样就解决了问题。也可以写到ini文件中。

5.CString与TCHAR数组 相互转换

TCHAR数组转到CString很简单:使用CString的Format就行。

TCHAR m_buf[100] = _T("Hello");

CString str;

str.Format(L"%s",m_buf);

现在就来CString转为TCHAR数组,这个就有点麻烦了。因为网上有很多的解决方案,但是都不怎么理想。我们使用_tcscpy()宏。

CString str = L"sssssss";

TCHAR m_buf[20];

_tcscpy(m_buf, str);  //类型之间的转换真麻烦,知道定义这个宏的好处了。

自己找了半天,这个方法很有效!用memcpy,strcpy都不行。。。

TCHAR szDefaultDir[MAX_PATH];
CString strDef(_T("E:\\"));
memcpy(szDefaultDir, strDef.GetBuffer(strDef.GetLength() * ), strDef.GetLength() * );
strDef.ReleaseBuffer();
szDefaultDir[strDef.GetLength()] = ;

这样也是一种方法吧。

MFC记住上次路径---遇到的一些问题的更多相关文章

  1. windowsclient开发--使你的client执行时记住上次关闭的大小和位置

    差点儿全部的windowsclient都能够调整大小,所以用户依据自己的喜好调整client的大小和位置. 可是当该client退出后,又一次执行client的时候.我们往往又要调整自己喜好的大小和位 ...

  2. 根据窗体自动调整控件及文本框记住上次填写内容Demo

    第一次写文章,组词难免没有不通之处... 最近常用到Winform根据窗体大小自动调整空间大小及字体.文本框记住上次填写内容待下次输入某一段时候自动跳出上次输入内容.于是就随便把两个问题放到同一个de ...

  3. vue单页应用中 返回列表记住上次滚动位置、keep-alive缓存之后更新列表数据 那点事

    实践场景需求 产品列表中,滚动到一定位置的时候,点击查看产品信息,后退之后,需要回到原先的滚动位置,这是常见的需求 所有页面均在router-view中,暂时使用了keep-alive来缓存所有页面, ...

  4. ubuntu12.04不能记住上次编辑位置的解决方案

    1:按照网上的代码 au BufReadPost * |if line("'\"") <= line("$")|exe("norm ' ...

  5. MFC 添加文件路径 遍历文件

    .添加MFC选择文件路径,使用MessageBox显示信息. void CMyCalLawsDlg::OnBnClickedAddfolder() { wchar_t* p; wchar_t szPa ...

  6. 用Cookie记住上次登录用户名

    一个登录页面设置查看Cookie中的数据(Cookie不为null);然后将页面提交到另一个页面去,在这个页面中的到是否选择记住用户名,如果选择了, 就创建Cookie对象,将用户名存储起来,下次登录 ...

  7. MFC获取文件路径和文件夹路径

    MFC的界面中,需要实现这样两个功能: 1.在界面上加一个按钮,单击按钮弹出一个对话框选择文件,在工程中获得文件的路径: 2.在界面上加一个按钮,单击按钮弹出一个对话框选择文件夹,在工程中获取文件夹的 ...

  8. Sublime Text 3中设置不记住上次打开的文件

    转自:https://blog.csdn.net/nicholaszao/article/details/79575251 在”User/Preferences.sublime-settings”配置 ...

  9. Sublime Text 3中关闭记住上次打开的文件

    使用UltraEdit的时候,每次安装后就得修改一堆配置,其中一项便是关闭“打开上一次未关闭的文件”,Sublime Text 2也有这么一个默认的功能,在实际使用中,这种方式确实可以较快速的访问文件 ...

随机推荐

  1. C语言中时间调用处理的相关函数介绍

    asctime(将时间和日期以字符串格式表示) 相关函数:time,ctime,gmtime,localtime 表头文件:#include<time.h> 定义函数:char * asc ...

  2. Java多线程4:synchronized关键字

    原文:http://www.cnblogs.com/skywang12345/p/3479202.html 1. synchronized原理在java中,每一个对象有且仅有一个同步锁.这也意味着,同 ...

  3. Filter设计实现IP地址限制

    示例:创建一个IP过滤Filter,当一个用户发出访问请求的时候,首先通过过滤器进行判断, 如果用户的IP地址被限制,就禁止访问,只有合法的IP才可以继续访问.IP过滤Filter代码如下: IPFi ...

  4. Java API —— System类

    1.System类概述         System 类包含一些有用的类字段和方法.它不能被实例化.  2.成员方法         public static void gc():运行垃圾回收器   ...

  5. java服务器知识

    http://blog.csdn.net/chenyi8888/article/details/4484641 http://blog.csdn.net/chenyi8888/article/deta ...

  6. What's New for Visual C# 6.0

    https://msdn.microsoft.com/en-us/library/hh156499.aspx nameof You can get the unqualified string nam ...

  7. C++ STL之list容器的基本操作

    由于list和vector同属于序列式容器,有很多相同的地方,而上一篇中已经写了vector,所以这一篇着重写list和vector的不同之处和特有之处. 特别注意的地方: (1)STL中迭代器容器中 ...

  8. Android开发学习笔记:浅谈GridView

    GridView(网格视图)是按照行列的方式来显示内容的,一般用于显示图片,图片等内容,比如实现九宫格图,用GridView是首选,也是最简单的.主要用于设置Adapter. GridView常用的X ...

  9. Qt之自定义界面(添加自定义标题栏)

    简述 通过上节内容,我们实现了自定义窗体的移动,但是我们缺少一个标题栏来显示窗体的图标.标题,以及控制窗体最小化.最大化.关闭的按钮. 自定义标题栏后,所有的控件我们都可以定制,比如:在标题栏中添加换 ...

  10. Sass结合Modernizr的使用方法

    Modernizr在初始化的时候会首先找寻class=“no-js”的元素: <!DOCTYPE html> <html class="no-js"> &l ...