天天看點

IContextMenu第六部分:顯示菜單幫助資訊

關于上下文菜單,還有一個值得關注的地方是在狀态欄上顯示對應的幫助資訊。到目前為止,我們的例子程式還沒有涉及到狀态欄,但是沒關系,為了示範今天的主題,我們将菜單幫助資訊顯示在視窗的标題欄,也是一樣的效果。正文即将開始,請做好扶穩。

關于菜單幫助資訊,一個關鍵的接口方法是

IContextMenu::GetCommandString,它主要用來和上下文菜單處理器進行通信。為了友善示範,我再一次地将本應該聲明為成員的變量聲明為了一個全局變量,但實際工程開發中,請盡量避免全局變量的使用。

IContextMenu第六部分:顯示菜單幫助資訊

在我們調用TrackPopupMenuEx的前後,我們将對這個變量進行更新,如下圖所示:

IContextMenu第六部分:顯示菜單幫助資訊

做好了如上的準備工作之後,我們就可以開始編寫代碼,實作在使用者浏覽上下文菜單項時顯示對應的幫助資訊了,我們先看看下面的代碼:

IContextMenu第六部分:顯示菜單幫助資訊

這個函數首先檢查被選中的菜單是否位于我們定義的範圍,如果是,則我們通過調用GetCommandString方法來擷取對應的幫助資訊,并顯示在視窗的标題欄上。

最後,我們将這個函數內建到我們的視窗過程中。我們希望即使上下文菜單處理器會對菜單做後續的操作,我們也能更新菜單項的選中狀态并顯示在視窗的标題欄上,是以,這裡我們在将消息分發到菜單處理器之前就調用了我們定義的OnMenuSelect函數,如下圖所示:

IContextMenu第六部分:顯示菜單幫助資訊

先等會

細心的讀者可能發現了,在上面的代碼中,我們有一條注釋說以下代碼可能存在Bug,具體是什麼神仙Bug呢?

請稍安勿躁,其實技術上來說,也沒有什麼Bug,隻是,當你嘗試運作這段代碼的時候,你會覺察到程式的行為有些怪異。

這是因為,有一些上下文菜單處理器沒有很好地實作,Bug也源自于此。

有一些處理器沒有支援Unicode,有一些則沒有支援ANSI。更加有意思的是,他們沒有實作對應的代碼,同時,沒有按照慣例傳回E_NOTIMPL錯誤代碼,而是直接傳回了S_OK。還有另外一些處理器存在潛在的緩沖區溢出問題,他們會在超出記憶體邊界的位置寫入資料。

很好,歡迎大家再次來到應用程式相容性的世界。

下面我們來寫一個幫助函數,試着解決上面所提到的各種問題。

IContextMenu第六部分:顯示菜單幫助資訊
IContextMenu第六部分:顯示菜單幫助資訊

在外殼代碼實作中,類似于上面的代碼随處可見。

接下來,我們将這個幫助函數內建到OnMenuSelect中,如下圖所示:

IContextMenu第六部分:顯示菜單幫助資訊

新的版本可以正确地顯示被支援的菜單項幫助資訊,也能容忍一些未能正确實作的處理器錯誤,甚至是一些比較嚴重的安全性問題,例如緩沖區溢出問題。

好了,今天的支線任務就先到這裡。在下一篇文章中,我們将回到主線,即預設操作的調用。

總結

其實擷取幫助資訊的實作并不複雜,隻是你需要面對一個不那麼完美的真實世界。

為了保持相容性,還得在設計上多考慮各種意外情況,在代碼上也多下些功夫。

最後

最近我寫了個東西

繼續閱讀