フォルダーの内容に関する情報の取得
「フォルダーの ID の取得」セクションでは、項目識別子リスト (PIDL) への名前空間オブジェクトのポインターを取得するための 2 つの方法について説明しました。 1 つの明白な質問として、PIDL を取得したら、何を行うことができるかというものがあります。 それに関連する質問として、どちらのアプローチも機能していない場合、またはアプリケーションに適していない場合はどうかというのもあります。 この 2 つの質問に対する答えは、名前空間がどのように実装されているかを詳しく見る必要があります。 キーは IShellFolder インターフェイスです。
- IShellFolder インターフェイスの使用
- フォルダーの内容の列挙
- 表示名とその他のプロパティの決定
- サブフォルダーの IShellFolder インターフェイスへのポインターの取得
- オブジェクトの親フォルダーの決定
IShellFolder インターフェイスの使用
このドキュメントの前半では、名前空間フォルダーはオブジェクトと呼ばれてました。 その時点で、この用語は緩やかな意味で使用されていましたが、実際には厳密な意味でも当てはまります。 すべての名前空間フォルダーは、コンポーネント オブジェクト モデル (COM) オブジェクトによって表されます。 各フォルダー オブジェクトには、さまざまなタスクに使用できるインターフェイスが多数公開されています。 オプションの一部のインターフェイスは、すべてのフォルダーで公開されない場合があります。 ただし、すべてのフォルダーで基本的なインターフェイスである IShellFolder を公開する必要があります。
フォルダー オブジェクトを使用する最初の手順は、その IShellFolder インターフェイスへのポインターを取得することです。 IShellFolder は、オブジェクトの他のインターフェイスへのアクセスを提供するだけでなく、多くの一般的なタスクを処理するメソッドのグループを公開しています。そのうちのいくつかについては、このセクションで説明します。
名前空間オブジェクトの IShellFolder インターフェイスへのポインターを取得するには、最初に SHGetDesktopFolder を呼び出す必要があります。 この関数は、名前空間ルート (デスクトップ) の IShellFolder インターフェイスへのポインターを返します。 デスクトップの IShellFolder インターフェイスを用意したら、さまざまな方法で作業を進められます。
たとえば、SHGetFolderLocation を呼び出すことによって、目的のフォルダーの PIDL が既にある場合は、デスクトップの IShellFolder::BindToObject メソッドを呼び出して IShellFolder インターフェイスを取得できます。 ファイル システム オブジェクトのパスがある場合は、まずデスクトップの IShellFolder::P arseDisplayName メソッドを呼び出して PIDL を取得してから、IShellFolder::BindToObject を呼び出す必要があります。 どちらの方法も適用できない場合は、他の IShellFolder メソッドを使用して名前空間を移動できます。 詳細については、「名前空間の移動」を参照してください。
フォルダーの内容の列挙
通常、フォルダーに対して行う最初の操作は、フォルダーに含まれている内容を調べることです。 最初に、フォルダーの IShellFolder::EnumObjects メソッドを呼び出す必要があります。 フォルダーは標準の OLE 列挙オブジェクトを作成し、その IEnumIDList インターフェイスを返します。 このインターフェイスは、フォルダーの内容を列挙するために使用できる 4 つの標準メソッド (Clone、Next、Reset、Skip) を公開します。
フォルダーの内容を列挙する基本的な手順は次のとおりです。
- フォルダーの IShellFolder::EnumObjects メソッドを呼び出して、列挙オブジェクトの IEnumIDList インターフェイスへのポインターを取得します。
- 未割り当ての PIDL を IEnumIDList::Next に渡します。 Next に PIDL の割り当てが行われますが、不要になったら、アプリケーションで割り当てを解除する必要があります。 Next が返されると、PIDL にはオブジェクトの項目 ID と最後の NULL 文字だけが含まれます。 言い換えれば、これは完全修飾された PIDL ではなく、フォルダーに対する相対的な単一レベルの PIDL です。
- NEXT がすべての項目が列挙されたことを示す S_FALSE を返すまで 、手順 2. を繰り返します。
- IEnumIDList::Release を呼び出して列挙オブジェクトを解放します。
Note
完全な PIDL と相対的な PIDL のどちらを使用しているかを追跡することが重要です。 一部の関数とメソッドはどちらかを受け入れますが、関数とメソッドによってはどちらか一方しか受け入れないものもあります。
残りの 3 つの IEnumIDList メソッド (Reset、Skip、Clone) は、フォルダーの列挙を繰り返す必要がある場合に便利です。 これにより列挙をリセットしたり、1 つ以上のオブジェクトをスキップしたり、列挙オブジェクトのコピーを作成してその状態を保持したりできます。
表示名とその他のプロパティの決定
フォルダーに含まれるすべての PIDL を列挙すると、それらがどのようなオブジェクトを表しているかを確認できます。 IShellFolder インターフェイスには便利なメソッドが多数用意されており、ここではそのうちの 2 つについて説明します。 その他の IShellFolder メソッドとその他のシェル フォルダー インターフェイスについては、後で説明します。
最も便利なプロパティの一つは、オブジェクトの表示名です。 オブジェクトの表示名を取得するには、その PIDL を IShellFolder::GetDisplayNameOf に渡します。 オブジェクトは名前空間内の親フォルダーより下の任意の場所に配置できますが、その PIDL はフォルダーに対して相対的である必要があります。
IShellFolder::GetDisplayNameOf は、表示名を STRRET 構造体の一部として返します。 STRRET 構造体から表示名を抽出するのは少し難しい場合があるため、シェルには、StrRetToStr と StrRetToBuf という 2 つの関数が提供されています。 どちらの関数も STRRET 構造体を受け取り、表示名を通常の文字列として返します。 両社の違いは、文字列の割り当て方法のみです。
オブジェクトは、表示名に加えて、フォルダーかどうか、移動可能かどうかなど、さまざまな属性を持つことができます。 オブジェクトの属性を取得するには、その PIDL を IShellFolder::GetAttributesOf に渡します。 属性の完全なリストは非常に大きいため、詳細についてはリファレンスを参照してください。 GetAttributesOf に渡す PIDL は単一レベルである必要があることに注意してください。 特に、 IShellFolder::GetAttributesOf は IEnumIDList::Nextによって返される PIDL を受け入れます。 PIDL の配列を渡すことができ、GetAttributesOf は、配列内のすべてのオブジェクトに共通する属性を返します。
オブジェクトの完全修飾パスまたは PIDL がある場合、SHGetFileInfo は、多くの目的に十分なオブジェクトに関する情報を簡単に取得する方法を提供します。 SHGetFileInfo は完全修飾パスまたは PIDL を受け取り、次のようなオブジェクトに関するさまざまな情報を返します。
- オブジェクトの表示名
- オブジェクトの属性
- オブジェクトのアイコンへのハンドル
- システム イメージ リストへのハンドル
- オブジェクトのアイコンを含むファイルのパス
サブフォルダーの IShellFolder インターフェイスへのポインターの取得
フォルダーにサブフォルダーが含まれているかどうかを確認するには、IShellFolder::GetAttributesOf を呼び出して、SFGAO_FOLDER フラグが設定されているかどうかを確認することで判断できます。 オブジェクトがフォルダーの場合は、そのオブジェクトにバインドすることで、その IShellFolder インターフェイスへのポインターが提供されます。
サブフォルダーにバインドするには、親フォルダーの IShellFolder::BindToObject メソッドを呼び出します。 このメソッドは、サブフォルダーの PIDL を受け取り、その IShellFolder インターフェイスへのポインターを返します。 このポインターを取得したら、IShellFolder メソッドを使用してサブフォルダーの内容を列挙したり、そのプロパティを決定したりできます。
オブジェクトの親フォルダーの決定
オブジェクトの PIDL がある場合は、親フォルダーによって公開されているインターフェイスの 1 つに対するハンドルが必要な場合があります。 たとえば、IShellFolder::GetDisplayNameOf を使用して PIDL に関連付けられている表示名を決定する場合は、まずオブジェクトの親の IShellFolder インターフェイスを取得する必要があります。 これは、前のセクションで説明した手法で取得できます。 しかし、シェル関数 SHBindToParent を使用することで、より簡単に取得できます。 この関数は、オブジェクトの完全修飾 PIDL を受け取り、親フォルダー上の指定されたインターフェイス ポインターを返します。 必要に応じて、IShellFolder::GetAttributesOf などのメソッドで使用する項目の単一レベルの PIDL も返します。
次のサンプル コンソール アプリケーションは、System の特殊フォルダーの PIDL を取得し、その表示名を返します。
#include <shlobj.h>
#include <shlwapi.h>
#include <iostream.h>
#include <objbase.h>
int main()
{
IShellFolder *psfParent = NULL;
LPITEMIDLIST pidlSystem = NULL;
LPCITEMIDLIST pidlRelative = NULL;
STRRET strDispName;
TCHAR szDisplayName[MAX_PATH];
HRESULT hr;
hr = SHGetFolderLocation(NULL, CSIDL_SYSTEM, NULL, NULL, &pidlSystem);
hr = SHBindToParent(pidlSystem, IID_IShellFolder, (void **) &psfParent, &pidlRelative);
if(SUCCEEDED(hr))
{
hr = psfParent->GetDisplayNameOf(pidlRelative, SHGDN_NORMAL, &strDispName);
hr = StrRetToBuf(&strDispName, pidlSystem, szDisplayName, sizeof(szDisplayName));
cout << "SHGDN_NORMAL - " <<szDisplayName << '\n';
}
psfParent->Release();
CoTaskMemFree(pidlSystem);
return 0;
}
アプリケーションはまず、SHGetFolderLocation を使用してSystem のフォルダーの PIDL を取得します。 次に、SHBindToParent を呼び出し、親フォルダーの IShellFolder インターフェイスへのポインターと、System のフォルダーの PIDL を返します。 次に、親フォルダーの IShellFolder::GetDisplayNameOf メソッドを使用して、System のフォルダーの表示名を取得します。 GetDisplayNameOf は STRRET 構造体を返すため、StrRetToBuf を使用して表示名を通常の文字列に変換します。 表示名を表示すると、インターフェイス ポインターが解放され、システム PIDL が解放されます。 SHBindToParent によって返される相対 PIDL を解放しないでください。