Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Выравнивание колонок StringGrid 5

Delphi , Компоненты и Классы , TStringGrid и TDrawGrid

Выравнивание колонок StringGrid 5

Автор: Pavel Stont


{
Код компонента для Delphi на основе стандартного TStringGrid.

Компонет позволяет переносить текст в TStringGrid.

В качестве исходного текста был использован компонент TWrapGrid.
Автор Luis J. de la Rosa.
E-mail: delarosa@ix.netcom.com
Вы свободны в использовании, распространении и улучшении кода.
Пожалуйста шлите любые комментарии и пожелания на адрес delarosa@ix.netcom.com.

Далее были внесены изменения в исходный код, а именно добавлены методы вывода
текста:
1. atLeft - Вывод текста по левой границе;
2. atCenter - Вывод текста по центру ячейки (по горизонтали);
3. atRight - Вывод текста по правой границе;
4. atWrapTop - Вывод и перенос текста по словам относительно верхней границы
ячейки;
5. atWrapCenter - Вывод и перенос текста по словам относительно центра ячейки
(по вертикали);
6. atWrapBottom - Вывод и перенос текста по словам относительно нижней границы
ячейки;

Вносил изменения и тестировал в Delphi 3/4/5:
Автор Pavel Stont.
E-mail: pavel_stont@mail.ru.
Никаких ограничений на использование, распростанение и улучшение кода не налогаются.
Буду очень признателен, если о всех замеченных неполадках сообщите по e-mail.

Для использования:
Выберите в Delphi пункты меню 'Options' - 'Install Components'.
Нажмите 'Add'.
Найдите и выберите файл с именем 'NewStringGrid.pas'.
Нажмите 'OK'.
После этого вы увидете компонент во вкладке "Other" палитры компонентов
Delphi.
После этого вы можете использовать компонент вместо стандартного TStringGrid.

Успехов!

Несколько дополнительных замечаний по коду:
1. Методы Create и DrawCell были перекрыты.
2. Введены два новых свойства, а именно AlignText и AlignCaption соответсвенно методы
выравнивания текста в ячейках данных (обычно - белого цвета) и в фиксированных ячейках
(обычно - серого цвета).
3. Свойство Center - центрация текста по горизонтали независимо от метода.
}

unit NewStringGrid;

interface

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids;

type

  TAlignText = (atLeft, atCenter, atRight, atWrapTop, atWrapCenter,
    atWrapBottom);

type

  TNewStringGrid = class(TStringGrid)
  private
    { Private declarations }
    FAlignText: TAlignText;
    FAlignCaption: TAlignText;
    FCenter: Boolean;
    procedure SetAlignText(Value: TAlignText);
    procedure SetAlignCaption(Value: TAlignText);
    procedure SetCenter(Value: Boolean);
  protected
    { Protected declarations }
    procedure DrawCell(ACol, ARow: Longint; ARect: TRect;
      AState: TGridDrawState); override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
  published
    { Published declarations }
    property AlignText: TAlignText read FAlignText write SetAlignText;
    property AlignCaption: TAlignText read FAlignCaption write SetAlignCaption;
    property Center: Boolean read FCenter write SetCenter;
  end;

procedure Register;

implementation

procedure Register;
begin

  RegisterComponents('Other', [TNewStringGrid]);
end;

{ TNewStringGrid }

constructor TNewStringGrid.Create(AOwner: TComponent);
begin

  { Создаем TStringGrid }
  inherited Create(AOwner);
  { Задаем начальные параметры компонента }
  AlignText := atLeft;
  AlignCaption := atCenter;
  Center := False;
  DefaultColWidth := 80;
  DefaultRowHeight := 18;
  Height := 100;
  Width := 408;
  { Заставляем компонент перерисовываться нашей процедурой
  по умолчанию DrawCell }
  DefaultDrawing := FALSE;
end;

{ Процедура DrawCell осуществляет перенос текста в ячейке }

procedure TNewStringGrid.DrawCell(ACol, ARow: Integer; ARect: TRect;

  AState: TGridDrawState);
