有关Shell编程:IMalloc::Free()在_MBCS下编译运行正常,在_UNICODE下失败
我现在是实现一个Shell Tree显示桌面为根的树状列表
typedef struct tagID
{
// Contains the LPIDL of the desktop
LPSHELLFOLDER lpsfParent;
// Contains the LPITEMIDLIST of the file / folder relatived
// to the parent folder
LPITEMIDLIST lpi;
// Contains the full LPITEMIDLIST of the file / folder relatived
// to the desktop
LPITEMIDLIST lpifq;
} TVITEMDATA, *LPTVITEMDATA;
用这个结构作为TREEITEM 的lParam
下面是几个相关的函数
// Get the subfolders of the current folder and display them
// Params:
// lpsf: the ISHELLFOLDER object of the folder
// lpifq
void CShellTreeCtrl::DisplaySubItems(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent)
{
// the TV_ITEM struct used to insert item
TV_ITEM tvi;
// The TV_INSERTSTRUCT struct of the item to be inserted
TV_INSERTSTRUCT tvins;
// The previouse added item handle
HTREEITEM hPrevTreeItem = NULL;
// IEnumIDList interface point
LPENUMIDLIST lpe = NULL;
LPITEMIDLIST lpi = NULL, lpiTemp = NULL, lpidlThisItem = NULL;
LPTVITEMDATA lptvid = NULL;
LPMALLOC lpMalloc = NULL;
// ULONG ulFetched;
// Count
UINT uCount=0;
HRESULT hr;
TCHAR szBuff[MAX_PATH];
// The handle of the parent window
HWND hwnd = GetParent()->m_hWnd;
// Alloc shell memory
hr = SHGetMalloc( &lpMalloc );
if (FAILED(hr))
return;
// Get the IEnumIDList of the IShellFolder interface
hr = lpsf->EnumObjects(hwnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &lpe);
if (SUCCEEDED(hr))
{
while (S_OK == lpe->Next(1, &lpi, NULL))
{
// Attributes flag: is folder and if has sub folder
ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_LINK;
lpsf->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);
// If the current item is directory
if (ulAttrs & SFGAO_FOLDER)
{
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
//if (ulAttrs & SFGAO_HASSUBFOLDER)
//{
// tvi.cChildren=1;
// tvi.mask |= TVIF_CHILDREN;
//}
// Alloc memory
lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));
if (!lptvid)
goto Done;
// Get the item name
if (!GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
goto Done;
tvi.pszText = szBuff;n
#ifdef DEBUG
TRACE( _T("Displaying %s\r\n"), szBuff );
#endif
// If the folder has sub folders / files,
// set corresponding Treectrl item attribute
if( (ulAttrs & SFGAO_HASSUBFOLDER) || HasGotSubEntries(lpsf, lpi) )
{
tvi.cChildren=1;
tvi.mask |= TVIF_CHILDREN;
}
tvi.cchTextMax = _MAX_PATH;
lpidlThisItem = ConcatPidls(lpifq, lpi);
//Copy ITEMIDLIST
lptvid->lpi = CopyITEMID(lpMalloc, lpi);
tvi.iImage = GetIconIndex(lpidlThisItem);
tvi.iSelectedImage = GetSelIconIndex(lpidlThisItem);
// Save the parent folder
lptvid->lpsfParent = lpsf;
lpsf->AddRef();
lptvid->lpifq = ConcatPidls(lpifq, lpi);
tvi.lParam = (LPARAM)lptvid;
// Insert a file / folder item to treectrl
tvins.item = tvi;
tvins.hInsertAfter = hPrevTreeItem;
tvins.hParent = hParent;
hPrevTreeItem = InsertItem(&tvins);
}
else
// Ignoure the shortcuts
if( !(SFGAO_LINK & ulAttrs) )
{
tvi.mask= TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
// Alloc memory
lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));
if (!lptvid)
goto Done;
// Get the item name
if (!GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
goto Done;
///*
// If m_sFileFilter is not empty, do the estimate work
if( !m_sFileFilter.IsEmpty() )
{
if( !MatchFilters(szBuff) )
{
lpMalloc->Free(lpidlThisItem);
lpidlThisItem = 0;
continue;
}
}//*/
tvi.pszText = szBuff;
tvi.cchTextMax = MAX_PATH;
lpidlThisItem = ConcatPidls(lpifq, lpi);
//Copy ITEMIDLIST
lptvid->lpi = CopyITEMID(lpMalloc, lpi);
tvi.iImage = GetIconIndex(lpidlThisItem);
tvi.iSelectedImage = GetSelIconIndex(lpidlThisItem);
// Save the parent folder
lptvid->lpsfParent = lpsf;
lpsf->AddRef();
//lptvid->lpifq = ConcatPidls(lpifq, lpi);
lptvid->lpifq = lpidlThisItem;
tvi.lParam = (LPARAM)lptvid;
// Insert a file / folder item to TreeCtrl
tvins.item = tvi;
tvins.hInsertAfter = hPrevTreeItem;
tvins.hParent = hParent;
hPrevTreeItem = InsertItem(&tvins);
}
if( lpidlThisItem )
{
lpMalloc->Free( lpidlThisItem );
lpidlThisItem = 0;
}
}// End while
// Free memory.
if( lpi )
{
lpMalloc->Free(lpi);
lpi=0;
}
} // end if
// Do the clean up work
Done:
if (lpe)
lpe->Release();
if (lpi && lpMalloc)
lpMalloc->Free(lpi);
if (lpidlThisItem && lpMalloc)
lpMalloc->Free(lpidlThisItem);
if (lpMalloc)
lpMalloc->Release();
}