关于CFileDialog和SHBrowseForFolder浏览限制问题
如题,1:我如何将CFileDialog和SHBrowseForFolder的对话框浏览的路径限制在E盘?即其它盘屏蔽掉。
如果不能屏蔽的话,当选择别的盘符自动跳回到E盘。
问题点数:60、回复次数:26Top
1 楼billy145533($_$)回复于 2006-03-03 15:26:07 得分 0
晕,看来不行
关注Top
2 楼striking(庸人自扰)回复于 2006-03-03 15:37:54 得分 30
我如何将CFileDialog和SHBrowseForFolder的对话框浏览的路径限制在E盘?即其它盘屏蔽掉。
===这个似乎不行.
如果不能屏蔽的话,当选择别的盘符自动跳回到E盘。
====这个可以实现..
#include <shlobj.h>
INT CALLBACK BrowseCallbackProc(HWND hwnd,
UINT uMsg,
LPARAM lp,
LPARAM pData)
{
TCHAR szDir[MAX_PATH];
pData;
switch(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)(LPCTSTR)pData);//默认的路径
break;
case BFFM_SELCHANGED:
// Set the status window to the currently selected path.
if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
{
//这边是用户选择目录后发出的消息. 你可以在这边判断szDir是否在e盘,不是的话,继续发送
//BFFM_INITIALIZED消息..
//否则
SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
}
break;
}
return 0;
}
BROWSEINFO bi;
TCHAR szDir[MAX_PATH];
LPITEMIDLIST pidl;
LPMALLOC pMalloc;
if (SUCCEEDED(SHGetMalloc(&pMalloc)))
{
ZeroMemory(&bi,sizeof(bi));
bi.hwndOwner = NULL;
bi.pszDisplayName = 0;
bi.pidlRoot = 0;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM)defaultPath; // pass address of object to callback function
pidl = SHBrowseForFolder(&bi);
if (pidl)
{
if (SHGetPathFromIDList(pidl,szDir))
{
UpdateData(FALSE);
}
pMalloc->Free(pidl);
pMalloc->Release();
}
}
Top
3 楼huziwu(虎子)回复于 2006-03-03 17:17:49 得分 0
To striking:
你给的代码是重载SHBrowseForFolder吗?该怎么重载呢?头一次用不是很懂啊。
还有在CFileDialog怎么实现呢
我的代码:
void CMyFileDlg::OnFolderChange()
{
CString GetFileName;
GetFileName=CMyFileDlg::GetFolderPath();
if(GetFileName.Left(1)!="E")
{
//该怎么处理呢?
}
}
或有什么别的办法呢?Top
4 楼striking(庸人自扰)回复于 2006-03-03 22:45:59 得分 0
BROWSEINFO bi;
TCHAR szDir[MAX_PATH];
LPITEMIDLIST pidl;
LPMALLOC pMalloc;
if (SUCCEEDED(SHGetMalloc(&pMalloc)))
{
ZeroMemory(&bi,sizeof(bi));
bi.hwndOwner = NULL;
bi.pszDisplayName = 0;
bi.pidlRoot = 0;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM)defaultPath; // pass address of object to callback function
pidl = SHBrowseForFolder(&bi);
if (pidl)
{
if (SHGetPathFromIDList(pidl,szDir))
{
UpdateData(FALSE);
}
pMalloc->Free(pidl);
pMalloc->Release();
}
}
这段添加到要浏览目录的地方Top
5 楼striking(庸人自扰)回复于 2006-03-03 22:46:23 得分 0
#include <shlobj.h>
INT CALLBACK BrowseCallbackProc(HWND hwnd,
UINT uMsg,
LPARAM lp,
LPARAM pData)
{
TCHAR szDir[MAX_PATH];
pData;
switch(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)(LPCTSTR)pData);//默认的路径
break;
case BFFM_SELCHANGED:
// Set the status window to the currently selected path.
if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
{
//这边是用户选择目录后发出的消息. 你可以在这边判断szDir是否在e盘,不是的话,继续发送
//BFFM_INITIALIZED消息..
//否则
SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
}
break;
}
return 0;
}
这段添加到cpp前面Top
6 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-03-04 06:58:48 得分 30
CFileDialog 不行,不过你可以在DoModal之后提示路径不符并且重新显示一个CFileDialog
用SHBrowseForFolder的话可以直接设置BROWSEINFO的pidlRoot成员为E:的pidl。Top
7 楼huziwu(虎子)回复于 2006-03-06 11:24:29 得分 0
To striking:我用你的方法还是不行,以下是我对你的代码进行的修改。
INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg,LPARAM lp,LPARAM pData)
{
TCHAR szDir[MAX_PATH];
pData;
switch(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)(LPCTSTR)"e:\\");//默认的路径
break;
case BFFM_SELCHANGED:
// Set the status window to the currently selected path.
if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
{
//这边是用户选择目录后发出的消息. 你可以在这边判断szDir是否在e盘,不是的话,继续发送
//BFFM_INITIALIZED消息..
CString path;
path.Format(szDir);
if(path.Left(1)=='e' || path.Left(1)=='E')
{
SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);//否则:
}
else
{
SendMessage(hwnd,BFFM_INITIALIZED,0,(LPARAM)"e:\\");
}
}
break;
}
return 0;
}
虽然选中别的盘符时浏览框上面显示的是E盘,但还是不能跳到E盘目录下Top
8 楼striking(庸人自扰)回复于 2006-03-06 11:30:04 得分 0
jiangsheng(蒋晟.Net[MVP]) 厉害, 我怎么没有想到呢, 唉. lz参考jiangsheng(蒋晟.Net[MVP]) 的方法.Top
9 楼huziwu(虎子)回复于 2006-03-06 11:43:54 得分 0
怎么改呢?
我有试过
bi.pidlRoot="e:\\";
说类型不匹配。
还有我觉得我在修改的地方也不对,我是在浏览目录的地方改的。
Top
10 楼huziwu(虎子)回复于 2006-03-06 11:59:27 得分 0
bi.pidlRoot的元素有:
USHORT cb;
BYTE abID[1];
现在不知怎么给这两个元素赋值。
我的代码是这样的:
bi.pidlRoot->mkid.abID[0]=(BYTE)'e';
编译时提示错误为:error C2166: l-value specifies const object
这是为什么呢?Top
11 楼striking(庸人自扰)回复于 2006-03-06 15:04:02 得分 0
if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
{
//这边是用户选择目录后发出的消息. 你可以在这边判断szDir是否在e盘,不是的话,继续发送
//BFFM_INITIALIZED消息..
CString path;
path.Format(szDir);
if(path.Left(1)=='e' || path.Left(1)=='E')
{
SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);//否则:
}
else
{
SendMessage(hwnd,BFFM_INITIALIZED,0,(LPARAM)"e:\\");//改成
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)(LPCTSTR)"e:\\");//默认的路径
}
}
break;
Top
12 楼huziwu(虎子)回复于 2006-03-06 16:18:58 得分 0
To striking:
按你的方法解决自动跳到E盘,但是D盘(或其它被双击的盘)同时也会展开目录树。
能不能实现我双击D盘时自动跳到E盘,且D盘不会展开目录树呢?
先谢谢大家了!特别感谢striking一路帮忙!解决问题后外开帖加分!!!!!!
Top
13 楼striking(庸人自扰)回复于 2006-03-06 17:07:48 得分 0
最终解决方案:
第一步: 将E盘转化为pidl
LPITEMIDLIST pidl;
LPSHELLFOLDER pDesktopFolder;
char szPath[MAX_PATH];
OLECHAR olePath[MAX_PATH];
ULONG chEaten;
ULONG dwAttributes;
HRESULT hr;
strcpy(szPath, "E:\\" );
//
// Get a pointer to the Desktop's IShellFolder interface.
//
if (SUCCEEDED(SHGetDesktopFolder(&pDesktopFolder)))
{
//
// IShellFolder::ParseDisplayName requires the file name be in
// Unicode.
//
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1,
olePath, MAX_PATH);
//
// Convert the path to an ITEMIDLIST.
//
hr = pDesktopFolder->ParseDisplayName(NULL,NULL,
olePath,
&chEaten,
&pidl,
&dwAttributes);
if (FAILED(hr))
{
// Handle error.
return ;
}
//
// pidl now contains a pointer to an ITEMIDLIST for .\readme.txt.
// This ITEMIDLIST needs to be freed using the IMalloc allocator
// returned from SHGetMalloc().
//
//release the desktop folder object
pDesktopFolder->Release();
}
第二步: 设置BROWSEINFO
#include <shlobj.h>
INT CALLBACK BrowseCallbackProc(HWND hwnd,
UINT uMsg,
LPARAM lp,
LPARAM pData)
{
TCHAR szDir[MAX_PATH];
pData;
switch(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, 0, pData );// 默认的路径,, 这边有修改
break;
case BFFM_SELCHANGED:
// Set the status window to the currently selected path.
if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
{
SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
}
break;
}
return 0;
}
BROWSEINFO bi;
TCHAR szDir[MAX_PATH];
LPITEMIDLIST pidl;//这个为第一步的结果
LPMALLOC pMalloc;
if (SUCCEEDED(SHGetMalloc(&pMalloc)))
{
ZeroMemory(&bi,sizeof(bi));
bi.hwndOwner = NULL;
bi.pszDisplayName = 0;
bi.pidlRoot = pidl;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM)pidl; // pass address of object to callback function
pidl = SHBrowseForFolder(&bi);
if (pidl)
{
if (SHGetPathFromIDList(pidl,szDir))
{
UpdateData(FALSE);
}
pMalloc->Free(pidl);
pMalloc->Release();
}
}
Top
14 楼huziwu(虎子)回复于 2006-03-07 16:36:57 得分 0
To striking:
非常感谢硬撑者,浏览目录的问题解决了。
还有一个问题是CFileDialog有没有办法也限制在e盘啊。
另开帖给striking:加60分,贴题为striking兄弟请进来.Top
15 楼striking(庸人自扰)回复于 2006-03-07 16:54:36 得分 0
呵呵. 得到蒋大人的提示. 也一并谢谢蒋大人吧.
引用:
jiangsheng(蒋晟.Net[MVP]) ( ) 信誉:290 2006-03-04 06:58:00 得分: 0
CFileDialog 不行,不过你可以在DoModal之后提示路径不符并且重新显示一个CFileDialog
用SHBrowseForFolder的话可以直接设置BROWSEINFO的pidlRoot成员为E:的pidl。
////////////
我帮你写了实现而已.
Top
16 楼huziwu(虎子)回复于 2006-03-07 17:11:45 得分 0
呵呵,帮忙的都要谢啊。
我是菜鸟,有时只讲方法领会不了,郁闷啊。
感谢jiangsheng(蒋晟.Net[MVP])大哥,striking(硬撑者)大哥。
先在此谢谢看贴的顶的兄弟姐妹们。
还有一问题没解决先不结贴。Top
17 楼huziwu(虎子)回复于 2006-03-07 17:15:18 得分 0
重载CFileDialog也不行吗?
我就不是想让操作者看到别的盘上的东西啊。
不行有别的办法吗?不用CFileDialog也行。这个不只是显示目录,还要显示文件。
Top
18 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-03-07 23:35:01 得分 0
SHBrowseForFolder可以用来选择单个文件(BROWSEINFO.ulFlags|=BIF_BROWSEINCLUDEFILES)
你也可以考虑重载BOOL CFileDialog::OnFileNameOKTop
19 楼huziwu(虎子)回复于 2006-03-08 09:00:43 得分 0
TO:jiangsheng(蒋晟.Net[MVP])
大哥你太牛了,用你的方法问题解决了。用SHBrowseForFolder解决的。
再次谢谢各位大哥帮忙,另开帖加分了!!!!!!!!标题:jiangsheng大哥请进
怎样才能拦载CFileDialog的消息呢,CFileDialog类里怎么ClassWizard里没有像PreTranslateMessage或Oncommand之类的事件呢?Top
20 楼huziwu(虎子)回复于 2006-03-08 09:16:16 得分 0
一时高兴过头,忘了一件事。用SHBrowseForFolder能不能过滤文件呢,例如我只要显示*.bmp文件其它类型文件不显示。Top
21 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-03-08 10:43:20 得分 0
http://msdn.microsoft.com/msdnmag/issues/05/06/CAtWork/default.aspxTop
22 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-03-08 11:26:03 得分 0
I suspect the nub of the probem lies in the fact that your class is not the
hierarchical parent of the dialog that you see on the screen. To put it
another way, your class actually becomes a child of the file open dialog
window. Use Spy++ to look at the hierarchy and you'll see what I mean. It
appears that the real dialog window (which I assume does get the message)
examines the various messages and decides to whom it should pass on
messages.Top
23 楼huziwu(虎子)回复于 2006-03-08 11:57:07 得分 0
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_BROWSEINCLUDEFILES ;
我用SHGetPathFromIDList(pidl,szDir),返回结果szDir不带扩展名,怎么获得扩展名?Top
24 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-03-08 13:07:16 得分 0
IShellFolder::GetAttributesOf ?Top
25 楼huziwu(虎子)回复于 2006-03-10 10:02:23 得分 0
仿造CFileDialog我自己做了一个打开文件的对话框,可是在CListBox里显示文件太单调了,就只显示了文件名,没有图标。例如文件夹的显示:[新建文件夹],多了[]。如何像CFileDialog里显示那样加图标呢?Top
26 楼huziwu(虎子)回复于 2006-03-10 16:35:29 得分 0
结贴了谢谢 硬撑者 和 蒋晟 两位大哥的帮忙!!!!!!!!!!!Top




