Arhn - архитектура программирования

Реализовать свойство Columns.Columns в настраиваемом компоненте Delphi

Я делаю преобразование нескольких приложений Delphi 2005 в XE2, и они используют компонент, который больше не доступен, поэтому я написал свой собственный компонент для обработки основ, что обычно нормально, когда вы помещаете компонент в форму. Однако я столкнулся с проблемой при открытии формы VCL, содержащей этот компонент, свойства которого уже установлены в DFM.

Delphi 2005 DFM содержит что-то вроде этого:

  object ExtendedGrid1: TExtendedGrid
    Left = 32
    Top = 16
    Width = 577
    Height = 257
    TabOrder = 0
    Columns.Columns = (
      'OE6.02'
      (
        'Test1'
        64
        False
        0
        'clWindowText'
        -11
        'Tahoma'
        0
        8
        False
        False
        False
        False
        0
        1
        0
        0
        0
        1
        0
        'clWindowText'
        -11
        'Tahoma'
        0
        8
        False
        False
        False
        False
        0
        1
        0
        'test2'
        64
        False
        0
        'clWindowText'
        -11
        'Trebuchet MS'
        0
        8
        True
        True
        False
        False
        0
        1
        0
        0
        0
        1
        0
        'clWindowText'
        -11
        'Tahoma'
        0
        8
        False
        False
        False
        False
        0
        1
        0
        ''
        '0'))
    RowHeights = (
      19
      19)
  end

Несмотря на то, что у моего компонента есть свойство Columns, основанное на классе, унаследованном от TCollection, и я добавил свойство Columns в коллекцию, которая использует унаследованные элементы, я получаю эту ошибку, когда пытаюсь открыть форму в конструкторе:

Ошибка создания формы: Ошибка чтения MyGrid1.Columns.Columns: Property Columns не существует.

Если я создаю новую копию своего компонента, а затем настраиваю столбцы, я вижу в DFM что-то совершенно другое:

Columns = <
  item
    Title = 'Test1'
    Width = 64
    Editable = False
    HeaderClipStyle = csClip
    HeaderFont.Charset = DEFAULT_CHARSET
    HeaderFont.Color = clWindowText
    HeaderFont.Height = -11
    HeaderFont.Name = 'Tahoma'
    HeaderFont.Style = []
    HeaderHAlign = haRight
    HeaderInnerBevel = bvNone
    HeaderOuterBevel = bvNone
    HeaderBorderWidth = 0
    HeaderBevelWidth = 0
    ContentsClipStyle = csClip
    ContentsFont.Charset = DEFAULT_CHARSET
    ContentsFont.Color = clWindowText
    ContentsFont.Height = -11
    ContentsFont.Name = 'Tahoma'
    ContentsFont.Style = []
    ComboFilled = False
    ComboEditable = False
  end
  item
    Title = 'test2'
    Width = 64
    Editable = False
    HeaderClipStyle = csClip
    HeaderFont.Charset = DEFAULT_CHARSET
    HeaderFont.Color = clWindowText
    HeaderFont.Height = -11
    HeaderFont.Name = 'Trebuchet MS'
    HeaderFont.Style = []
    HeaderInnerBevel = bvNone
    HeaderOuterBevel = bvNone
    HeaderBorderWidth = 0
    HeaderBevelWidth = 0
    ContentsClipStyle = csClip
    ContentsFont.Charset = DEFAULT_CHARSET
    ContentsFont.Color = clWindowText
    ContentsFont.Height = -11
    ContentsFont.Name = 'Tahoma'
    ContentsFont.Style = []
    ComboFilled = False
    ComboEditable = False
  end
  end>

Может ли кто-нибудь указать мне на некоторые статьи или пояснения, которые позволят мне написать свой собственный компонент, чтобы он мог работать со старыми DFM Delphi 2005? Спасибо.

18.07.2012

  • Я подозреваю, что вам нужно будет использовать WriteListBegin / WriteListEnd и ReadListBegin / ReadListEnd. Посмотрите, как свойства RowHeights и ColWidths обрабатываются в TCustomGrid. Посмотрите TCustomGrid.DefineProperties. 18.07.2012

Ответы:


1

Это не полный ответ, но он может помочь вам начать работу (вам нужно добавить все необходимые свойства в TColumn и реализовать их чтение / запись в _2 _ / _ 3_ методах):

unit Unit2;

interface

uses
  Classes, SysUtils, Contnrs;

