自定义绘图 TPopupMenu 似乎不起作用
Custom Drawing TPopupMenu doesn't seem to work
使用 C++ Builder 2009。试验看看我是否可以为 Windows 11
改进 TPopupMenu
(还有 TMainMenu
)
我的 AdvancedDrawItem
函数从未被调用。我不确定为什么。我错过了什么傻事吗?
//---------------------------------------------------------------------------
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。在另一个复杂得多的项目中,我确实让它在继承自 TPopupMenu
的对象中触发。我现在很困惑为什么我不能让这个简单的代码工作。但是,我开始意识到这是一个半任务,因为 DrawThemeBackground()
在此事件期间似乎没有做任何事情,而我有点依赖它。此外,在绘画时考虑快捷方式、图标等将成为 PITA。
PopupMenu1->Items->OnAdvancedDrawItem = AdvancedDrawItem ;
这是错误的。您需要将 OnAdvancedDrawItem
处理程序分配给菜单中每个单独的 visible TMenuItem
(即 test1
和 test2
),而不是到拥有这些项目的 TPopupMenu::Items
集合。
ACanvas->TextRect((TRect&)ARect, (String&)Item->Caption, TF) ;
两种类型转换都是错误的。
由于您没有使用允许 TextRect()
修改参数值(tfCalcRect
或 tfModifyString
)的 TF
标志,您可以使用 const_cast
替换第一个:
const_cast<TRect&>(ARect)
但是,技术上没有合法的方法将右值(例如TMenuItem::Caption
的return值)转换为左值引用,需要变量或函数调用,所以只需使用一个变量:
String str = Item->Caption;
ACanvas->TextRect(const_cast<TRect&>(ARect), str, TF);
在这种情况下,您也可以为第一个参数使用变量:
TRect rect = ARect;
String str = Item->Caption;
ACanvas->TextRect(rect, str, TF);
使用 C++ Builder 2009。试验看看我是否可以为 Windows 11
改进TPopupMenu
(还有 TMainMenu
)
我的 AdvancedDrawItem
函数从未被调用。我不确定为什么。我错过了什么傻事吗?
//---------------------------------------------------------------------------
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。在另一个复杂得多的项目中,我确实让它在继承自 TPopupMenu
的对象中触发。我现在很困惑为什么我不能让这个简单的代码工作。但是,我开始意识到这是一个半任务,因为 DrawThemeBackground()
在此事件期间似乎没有做任何事情,而我有点依赖它。此外,在绘画时考虑快捷方式、图标等将成为 PITA。
PopupMenu1->Items->OnAdvancedDrawItem = AdvancedDrawItem ;
这是错误的。您需要将 OnAdvancedDrawItem
处理程序分配给菜单中每个单独的 visible TMenuItem
(即 test1
和 test2
),而不是到拥有这些项目的 TPopupMenu::Items
集合。
ACanvas->TextRect((TRect&)ARect, (String&)Item->Caption, TF) ;
两种类型转换都是错误的。
由于您没有使用允许 TextRect()
修改参数值(tfCalcRect
或 tfModifyString
)的 TF
标志,您可以使用 const_cast
替换第一个:
const_cast<TRect&>(ARect)
但是,技术上没有合法的方法将右值(例如TMenuItem::Caption
的return值)转换为左值引用,需要变量或函数调用,所以只需使用一个变量:
String str = Item->Caption;
ACanvas->TextRect(const_cast<TRect&>(ARect), str, TF);
在这种情况下,您也可以为第一个参数使用变量:
TRect rect = ARect;
String str = Item->Caption;
ACanvas->TextRect(rect, str, TF);