前節ではCEnumIDListを実装し、このオブジェクトをCShellFolder::EnumObjectsで返すことに成功しました。そのアイテムがフォルダビューで正しく機能するかどうかはまた別の話になります。CShellFolderはこうしたUI情報についても考慮する必要があります。UI情報を取得する際に呼ばれるメソッドは、IShellFolder::GetUIObjectOfです。そこにはIContextMenuやIExtractIconなどのIIDも含まれます。これらのインターフェースは可能な限り返すようにしたほうがよいでしょう。例によってオブジェクトのためのクラスを定義することになります。*m_pUnkSite;};IContextMenuとIExtractIconを継承したCUIObjectというクラスを定義しています。1つのクラスでまとめて継承するようにしています。IObjectWithSiteについては後述します。CUIObjectのオブジェクトは、CShellFolder::GetUIObjectOfで作成します。hr;}CUIObjectのコンストラクタの第1引数は、アイテムのPIDLを指定することになります。これは必要な情報になります。実装しなくても特に問題はありません。CUIObjectはIContextMenuを継承していますから、IContextMenuのメソッドを実装することになります。ダブルクリックされた場合に呼ばれます。1);}InsertMenuItemを呼び出して、第1引数のポップアップメニューに独自の項目を追加します。項目のIDはidCmdFirstからidCmdLastの間でなければならないため、MENUITEMINFO構造体のwIDにはidCmdFirstを指定しています。項目をさらに追加する場合は、idCmdFirstを1つカウントするようにしてください。fStateにMFS_DEFAULTを指定するのは非常に重要です。ダブルクリック時にInvokeCommandが呼ばれるようになります。MAKE_SCODEの第3引数は追加した項目の数であるため、1を指定します。ポップアップメニューを表示するだろうと思われます。項目が選択された場合はそれを実行するためにInvokeCommandが呼ばれます。S_OK;}pici->lpVerbの下位ワードには、選択された項目へのオフセットが格納されることになっています。LOWORDマクロで取得することになります。上位ワードに0でない値が格納されている場合は、処理を続行する必要はありません。選択されたアイテムがフォルダであるかどうかで実行する処理を分岐させます。その事をエクスプローラに伝えるためにIShellBrowser::BrowseObjectを呼び出す必要があります。その後にIServiceProvider::QueryServiceにSID_STopLevelBrowserとIID_IShellBrowserを指定することで取得できます。BrowseObjectの第1引数は、実行するアイテムのPIDLを指定します。このPIDLは完全なPIDLではないため、第2引数にはSBSP_RELATIVEを指定するようにします。新しくフォルダを作成したい場合はSBSP_NEWBROWSERを指定するようにしてください。選択したアイテムがフォルダでない場合は、そのアイテムに応じた動作を行うことになります。実際の開発ではダイアログなどを表示することになると思われます。IShellBrowser::QueryActiveShellViewを呼び出してください。続いて、IExtractIconのメソッドについて見ていきます。アイコンを取得する段階で先に呼ばれるのはGetIconLocationです。第4引数に取得するアイコンのインデックスを格納することになっています。第5引数のフラグにGIL_NOTFILENAMEを指定しています。これを指定した場合は、第2引数と第4引数を初期化する必要はなくなります。GIL_DONTCACHEは、デバッグ段階では指定しておいたほうがよいでしょう。新しいアイコンを確認できないことになります。GetIconLocationが成功すれば、Extractが呼ばれます。S_OK;}Extractでは、第3引数に大きいアイコンのハンドルを返し、第4引数に小さいアイコンのハンドルを返すことになります。今回は簡単のため、LoadImageで既定のアイコンのハンドルを取得しています。これはIContextMenuを使用する側がオブジェクトに対して情報を与えるために必要です。IObjectWithSite::SetSiteを通じてIShellBrowserに関連するインターフェースを取得できるようになります。メンバとして保存することになります。GetSiteについては、SetSiteで保存したメンバのQueryInterfaceを呼び出します。これはシェル拡張内で自作されたものでなくても構いません。このアドレスを返しても問題ありません。ppv);}デフォルトメニューの欠点は、メニュー項目にアプリケーションの意思が反映されないことだと思われます。属性が0であるアイテムに対してはメニュー自体が表示されません。IContextMenuを実装したオブジェクトを自作する必要があるといえます。IExtractIconを実装したデフォルトのオブジェクトも取得することができます。QueryInterfaceを呼び出すことでIExtractIconを取得することができます。ppv);pDefaultExtractIconInit->Release();}}QueryInterfaceを呼び出す前にSetNormalIconを呼び出している点が重要です。これによりIExtractIconは、第1引数のファイルから第2引数のインデックスのアイコンを取得すればよいものと理解できます。