Pavel Stont предлагает свой вариант TStringGrid'а с выравниванием строк:
{ Код компонента для 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. |
[001796]