调用API:SHBrowseForFolder()选择文件夹总是报错,为什么?
我写了一个选择文件夹的函数,代码如下:
VOID SelectPath(HWND hwnd)
{
BROWSEINFO bi = { 0 };
LPMALLOC pMlc;
TCHAR szDisplayName[MAX_PATH];
TCHAR szPath[MAX_PATH];
SecureZeroMemory(szDisplayName, sizeof(szDisplayName)); SecureZeroMemory(szPath, sizeof(szPath));
if (SHGetMalloc(&pMlc) == E_FAIL)
{
MessageBox(hwnd,
TEXT("Call to SHGetMalloc() failed."),
TEXT("Error"),
MB_OK | MB_ICONERROR);
return;
}
bi.hwndOwner = hwnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = szDisplayName;
bi.lpszTitle = TEXT("Please select the path to create the file:");
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
LPITEMIDLIST pIdl = SHBrowseForFolder(&bi);
if (pIdl == NULL)
{
pMlc->Release();
return;
}
SHGetPathFromIDList(pIdl, szPath);
if (szPath[lstrlen(szPath) - 1] != TEXT('\\'))
lstrcat(szPath, TEXT("\\"));
SetWindowText(GetDlgItem(hwnd, IDC_PATH), szPath);
pMlc->Free(pIdl);
pMlc->Release();
}
在程序的初始化过程中我已经调用了CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)函数用来加载COM library,在程序的结束过程中也调用了CoUninitialize()函数用来关闭COM library。
在程序的执行过程中,首次调用SelectPath()时运行正常,但是当我第二或者第三次调用SelectPath()时程序就有可能报如下错误:
“xxx”指令引用的内存“xxx”。该内存不能为“written”。
而且该错误不是总能再现的,但是出现频率较高。
请大侠们指点迷津,非常感谢!
问题点数:100、回复次数:3Top
1 楼legendhui(秋天的叶子)回复于 2005-04-15 15:34:35 得分 30
You must initialize Component Object Model (COM) using CoInitializeEx with the COINIT_APARTMENTTHREADED flag set in the dwCoInit parameter prior to calling SHBrowseForFolder. You can also use CoInitialize or OleInitialize, which always use apartment threading.
Note If COM is initialized using CoInitializeEx with the COINIT_MULTITHREADED flag, SHBrowseForFolder fails if the caller uses the BIF_USENEWUI or BIF_NEWDIALOGSTYLE flag in the BROWSEINFO structure.
The calling application is responsible for freeing the returned PIDL by using the Shell allocator's IMalloc::Free method. To retrieve a handle to that IMalloc interface, call SHGetMalloc. For further discussion of the Shell allocator and PIDLs, see The Shell Namespace.
There are two styles of dialog box available. The older style is displayed by default and is not resizable. To specify a dialog box using the newer style, set the BIF_USENEWUI flag in the ulFlags member of the BROWSEINFO structure. The newer style provides a number of additional features, including drag and drop capability within the dialog box, reordering, deletion, shortcut menus, the ability to create new folders, and other shortcut menu commands. Initially, it is larger than the older dialog box, but can be resized by the user.
If you implement a callback function, you receive a handle to the dialog box. One use of this window handle is to modify the layout or contents of the dialog box. Because it is not resizable, modifying the older style dialog box is relatively straightforward. Modifying the newer style dialog box is much more difficult, and not recommended. Not only does it have a different size and layout than the old style, but its dimensions and the positions of its controls change every time it is resized by the user.
If the BIF_RETURNONLYFSDIRS flag is set in the ulFlags member of the BROWSEINFO structure, the OK button will remain enabled for "\\server" items, as well as "\\server\share" and directory items. However, if the user selects a "\\server" item, passing the returned PIDL to SHGetPathFromIDList fails.
Custom Filtering
Under Microsoft® Windows® XP, SHBrowseForFolder supports custom filtering on the contents of the dialog box. To create a custom filter, follow these steps.
Set the BIF_NEWDIALOGSTYLE flag in the ulFlags member of the BROWSEINFO parameter structure.
Specify a callback function in the lpfn member of the BROWSEINFO parameter structure.
The callback function receives BFFM_INITIALIZED and BFFM_IUNKNOWN messages. On receipt of the BFFM_IUNKNOWN message, the callback function's LPARAM parameter contains a pointer to an instance of IUnknown. Call QueryInterface on that IUnknown to obtain a pointer to an instance of IFolderFilterSite.
Create an object that implements IFolderFilter.
Call IFolderFilterSite::SetFilter, passing it a pointer to your IFolderFilter. IFolderFilter methods can then be used to include and exclude items from the tree.
Once the filter is created, the IFolderFilterSite interface is no longer needed. Call IFolderFilterSite::Release if you have no further use for it.Top
2 楼ColderRain(一切尽在不言中)回复于 2005-04-15 20:17:01 得分 40
// Displays the dialog
CSBrowseFolder::retCode CSBrowseFolder::Show(HWND parent, LPSTR pathBuffer)
{
// Passed in a NULL pointer (!)
ASSERT(pathBuffer);
if (!pathBuffer)
return RET_NOPATH;
// Return value for the function
retCode ret = RET_OK;
LPITEMIDLIST itemIDList;
// Set up the params
BROWSEINFO browseInfo;
// The dialog must have a parent
ASSERT(parent);
browseInfo.hwndOwner = parent;
browseInfo.pidlRoot = m_root;
browseInfo.pszDisplayName = m_displayName;
browseInfo.lpszTitle = m_title;
browseInfo.ulFlags = m_style;
browseInfo.lpfn = NULL;
browseInfo.lParam = 0;
// Show the dialog
itemIDList = SHBrowseForFolder(&browseInfo);
// Did user press cancel?
if (!itemIDList)
ret = RET_CANCEL;
// Is everything so far?
if (ret != RET_CANCEL) {
// Get the path from the returned ITEMIDLIST
if (!SHGetPathFromIDList(itemIDList, pathBuffer))
ret = RET_NOPATH;
// Now we need to free the ITEMIDLIST the shell allocated
LPMALLOC shellMalloc;
HRESULT hr;
// Get pointer to the shell's malloc interface
hr = SHGetMalloc(&shellMalloc);
// Did it work?
if (SUCCEEDED(hr)) {
// Free the shell's memory
shellMalloc->Free(itemIDList);
// Release the interface
shellMalloc->Release();
}
}
return ret;
}Top
3 楼vcmute(BCare4 H1Rest Good9!)回复于 2005-04-16 09:15:39 得分 30
我这正常
去掉BIF_NEWDIALOGSTYLE看看
还有你的SecureZeroMemoryTop
相关问题
- 调用API:SHBrowseForFolder()选择文件夹总是报错,为什么?
- 调用API:SHBrowseForFolder()选择文件夹总是报错,为什么?
- 如何使用API得到文件夹?
- 高分求解:使用SHBrowseForFolder API可以打开浏览文件夹对话框,如何让"确定"按钮"的enable状态随文件夹中是否有要找的文件的是否存在而
- 把文件夹绑定到listbox,能显示文件夹里所有的文件名.可当选择一条里面的文件名作为参数,却报错.
- 有没有API函数调用“浏览文件夹”让用户选择文件夹?
- 谁会用API清除INTERNET TEMP文件夹里的东西。
- 怎样调用api修改文件夹图标
- pb中怎样用api函数删除文件夹?
- 有没有判断文件夹是否存在的API函数?




