#delphi #delphi-xe2 #firemonkey
#delphi #delphi-xe2 #firemonkey
Вопрос:
Я вроде как задавал этот вопрос в конце другого поста, но чувствую, что эта тема нуждается в отдельном вопросе…
Если я создал свой собственный компонент с собственным .style, какова правильная процедура для объединения его с определенными стилями, поставляемыми с Delphi, без изменения значений по умолчанию?
Могу ли я встроить стиль по умолчанию в созданный мной компонент и может ли этот встроенный стиль унаследовать большую часть стиля его родительского элемента управления?
Я чувствую, что мне не хватает ссылки, которую я изо всех сил пытаюсь описать. В моем приложении есть TStyleBook, в котором (например) по умолчанию загружен «dark.style». У моего компонента есть свой собственный файл «MyComponent.style». TStyleBook может загружать либо «dark.style», либо «MyComponent.style», но не оба. И кажется неправильным, что приложение должно загружать «MyComponent.style», поскольку на это должен каким-то образом ссылаться компонент. Это не делает компонент очень переносимым, если каждый раз, когда он используется в приложении, также требуется отдельный файл стиля.
Я мог бы отредактировать свой собственный «MyDark.style» и добавить в него MyComponent, но это тоже кажется неправильным, поскольку создает проблему для обновления его с изменениями, внесенными Embarcadero.
Я надеюсь, что я это ясно объяснил. Мартин
Ответ №1:
Спасибо Рэю Конопке, который провел отличный доклад о CodeRage и направил меня на правильный путь, чтобы ответить на эти вопросы.
Вопрос 1. Могу ли я встроить стиль по умолчанию в компонент?
Да, вы вставляете стиль по умолчанию, который хотите распространять вместе с компонентом, в ресурс типа RT_RCDATA. Затем просто включите этот ресурс в исходный код:
{$R *.res}
Примечание: Вам необходимо удалить внешний объект (TLayout), если вы создали его в редакторе компоновки, прежде чем помещать его в res.
Затем переопределите метод GetStyleObject, чтобы загрузить стиль из ресурса.
function TLFButton.GetStyleObject: TControl;
var
S: TResourceStream;
obj: TLayout;
const
Style = 'LFButtonStyle';
begin
result := inherited GetStyleObject;
if FStyleLookup = 'cornerbuttonstyle' then
begin
if FindResource(HInstance, PChar(Style), RT_RCDATA) <> 0 then
begin
S := TResourceStream.Create(HInstance, Style, RT_RCDATA);
try
obj := TLayout(TStyleManager.LoadFromResource(HInstance, Style, RT_RCDATA));
//obj := TLayout( CreateObjectFromStream(nil, S) ); << XE2 version
Result.AddObject(obj);
Exit;
finally
S.Free;
end;
end;
end;
end;
Вопрос 2. Как объединить его со стилем по умолчанию.
В моем случае основой моего компонента был TCornerButton . Я урезал свой файл .style, чтобы в нем был только код для дополнительных битов, которые я хотел. В этом случае маленький треугольник для обозначения выпадающей кнопки и линия для разделения кнопки:
object TLayout
Align = alRight
Position.Point = '(76,0)'
Locked = True
Width = 15.000000000000000000
Height = 24.000000000000000000
object TPath
StyleName = 'dropdownbutton'
Align = alCenter
Position.Point = '(4,9)'
Width = 8.000000000000000000
Height = 5.000000000000000000
HitTest = False
Fill.Color = claBlack
Stroke.Kind = bkNone
Data.Path = {
04000000000000000000000000000000010000000000803F0000000001000000
0000003F0000803F030000000000000000000000}
end
object TLine
StyleName = 'dropdownsplit'
Align = alLeft
Width = 1.000000000000000000
Height = 24.000000000000000000
HitTest = False
LineType = ltLeft
end
end
И я помещаю это в ресурс точно таким же образом.
В моем конструкторе я установил для StyleLookup значение «cornerbuttonstyle»
constructor TLFButton.Create(AOwner: TComponent);
begin
FStyleLookup := 'cornerbuttonstyle';
FDropDownButton := false;
inherited;
end;
Затем я изменяю GetStyleObject так, чтобы он загружал новые материалы и добавлял их к существующему стилю.
function TLFButton.GetStyleObject: TControl;
var
S: TResourceStream;
obj: TLayout;
const
Style = 'LFButtonStyle';
begin
result := inherited GetStyleObject;
if FStyleLookup = 'cornerbuttonstyle' then
begin
if FindRCData(HInstance, Style) then
begin
S := TResourceStream.Create(HInstance, Style, RT_RCDATA);
try
obj := TLayout( CreateObjectFromStream(nil, S) );
Result.AddObject(obj);
Exit;
finally
S.Free;
end;
end;
end;
end;
Я надеюсь, что это поможет кому-то еще, и я обнаружил, что все это очень сложно получить информацию.
Мартин
Комментарии:
1. Очень полезно. Спасибо!
Ответ №2:
Использование: MergeStyle(‘MyComponent.Стиль’, StyleBook1);
procedure MergeStyle(const aFilename: string; aStyleBook: TStyleBook);
var
sb: TStyleBook;
I: Integer;
begin
sb := TStyleBook.Create(nil);
try
sb.FileName := aFilename;
for I := 0 to sb.Root.ChildrenCount - 1 do
// Prevent duplicates
if aStyleBook.Root.FindStyleResource(sb.Root.Children[I].StyleName) = nil then
aStyleBook.Root.AddObject(sb.Root.Children[I].Clone(aStyleBook.Root));
aStyleBook.UpdateScenes;
finally
sb.Free;
end;
end;