(C++Builder 11(
由于我需要使用带有字幕的TSpeedButton
(不是在字形的顶部、底部、左侧或右侧(,我遵循了Ted Lyngmo的建议(字幕在TSpeedButton中的位置(创建了一个新的VCL组件。我从TCustomSpeedButton
开始创建了一个新组件,并且只发布了几个属性,不包括Caption
。我添加了CustomCaption
属性,并尝试覆盖Paint()
方法以在按钮中间写入文本。生成的组件可以加载一个图示符来显示按下和未按下的状态,CustomCaption
的内容写在其中间
但我的CustomCaption
的行为与最初的Caption
相去甚远。
首先,如果我更改CustomCaption
的内容,在设计时,按钮不会发生变化,直到我没有点击它(我在设计器中执行Paint()
方法,我认为…(
然后,如果我在设计时更改字体,我的CustomCaption
字体根本不会更改。
我尝试使用CM_FONTCHANGED
和CM_TEXTCHANGED
消息,但可能方式不对。
这是代码
//header file
class PACKAGE TSpecialSpeedButton : public TCustomSpeedButton
{
private:
String fCustomCaption;
//int fCustomCaptionTop, fCustomCaptionLeft;
MESSAGE void __fastcall CMFontChanged(TMessage &Msg);
MESSAGE void __fastcall CMTextChanged(TMessage &Msg);
protected:
void __fastcall Paint() override;
public:
__fastcall TSpecialSpeedButton(TComponent* Owner) override;
__published:
__property String CustomCaption = {read = fCustomCaption, write = fCustomCaption};
//__property int CustomCaptionTop = {read = fCustomCaptionTop, write = fCustomCaptionTop};
//__property int CustomCaptionLeft = {read = fCustomCaptionLeft, write = fCustomCaptionLeft};
__property Glyph;
__property GroupIndex = {default=0};
__property Font;
__property NumGlyphs = {default=1};
__property OnClick;
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(CM_FONTCHANGED, TMessage, CMFontChanged)
VCL_MESSAGE_HANDLER(CM_TEXTCHANGED, TMessage, CMTextChanged)
END_MESSAGE_MAP(TCustomSpeedButton)
};
//cpp file
static inline void ValidCtrCheck(TSpecialSpeedButton *)
{
new TSpecialSpeedButton(NULL);
}
//---------------------------------------------------------------------------
__fastcall TSpecialSpeedButton::TSpecialSpeedButton(TComponent* Owner)
: TCustomSpeedButton(Owner)
{
//fCustomCaptionTop = 0;
//fCustomCaptionLeft = 0;
Height = 50;
Width = 50;
}
//---------------------------------------------------------------------------
namespace Tspecialspeedbutton
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TSpecialSpeedButton)};
RegisterComponents(L"My Components", classes, 0);
}
}
//---------------------------------------------------------------------------
void __fastcall TSpecialSpeedButton::Paint()
{
TRect PtRect;
TCustomSpeedButton::Paint();
PtRect.Left = 0;
PtRect.Top = 0;
PtRect.Right = Width;
PtRect.Bottom = Height;
Canvas->Font = Font; //this seems to have no effect
DrawTextW(Canvas->Handle, fCustomCaption.c_str(), fCustomCaption.Length(), &PtRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
//---------------------------------------------------------------------------
void __fastcall TSpecialSpeedButton::CMFontChanged(TMessage &Msg)
{
Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TSpecialSpeedButton::CMTextChanged(TMessage &Msg)
{
Invalidate();
}
//---------------------------------------------------------------------------
我无法以正确的方式管理CustomCaption
,即原始的Caption
。我已经在互联网上搜索了信息,在Embarcadero docwiki-组件作者指南中,在Vcl.Buttons.pas文件中,但我找不到正确的方法,有人能帮我吗?
Embarcadero不久前进行了一些更改,这些更改会导致Windows资源(如TFont、TBrush、TPen等(出现细微问题。您遇到的问题是TFont.Assign并不总是导致TCanvas重新创建Windows字体对象。若要强制重新创建字体对象,您需要强制对TFont.Changed进行内部调用。一种简单的方法是为TFont.Color分配一个不需要的值,然后将其设置回您真正想要的颜色。例如:
Canvas->Font = Font;
Canvas->Font->Color = clNone;
Canvas->Font->Color = Font->Color;
我无法以正确的方式管理CustomCaption
我不知道你说的";以正确的方式";。如果您的意思是希望更改CustomCaption以引起重绘,请为该属性添加一个写入程序,然后在值更改时调用Invalidate。
protected:
void __fastcall SetCustomCaption(String Value);
__published:
__property String CustomCaption = { read = fCustomCaption, write = SetCustomCaption };
void __fastcall TSpecialSpeedButton::SetCustomCaption(String Value)
{
if (fCustomCaption != Value)
{
fCustomCaption = Value;
Invalidate();
}
}
CM_TEXTCHANGED是在继承的文本/标题属性更改时发送的Windows消息。由于您没有使用继承的属性,因此很可能不需要处理该消息。除非您希望始终将其设置为空字符串。