![]()
SHMultiFilePropertiesを利用するとファイルやフォルダなどのプロパティを表示できる。複数のファイルなどを選択した場合でも使える。
#include "atlstr.h"
#include "atlcoll.h"
#include "shlobj.h"
/*!
* \brief
* パスからPIDLを取得する
*
* 取得したPIDLは必ず CoTaskMemFree、ILFree、IMalloc::Free() のいずれかで解放すること!
*
* \param[in] pszPath
* PIDLを取得したいパス
*
* \param[out] ppItemIdList
* 取得したPIDL
*
* \retval true 成功
* \retval false 失敗
*
*/
bool GetItemIdListFromPath(LPCTSTR pszPath,LPITEMIDLIST* ppItemIdList)
{
if(ppItemIdList == NULL || pszPath == NULL || *pszPath == NULL)
return false;
//ILCreateFromPathで取得
*ppItemIdList = ::ILCreateFromPath(pszPath);
if(*ppItemIdList)
return true; //取得成功
//SHSimpleIDListFromPathで取得
*ppItemIdList = ::SHSimpleIDListFromPath((CAtlStringW)pszPath);
if(*ppItemIdList)
return true; //取得成功
//IShellFolderで取得
{
CComPtr<IShellFolder> pIShellFolder;
HRESULT hr;
hr = ::SHGetDesktopFolder(&pIShellFolder);
if(pIShellFolder == NULL)
return false;
#ifdef UNICODE
hr = pIShellFolder->ParseDisplayName(NULL,NULL,pszPath,NULL,&pItemIdList,NULL);
#else
{
CAtlStringW ustrPath;
//簡単にUnicode変換
ustrPath = pszPath;
hr = pIShellFolder->ParseDisplayName(NULL,NULL,ustrPath.GetBuffer(0),NULL,ppItemIdList,NULL);
}
#endif
if(SUCCEEDED(hr))
return true; //取得成功
}
return false;
}
//
// ファイルやフォルダのプロパティを表示する
//
bool ShowPropertyDialog(LPCTSTR pszPath)
{
HRESULT hr;
bool ret;
LPITEMIDLIST pItemIdList;
CComPtr<IShellFolder> pIShellFolder;
CComPtr<IDataObject> pIDataObject;
hr = ::SHGetDesktopFolder(&pIShellFolder);
if(FAILED(hr))
return false;
ret = GetItemIdListFromPath(pszPath,&pItemIdList);
if(ret == false)
return false;
hr = pIShellFolder->GetUIObjectOf(NULL,1,(LPCITEMIDLIST*)&pItemIdList,IID_IDataObject,NULL,(void**)&pIDataObject);
::ILFree(pItemIdList);
if(FAILED(hr))
return false;
hr = ::SHMultiFileProperties(pIDataObject,0);
return SUCCEEDED(hr) ? true : false;
}
//
// 複数のファイルやフォルダのプロパティを表示する
//
bool ShowMultiPropertyDialog(const CAtlArray<CAtlString>& astrPath)
{
HRESULT hr;
CComPtr<IShellFolder> pIShellFolder;
CComPtr<IDataObject> pIDataObject;
hr = ::SHGetDesktopFolder(&pIShellFolder);
if(FAILED(hr))
return false;
//複数ファイルのPIDLを取得し、IDataObjectに結びつける
{
size_t i;
size_t nSize;
bool ret;
LPITEMIDLIST* ppItemIdList;
nSize = astrPath.GetCount();
ppItemIdList = new LPITEMIDLIST[nSize];
if(ppItemIdList == NULL)
return false;
for(i = 0; i < nSize; i++)
{
ret = GetItemIdListFromPath(astrPath[i],&ppItemIdList[i]);
if(ret == false)
break;
}
if(ret == false)
nSize = i;
if(ret)
hr = pIShellFolder->GetUIObjectOf(NULL,(UINT)nSize,(LPCITEMIDLIST*)ppItemIdList,IID_IDataObject,NULL,(void**)&pIDataObject);
for(i = 0; i < nSize; i++)
::ILFree(ppItemIdList[i]);
delete ppItemIdList;
if(ret == false || FAILED(hr))
return false;
}
//この関数を複数のファイルのプロパティを表示できるように改造する場合は
//以下のコメントアウト処理をSHMultiFilePropertiesの前に実行する(KB330040)
{
LPITEMIDLIST pItemIdList;
IDataObject* pIDataObject;
hr = ::SHGetSpecialFolderLocation(NULL,CSIDL_DRIVES,&pItemIdList);
if(SUCCEEDED(hr))
{
hr = pIShellFolder->GetUIObjectOf(NULL,1,(LPCITEMIDLIST*)&pItemIdList,IID_IDataObject,NULL,(void**)&pIDataObject);
::ILFree(pItemIdList);
}
pIDataObject->Release();
}
hr = ::SHMultiFileProperties(pIDataObject,0);
return SUCCEEDED(hr) ? true : false;
}
void Test(void)
{
::CoInitialize(NULL);
//1つのファイルのプロパティ表示
ShowPropertyDialog(_T("c:\\autoexec.bat"));
//3つのファイルのプロパティ表示
{
CAtlArray<CAtlString> astrPath;
astrPath.Add(_T("c:\\config.sys"));
astrPath.Add(_T("c:\\autoexec.bat"));
astrPath.Add(_T("c:\\pagefile.sys"));
ShowMultiPropertyDialog(astrPath);
}
::MessageBox(NULL,_T("ダミーメッセージボックス"),_T(""),MB_OK);
::CoUninitialize();
}
