フォルダー ビューの実装
Windows Shell には、フォルダー ビューの既定の実装 (DefView と呼ばれます) が用意されているため、独自の名前空間拡張機能を実装する作業の多くを回避できます。 一部のビュー機能はカスタム ビューでは実現できないため、多くの場合、カスタム ビューの代わりに既定のシステム フォルダー ビュー オブジェクトを使用することをお勧めします。 詳細については、「 SHCreateShellFolderView」を参照してください。 このトピックの残りの部分では、新しいビュー機能をサポートできないカスタム フォルダー ビューの実装について説明します。
ツリー ビューとは異なり、Windows エクスプローラーはフォルダー ビューの内容を管理しません。 代わりに、フォルダー ビュー ウィンドウは、フォルダー オブジェクトによって提供される子ウィンドウをホストします。 フォルダー オブジェクトは、子ウィンドウにフォルダーの内容を表示するフォルダー ビュー オブジェクトを作成する役割を担います。
フォルダー ビュー オブジェクトを実装するためのキーは、 IShellView インターフェイスです。 このインターフェイスは、フォルダー ビュー オブジェクトと通信するために Windows エクスプローラーによって使用されます。 フォルダー ビューを表示する前に、Windows エクスプローラーはフォルダー オブジェクトの IShellFolder::CreateViewObject メソッドを呼び出し、riid を IID_IShellView に設定します。 フォルダー ビュー オブジェクトを作成し、その IShellView インターフェイスを返します。 フォルダー ビュー オブジェクトは、フォルダー ビュー ウィンドウの子ウィンドウを作成し、子ウィンドウを使用してフォルダーの内容に関する情報を表示する必要があります。
拡張機能では、データの表示方法を制御するだけでなく、Windows エクスプローラーのさまざまな機能をカスタマイズすることもできます。 たとえば、拡張機能では、ツール バーまたはメニュー バーに項目を追加したり、ステータス バーに情報を表示したりできます。
- フォルダー ビュー オブジェクト
- フォルダー ビュー オブジェクトの初期化
- フォルダー ビューの表示
- IShellView の実装
- IShellBrowser を使用して Windows エクスプローラーと通信する
フォルダー ビュー オブジェクト
フォルダー ビュー オブジェクトは、 IShellView インターフェイスを公開するコンポーネント オブジェクト モデル (COM) オブジェクトです。 このオブジェクトは次の役割を担います。
- フォルダー ビュー ウィンドウの子ウィンドウを作成し、それを使用してフォルダーの内容を表示します。
- Windows エクスプローラーとの通信の処理。
- フォルダー固有のコマンドを Windows エクスプローラー メニュー バーとツール バーに追加し、選択時にそれらのコマンドを処理します。
- ショートカット メニューの表示やドラッグ アンド ドロップ操作の処理など、フォルダー ビュー ウィンドウでのユーザー操作の管理。
このドキュメントでは、最初の 3 つのトピックについて説明します。 フォルダー ビューに対するユーザー操作は子ウィンドウ内で行われるため、フォルダー ビュー オブジェクトは他のウィンドウと同様に処理を行います。
Windows エクスプローラーは、フォルダー オブジェクトの IShellFolder::CreateViewObject を呼び出し、riid を IID_IShellView に設定して、フォルダー ビュー オブジェクトを要求します。 フォルダー ビューを作成する手順は次のとおりです。
- フォルダー オブジェクトは、フォルダー ビュー オブジェクトの新しいインスタンスを作成し、その IShellView インターフェイスへのポインターを返します。
- Windows エクスプローラーは、IShellView::CreateViewWindow メソッドを呼び出してフォルダー ビュー オブジェクトを初期化します。 フォルダー ビュー ウィンドウの子ウィンドウを作成し、そのハンドルを Windows エクスプローラーに返します。
- フォルダー ビュー オブジェクトは、Windows エクスプローラー IShellBrowser インターフェイスを使用して、Windows エクスプローラー ツール バー、メニュー バー、ステータス バーをカスタマイズします。
- フォルダー ビュー オブジェクトは、子ウィンドウにフォルダーの内容を表示します。
- フォルダー ビュー オブジェクトは、フォルダー ビューおよびフォルダー固有のツール バーまたはメニュー バー項目に対するユーザー操作を処理します。
フォルダー ビュー オブジェクトの初期化
Windows エクスプローラーは、IShellView::CreateViewWindow メソッドを呼び出してフォルダー ビュー オブジェクトを初期化します。 メソッドのパラメーターは、フォルダー ビュー オブジェクトに、フォルダーの内容を表示するために使用される子ウィンドウを作成するために必要な情報を提供します。
- 前のフォルダー ビュー オブジェクトの IShellView インターフェイスへのポインター。 このパラメーターは NULL に設定できます。
- 以前のフォルダー ビューの設定を含む FOLDERSETTINGS 構造体。
- Windows エクスプローラー IShellBrowser インターフェイスへのポインター。
- フォルダー ビュー ウィンドウのディメンションを持つ RECT 構造体。
IShellView::CreateViewWindow メソッドは、前のフォルダー ビュー オブジェクトが破棄される前に呼び出されます。 したがって 、IShellView インターフェイス ポインターを使用すると、前のフォルダー ビュー オブジェクトと通信できます。 このインターフェイスは、以前のフォルダーが拡張機能に属し、同じ表示スキームを使用している場合に主に役立ちます。 その場合は、プライベート設定の交換などの目的で、前のフォルダー ビュー オブジェクトと通信できます。
IShellView ポインターが拡張機能に属しているかどうかを判断する簡単な方法は、すべてのフォルダー ビュー オブジェクトがプライベート インターフェイスを公開することです。 IShellView::QueryInterface を呼び出してプライベート インターフェイスを要求し、戻り値を調べてフォルダー ビュー オブジェクトが自分のものかどうかを判断します。 その後、そのインターフェイスでプライベート メソッドを使用して情報を交換できます。
FOLDERSETTINGS 構造体には、以前のフォルダー ビューの表示設定が含まれています。 主な設定は、大きなアイコン、小さいアイコン、リスト、または詳細の表示モードです。 また、ビューを左揃えにするかどうかなど、さまざまな表示オプションの設定を含むフラグもあります。 フォルダーの表示は、可能な限りこれらの設定に従って、あるフォルダーから別のフォルダーに移動する際に一貫したエクスペリエンスをユーザーに提供する必要があります。 この構造を格納し、設定の変更に合って更新する必要があります。 Windows エクスプローラーは IShellView::GetCurrentInfo を呼び出して、次のフォルダー ビューを開く前に、この構造体の最新の値を取得します。
IShellBrowser インターフェイスは、Windows エクスプローラーによって公開されます。 このインターフェイスは IShellView のコンパニオンであり、フォルダー ビュー オブジェクトが Windows エクスプローラーと通信できるようにします。 このインターフェイス ポインターを取得する方法は他にないため、フォルダー ビュー オブジェクトは後で使用できるように格納する必要があります。 特に、 IShellBrowser::GetWindow を呼び出して、子ウィンドウの作成に使用する親フォルダー ビュー ウィンドウを取得する必要があります。 IShellBrowser::GetWindow メソッドは IOleWindow から継承されるため、IShellBrowser ドキュメントには含まれていないことに注意してください。 インターフェイス ポインターを格納した後は、 IShellBrowser::AddRef を呼び出して、インターフェイスの参照カウントをインクリメントすることを忘れないでください。 インターフェイスが不要になったら、 IShellBrowser::Release を呼び出します。
子ウィンドウを作成するには:
- FOLDERSETTINGS と RECT 構造体を調べます。
- 必要に応じて、前のフォルダー ビュー オブジェクトからプライベート設定を取得します。
- IShellBrowser::GetWindow を呼び出して、親フォルダー ビュー ウィンドウを取得します。
- 前の手順で取得したフォルダー ビュー ウィンドウの子を作成し、Windows エクスプローラーに返します。
フォルダー ビューの表示
子ウィンドウを作成して Windows エクスプローラーに返すと、フォルダーの内容を表示できます。 通常、拡張機能は、リスト ビュー コントロール または WebBrowser コントロールを子ウィンドウ ホストにすることで、その情報を表示します。 リスト ビュー コントロールを使用すると、Windows エクスプローラークラシック ビューをレプリケートできます。 WebBrowser コントロールを使用すると、Windows エクスプローラー Web ビューと同様に、動的 HTML (DHTML) ドキュメントを使用して情報を表示できます。 詳細については、これらのコントロールのドキュメントを参照してください。
フォルダー ビュー ウィンドウは、フォーカスがない場合でも常に存在します。 したがって、子ウィンドウには次の 3 つの状態を維持する必要があります。
- フォーカスを使用してアクティブ化されます。 フォルダー ビューが作成され、フォーカスが設定されています。 フォーカス状態に適したメニュー バーまたはツール バー項目を設定します。
- フォーカスなしでアクティブ化されます。 フォルダー ビューは作成され、アクティブですが、フォーカスがありません。 フォーカスされていない状態に適したメニュー バーまたはツール バー項目を設定します。 フォルダー ビュー内の項目の選択に適用される項目は省略します。
- 非 アクティブ。 フォルダー ビューが破棄されようとしています。 フォルダー固有のすべてのメニュー項目を削除します。
Windows エクスプローラーは、IShellView::UIActivate を呼び出してウィンドウの状態が変化したときに、フォルダー ビュー オブジェクトに通知します。 さらに、ユーザーが IShellBrowser::OnViewWindowActive を呼び出してフォルダー ビュー ウィンドウをアクティブ化したときに、フォルダー ビュー オブジェクトは Windows エクスプローラーに通知する必要があります。 このインターフェイスの詳細については、「IShellBrowser を使用した Windows エクスプローラーとの通信」を参照してください。
フォルダー ビューがアクティブな間は、子ウィンドウに属するすべての Windows メッセージ ( WM_SIZEなど) を処理する必要があります。 また、ウィンドウ プロシージャは、Windows エクスプローラー メニュー バーまたはツール バーに追加したすべての項目のWM_COMMANDメッセージも受信します。
フォルダー ビューを作成した後、Windows エクスプローラーはフォルダー ビュー オブジェクトの IShellView インターフェイスを呼び出して、さまざまな情報を渡します。 オブジェクトは、それに応じて表示を変更する必要があります。 フォルダー ビューが破棄されようとしている場合、Windows エクスプローラーは IShellView::D estroyViewWindow メソッドを呼び出してフォルダー ビュー オブジェクトに通知します。
IShellView の実装
フォルダー オブジェクトが作成されると、Windows エクスプローラーはさまざまな IShellView メソッドを呼び出して情報を要求するか、Windows エクスプローラーの状態の変更をオブジェクトに通知します。 このセクションでは、これらの IShellView メソッドを実装する方法について説明します。 残りのメソッドは、[ファイルを開く] 一般的なダイアログ ボックスなど、より特殊な目的で使用されます。 詳細については、 IShellView のドキュメントを参照してください。
AddPropertySheetPages
ユーザーが Windows エクスプローラー Tools メニューから [フォルダー オプション] を選択すると、ユーザーがフォルダー オプションを変更できるプロパティ シートが表示されます。 Windows エクスプローラーは、フォルダー ビュー オブジェクトの IShellView::AddPropertySheetPages メソッドを呼び出して、このプロパティ シートにページを追加できるようにします。
Windows エクスプローラーは、IShellView::AddPropertySheetPages の lpfn パラメーターで AddPropSheetPageProc コールバック関数へのポインターを渡します。 CreatePropertySheetPage を呼び出してページを作成し、AddPropSheetPageProc を呼び出してプロパティ シートに追加します。 プロパティ シートの処理方法の詳細については、「プロパティ シート」を参照してください。
GetCurrentInfo
ユーザーが 1 つのフォルダーから別のフォルダーに切り替えると、Windows エクスプローラーは同様のフォルダー ビューを維持しようとします。 たとえば、前のフォルダー ビューに大きなアイコンが表示されている場合は、次のアイコンも表示されます。 Windows エクスプローラーが IShellView::CreateViewWindow を呼び出してフォルダー ビュー オブジェクトを初期化すると、メソッドは FOLDERSETTINGS 構造体を受け取ります。 この構造体には、前のフォルダー ビューと一貫性のあるフォルダー ビューを表示できるようにする情報が含まれています。
次のビューが現在のビューと一致していることを確認するには、 FOLDERSETTINGS 構造体を 格納します。 たとえば、大きなアイコンから小さいアイコンにビューが変更された場合は、それに応じて構造を更新します。 ビューを切り替える前に、Windows エクスプローラーは IShellView::GetCurrentInfo を呼び出して、現在の FOLDERSETTINGS 値を次のフォルダー ビュー オブジェクトに渡すように要求します。
更新
ユーザーは、[表示] メニューから [最新の情報に更新] を選択するか、F5 キーを押すことで、フォルダー ビューにフォルダーの現在の状態を確実に反映させることができます。 ユーザーがそうすると、Windows エクスプローラーは IShellView::Refresh メソッドを呼び出します。 フォルダー ビュー オブジェクトは、フォルダー ビューの表示を直ちに更新する必要があります。
SaveViewState
Windows エクスプローラーは IShellView::SaveViewState メソッドを呼び出して、フォルダー ビュー オブジェクトにビュー ステートを保存するように求めます。 その後、次にフォルダーを表示するときに状態を回復できます。 ビュー ステートを保存する推奨される方法は、 IShellBrowser::GetViewStateStream メソッドを呼び出すことです。 このメソッドは、フォルダー ビュー オブジェクトが状態を保存するために使用できる IStream インターフェイスを返します。 別のフォルダー ビューを作成するときに、同じ IShellBrowser::GetViewStateStream メソッドを呼び出して、以前のフォルダー ビューによって保存された設定を読み取ることができる IStream ポインターを取得できます。
TranslateAcelerator
ユーザーがショートカット キーを押すと、Windows エクスプローラーは IShellView::TranslateAccelerator を呼び出して、フォルダー ビュー オブジェクトにメッセージを渡します。 Windows エクスプローラーでメッセージを処理するには、S_FALSEを返します。 フォルダー ビュー オブジェクトがメッセージを処理した場合は、S_OKを返します。
フォルダー ビュー ウィンドウにフォーカスがある場合、Windows エクスプローラーはメッセージを処理する前に IShellView::TranslateAccelerator を呼び出します。 ほとんどのメッセージは通常、Windows エクスプローラーメニュー バーまたはツール バー コマンドに関連付けられているため、フォルダー ビュー オブジェクトは通常、S_FALSEを返す必要があります。 Windows エクスプローラーでは、メッセージを正常に処理できます。 メッセージがフォルダー固有であり、Windows エクスプローラーでそれ以上の処理を行わない場合にのみ、S_OKを返します。 フォルダー ビューにフォーカスがない場合、Windows エクスプローラーは最初にメッセージを処理します。 IShellBrowser::TranslateAcceleratorSB は、メッセージを処理しない場合にのみ呼び出します。
IShellBrowser を使用した Windows エクスプローラーとの通信
IShellBrowser インターフェイスは、次のようなさまざまな目的で Windows エクスプローラーと通信するために、フォルダー ビュー オブジェクトによって使用されます。
Windows エクスプローラー メニュー バーの変更
Windows エクスプローラー メニュー バーを使用すると、ユーザーはさまざまなコマンドを起動できます。 既定では、メニュー バーは Windows エクスプローラーに固有のコマンドのみをサポートします。 関連するWM_COMMAND メッセージは Windows エクスプローラーによって処理され、フォルダー ビュー オブジェクトには渡されません。 ただし、 IShellBrowser を使用して 1 つ以上のフォルダー固有のメニュー項目を含むようにメニュー バーを変更できます。 Windows エクスプローラーは、これらのアイテムの関連するWM_COMMAND メッセージを、処理のためにフォルダー オブジェクトのウィンドウ プロシージャに渡します。 また、アプリケーションに適用されない標準コマンドを削除または無効にすることもできます。
フォルダー ビュー オブジェクトは、通常、フォルダー ビューが最初に表示される前にメニュー バーを変更します。 フォルダー ビューが破棄されたときに、メニュー バーを元の状態に戻す必要があります。 また、フォルダー ビューがフォーカスを取得または失うたびにメニュー バーを変更する必要がある場合もあります。
Windows エクスプローラーは、フォルダー ビュー ウィンドウの状態が変わるたびに IShellView::UIActivate を呼び出すので、通常、メニュー バーの変更はそのメソッドの実装に含まれます。 Windows エクスプローラー メニュー バーを変更する基本的な手順は次のとおりです。
- CreateMenu を呼び出して、メニュー ハンドルを作成します。
- IShellBrowser::InsertMenusSB を呼び出して、そのメニュー ハンドルを Windows エクスプローラーに渡します。 Windows エクスプローラーはメニュー情報を入力します。
- 必要に応じてメニューを変更します。
- IShellBrowser::SetMenuSB を呼び出して、Windows エクスプローラーに変更されたメニュー バーを表示させます。
Windows エクスプローラーには、メニュー バーに 6 つのポップアップ メニューがあります。 すべての OLE コンテナーと同様に、Windows エクスプローラー メニューは、ファイル、編集、コンテナー、オブジェクト、ウィンドウ、ヘルプの 6 つのグループに分かれています。 次の表に、Windows エクスプローラーポップアップ メニューとそれに関連付けられているグループとメニュー ID を示します。
ポップアップ メニュー | id | グループ |
---|---|---|
ファイル | FCIDM_MENU_FILE | ファイル |
[編集] | FCIDM_MENU_EDIT | ファイル |
表示 | FCIDM_MENU_VIEW | コンテナー |
お気に入り | FCIDM_MENU_FAVORITES | コンテナー |
ツール | FCIDM_MENU_TOOLS | コンテナー |
ヘルプ | FCIDM_MENU_HELP | ウィンドウ |
IShellBrowser::InsertMenusSB を呼び出してメニュー ハンドルを Windows エクスプローラーに渡す場合は、メンバーが 0 に初期化されている OLEMENUGROUPWIDTHS 構造体へのポインターも渡す必要があります。
IShellBrowser::InsertMenusSB が返されると、Windows エクスプローラーによってメニュー項目が追加されます。 次に、返されたメニュー ハンドルを 、InsertMenuItem などの標準の Windows メニュー関数と共に使用して、次の操作を行うことができます。
- Windows エクスプローラー ポップアップ メニューに項目を追加します。
- Windows エクスプローラー ポップアップ メニューの既存の項目を変更または削除します。
- 新しいポップアップ メニューを追加します。
表に示されている ID を使用して、さまざまな Windows エクスプローラー ポップアップ メニューを識別します。
Note
Windows エクスプローラー コマンド ID との競合を回避するには、追加するメニュー項目の ID がFCIDM_SHVIEWFIRSTとFCIDM_SHVIEWLASTの間に収まる必要があります。 これら 2 つの値は Shlobj.h で定義されています。
メニューの変更が完了したら、IShellBrowser::SetMenuSB を呼び出して、Windows エクスプローラー新しいメニュー バーを表示します。
フォルダー ビューが最初に表示されると、Windows エクスプローラーは、フォルダー ビューがフォーカスを取得または失うたびに IShellView::UIActivate を呼び出します。 フォルダー ビューの状態に依存するメニュー項目がある場合は、状態が変更されるたびに、それに応じてメニューを変更する必要があります。 たとえば、ユーザーが選択したフォルダー ビューの項目に対して動作するメニュー項目があるとします。 フォルダー ビューがフォーカスを失った場合は、このメニュー項目を無効または削除する必要があります。
Windows エクスプローラーが IShellView::UIActivate を呼び出してフォルダー ビューが非アクティブ化されていることを示す場合は、IShellBrowser::RemoveMenusSB を呼び出してメニュー バーを元の状態に戻します。
Windows エクスプローラー ツール バーの変更
Windows エクスプローラー メニュー バーを変更するだけでなく、ツール バーにボタンを追加することもできます。 メニュー バーと同様に、ツール バーの変更は通常 、IShellView::UIActivate 実装の一部です。 Windows エクスプローラー ツール バーにボタンを追加する手順は次のとおりです。
- ボタンのビットマップをツール バーのイメージ リストに追加します。
- ボタンのテキスト文字列を定義します。
- ボタンをツール バーに追加します。
ツール バーのイメージ リストにビットマップを追加するには、IShellBrowser::SendControlMsg を呼び出して、ツール バーにTB_ADDBITMAPメッセージを送信します。 ツール バー コントロールを指定するには、メソッドの id パラメーターを FCW_TOOLBARに設定します。 wParam をビットマップ内のボタン イメージの数に設定し、lParam を TBADDBITMAP 構造体のアドレスに設定します。 イメージ インデックスは pret パラメーターで返されます。
ボタンの文字列を定義するには、次の 2 つの方法があります。
- ボタンの TBBUTTON 構造体の iString メンバーに文字列を割り当てます。
- IShellBrowser::SendControlMsg を呼び出して、ツール バー コントロールにTB_ADDSTRING メッセージを送信します。 wParam パラメーターは 0 に、lParam パラメーターは文字列に設定する必要があります。 文字列インデックスは pret パラメーターで返されます。
ボタンをツール バーに追加するには、 TBBUTTON 構造体を入力し、 IShellBrowser::SetToolbarItems に渡します。 メニューと同様に、コマンド ID はFCIDM_SHVIEWFIRSTとFCIDM_SHVIEWLASTの間に収まる必要があります。 ツール バーは、既存のボタンの右側にボタンを追加します。
たとえば、次のコード フラグメントは、コマンド ID が IDB_MYBUTTON の Windows エクスプローラー ツール バーに 1 つの標準ボタンを追加します。
TBADDBITMAP tbadbm;
int iButtonIndex;
TBBUTTON tbb;
tbadbm.hInst = g_hInstance; // The module's instance handle
tbadbm.nID = IDB_BUTTONIMAGE; // The bitmap's resource ID
psb->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 1,
reinterpret_cast<LPARAM>(&tbadbm), &iButtonIndex);
psb->SendControlMsg(FCW_TOOLBAR, TB_ADDSTRING, NULL,
reinterpret_cast<LPARAM>(szLabel), &iStringIndex);
ZeroMemory(&tbb, sizeof(TBBUTTON));
tbb.iBitmap = iButtonIndex;
tbb.iCommand = IDB_MYBUTTON;
tbb.iString = iStringIndex;
tbb.fsState = TBSTATE_ENABLED;
tbb.fsStyle = TBSTYLE_BUTTON;
psb->SetToolbarItems(&tbb, 1, FCT_MERGE);
ツール バー コントロールの処理方法の詳細については、「 ツール バー コントロール」を参照してください。
Windows エクスプローラー ステータス バーの変更
Windows エクスプローラーステータス バーを使用すると、さまざまな有用な情報を表示できます。 ステータス バーを使用するには、次の 2 つの方法があります。
- IShellBrowser::SetStatusTextSB を使用して、ステータス バーにテキスト文字列を表示します。
- IShellBrowser::SendControlMsg を使用して、ステータス バー コントロールに直接メッセージを送信します。
最初の方法は簡単ですが、多くの目的に十分です。 柔軟性を高めるために、id パラメーターを FCW_STATUS に設定して IShellBrowser::SendControlMsg を呼び出すことで、ステータス バー コントロールに直接メッセージを送信できます。 ステータス バー コントロールの詳細については、「 ステータス バー」を参照してください。
ビュー固有の情報の格納
ビューが破棄されようとしている場合、ビューの状態や設定などの情報を格納すると便利です。 Windows エクスプローラーでは、IShellView::SaveViewState を呼び出してこのタスクを実行するように求められます。 ビュー固有の情報を保存する推奨される方法は、 IShellBrowser::GetViewStateStream を呼び出す方法です。 このメソッドは、情報の格納に使用できる IStream インターフェイスを提供します。 任意の適切なデータ形式を自由に使用できます。