Правильный способ создания стилей для пользовательских компонентов - PullRequest
7 голосов
/ 17 октября 2011

Я как бы задал этот вопрос в конце другого поста, но чувствую, что эта тема нуждается в отдельном вопросе ...

Если я создал свой собственный компонент со своим собственным .style, что является правильнымпроцедура объединения этого с определенными стилями, поставляемыми с Delphi, без изменения значений по умолчанию?

Можно ли встроить стиль по умолчанию в созданный мною компонент, и может ли этот встроенный стиль наследовать большую часть стиля его родительского элемента управления?

Я чувствую, что мне не хватает ссылки, которую я изо всех сил пытаюсь описать.В моем приложении есть TStyleBook, в котором (например) по умолчанию загружен «dark.style».Мой компонент имеет свой собственный файл "MyComponent.style".TStyleBook может загружать «dark.style» или «MyComponent.style», но не оба одновременно.И кажется неправильным, что приложение должно загружать «MyComponent.style», так как компонент должен каким-то образом ссылаться на него.Это не делает компонент очень переносимым, если каждый раз, когда он используется в приложении, необходим также отдельный файл стиля.

Я мог бы отредактировать свой собственный «MyDark.style» и добавить в него MyComponent, но это не кажетсяПравильно, так как это создает проблему, чтобы держать ее в курсе изменений, внесенных Embarcadero.

Надеюсь, я четко объяснил это.Martin

Ответы [ 2 ]

4 голосов
/ 21 октября 2011

Спасибо за Рэя Конопку, который выступил с отличным докладом о 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 как «угловой стиль»

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;

Я надеюсь, что это поможет кому-то еще, и мне было очень сложно получить информацию.

Martin

2 голосов
/ 18 октября 2011

Использование: MergeStyle ('MyComponent.Style', 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;
...