var

  CountI, { Счетчик }
  CountWord: Integer; { Счетчик }
  Sentence, { Выводимый текст }
  CurWord: string; { Текущее выводимое слово }
  SpacePos, { Позиция первого пробела }
  CurXDef, { X-координата 'курсора' по умолчанию }
  CurYDef, { Y-координата 'курсора' по умолчанию }
  CurX, { Х-координата 'курсора' }
  CurY: Integer; { Y-координата 'курсора' }
  EndOfSentence: Boolean; { Величина, указывающая на заполненность ячейки }
  Alig: TAlignText; { Тип выравнивания текста }
  ColPen: TColor; { Цвет карандаша по умолчанию }
  MassWord: array[0..255] of string;
  MassCurX, MassCurY: array[0..255] of Integer;
  LengthText: Integer; { Длина текущей строки }
  MassCurYDef: Integer;
  MeanCurY: Integer;

  procedure VisualCanvas;
  begin
    { Прорисовываем ячейку и придаем ей 3D-вид }
    with Canvas do
    begin
      { Запоминаем цвет пера для последующего вывода текста }
      ColPen := Pen.Color;
      if gdFixed in AState then
      begin
        Pen.Color := clWhite;
        MoveTo(ARect.Left, ARect.Top);
        LineTo(ARect.Left, ARect.Bottom);
        MoveTo(ARect.Left, ARect.Top);
        LineTo(ARect.Right, ARect.Top);
        Pen.Color := clBlack;
        MoveTo(ARect.Left, ARect.Bottom);
        LineTo(ARect.Right, ARect.Bottom);
        MoveTo(ARect.Right, ARect.Top);
        LineTo(ARect.Right, ARect.Bottom);
      end;
      { Восстанавливаем цвет пера }
      Pen.Color := ColPen;
    end;
  end;

  procedure VisualBox;
  begin
    { Инициализируем шрифт, чтобы он был управляющим шрифтом }
    Canvas.Font := Font;
    with Canvas do
    begin
      { Если это фиксированная ячейка, тогда используем фиксированный цвет }
      if gdFixed in AState then
      begin
        Pen.Color := FixedColor;
        Brush.Color := FixedColor;
      end
        { в противном случае используем нормальный цвет }
      else
      begin
        Pen.Color := Color;
        Brush.Color := Color;
      end;
      { Рисуем подложку цветом ячейки }
      Rectangle(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
    end;
  end;

  procedure VisualText(Alig: TAlignText);
  begin
    case Alig of
      atLeft:
        begin
          with Canvas do
            { выводим текст }
            TextOut(CurX, CurY, Sentence);
          VisualCanvas;
        end;
      atRight:
        begin
          with Canvas do
            { выводим текст }
            TextOut(ARect.Right - TextWidth(Sentence) - 2, CurY, Sentence);
          VisualCanvas;
        end;
      atCenter:
        begin
          with Canvas do
            { выводим текст }
            TextOut(ARect.Left + ((ARect.Right - ARect.Left -
              TextWidth(Sentence)) div 2), CurY, Sentence);
          VisualCanvas;
        end;
      atWrapTop:
        begin
          { для каждого слова ячейки }
          EndOfSentence := FALSE;
          CountI := 0;
          while CountI <= SpacePos do
          begin
            MassWord[CountI] := '';
            CountI := CountI + 1;
          end;
          CountI := 0;
          CountWord := CurY;
          while (not EndOfSentence) do
          begin
            { для получения следующего слова ищем пробел }
            SpacePos := Pos(' ', Sentence);
            if SpacePos > 0 then
            begin
              { получаем текущее слово плюс пробел }
              CurWord := Copy(Sentence, 0, SpacePos);
              { получаем остальную часть предложения }
              Sentence := Copy(Sentence, SpacePos + 1, Length(Sentence) -
                SpacePos);
            end
            else
            begin
              { это - последнее слово в предложении }
              EndOfSentence := TRUE;
              CurWord := Sentence;
            end;
            with Canvas do
            begin
              { если текст выходит за границы ячейки }
              LengthText := TextWidth(CurWord) + CurX + 2;
              if LengthText > ARect.Right then
              begin
                { переносим на следующую строку }
                CurY := CurY + TextHeight(CurWord);
                CurX := CurXDef + 2;
              end;
              if CountWord <> CurY then
                CountI := CountI + 1;
              MassWord[CountI] := MassWord[CountI] + CurWord;
              { увеличиваем X-координату курсора }
              CurX := CurX + TextWidth(CurWord);
              CountWord := CurY;
            end;
          end;
          with Canvas do
          begin
            CountWord := 0;
            CurY := CurYDef + 2;
            CurX := CurXDef + 2;
            while CountWord <= CountI do
            begin
              case Center of
                True:
                  begin
                    CurWord := MassWord[CountWord];
                    if Copy(CurWord, Length(CurWord) - 1, 1) = ' ' then
                      MassWord[CountWord] := Copy(CurWord, 0, Length(CurWord) -
                        1);
                    MassCurX[CountWord] := ARect.Left + ((ARect.Right -
                      ARect.Left - TextWidth(MassWord[CountWord])) div 2);
                    MassWord[CountWord] := CurWord;
                  end;
                False: MassCurX[CountWord] := CurX;
              end;
              MassCurY[CountWord] := CurY;
              { выводим слово }
              TextOut(MassCurX[CountWord], MassCurY[CountWord],
                MassWord[CountWord]);
              CurY := CurY + TextHeight(MassWord[CountWord]);
              CountWord := CountWord + 1;
            end;
          end;
          VisualCanvas;
        end;
      atWrapCenter:
        begin
          { для каждого слова ячейки }
          EndOfSentence := FALSE;
          CountI := 0;
          while CountI <= SpacePos do
          begin
            MassWord[CountI] := '';
            CountI := CountI + 1;
          end;
          CountI := 0;
          CountWord := CurY;
          while (not EndOfSentence) do
          begin
            { для получения следующего слова ищем пробел }
            SpacePos := Pos(' ', Sentence);
            if SpacePos > 0 then
            begin
              { получаем текущее слово плюс пробел }
              CurWord := Copy(Sentence, 0, SpacePos);
              { получаем остальную часть предложения }
              Sentence := Copy(Sentence, SpacePos + 1, Length(Sentence) -
                SpacePos);
            end
            else
            begin
              { это - последнее слово в предложении }
              EndOfSentence := TRUE;
              CurWord := Sentence;
            end;
            with Canvas do
            begin
              { если текст выходит за границы ячейки }
              LengthText := TextWidth(CurWord) + CurX + 2;
              if LengthText > ARect.Right then
              begin
                { переносим на следующую строку }
                CurY := CurY + TextHeight(CurWord);
                CurX := CurXDef + 2;
              end;
              if CountWord <> CurY then
                CountI := CountI + 1;
              MassWord[CountI] := MassWord[CountI] + CurWord;
              { увеличиваем X-координату курсора }
              CurX := CurX + TextWidth(CurWord);
              CountWord := CurY;
            end;
          end;
          with Canvas do
          begin
            CountWord := 0;
            CurX := CurXDef + 2;
            while CountWord <= CountI do
            begin
              case Center of
                True:
                  begin
                    CurWord := MassWord[CountWord];
                    if Copy(CurWord, Length(CurWord) - 1, 1) = ' ' then
                      MassWord[CountWord] := Copy(CurWord, 0, Length(CurWord) -
                        1);
                    MassCurX[CountWord] := ARect.Left + ((ARect.Right -
                      ARect.Left - TextWidth(MassWord[CountWord])) div 2);
                    MassWord[CountWord] := CurWord;
                  end;
                False: MassCurX[CountWord] := CurX;
              end;
              MassCurY[CountWord] := TextHeight(MassWord[CountWord]);
              CountWord := CountWord + 1;
            end;
            CountWord := 0;
            MassCurYDef := 0;
            while CountWord <= CountI do
            begin
              MassCurYDef := MassCurYDef + MassCurY[CountWord];
              CountWord := CountWord + 1;
            end;
            MassCurYDef := (ARect.Bottom - ARect.Top - MassCurYDef) div 2;
            CountWord := 0;
            MeanCurY := 0;
            while CountWord <= CountI do
            begin
              MassCurY[CountWord] := ARect.Top + MeanCurY + MassCurYDef;
              MeanCurY := MeanCurY + TextHeight(MassWord[CountWord]);
              CountWord := CountWord + 1;
            end;
            CountWord := -1;
            while CountWord <= CountI do
            begin
              CountWord := CountWord + 1;
              if MassCurY[CountWord] < (ARect.Top + 2) then
                Continue;
              { выводим слово }
              TextOut(MassCurX[CountWord], MassCurY[CountWord],
                MassWord[CountWord]);
            end;
          end;
          VisualCanvas;
        end;
      atWrapBottom:
        begin
          { для каждого слова ячейки }
          EndOfSentence := FALSE;
          CountI := 0;
          while CountI <= SpacePos do
          begin
            MassWord[CountI] := '';
            CountI := CountI + 1;
          end;
          CountI := 0;
          CountWord := CurY;
          while (not EndOfSentence) do
          begin
            { для получения следующего слова ищем пробел }
            SpacePos := Pos(' ', Sentence);
            if SpacePos > 0 then
            begin
              { получаем текущее слово плюс пробел }
              CurWord := Copy(Sentence, 0, SpacePos);
              { получаем остальную часть предложения }
              Sentence := Copy(Sentence, SpacePos + 1, Length(Sentence) -
                SpacePos);
            end
            else
            begin
              { это - последнее слово в предложении }
              EndOfSentence := TRUE;
              CurWord := Sentence;
            end;
            with Canvas do
            begin
              { если текст выходит за границы ячейки }
              LengthText := TextWidth(CurWord) + CurX + 2;
              if LengthText > ARect.Right then
              begin
                { переносим на следующую строку }
                CurY := CurY + TextHeight(CurWord);
                CurX := CurXDef + 2;
              end;
              if CountWord <> CurY then
                CountI := CountI + 1;
              MassWord[CountI] := MassWord[CountI] + CurWord;
              { увеличиваем X-координату курсора }
              CurX := CurX + TextWidth(CurWord);
              CountWord := CurY;
            end;
          end;
          with Canvas do
          begin
            CountWord := 0;
            CurX := CurXDef + 2;
            while CountWord <= CountI do
            begin
              case Center of
                True:
                  begin
                    CurWord := MassWord[CountWord];
                    if Copy(CurWord, Length(CurWord) - 1, 1) = ' ' then
                      MassWord[CountWord] := Copy(CurWord, 0, Length(CurWord) -
                        1);
                    MassCurX[CountWord] := ARect.Left + ((ARect.Right -
                      ARect.Left - TextWidth(MassWord[CountWord])) div 2);
                    MassWord[CountWord] := CurWord;
                  end;
                False: MassCurX[CountWord] := CurX;
              end;
              MassCurY[CountWord] := TextHeight(MassWord[CountWord]);
              CountWord := CountWord + 1;
            end;
            CountWord := 0;
            MassCurYDef := 0;
            while CountWord <= CountI do
            begin
              MassCurYDef := MassCurYDef + MassCurY[CountWord];
              CountWord := CountWord + 1;
            end;
            MassCurYDef := ARect.Bottom - MassCurYDef - 2;
            CountWord := 0;
            MeanCurY := -MassCurY[CountWord];
            while CountWord <= CountI do
            begin
              MeanCurY := MeanCurY + MassCurY[CountWord];
              MassCurY[CountWord] := MassCurYDef + MeanCurY;
              CountWord := CountWord + 1;
            end;
            CountWord := -1;
            while CountWord <= CountI do
            begin
              CountWord := CountWord + 1;
              if MassCurY[CountWord] < (ARect.Top + 2) then
                Continue;
              { выводим слово }
              TextOut(MassCurX[CountWord], MassCurY[CountWord],
                MassWord[CountWord]);
            end;
          end;
          VisualCanvas;
        end;
    end;
  end;

begin

  VisualBox;
  VisualCanvas;
  { Начинаем рисование с верхнего левого угла ячейки }

  CurXDef := ARect.Left;
  CurYDef := ARect.Top;
  CurX := CurXDef + 2;
  CurY := CurYDef + 2;
  { Здесь мы получаем содержание ячейки }

  Sentence := Cells[ACol, ARow];
  { Если ячейка пуста выходим из процедуры }

  if Sentence = '' then
    Exit;
  { Проверяем длину строки (не более 256 символов) }

  if Length(Sentence) > 256 then
  begin
    MessageBox(0, 'Число символов не должно быть более 256.',
      'Ошибка в таблице', mb_OK);
    Cells[ACol, ARow] := '';
    Exit;
  end;
  { Узнаем сколько в предложении слов и задаем размерность массивов }

  SpacePos := Pos(' ', Sentence);
  { Узнаем тип выравнивания текста }

  if gdFixed in AState then
    Alig := AlignCaption
  else
    Alig := AlignText;
  VisualText(Alig);
end;

procedure TNewStringGrid.SetAlignCaption(Value: TAlignText);
begin
  if Value <> FAlignCaption then
    FAlignCaption := Value;
end;

procedure TNewStringGrid.SetAlignText(Value: TAlignText);
begin
  if Value <> FAlignText then
    FAlignText := Value;
end;

procedure TNewStringGrid.SetCenter(Value: Boolean);
begin
  if Value <> FCenter then
    FCenter := Value;
end;

end.

Это компонент Delphi, конкретно custom grid control, называемый TNewStringGrid, который расширяет стандартный компонент TStringGrid. Код добавляет дополнительную функциональность для выравнивания текста в ячейках.

Обзор изменений:

  1. Новые свойства:
    • AlignText: определяет выравнивание текста в ячейках с данными.
    • AlignCaption: определяет выравнивание текста в фиксированных ячейках (например, заголовках).
    • Center: булевое свойство, которое determines whether the text should be centered horizontally.
  2. Переопределенные методы:
    • Create: инициализирует компонент с 기본ными значениями.
    • DrawCell: переопределяет стандартный метод рисования для предоставления custom text alignment and wrapping.

Метод DrawCell responsible for rendering the cell content. Он учитывает свойства AlignText, AlignCaption и Center для определения, как текст должен быть выравнен в ячейке.

Разбивка метода DrawCell:

  1. Инициализация:
    • Устанавливает канвас, шрифт и цвета.
  2. Выравнивание текста и обрезка:
    • В зависимости от свойства AlignText, текст выравнивается слева, по центру или справа в ячейке.
    • Если текст слишком длинный для одного ряда, он обрезается до следующего ряда с помощью процедуры VisualText.
  3. Фиксированные ячейки (заголовки):
    • Если ячейка является фиксированной (например, заголовком), используется свойство AlignCaption для выравнивания.

Процедура VisualText responsible for rendering the wrapped text within the cell. Она учитывает свойство Center для определения, должен ли текст быть центрирован горизонтально.

В целом, этот custom grid control provides more flexibility in terms of text alignment and wrapping, making it useful for creating more complex and visually appealing user interfaces.

Обратите внимание, что есть некоторые ограничения и потенциальные проблемы с этим кодом:

  • Механизм обрезки текста может не работать хорошо для очень длинных текстов или когда ячейка слишком узкая.
  • Нет поддержки праворучных языков (RTL) или bidirectional text.
  • Компонент может не быть совместимым с некоторыми версиями Delphi.

Чтобы использовать этот компонент, вам нужно зарегистрировать его в вашем проекте Delphi, добавив ссылку на unit NewStringGrid и создавая экземпляр TNewStringGrid.

Выравнивание колонок StringGrid 5: компонент позволяющий переносить текст в TStringGrid, с возможностью выравнивания текста по левому краю, центру или правому краю ячейки, а также при необходимости - по словам.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: TStringGrid и TDrawGrid ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-16 03:25:21/0.0075159072875977/0