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

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

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. MIT算法导论——第二讲.Solving Recurrence

    本栏目(Algorithms)下MIT算法导论专题是个人对网易公开课MIT算法导论的学习心得与笔记.所有内容均来自MIT公开课Introduction to Algorithms中Charles E. ...

  2. Android:界面设计工具DroidDraw

    DroidDraw是款强大的安卓界面设计软件,基于Java Swing开发,可以通过它拖动控件.设置层属性.设置颜色等步骤轻松地生成复杂的安卓XML布局文件. >>>>> ...

  3. Tomcat启动后访问首页报错 显示JSP 空指针异常

    HTTP Status 500 - type Exception report message description The server encountered an internal error ...

  4. Filter登录验证过滤器(全局)

    通过Filter来定义一个登录验证过滤器,这是就不需要在每一个JSP页面添加判断用户合法性的代码了. 以下示例中包含了5个文件,一个是登录表单LoginForm.jsp,一个是登录判断页LoginCo ...

  5. LTDFZ

    开关稳压器

  6. TCSRM 591 div2(1000)(dp)

    挺好的dp 因为有一点限制 必须任意去除一个数 总和就会小于另一个总和 换句话来说就是去除最小的满足 那么就都满足 所以是限制最小值的背包 刚开始从小到大定住最小值来背 TLE了一组数据 后来发现如果 ...

  7. System.exit(0)

    表示程序正常退出 System.exit(status) 当status非0时,表示程序为非正常退出. status=0, 关闭当前正在运行的虚拟机. 求质因数分解的程序如下: 两种算法: 一种是用S ...

  8. 装个Redmine真是麻烦啊

    弄个大半天终于看到这个界面出来了,不容易啊

  9. UVa 12716 (GCD == XOR) GCD XOR

    题意: 问整数n以内,有多少对整数a.b满足(1≤b≤a)且gcd(a, b) = xor(a, b) 分析: gcd和xor看起来风马牛不相及的运算,居然有一个比较"神奇"的结论 ...

  10. hdu2457:DNA repair

    AC自动机+dp.问改变多少个字符能让目标串不含病毒串.即走过多少步不经过病毒串终点.又是同样的问题. #include<cstdio> #include<cstring> # ...