天天看點

IContextMenu第一部分:基本介紹

網絡上有很多技術文檔描述了如何在資料總管的上下文菜單中插入自己的菜單,并實作一個上下文菜單的提供者(context menu provider),你可以找到一些資料,教你如何承載(host)一個上下文菜單。

(今天這篇文章是接下來的11篇系列文章的第一篇,是的,你沒有看錯,關于IContextMenu這一主題,我會寫上11篇文章。各位讀者,如果你來到我的部落格,主要是想看看我寫的一些曆史小故事的話,抱歉了啊。當然,我也會在間歇的時間中,寫一些其他主題的文章,以供你們消遣)

對于IContextMenu接口的使用,一般采用如下的模式:

> 建立。

>

IContextMenu::QueryContextMenu這個方法可以用來初始化上下文菜單。在此方法調用期間,上下文菜單會根據你傳入的标志位參數,來決定哪些菜單條目會顯示在菜單中。

> 使用

IContextMenu::GetCommandString方法來顯示菜單或者選擇一個菜單指令來準備執行。另外兩個方法,IContextMenu2::HandleMenuMsg 和 IContextMenu3::HandleMenuMsg2 則用來處理使用者界面互動。

> 使用

IContextMenu::InvokeCommand方法來執行菜單指令。

下面我們來從實作IContextMenu的角度看看底層都做了些什麼。

外殼會首先調用

IContextMenu::QueryContextMenu方法。它會傳遞一個HMENU句柄給這個方法,這樣QueryContextMenu就可以向指定的菜單來添加菜單項。如果使用者用滑鼠指向了這些菜單項中的一個,則IContextMenu::GetCommandString方法會被調用,并擷取該菜單項的幫助資訊,這些幫助資訊會被顯示在資料總管的狀态欄上。如果使用者點選了菜單項,則外殼會調用IContextMenu::InvokeCommand方法。然後該菜單項對應的處理例程會開始執行。

作為IContextMenu的宿主,你需要做下面的事情:

IContextMenu宿主會首先調用

IContextMenu::QueryContextMenu方法,它會向此方法傳遞一個HMENU句柄以用來向上下文菜單中添加菜單項。如果使用者用滑鼠指向了菜單項中的一個,則IContextMenu::GetCommandString會被調用以擷取該菜單項對應的幫助資訊,并顯示在宿主的狀态欄上。如果使用者點選了菜單項,則IContextMenu宿主會調用IContextMenu::InvokeCommand方法。IConectMenu所實作的處理例程會執行對應的菜單項動作。

接下來幾周的重點。我們會進一步解釋上下文菜單的更多細節。

好了,讓我們開始寫代碼吧。

我們還是以之前的例子程式為基礎,在這裡我假定你已經熟悉了外殼命名空間和pidls,是以不會重點解釋它們,我會将重點放在上下文菜單部分。

IContextMenu第一部分:基本介紹

上述代碼定義了一個簡單函數,該函數接受一個路徑并從中擷取一個外殼UI對象。 我們使用 SHParseDisplayName 将路徑轉換為 pidl,然後使用 SHBindToParent 綁定到 pidl 的父級,然後使用

IShellFolder::GetUIObjectOf 向父級詢問子級的 UI 對象。

(輔助函數 SHParseDisplayName 和 SHBindToParent 不會做任何你自己無法完成的事情。它們隻是為你節省了一些輸入。一旦你開始使用外殼命名空間,你就可以像這樣建立一個個小函數庫。)

從上述代碼得知,我們要做的就是在使用者右鍵單擊時調用檔案上的“播放”動作。 (為什麼要右鍵單擊?因為該程式的未來版本将顯示上下文菜單。)

IContextMenu第一部分:基本介紹

在上面的代碼中,首先我們建立 IContextMenu,然後通過調用

IContextMenu::QueryContextMenu 對其進行初始化。 請注意,即使我們不打算顯示菜單,我們仍然需要建立一個彈出菜單,因為 IContextMenu::QueryContextMenu 需要打開。 然而,我們實際上并沒有顯示結果菜單; 我們不是要求使用者從菜單中選擇一個項目,而是為使用者做出選擇并選擇“播放”,填充 CMINVOKECOMMANDINFO 結構并調用它。

但是我們怎麼知道正确的動作是“播放”呢? 在這種情況下,我們知道是因為我們将檔案寫死為“clock.avi”,并且我們知道 AVI 檔案有一個“播放”動作。 但當然,這在一般情況下是行不通的。 在開始調用預設動作之前,讓我們先采取更簡單的步驟,詢問使用者要調用什麼動作。

如果上面的代碼就是你真正想要的(在檔案上調用一個固定的動作),那麼你不需要浏覽所有上下文菜單的東西。 上面的代碼等效于調用 ShellExecuteEx 函數,即傳遞 SEE_MASK_INVOKEIDLIST 标志并訓示你希望調用IContextMenu的相關方法。

總結

通過本文,我們應該可以基本了解IContextMenu的用法。後續會繼續關注這一主題。

最後

最近我寫了個東西

繼續閱讀