Я хочу, чтобы всплывающее меню выше кнопки:Как вы выстраиваете TPopupMenu так, чтобы он точно позиционировал себя над кнопкой?
Delphi облегает систему меню Win32 таким образом, что кажется, исключает каждый режим или флаг, лежащий в основе Win32 API предусматривает, что не было в VCL автора мозг в этот день. Одним из таких примеров является TPM_BOTTOMALIGN
, который может быть передан в TrackPopupMenu
, но, как представляется, оболочка Delphi делает это не только невозможным в запасе VCL, но и вредоносным использованием частных и защищенных методов невозможно (по крайней мере, мне кажется быть невозможным) делать либо точно во время выполнения, либо путем переопределения. Компонент VCL TPopupMenu также не очень хорошо разработан, так как он должен иметь виртуальный метод с именем PrepareForTrackPopupMenu
, который сделал все, кроме вызова TrackPopupMenu
или TrackPopupMenuEx
, а затем разрешить кому-то переопределить метод, который фактически вызывает этот метод Win32. Но сейчас уже слишком поздно. Возможно, Delphi XE5 будет иметь это основное покрытие Win32 API, сделанное правильно.
подходов я пытался:
подхода: Использование METRICS или шрифты:
определяет высоту точно всплывающее меню, так что я могу вычесть значение Y перед вызовом popupmenu.Popup (х, у). Результаты: нужно было бы обрабатывать все варианты тематики Windows и делать предположения, о которых я, похоже, не могу быть уверен. Кажется, вряд ли это приведет к хорошим результатам в реальном мире. Вот пример базовой метрики шрифта подхода:
height := aPopupMenu.items.count * (abs(font.height) + 6) + 34;
Вы можете принять во внимание скрытые элементов, и для одной версии окон с одной настройкой режима темы в действительности, вы можете получить близко, как это, но не абсолютно верно.
Подход 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
, не оценивая высоту.
Update: Вызов TrackPopupMenu
напрямую не работает, потому что остальные шаги в методе VCL TPopupMenu.Popup(x,y)
необходимо вызвать для моего приложения, чтобы нарисовать его меню и он выглядит корректно, однако, невозможно вызвать их без зла обман, потому что они частные методы. Изменение VCL - адское предложение, и я тоже не хочу это развлекать.
Почему бы просто не вызвать 'TrackPopupMenu' непосредственно с' aPopupMenu.Handle' и передать ему все флаги и т. Д., Которые вы хотите предоставить? @Sertac опубликовал пример [здесь] (http://stackoverflow.com/a/11649119/62576) –
Это не похоже на то, что происходит, когда я вызываю TPopupMenu.Popup, хотя и нет VCL ready-for- call-of-trackpopupmenu, но не вызывать всплывающее меню трека. –
Я думаю, вы можете попробовать получить кнопку с открытым исходным кодом с меню или панелью инструментов с компонентами кнопок и узнать их источники. Как JvArrowButton из JVCL или ToolBar2000 или какой-либо другой кнопки или панели инструментов от torry.net - просто найдите нужный компонент и узнайте от него –