我想要一個按鈕上方的彈出菜單:如何排列TPopupMenu,使其在按鈕上精確定位?
德爾福包裝在Win32菜單系統中,這似乎排除每一個模式或基礎Win32 API提供了是不是在VCL筆者的標誌的方式大腦在那一天。一個這樣的例子似乎是TPM_BOTTOMALIGN
,它可以傳遞到TrackPopupMenu
,但是,Delphi包裝似乎使這不僅在股票VCL中不可能,而且通過不公正地使用私有和受保護的方法是不可能的(至少在我看來是不可能的)在運行時準確地執行或覆蓋。 VCL組件TPopupMenu的設計也不是很好,因爲它應該有一個名爲PrepareForTrackPopupMenu
的虛擬方法,該方法除了調用TrackPopupMenu
或TrackPopupMenuEx
之外的其他功能,然後允許某人覆蓋實際調用該Win32方法的方法。但現在已經太晚了。也許Delphi XE5將完成Win32 API的基本覆蓋。
途徑我曾嘗試:
解決方法A:使用指標或字體:
準確判斷一個彈出菜單的高度,所以我可以調用popupmenu.Popup(X,Y)之前減去Y值。結果:必須處理Windows主題的所有變體,並假設我似乎無法確定。似乎不太可能在現實世界中產生好的結果。這是一個基本的字體度量方法的一個例子:
height := aPopupMenu.items.count * (abs(font.height) + 6) + 34;
您可以考慮隱藏物品,和Windows的單一版本實際上是一個單一的主題模式設置,你可能會得到接近這樣的,但不非常正確。
方法B:讓Windows做它:
嘗試在TPM_BOTTOMALIGN
傳遞給最終達到Win32 API調用TrackPopupMenu
。
到目前爲止,我認爲我可以做到,如果我修改VCL menus.pas ..我在這個項目中使用Delphi 2007。不過,我對這個想法並不滿意。
這裏是我想要的那種代碼:
procedure TMyForm.ButtonClick(Sender: TObject);
var
pt:TPoint;
popupMenuHeightEstimate:Integer;
begin
// alas, how to do this accurately, what with themes, and the OnMeasureItem event
// changing things at runtime.
popupMenuHeightEstimate := PopupMenuHeight(BookingsPopupMenu);
pt.X := 0;
pt.Y := -1*popupMenuHeightEstimate;
pt := aButton.ClientToScreen(pt); // do the math for me.
aPopupMenu.popup(pt.X, pt.Y);
end;
另外我想這樣做:
pt.X := 0;
pt.Y := 0;
pt := aButton.ClientToScreen(pt); // do the math for me.
aPopupMenu.popupEx(pt.X, pt.Y, TPM_BOTTOMALIGN);
當然,popupEx是不存在的VCL。也沒有任何方法可以將更多的 標誌傳遞給TrackPopupMenu
,而不是那些VCL傢伙可能在1995年添加的版本, 版本1.0。
注意:我相信在顯示菜單之前估計高度的問題是不可能的,因此我們應該通過TrackPopupMenu
來解決問題,而不是通過估計高度。
更新:調用TrackPopupMenu
直接不起作用,因爲在VCL方法TPopupMenu.Popup(x,y)
其餘步驟都需要調用我的應用程序繪製它的菜單,並讓它看起來是正確的,但它是不可能來調用它們而不惡欺騙,因爲它們是私人方法。修改VCL是一個地獄般的主張,我也不希望這樣做。
爲什麼不直接用'aPopupMenu.Handle'直接調用'TrackPopupMenu'並傳遞它要提供的任何標誌等等? @Sertac發佈了一個例子[這裏](http://stackoverflow.com/a/11649119/62576) –
雖然這並沒有發生在我調用TPopupMenu.Popup時發生的所有事情,並且沒有VCL準備工作, call-of-trackpopupmenu,但不要調用跟蹤彈出式菜單。 –
我認爲你可以嘗試使用帶按鈕組件的菜單或工具欄來獲得一些開源按鈕,並瞭解它們的來源。像JVCL的JvArrowButton或ToolBar2000或torry.net的其他一些按鈕或工具欄 - 找到正確的組件並從中學習 –