Tôi muốn có một popup menu ở trên một nút:Làm thế nào để bạn xếp hàng TPopupMenu để nó chính xác vị trí chính nó trên một nút?
Delphi kết thúc tốt đẹp hệ thống menu Win32 trong một cách mà dường như ngăn cản mỗi chế độ hoặc cờ mà cơ bản Win32 API cung cấp đó không phải là trong tác giả của VCL não vào ngày đó. Một ví dụ có vẻ như là TPM_BOTTOMALIGN
có thể được chuyển vào TrackPopupMenu
nhưng, trình bao bọc Delphi dường như không thể làm điều này không chỉ trong VCL cổ phiếu, mà bằng cách sử dụng các phương pháp riêng tư và được bảo vệ cẩn thận là điều không thể là không thể) để thực hiện chính xác vào thời gian chạy hoặc bằng ghi đè. Thành phần VCL TPopupMenu không được thiết kế rất tốt, vì nó phải có một phương thức ảo gọi là PrepareForTrackPopupMenu
đã làm mọi thứ khác ngoài lệnh gọi TrackPopupMenu
hoặc TrackPopupMenuEx
, và sau đó cho phép người khác ghi đè phương thức thực sự gọi phương thức Win32 đó. Nhưng giờ đã quá muộn rồi. Có lẽ Delphi XE5 sẽ có phạm vi bảo hiểm cơ bản của API Win32 được thực hiện đúng.
phương pháp tiếp cận Tôi đã thử:
Tiếp cận A: Sử dụng số liệu hoặc Fonts:
xác định chính xác chiều cao của một popup menu để tôi có thể trừ đi giá trị Y trước khi gọi popupmenu.Popup (x, y). Kết quả: Sẽ phải xử lý tất cả các biến thể của Windows theming, và làm cho các giả định mà tôi dường như không thể chắc chắn về. Dường như không có kết quả tốt trong thế giới thực. Dưới đây là một ví dụ về cách tiếp cận của font chữ cơ bản:
height := aPopupMenu.items.count * (abs(font.height) + 6) + 34;
Bạn có thể đưa vào các mục ẩn tài khoản, và cho một phiên bản duy nhất của cửa sổ với một thiết lập chế độ chủ đề duy nhất có hiệu lực, bạn có thể nhận được gần như thế, nhưng không phải chính xác.
Tiếp cận B: Chúng ta hãy cầu Windows thực hiện:
Cố gắng vượt qua trong TPM_BOTTOMALIGN
để cuối cùng đạt Win32 API gọi TrackPopupMenu
.
Cho đến nay, tôi nghĩ rằng tôi có thể làm điều đó, nếu tôi sửa đổi các menu VCL.pas .. Tôi đang sử dụng Delphi 2007 trong dự án này. Tôi không phải tất cả những gì hạnh phúc về ý tưởng đó.
Dưới đây là các loại mã tôi đang cố gắng:
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;
Ngoài ra tôi muốn làm điều này:
pt.X := 0;
pt.Y := 0;
pt := aButton.ClientToScreen(pt); // do the math for me.
aPopupMenu.popupEx(pt.X, pt.Y, TPM_BOTTOMALIGN);
Tất nhiên, popupEx là không có trong VCL. Cũng không có cách nào để chuyển vào nhiều hơn cờ đến TrackPopupMenu
so với những người mà VCL đã thêm vào có thể vào năm 1995, trong phiên bản 1.0.
Lưu ý: Tôi tin rằng vấn đề ước tính chiều cao trước khi hiển thị menu là không thể, do đó chúng tôi thực sự cần giải quyết vấn đề bằng cách TrackPopupMenu
không bằng cách ước tính chiều cao.
Cập nhật: Gọi TrackPopupMenu
trực tiếp không hoạt động, vì các bước còn lại trong phương pháp VCL TPopupMenu.Popup(x,y)
là cần thiết để ứng dụng của tôi vẽ thực đơn của nó và có vẻ chính xác, tuy nhiên không thể gọi chúng lừa bởi vì họ là phương pháp riêng tư. Sửa đổi VCL là một đề xuất địa ngục và tôi cũng không muốn giải trí.
Tại sao không chỉ gọi 'TrackPopupMenu' trực tiếp với 'aPopupMenu.Handle' và chuyển bất kỳ cờ, v.v ... mà bạn muốn cung cấp? @Sertac đăng một ví dụ [ở đây] (http://stackoverflow.com/a/11649119/62576) –
Điều đó dường như không làm mọi thứ xảy ra khi tôi gọi TPopupMenu.Popup, mặc dù, và không có chuẩn bị VCL cho call-of-trackpopupmenu nhưng không gọi menu popup theo dõi. –
tôi nghĩ rằng bạn có thể thử để có được một số nút nguồn mở với menu hoặc thanh công cụ với các thành phần nút và tìm hiểu nguồn của họ. Giống như JvArrowButton của JVCL hoặc ToolBar2000 hoặc một số nút hoặc thanh công cụ khác từ torry.net - chỉ cần tìm thành phần thích hợp và tìm hiểu từ nó –