Установка родителя в пользовательском компоненте
Я создал два пользовательских компонента в XE5. Первый является потомком TCustomPanel, и его назначение - быть контейнером для второго компонента, который является потомком TCustomLabel.
Контейнер.
class PACKAGE TMenuPanel : public TCustomPanel
{
private:
protected:
public:
__fastcall TMenuPanel(TComponent* Owner);
__published:
__property Align;
__property Caption;
};
static inline void ValidCtrCheck(TMenuPanel *)
{
new TMenuPanel(NULL);
}
//---------------------------------------------------------------------------
__fastcall TMenuPanel::TMenuPanel(TComponent* Owner)
: TCustomPanel(Owner)
{
}
//---------------------------------------------------------------------------
namespace Menupanel
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TMenuPanel)};
RegisterComponents(L"Isis", classes, 0);
}
}
Содержится
//---------------------------------------------------------------------------
class PACKAGE TMenuLabel : public TCustomLabel
{
private:
UnicodeString FOption;
int FIndex;
bool FHighlighted;
protected:
UnicodeString __fastcall GetOption();
void __fastcall SetOption(UnicodeString Option);
int __fastcall GetIndex();
void __fastcall SetIndex(int Index);
void __fastcall SetHighlighted(bool Flag);
void __fastcall RecaptionLabel();
public:
__fastcall TMenuLabel(TComponent* Owner);
__published:
__property int Index = {read=GetIndex, write=SetIndex, nodefault};
__property UnicodeString Option = {read=GetOption, write=SetOption, nodefault};
__property bool Highlighted = {read=FHighlighted, write=SetHighlighted, nodefault};
};
static inline void ValidCtrCheck(TMenuLabel *)
{
new TMenuLabel(NULL);
}
//---------------------------------------------------------------------------
__fastcall TMenuLabel::TMenuLabel(TComponent* Owner)
: TCustomLabel(Owner)
{
if (!Name.IsEmpty()) {
FOption = L"Option"+Name;
} else {
FOption = L"Option";
}
FHighlighted = false;
}
Пока все хорошо, компоненты установлены, они отображаются в палитре, а их свойства в инспекторе. Но...
Если MenuPanel размещен в форме, MenuLabels размещается в нем. Если он размещен на панели в форме, метки меню размещаются на панели. Забавно, что если панель меню, размещенная в форме, обрезается и вставляется на панель, метки меню находятся в панели меню.
Я знаю, что это связано с установкой родительского свойства для MenuPanel, но конструктор принимает параметр TComponent *Owner, который является формой. Тем не менее, панели могут быть размещены внутри панелей, внутри панелей, и метка будет размещена в правой.
Кто-нибудь сталкивался с такой же проблемой?
2 ответа
Мне нужна была ссылка на родительский компонент, так как он имеет значения для определенных цветов шрифта дочерних компонентов. ParentFont предоставляет FontName, Size, Styles, но контейнер определяет цветовые атрибуты шрифта для определенных производных компонентов TStaticText.
Контейнер определяет:
MESSAGE void __fastcall MPIntHandler(TMyIntMessage &Msg);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(IC_GETCOLOR, TMyIntMessage, MPIntHandler);
END_MESSAGE_MAP(TComponent)
//---------------------------------------------------------------------------
void __fastcall TMenuPanel::MPIntHandler(TMyIntMessage &Msg)
{
WPARAM WP = *Msg.wparam;
WORD lWord = LOWORD(WP);
if (lWord == CLR_LABEL) {
OutputDebugStringA("Returning FLabelColor");
Msg.Result = (long)FLabelColor;
} else {
OutputDebugStringA("lWord != CLR_LABEL");
Msg.Result = (long)clRed;
}
}
Ребенок переопределяет CreateParams:
//---------------------------------------------------------------------------
void __fastcall TMenuLabel::CreateParams(TCreateParams &Params)
{
int wParam = MAKEWPARAM(CLR_LABEL,0);
int lParam = 0;
OutputDebugStringA("CreateParams");
TStaticText::CreateParams(Params);
if (Params.WndParent != NULL) {
hwndParent = Params.WndParent;
LRESULT lRes = SendGetIntMessage(hwndParent,IC_GETCOLOR,wParam,lParam);
Font->Color = (TColor)lRes;
}
}
Это работает как при проектировании, так и во время выполнения.
Когда вы удаляете компонент в конструкторе форм, его Parent
становится в настоящее время сосредоточенным компонентом (если его ControlStyle
содержит csAcceptsControls
иначе его Parent
используется вместо этого, и так до csAcceptsControls
найден). Поэтому убедитесь, что ваш компонент MenuPanel имеет csAcceptsControls
флаг включен в его конструкторе, и что ваша MenuPanel выбрана в конструкторе форм при удалении объектов MenuLabel.