Выравнивание колонок StringGrid
Выравнивание колонок StringGrid Автор: Kurt
Организуйте обработчик события сетки OnDrawCell. Создайте код обработчика подобный этому:
Rect: TRect; State: TGridDrawState);
var
Txt: array[0..255] of Char;
begin
StrPCopy(Txt, StringGrid1.Cells[Col, Row]);
SetTextAlign(StringGrid1.Canvas.Handle,
GetTextAlign(StringGrid1.Canvas.Handle)
and not (TA_LEFT or TA_CENTER) or TA_RIGHT);
ExtTextOut(StringGrid1.Canvas.Handle, Rect.Right - 2, Rect. + 2,
ETO_CLIPPED or ETO_OPAQUE, @Rect, Txt, StrLen(Txt), nil);
end;
http://delphiworld.narod.ru/ DelphiWorld 6.0
Нижеприведенный код выравняет данные компонента по правому краю:
Longint; Rect: TRect; State: TGridDrawState);
var
lRow, lCol: Longint;
begin
lRow := Row;
lCol := Col;
with Sender as TStringGrid, Canvas do
begin
if (gdSelected in State) then
begin
Brush.Color := clHighlight;
end
else if (gdFixed in State) then
begin
Brush.Color := FixedColor;
end
else
begin
Brush.Color := Color;
end;
FillRect(Rect);
SetBkMode(Handle, TRANSPARENT);
SetTextAlign(Handle, TA_RIGHT);
TextOut(Rect.Right - 2, Rect. + 2, Cells[lCol, lRow]);
end;
end;
Хитрость заключается в установке выравнивания текста TA_RIGHT, позволяющей осуществлять вывод текста, начиная с правой стороны (от правой границы). Не бойтесь, текст не будет напечатан задом наперед!
Вы наверное уже обратили внимание на объявление локальных переменных lCol и lRow. На входе я присваиваю им значения параметров Col и Row (имя, которое дало мне Delphi IDE). Дело в том, что объект TStringGrid имеет свойства с именами Col и Row. Эти свойства будут доступны в теле блока "with Sender as TStringGrid", но они не являются параметрами для всех обявленных в шапке блока объектов ((речь идет об объекте Canvas, у которого нет свойств с именами Col и Row - В.О.)).
http://delphiworld.narod.ru/ DelphiWorld 6.0
const Text: string; Format: Word);
var
S: array[0..255] of Char;
B, R: TRect;
begin
with ACanvas, ARect do
begin
case Format of
DT_LEFT: ExtTextOut(Handle, Left + DX, + DY, ETO_OPAQUE or
ETO_CLIPPED,
@ARect, StrPCopy(S, Text), Length(Text), nil);
DT_RIGHT: ExtTextOut(Handle, Right - TextWidth(Text) - 3, + DY,
ETO_OPAQUE or ETO_CLIPPED, @ARect, StrPCopy(S, Text),
Length(Text), nil);
DT_CENTER: ExtTextOut(Handle, Left + (Right - Left - TextWidth(Text)) div
2,
+ DY, ETO_OPAQUE or ETO_CLIPPED, @ARect,
StrPCopy(S, Text), Length(Text), nil);
end;
end;
end;
procedure TBEFStringGrid.DrawCell(Col, Row: Longint; Rect: TRect; State:
TGridDrawState);
var
procedure Display(const S: string; Alignment: TAlignment);
const
Formats: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
WriteText(Canvas, Rect, 2, 2, S, Formats[Alignment]);
end;
begin
{ здесь задаем аргументы Col и Row, и форматируем как угодно ячейки }
case Row of
0: { Центрирование заголовков колонок }
if (Col < ColCount) then
Display(Cells[Col, Row], taCenter)
else
{ Все другие данные имеют правое центрирование }
Display(Cells[Col, Row], taRight);
end;
end;
http://delphiworld.narod.ru/ DelphiWorld 6.0
Создайте ваш собственный метод drawcell на примере того, что приведен ниже:
Rect: TRect; State: TGridDrawState);
var
l_oldalign: word;
begin
if (row = 0) or (col < 2) then
{устанавливаем заголовок в жирном начертании}
grid1.canvas.font.style := grid1.canvas.font.style + [fsbold];
if col <> 1 then
begin
l_oldalign := settextalign(grid1.canvas.handle, ta_right);
{NB использует для рисования правую сторону квадрата}
grid1.canvas.textrect(rect, rect.right - 2, Rect.top + 2, grid1.cells[col,
row]);
settextalign(grid1.canvas.handle, l_oldalign);
end
else
begin
grid1.canvas.textrect(rect, rect.left + 2, rect.top + 2, grid1.cells[col,
row]);
end;
grid1.canvas.font.style := grid1.canvas.font.style - [fsbold];
end;
http://delphiworld.narod.ru/ DelphiWorld 6.0
Автор: 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. atWrap - Вывод и перенос текста по словам относительно верхней границы
ячейки;
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, atWrap, 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.);
LineTo(ARect.Left, ARect.Bottom);
MoveTo(ARect.Left, ARect.);
LineTo(ARect.Right, ARect.);
Pen.Color := clBlack;
MoveTo(ARect.Left, ARect.Bottom);
LineTo(ARect.Right, ARect.Bottom);
MoveTo(ARect.Right, ARect.);
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., 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;
atWrap:
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. - MassCurYDef) div 2;
CountWord := 0;
MeanCurY := 0;
while CountWord <= CountI do
begin
MassCurY[CountWord] := ARect. + 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. + 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. + 2) then
Continue;
{ выводим слово }
TextOut(MassCurX[CountWord], MassCurY[CountWord],
MassWord[CountWord]);
end;
end;
VisualCanvas;
end;
end;
end;
begin
VisualBox;
VisualCanvas;
{ Начинаем рисование с верхнего левого угла ячейки }
CurXDef := ARect.Left;
CurYDef := ARect.;
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.
http://delphiworld.narod.ru/ DelphiWorld 6.0
Отправить комментарий