如何为自定义VCL组件TGroupBoxE配置自定义TSeStyleObject样式
在RAD Studio 12.2 C++Builder中,我基于TGroupBox继承实现了新组件TGroupBoxE,它继承了TGroupBox的所有图形属性。我希望这个新组件不再使用TGroupBox的默认样式,而是改用自己通过Bitmap Style Designer创建的无框样式——我在设计器中复制了原GroupBox (TSeStyleObject),命名为GroupBoxE并修改了渲染逻辑使其不显示边框。
目前组件已成功注册到Samples分类,可在应用中正常使用,但不知道如何让它正确关联自定义的TSeStyleObject样式。
附现有组件代码:
//-----------------------GroupBoxE.cpp--------------------------------------- #include <vcl.h> #pragma hdrstop #include "GroupBoxE.h" #pragma package(smart_init) __fastcall TGroupBoxE::TGroupBoxE(TComponent* Owner) : TGroupBox(Owner)//, FFrameWidth(1), FCustomShowFrame(true) { } //--------------------------------------------------------------------------- TRect __fastcall TGroupBoxE::GetClientRect() { TRect Rect = TGroupBox::GetClientRect(); if (Caption.IsEmpty()) { int CaptionHeight = Canvas->TextHeight("A"); Rect.Top -= CaptionHeight; } return Rect; } //--------------------------------------------------------------------------- void __fastcall TGroupBoxE::WndProc(TMessage &Message) { if (Message.Msg == WM_SIZE && FOnResize) FOnResize(this); TGroupBox::WndProc(Message); } //--------------------------------------------------------------------------- namespace Groupboxe { void __fastcall PACKAGE Register() { TComponentClass classes[1] = {__classid(TGroupBoxE)}; RegisterComponents(L"Samples", classes, 0); } } //---------------------------------------------------------------------------
//--------------------------------GroupBoxE.h-------------------------------- #ifndef GroupBoxEH #define GroupBoxEH //--------------------------------------------------------------------------- #include <System.Classes.hpp> #include <Vcl.Controls.hpp> #include <Vcl.StdCtrls.hpp> //--------------------------------------------------------------------------- class PACKAGE TGroupBoxE : public TGroupBox { private: TNotifyEvent FOnResize; protected: virtual void __fastcall WndProc(TMessage &Message) override; public: __fastcall TGroupBoxE(TComponent* Owner) override; __published: virtual TRect __fastcall GetClientRect() override; __property TNotifyEvent OnResize = {read=FOnResize, write=FOnResize}; }; //--------------------------------------------------------------------------- #endif
要让TGroupBoxE关联自定义样式,核心是让VCL样式系统识别到组件应使用GroupBoxE样式而非默认的GroupBox样式,具体操作如下:
1. 重写GetStyleName方法
VCL样式系统通过组件的StyleName(或GetStyleName返回值)匹配对应的TSeStyleObject。在TGroupBoxE中重写该方法,返回自定义样式名称GroupBoxE即可完成关联。
修改头文件(GroupBoxE.h)
在protected段添加方法声明:
class PACKAGE TGroupBoxE : public TGroupBox { private: TNotifyEvent FOnResize; protected: virtual void __fastcall WndProc(TMessage &Message) override; // 添加GetStyleName声明 virtual UnicodeString __fastcall GetStyleName(void) override; public: __fastcall TGroupBoxE(TComponent* Owner) override; __published: virtual TRect __fastcall GetClientRect() override; __property TNotifyEvent OnResize = {read=FOnResize, write=FOnResize}; };
修改实现文件(GroupBoxE.cpp)
添加方法实现:
UnicodeString __fastcall TGroupBoxE::GetStyleName(void) { return L"GroupBoxE"; // 返回自定义样式的名称 }
2. 确保自定义样式正确加载
- 将Bitmap Style Designer中导出的样式文件(.vsf)添加到项目资源,或在应用启动时通过
TStyleManager::LoadStyleFromFile加载。 - 确保应用启用VCL样式:可在项目选项中勾选「Enable runtime themes」,或在代码中调用
TStyleManager::SetStyle设置加载后的样式。
3. 验证效果
重新编译组件包与应用,拖放TGroupBoxE到窗体并启用样式后,组件将自动使用你定义的无框样式。
额外说明
若需深度自定义样式渲染逻辑(比如扩展TSeStyleObject),可创建继承自TSeGroupBoxStyleObject的新样式类并注册到样式系统,但你已通过Bitmap Style Designer修改了原样式的渲染逻辑,仅重写GetStyleName即可满足需求。
内容的提问来源于stack exchange,提问作者Lubo

