アイテム ID リスト



ホーム > Windowsプログラミング


シェル名前空間とは、簡単に言うと通常のファイルシステムの上位概念のことです。
シェル名前空間のアイテムを識別するためのものがアイテム ID リストになります。
図と表にまとめるとこんな感じです。

tip0011_ItemIDList.bmp


ファイルシステム シェル名前空間
要素 ファイル
フォルダ
ファイル
フォルダ
仮想フォルダ
ルート ドライブ名 デスクトップ
識別 パス アイテム ID リスト

図を見てもらえばわかるとおり、シェル名前空間はコンピュータやネットワークなどの仮想フォルダと通常のファイルシステムを含んでいます。
デスクトップは通常のファイルシステムとシェル名前空間の両方に属していますが、それぞれの場合で役割が全く異なります。
ファイルシステムのデスクトップは通常のフォルダと変わりません。しかし、シェル名前空間のデスクトップはシェル名前空間のルートで、直下にコンピュータやネットワークを保持しています。



  ITEMIDLIST
LPITEMIDLIST


//「絶対位置」を表すITEMIDLIST
  IDLIST_ABSOLUTE
 PIDLIST_ABSOLUTE
PCIDLIST_ABSOLUTE


//「相対位置」を表すITEMIDLIST
  IDLIST_RELATIVE
 PIDLIST_RELATIVE
PCIDLIST_RELATIVE


//「子要素」を表すITEMIDLIST
  PITEMID_CHILD
 PUITEMID_CHILD
 PCITEMID_CHILD
PCUITEMID_CHILD


//P:ポインタ
//C:const
//U:64-bit用

通常は ITEMIDLIST または IDLIST_ABSOLUTE を使い、用途を限定する場合に IDLIST_RELATIVE や PITEMID_CHILD を使うみたいです。



HRESULT SHGetSpecialFolderLocation(
    HWND             hwndOwner,		//NULLを指定
    int              nFolder,		//取得したいアイテムIDリストのCSIDL
    PIDLIST_ABSOLUTE *ppidl			//ここに格納される CoTaskMemFree()で解放する
);
HRESULT SHGetKnownFolderIDList(
    REFKNOWNFOLDERID rfid,			//取得したいアイテムIDリストのKNOWNFOLDERID
    DWORD            dwFlags,		//0でいい
    HANDLE           hToken,		//NULLでいい
    PIDLIST_ABSOLUTE *ppidl			//ここに格納される ILFree()で解放する
);

同様の方法でファイルパスを取得することもできます。

HRESULT SHGetKnownFolderPath(
    REFKNOWNFOLDERID rfid,			//取得したいアイテムIDリストのKNOWNFOLDERID
    DWORD            dwFlags,		//0でいい
    HANDLE           hToken,		//NULLでいい
    PWSTR            *ppsPath		//ここに格納される CoTaskMemFree()で解放する
);
CSIDL KNOWNFOLDERID 意味
CSIDL_DESKTOP(仮想フォルダ)
CSIDL_DESKTOPDIRECTORY(ファイルシステム)
FOLDERID_Desktop デスクトップ
CSIDL_DRIVES FOLDERID_ComputerFolder コンピュータ
CSIDL_CONTROLS FOLDERID_ControlPanelFolder コントロールパネル
CSIDL_COMPUTERSNEARME
CSIDL_NETWORK
FOLDERID_NetworkFolder ネットワーク
- FOLDERID_HomeGroup ホームグループ
- FOLDERID_Libraries ライブラリ
- FOLDERID_DocumentsLibrary ライブラリのドキュメント
- FOLDERID_PicturesLibrary ライブラリのピクチャ
- FOLDERID_VideosLibrary ライブラリのビデオ
- FOLDERID_MusicLibrary ライブラリのミュージック
CSIDL_BITBUCKET FOLDERID_RecycleBinFolder ごみ箱

その他に関しては msdn - CSIDLとか msdn - KNOWNFOLDERID を参照してください。



