我想以wordwrap格式在字符串网格单元格中显示一个长字符串,并找到以下代码:
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
//enable wordwrap in cells
var
S: String;
drawrect :trect;
begin
stringgrid1.Canvas.FillRect (Rect);
S:= (Sender As TStringgrid).Cells [ACol, ARow ];
If Length(S) > 0 Then Begin
drawrect := rect;
DrawText((Sender As TStringgrid).canvas.handle,
Pchar(S), Length(S), drawrect,
dt_calcrect or dt_wordbreak or dt_left );
If (drawrect.bottom - drawrect.top) >
(Sender As TStringgrid).RowHeights[Arow]
Then
(Sender As TStringgrid).RowHeights[Arow] :=
(drawrect.bottom - drawrect.top)
// changing the row height fires the event again!
Else Begin
drawrect.Right := rect.right;
(Sender As TStringgrid).canvas.fillrect( drawrect );
DrawText((Sender As TStringgrid).canvas.handle,
Pchar(S), Length(S), drawrect,
dt_wordbreak or dt_left);
End;
End;
end;
自动换行有效但单元格同时显示原始文本和包装文本。我假设因为这是一个onDrawCell事件,原始文本已经被绘制了,我会用第一行代码擦除它(stringgrid1.canvas.fillrect(rect),但这对显示没有影响。我是什么人丢失?
答案 0 :(得分:4)
...将用第一行代码擦除它 (stringgrid1.canvas.fillrect(rect),但这对于没有影响 显示
这是因为您在调用Brush.Style
f.ex之前未选择Brush.Color
(可能还有FillRect()
)。
stringgrid1.canvas.Brush.Style := bsSolid; // add this line
stringgrid1.canvas.Brush.Color := clWhite; // add this line
stringgrid1.Canvas.FillRect (Rect);
你会注意到单元格左边缘的默认图形中有一些残余物(在下面的图像中看不到,我已经修复了它们)。这是因为TStringGrid
内部用4个像素偏移单元格绘图。要进行更改,您需要使用-4来抵消Rect
参数的偏移,并在调用FillRect()
之前将宽度增加为+4。
经过上述更改后,网格看起来非常平坦和暗淡(在图像中我已经为第二个网格添加了颜色)。要为标题列和标题行恢复某些颜色差异,您需要使用gdFixed in State
处理不同Brush.Color
的单元格。具有gdSelected in State
的单元格相同。
如果您取消DefaultDrawing
,您还需要执行以上操作。第二个网格和附带的代码演示了这一点。请注意,该代码还包括在结束前DrawFocusRect
时调用gdFocused in State
。
请注意,我已将所有Sender as TStringGrid
替换为本地grid
变量。
procedure TForm4.StringGrid2DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
State: TGridDrawState);
var
grid: TStringGrid;
S: String;
drawrect: TRect;
bgFill: TColor;
begin
grid := Sender as TStringGrid;
if gdFixed in State then
bgFill := $FFF8F8
else
if gdSelected in State then
bgFill := $FFF0D0
else
bgFill := clWhite;
grid.Canvas.Brush.Color := bgFill;
grid.canvas.Brush.Style := bsSolid;
grid.canvas.fillrect(Rect);
S := grid.Cells[ACol, ARow];
if Length(S) > 0 then
begin
drawrect := Rect;
drawrect.Inflate(-4 , 0);
DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
dt_calcrect or dt_wordbreak or dt_left);
If (drawrect.bottom - drawrect.top) > grid.RowHeights[ARow] then
grid.RowHeights[ARow] := (drawrect.bottom - drawrect.top+2)
// changing the row height fires the event again!
else
begin
drawrect.Right := Rect.Right;
// grid.canvas.fillrect(drawrect);
DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
dt_wordbreak or dt_left);
end;
end;
if gdFocused in State then
grid.Canvas.DrawFocusRect(Rect);
end;
第三个网格演示最简单,IMO是最佳解决方案,完全跳过TStringGrid
并改为使用TDrawGrid
。您必须在某处单独保留要在网格中显示的数据。我定义了一个数组:s_arr: array of array of string;
。
在这种情况下,您可以启用DefaultDrawing
,因为TDrawGrid
在默认绘图期间不会绘制任何文字,内容绘制仅在OnDrawCell
事件中进行。
procedure TForm4.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
State: TGridDrawState);
var
S: string;
grid: TDrawGrid;
drawrect: TRect;
begin
grid := Sender as TDrawGrid;
S := s_arr[ACol, ARow];
If Length(S) > 0 Then
Begin
drawrect := Rect;
drawrect.Inflate(-4 , 0);
DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
dt_calcrect or dt_wordbreak or dt_left);
If (drawrect.bottom - drawrect.top) > grid.RowHeights[ARow] Then
grid.RowHeights[ARow] := (drawrect.bottom - drawrect.top + 2)
// changing the row height fires the event again!
Else
Begin
drawrect.Right := Rect.Right;
grid.canvas.fillrect(drawrect);
DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect, dt_wordbreak or dt_left);
End;
End;
end;
离开DefaultDrawing
,所有这些与主题相关的功能都由网格本身绘制,我们只在顶部绘制文字。