type
  TColumn = class
  private
    FName: string;
    FWidth: Integer;
  public
    property Name: string read FName;
    property Width: Integer read FWidth;
  end;

  TColumns = class(TPersistent)
  private
    FItems: TObjectList;
    FOwner: TComponent;
    function GetCount: Integer;
    function GetItems(Index: Integer): TColumn;
  protected
    procedure DefineProperties(Filer: TFiler); override;
    function GetOwner: TPersistent; override;
    function ReadColumn(Reader: TReader): TColumn;
    procedure ReadColumns(Reader: TReader);
    procedure WriteColumn(Writer: TWriter; Column: TColumn);
    procedure WriteColumns(Writer: TWriter);
  public
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    property Count: Integer read GetCount;
    property Items[Index: Integer]: TColumn read GetItems; default;
  end;

  TTestComponent = class(TComponent)
  private
    FColumns: TColumns;
    procedure AddTestColumns;
    procedure SetColumns(Value: TColumns);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Columns: TColumns read FColumns write SetColumns;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Test', [TTestComponent]);
end;

{ TColumns }

function TColumns.GetCount: Integer;
begin
  Result := FItems.Count;
end;

function TColumns.GetItems(Index: Integer): TColumn;
begin
  Result := TColumn(FItems[Index]);
end;

function TColumns.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

procedure TColumns.DefineProperties(Filer: TFiler);
begin
  inherited DefineProperties(Filer);
  Filer.DefineProperty('Columns', ReadColumns, WriteColumns, Count > 0);
end;

function TColumns.ReadColumn(Reader: TReader): TColumn;
begin
  Result := TColumn.Create;
  try
    Result.FName := Reader.ReadString;
    Result.FWidth := Reader.ReadInteger;
  except
    Result.Free;
    raise;
  end;
end;

procedure TColumns.ReadColumns(Reader: TReader);
var
  Version: string;
begin
  Reader.ReadListBegin;
  Version := Reader.ReadString;
  if Version = 'OE6.02' then
  begin
    Reader.ReadListBegin;
    FItems.Clear;
    while not Reader.EndOfList do
      FItems.Add(ReadColumn(Reader));
    Reader.ReadListEnd;
  end;
  Reader.ReadListEnd;
end;

procedure TColumns.WriteColumn(Writer: TWriter; Column: TColumn);
begin
  Writer.WriteString(Column.FName);
  Writer.WriteInteger(Column.FWidth);
end;

procedure TColumns.WriteColumns(Writer: TWriter);
var
  I: Integer;
begin
  Writer.WriteListBegin;
  Writer.WriteString('OE6.02');
  Writer.WriteListBegin;
  for I := 0 to Count - 1 do
    WriteColumn(Writer, Items[I]);
  Writer.WriteListEnd;
  Writer.WriteListEnd;
end;

constructor TColumns.Create(AOwner: TComponent);
begin
  inherited Create;
  FOwner := AOwner;
  FItems := TObjectList.Create;
end;

destructor TColumns.Destroy;
begin
  FItems.Free;
  inherited Destroy;
end;

procedure TColumns.Assign(Source: TPersistent);
var
  Column: TColumn;
  I: Integer;
begin
  if Source is TColumns then
  begin
    FItems.Clear;
    for I := 0 to TColumns(Source).Count - 1 do
    begin
      Column := TColumn.Create;
      try
        Column.FName := TColumns(Source)[I].FName;
        Column.FWidth := TColumns(Source)[I].FWidth;
        FItems.Add(Column);
      except
        Column.Free;
        raise;
      end;
    end;
  end;
end;

{ TTestComponent }

procedure TTestComponent.AddTestColumns;
  procedure AddColumn(const AName: string; AWidth: Integer);
  var
    Column: TColumn;
  begin
    Column := TColumn.Create;
    try
      Column.FName := AName;
      Column.FWidth := AWidth;
      FColumns.FItems.Add(Column);
    except
      Column.Free;
      raise;
    end;
  end;
begin
  AddColumn('Test1', 64);
  AddColumn('Test2', 128);
end;

procedure TTestComponent.SetColumns(Value: TColumns);
begin
  FColumns.Assign(Value);
end;

constructor TTestComponent.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FColumns := TColumns.Create(Self);
  AddTestColumns;
end;

destructor TTestComponent.Destroy;
begin
  FColumns.Free;
  inherited Destroy;
end;

end.

Этот код дает следующий результат в формате .dfm:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 282
  ClientWidth = 418
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object TestComponent1: TTestComponent
    Columns.Columns = (
      'OE6.02'
      (
        'Test1'
        64
        'Test2'
        128))
    Left = 200
    Top = 144
  end
end
18.07.2012
  • Это прекрасно помогло прочитать информацию о свойствах столбцов из старой формы Delphi 2005. Однако, хотя изначально я использовал TCollection и TCollectionItem, которые автоматически включали редактор свойств коллекции для компонента, новая реализация не позволяет мне изменять свойства отдельных объектов столбцов через конструктор. У свойства Columns больше нет кнопки ..., когда я просматриваю сетку в инспекторе объектов. Нужно ли мне писать собственный редактор собственности? 10.04.2013
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..