Пользовательский рисунок TPopupMenu, похоже, не работает

#c builder #vcl

Вопрос:

Использование C Builder 2009. Экспериментирую, чтобы посмотреть, смогу ли я улучшить TPopupMenu (также TMainMenu ) Windows 11

Моя AdvancedDrawItem функция никогда не вызывается. Я не знаю, почему. Я упускаю что-то глупое?

изображение

 //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) {  // Init done here for the sake of small code sample  PopupMenu1-gt;OwnerDraw = true ;  PopupMenu1-gt;Items-gt;OnAdvancedDrawItem = AdvancedDrawItem ;      PopupMenu1-gt;Popup(Left   Button2-gt;Left   50, Top   Button2-gt;Top   50) ; } //--------------------------------------------------------------------------- void __fastcall TForm1::AdvancedDrawItem(TObject *Sender, TCanvas *ACanvas, const TRect amp;ARect, TOwnerDrawState State) {  TMenuItem *Item = (TMenuItem*)Sender ;    TTextFormat TF = TTextFormat() lt;lt; tfVerticalCenter lt;lt; tfSingleLine lt;lt; tfEndEllipsis lt;lt; tfLeft ;    ACanvas-gt;TextRect((TRectamp;)ARect, (Stringamp;)Item-gt;Caption, TF) ; } //---------------------------------------------------------------------------  

пс. В другом проекте с гораздо большей сложностью я заставляю его срабатывать в объекте, который наследуется от TPopupMenu . В данный момент я совершенно сбит с толку, почему я не могу заставить этот простой код работать. Тем не менее, я начинаю понимать, что это полуторная задача, поскольку DrawThemeBackground() , похоже, ничего не делает во время этого события, и я как бы полагался на это. Кроме того, учет ярлыков, значков и т. Д. Во время рисования будет ПИТОЙ.

Ответ №1:

PopupMenu1-gt;Items-gt;OnAdvancedDrawItem = AdvancedDrawItem ;

Это неправильно. Вам нужно назначить OnAdvancedDrawItem обработчик каждому отдельному пользователю, видимому TMenuItem в меню (т. Е. test1 и test2 ), а не TPopupMenu::Items коллекции, которой принадлежат элементы.

ACanvas-gt;TextRect((TRectamp;)ARect, (Stringamp;)Item-gt;Caption, TF) ;

Оба типа неверны.

Поскольку вы не используете TF флаг, позволяющий TextRect() изменять значения параметров ( tfCalcRect или tfModifyString ), вы можете использовать const_cast для замены первого:

const_castlt;TRectamp;gt;(ARect)

Но технически нет законного способа преобразовать значение rvalue (например, возвращаемое значение TMenuItem::Caption ) в ссылку на значение lvalue, требуется вызов переменной или функции, поэтому просто используйте переменную:

 String str = Item-gt;Caption; ACanvas-gt;TextRect(const_castlt;TRectamp;gt;(ARect), str, TF);  

В этом случае вы также можете использовать переменную для 1-го параметра:

 TRect rect = ARect; String str = Item-gt;Caption; ACanvas-gt;TextRect(rect, str, TF);  

Комментарии:

1. Ах да, конечно, теперь я вижу, что упустил из виду. Если вы знаете классный трюк, чтобы каким-то образом заставить (древний компилятор) TPopupMenu нарисовать фон до того, как он нарисует значок, и clHighlightText при выборе цвета текста, дайте мне знать, и я отправлю вопрос 😉

2. Почему вы не можете справиться со всем этим в своем On(Advanced)DrawItem обработчике?

3. Ну, вот к чему, я боюсь, все это приведет. Я все еще надеялся на чудо 🙂 Есть о чем подумать. Ярлыки, значки и т.д.