chcę wyskakujące menu powyżej przycisku:Jak wyrównać menu TPopup, aby dokładnie ustawił się nad przyciskiem?
Delphi otacza menu systemu Win32 w sposób, który wydaje się wykluczać każdym trybie lub flagę bazowego Win32 API zapewnia, że nie był w VCL autora mózg tego dnia. Jednym z takich przykładów wydaje się być TPM_BOTTOMALIGN
, który może być przekazany do TrackPopupMenu
, ale opakowanie Delphi wydaje się uczynić to nie tylko niemożliwe w magazynie VCL, ale przez nierozsądne użycie prywatnych i chronionych metod, jest niemożliwe (przynajmniej wydaje mi się, że być niemożliwe), aby zrobić dokładnie w czasie wykonywania lub przez przesłonięcia. Komponent VCL TPopupMenu również nie jest zbyt dobrze zaprojektowany, ponieważ powinien mieć wirtualną metodę o nazwie PrepareForTrackPopupMenu
, która wykonała wszystko inne niż wywołanie TrackPopupMenu
lub TrackPopupMenuEx
, a następnie pozwoli komuś zastąpić metodę, która faktycznie wywołuje tę metodę Win32. Ale teraz jest już za późno. Być może Delphi XE5 będzie miało to podstawowe pokrycie API Win32.
Podejścia próbowałem:
Podejście: Użyj danych lub Czcionki:
dokładnie określić wysokość menu kontekstowego więc mogę odjąć wartość Y przed wywołaniem popupmenu.Popup (X, Y). Wyniki: Będą musiały obsłużyć wszystkie warianty motywów systemu Windows i przyjąć założenia, na które nie jestem pewny. Wydaje się mało prawdopodobne, aby przyniosło to dobre wyniki w realnym świecie. Oto przykład z podstawowego podejścia parametrów czcionki:
height := aPopupMenu.items.count * (abs(font.height) + 6) + 34;
Można uwzględniać ukrytych przedmiotów, a za jednym wersją systemu Windows za pomocą jednego ustawienia trybu motyw w efekcie może zbliżyć się w ten sposób, ale nie dokładnie tak.
Podejście B: Niech system Windows to zrobić:
Spróbuj przejść w końcu dotrzeć do TPM_BOTTOMALIGN
Win32 API wezwanie TrackPopupMenu
.
Do tej pory, myślę, że mogę to zrobić, jeśli zmodyfikuję menu VCL.pas .. Używam Delphi 2007 w tym projekcie. Jednak nie cieszę się z tego pomysłu.
Oto rodzaj kodu usiłuję:
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;
Alternatywnie Chciałem to zrobić:
pt.X := 0;
pt.Y := 0;
pt := aButton.ClientToScreen(pt); // do the math for me.
aPopupMenu.popupEx(pt.X, pt.Y, TPM_BOTTOMALIGN);
Oczywiście popupEx nie ma w VCL. Ani sposób na przekazanie większej liczby flag do TrackPopupMenu
niż tych, które dodali użytkownicy VCL prawdopodobnie w 1995 roku, w wersji 1.0.
Uwaga: Uważam, że problem oszacowania wysokości przed wyświetleniem menu jest niemożliwy, dlatego powinniśmy faktycznie rozwiązać problem przez TrackPopupMenu
, nie szacując wysokości.
Aktualizacja: wywołanie TrackPopupMenu
bezpośrednio nie działa, ponieważ pozostałe kroki w metodzie VCL TPopupMenu.Popup(x,y)
są konieczne, aby wywołać aplikację, aby malować menu i wyglądać poprawnie, jednak nie można ich wywołać bez zła oszustwo, ponieważ są to prywatne metody. Modyfikacja VCL jest piekielną propozycją i nie chcę tego zabawiać.
Dlaczego po prostu nie należy wywoływać 'TrackPopupMenu' bezpośrednio za pomocą' aPopupMenu.Handle' i przekazywać je niezależnie od flag itp., Które chcesz udostępnić? @Sertac opublikował przykład [tutaj] (http://stackoverflow.com/a/11649119/62576) –
Nie wydaje się, aby zrobił wszystko, co się dzieje, gdy zadzwonię do TPopupMenu.Popup, ale nie ma VCL przygotowanie-for- call-of-trackpopupmenu, ale nie wywołuj menu wyskakującego track. –
Myślę, że możesz spróbować uzyskać przycisk open-source z menu lub paska narzędzi z komponentami przycisków i poznać ich źródła. Podobnie jak JvArrowButton z JVCL lub ToolBar2000 lub inny przycisk lub pasek narzędzi z torry.net - wystarczy znaleźć odpowiedni komponent i uczyć się z niego –