Using C++ Builder 2009. Experimenting to see if I can improve TPopupMenu
(also TMainMenu
) for Windows 11
My AdvancedDrawItem
function is never called. I'm not sure why. Am I missing something silly?
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
// Init done here for the sake of small code sample
PopupMenu1->OwnerDraw = true ;
PopupMenu1->Items->OnAdvancedDrawItem = AdvancedDrawItem ;
PopupMenu1->Popup(Left + Button2->Left + 50, Top + Button2->Top + 50) ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::AdvancedDrawItem(TObject *Sender, TCanvas *ACanvas, const TRect &ARect, TOwnerDrawState State)
{
TMenuItem *Item = (TMenuItem*)Sender ;
TTextFormat TF = TTextFormat() << tfVerticalCenter << tfSingleLine << tfEndEllipsis << tfLeft ;
ACanvas->TextRect((TRect&)ARect, (String&)Item->Caption, TF) ;
}
//---------------------------------------------------------------------------
PS. In a different project with a lot more complexity, I do get it to fire in an object that inherits from TPopupMenu
. I'm thoroughly confused at the moment as to why I can't get this simple code to work. However, I'm starting to realize that this is a task and a half since DrawThemeBackground()
doesn't appear to do anything during this event, and I was sort of relying on that. Also, keeping into account shortcuts, icons, etc while painting is going to be a PITA.
PopupMenu1->Items->OnAdvancedDrawItem = AdvancedDrawItem ;
This is wrong. You need to assign the OnAdvancedDrawItem
handler to each individual visible TMenuItem
in the menu (ie, test1
and test2
), not to the TPopupMenu::Items
collection that owns the items.
ACanvas->TextRect((TRect&)ARect, (String&)Item->Caption, TF) ;
Both typecasts are wrong.
Since you are not using a TF
flag that allows TextRect()
to modify the parameter values (tfCalcRect
or tfModifyString
), you can use const_cast
to replace the first one:
const_cast<TRect&>(ARect)
But, there is technically no legal way to convert an rvalue (such as the return value of TMenuItem::Caption
) to an lvalue reference, a variable or function call is required, so just use a variable:
String str = Item->Caption;
ACanvas->TextRect(const_cast<TRect&>(ARect), str, TF);
In which case, you may as well use a variable for the 1st parameter, too:
TRect rect = ARect;
String str = Item->Caption;
ACanvas->TextRect(rect, str, TF);