線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1663
推到 Plurk!
推到 Facebook!

以 TrackPopupMenu 呼叫 PopupMenu 可否使用 OwnerDraw?

答題得分者是:Zard
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-12-07 04:36:14 IP:219.137.xxx.xxx 未訂閱
各位好,我在程式中的一個 Panel 的 OnMouseUp 事件中使用了 TrackPopupMenu 來呼叫 PopupMenu,以便在它顯示之前後可以做一些其它的設定 (例如:Timer on/off),原先一切運作都正常,後來因為要處理 PopupMenu 裡的字型變化,因此將 PopupMenu 的 OwnerDraw 屬性設為 true,並將各個 MenuItem 的 OnDrawItem 與 OnMeasureItem 事件設給對應的程序 (OnDrawItem 與 OnMeasureItem 事件的對應程序是原先使用在另一支程式作為繪製 MainMenu 之用,稍加修改後套用到現在寫的程式來),編譯過程很順利並未發生錯誤,結果在程式執行時,呼叫出來的 PopupMenu 是空的,經追蹤的結果,發現在 PopupMenu 顯示時,並未進入 OnDrawItem 與 OnMeasureItem 事件的對應程序,後來我將執行過程避開 TrackPopupMenu 程序 (將透過 TrackPopupMenu 呼叫 PopupMenu 的動作改為直接設定給一個 Panel 物件的 PopupMenu 屬性,並將 AutoPopup 為 true),重新執行的結果是選單項目能正常的顯示。 請問各位先進們,是否使用 TrackPopupMenu 來呼叫 PopupMenu 就無法使用 OwnerDraw 的功能?還是有什麼地方需要額外作一些設定?
Zard
尊榮會員


發表:24
回覆:396
積分:539
註冊:2003-11-26

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-12-07 09:59:29 IP:210.243.xxx.xxx 未訂閱
其實你猜對了, 直接呼叫TrackPopupMenu無法觸發OwnerDraw事件. 把TPopupMenu的原始碼挖出來看一下就可以知道原因了, TPopupMenu用來處理Popup的函式為 procedure TPopupMenu.Popup(X, Y: Integer); 他最後是用TrackPopupMenu(FItems.Handle, AFlags, X, Y, 0 { reserved }, PopupList.Window, nil); 來彈出選單的, 重點就在PopupList.Window, 這是指定處理彈出選單訊息的Parent Window, 而PopupList在他的訊息迴圈有這麼一段
    WM_DRAWITEM:
      ...........
      DrawMenuItem(MenuItem, Canvas, rcItem, TOwnerDrawState(LongRec(itemState).Lo));
      ...........        WM_MEASUREITEM:
      ...........
 
發現了嗎? 其實PopupList會先攔到WM_MEASUREITEM, WM_DRAWITEM這兩個事件, 攔到WM_DRAWITEM再去呼叫DrawMenuItem, DrawMenuItem呼叫AdvancedDrawItem, AdvancedDrawItem才呼叫你的OnDrawItem事件, WM_MEASUREITEM也是經過類似的步驟, 有興趣你可以去看看Delphi的原始碼. 不過建議你直接呼叫TPopupMenu.Popup(X, Y: Integer); 來取代TrackPopupMenu, 自己做太麻煩了.
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-12-07 19:42:22 IP:219.137.xxx.xxx 未訂閱
Zard 您好: 既然是 "先天" 上的限制,那我也就沒輒了,經過測試後 PopupMenu.Popup() 確實可以避開問題點,那我就先暫時這麼處理了,感謝您再次提供豐富經驗供我參考。
Zard
尊榮會員


發表:24
回覆:396
積分:539
註冊:2003-11-26

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-12-07 20:38:04 IP:61.64.xxx.xxx 未訂閱
引言: Zard 您好: 既然是 "先天" 上的限制,那我也就沒輒了,經過測試後 PopupMenu.Popup() 確實可以避開問題點,那我就先暫時這麼處理了,感謝您再次提供豐富經驗供我參考。
其實是可以做的, 方法就是像TPopupMenu.Popup一樣, 在呼叫TrackPopupMenu時指定一個處理Menu訊息的父視窗, 在這個父視窗的訊息迴圈中處理WM_MEASUREITEM, WM_DRAWITEM就可以了.
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-12-08 17:00:41 IP:218.19.xxx.xxx 未訂閱
Zard 您好: 我大概瞭解您的意思了,當初我查看說明文件時,文件上對 TrackPopupMenu 第六個參數 hWnd 值的說明是 "handle of owner window",而上網搜尋相關範例時也都是直接指向程式本身的 Handle 值,因此都沒能觸發到您所說的那個方向,原先我之所以會使用 TrackPopupMenu 來呼叫 PopupMenu,是因為我需要在 PopupMenu 出現的前/後有個 "暫停等待" 的時機,以便做 Timer off/on 等動作之處理,當我查看 BCB Help 時,TPopupMenu::Popup() 的說明太過簡要,並未讓我瞭解到它也會有 "等待" (以便於在視窗顯示前後做相關設定) 的效果,而讓我最意外的就是您所給予的 "答案" - TrackPopupMenu 會無法觸發 OwnerDraw 的事件,經過您的說明後,我改用 TPopupMenu::Popup() 來處理原先的動作,目前可達到原定需求,對於您所描述的方式,我欠缺相關的經驗,因此暫不去研究您說的自製程序,未來若有進一步需要的話,希望能有機會再向您討教,多謝您的協助與說明。
系統時間:2024-04-29 12:20:18
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!