скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Выравнивание колонок 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.






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook