Voglio un menu pop-up sopra un pulsante:Come si allinea un oggetto TPopup in modo che si posizioni esattamente sopra un pulsante?
Delphi avvolge il sistema di menu Win32 in un modo che sembra precludere ogni modalità o la bandiera che il sottostante Win32 API fornisce che non era in l'autore del VCL cervello in quel giorno. Uno di questi esempi sembra essere il TPM_BOTTOMALIGN
che può essere passato a TrackPopupMenu
ma, il wrapper Delphi sembra rendere questo non solo impossibile nel VCL di serie, ma da un uso improduttivo di metodi privati e protetti, è impossibile (almeno mi sembra essere impossibile) da eseguire in modo accurato in fase di esecuzione o in caso di sovrascritture. Il componente VCL TPopupMenu non è molto ben progettato, in quanto avrebbe dovuto avere un metodo virtuale chiamato PrepareForTrackPopupMenu
che faceva tutto tranne la chiamata a TrackPopupMenu
o TrackPopupMenuEx
e quindi consentire a qualcuno di sovrascrivere un metodo che effettivamente invoca quel metodo Win32. Ma è troppo tardi adesso. Forse Delphi XE5 avrà questa copertura di base dell'API Win32 eseguita correttamente.
Approcci ho provato:
Approccio A: Uso METRICS o Caratteri:
determinare con precisione l'altezza di un menu a tendina così posso sottrarre il valore Y prima di chiamare popupmenu.Popup (x, y). Risultati: Dovrebbe gestire tutte le varianti dei temi di Windows e fare supposizioni di cui non sembro essere sicuro. Sembra improbabile che porti a buoni risultati nel mondo reale. Ecco un esempio di un approccio di base metriche di font:
height := aPopupMenu.items.count * (abs(font.height) + 6) + 34;
si può prendere in considerazione gli elementi nascosti, e per una sola versione di Windows con una sola impostazione della modalità tema in effetti, si potrebbe avvicinarsi in quel modo, ma non completamente giusto.
Approccio B: Let di Windows Do It:
tenta di passare in TPM_BOTTOMALIGN
fine di raggiungere Win32 API chiamata TrackPopupMenu
.
Finora, penso di poterlo fare, se modifico i menu VCL.pas .. Sto usando Delphi 2007 in questo progetto. Non sono molto contento di questa idea però.
Ecco il tipo di codice che sto cercando:
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;
In alternativa ho voluto fare questo:
pt.X := 0;
pt.Y := 0;
pt := aButton.ClientToScreen(pt); // do the math for me.
aPopupMenu.popupEx(pt.X, pt.Y, TPM_BOTTOMALIGN);
Naturalmente, popupEx non è lì in VCL. Né alcun modo per trasmettere più flag a TrackPopupMenu
rispetto a quelli che i ragazzi VCL hanno aggiunto probabilmente nel 1995, nella versione 1.0.
Nota: Credo che il problema di stimare l'altezza prima di mostrare il menu sia impossibile, quindi dovremmo effettivamente risolvere il problema con TrackPopupMenu
non stimando l'altezza.
Aggiornamento: Calling TrackPopupMenu
direttamente non funziona, perché il resto dei passaggi nel metodo VCL TPopupMenu.Popup(x,y)
sono necessarie per invocare per la mia applicazione per dipingere il suo menu e hanno un aspetto corretto, tuttavia non è possibile invocare loro senza il male inganno perché sono metodi privati. Modificare la VCL è una proposta infernale e non desidero nemmeno intrattenerlo.
Perché non basta chiamare 'TrackPopupMenu' direttamente con' aPopupMenu.Handle' e passarlo qualunque bandiere, ecc si desidera fornire? @Sertac ha pubblicato un esempio [qui] (http://stackoverflow.com/a/11649119/62576) –
Questo non sembra fare tutto ciò che accade quando chiamo TPopupMenu.Popup, però, e non c'è VCL in preparazione per call-of-trackpopupmenu ma non richiamare il menu popup della traccia. –
Penso che si possa provare a ottenere un pulsante open source con menu o barra degli strumenti con componente pulsanti e apprendere le loro fonti. Come JvArrowButton di JVCL o ToolBar2000 o qualche altro pulsante o barra degli strumenti da torry.net - basta trovare il componente appropriato e imparare da esso –