使い終わったアイテム ID リストは解放する必要があります。

void CoTaskMemFree(
    LPVOID pv
);
void ILFree(
    PIDLIST_RELATIVE pidl
);



アイテム ID リストとファイルパスは相互に変換することができます。ただし、仮想フォルダは変換できません。

BOOL SHGetPathFromIDList(
    PCIDLIST_ABSOLUTE pidl,			//取得したいアイテム ID リスト(仮想フォルダ以外)
    LPTSTR            pszPath		//パスを受け取るバッファ
);
PIDLIST_ABSOLUTE ILCreateFromPath(
    PCTSTR pszPath			//対象のファイルパス
);

ILCreateFromPath() で取得したアイテム ID リストは使い終わったら ILFree() で解放する必要があります。


BOOL ILIsEqual(
    PCIDLIST_ABSOLUTE pidl1,
    PCIDLIST_ABSOLUTE pidl2
);

一致ならTRUEを、不一致ならFALSEを返します。



アイテム ID リストからファイルパスを文字列として取得することができます。しかし、仮想フォルダの場合は文字列として取得するすべがありません(私が知らないだけかもしれません)。なので、これを可能にする関数を作成します。

KNOWNFOLDERID fid[11] = {
    FOLDERID_Desktop,
    FOLDERID_ComputerFolder,
    FOLDERID_ControlPanelFolder,
    FOLDERID_NetworkFolder,
    FOLDERID_HomeGroup,
    FOLDERID_Libraries,
    FOLDERID_DocumentsLibrary,
    FOLDERID_PicturesLibrary,
    FOLDERID_VideosLibrary,
    FOLDERID_MusicLibrary,
    FOLDERID_RecycleBinFolder
};
 
TCHAR *stVirtual[11] = {
    TEXT("Desktop"),
    TEXT("Computer"),
    TEXT("ControlPanel"),
    TEXT("Network"),
    TEXT("HomeGroup"),
    TEXT("Liblary"),
    TEXT("Documents"),
    TEXT("Pictures"),
    TEXT("Videos"),
    TEXT("Music"),
    TEXT("ごみ箱")
};
 
//アイテムIDリストからパスを作成
int ConvertPIDLToPath(PCIDLIST_ABSOLUTE pidlDir, LPTSTR lpDir, TCHAR *lpDrive)
{
    for(int i=0; i<11; i++){
        //仮想フォルダかどうかチェック
        PIDLIST_ABSOLUTE pidl;
        SHGetKnownFolderIDList(fid[i], 0, NULL, &pidl);
        if(ILIsEqual(pidlDir, pidl)){
            //仮想フォルダ
            ILFree(pidl);
            lstrcpy(lpDir, stVirtual[i]);
            if(lpDrive != NULL)
                *lpDrive = 'C';
            return 1;
        }
    }
 
    if(SHGetPathFromIDList(pidlDir, lpDir)){
        //通常のフォルダ
        int n = PathGetDriveNumber(lpDir);
        if(lpDrive != NULL)
            *lpDrive = n + 'A';
        return 2;
    }else{
        //不明なフォルダ
        //ネットワークドライブなど
        lstrcpy(lpDir, TEXT("unknown"));
        if(lpDrive != NULL)
            *lpDrive = '@';
        return 3;
    }
}
 
//パスからアイテムIDリストを作成
//ILFree()で解放する
PIDLIST_ABSOLUTE ConvertPathToPIDL(LPCTSTR lpDir)
{
    for(int i=0; i<11; i++){
        if(lstrcmp(lpDir, stVirtual[i]) == 0){
            //仮想フォルダのアイテムIDリストを返す
            PIDLIST_ABSOLUTE pidl;
            SHGetKnownFolderIDList(fid[i], 0, NULL, &pidl);
            return pidl;
        }
    }
 
    //通常のフォルダのアイテムIDリストを返す
    return ILCreateFromPath(lpDir);
}



参考



inserted by FC2 system