我正在尝试编写自定义日期选择器(日历)。日期将显示在stringgrid上。我试图用自定义颜色填充单击的单元格,并使选定的单元格文本变为粗体。
这是我的代码:
type
TStringGrid = Class(Vcl.Grids.TStringGrid)
private
FHideFocusRect: Boolean;
protected
Procedure Paint;override;
public
Property HideFocusRect:Boolean Read FHideFocusRect Write FHideFocusRect;
End;
TfrmNepaliCalendar = class(TForm)
...
...
...
end;
procedure TfrmNepaliCalendar.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if gdSelected in State then begin
StringGrid.Canvas.Brush.Color := $00940A4B;
StringGrid.Canvas.FillRect(Rect);
StringGrid.Canvas.Font.Style := [fsBold];
StringGrid.Canvas.Font.Color := clHighlightText;
StringGrid.Canvas.TextOut(Rect.Left + 3, Rect.Top + 5, StringGrid.Cells[ACol,ARow]);
StringGrid.HideFocusRect := True;
end;
end;
{ TStringGrid }
procedure TStringGrid.Paint;
var
LRect: TRect;
begin
inherited;
if HideFocusRect then begin
LRect := CellRect(Col,Row);
if DrawingStyle = gdsThemed then InflateRect(LRect,-1,-1);
DrawFocusrect(Canvas.Handle,LRect)
end;
end;
输出,我得到了:
问题#1:我需要隐藏显示为所选单元格边框的不需要的矩形
问题#2:避免细胞背景剪辑
答案 0 :(得分:3)
在OnDrawCell程序中,在FillRect
Rect.Left := Rect.Left-4;
似乎工作。
替代
即使使用您的绘图程序插件,上述内容也无法完全解决焦点问题。有时在单元格边框内可以看到白线。
但以下是另一种解决方案,可以解决您的问题。它需要更多的编码,但不是那么多。另一方面,不需要子类化TStringGrid,Rect
调整
基础是禁用默认绘图,因此设置网格属性DefaultDrawing := false;
然后添加到OnDrawCell事件:
procedure TForm1.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if gdFixed in State then
begin
StringGrid.Canvas.Brush.Color := clGradientInactiveCaption;
StringGrid.Canvas.Font.Style := [];
StringGrid.Canvas.Font.Color := clBlack;
end
else
if gdSelected in State then
begin
StringGrid.Canvas.Brush.Color := $00940A4B;
StringGrid.Canvas.Font.Style := [fsBold];
StringGrid.Canvas.Font.Color := clHighlightText;
end
else
begin
StringGrid.Canvas.Brush.Color := $00FFFFFF;
StringGrid.Canvas.Font.Style := [];
StringGrid.Canvas.Font.Color := clWindowText;
end;
StringGrid.Canvas.FillRect(Rect);
StringGrid.Canvas.TextOut(Rect.Left + 3, Rect.Top + 5, StringGrid.Cells[ACol,ARow]);
end;
禁用默认绘图后,网格将绘制网格框架和网格线,但将所有其他绘图留给程序员。需要注意的是,如果需要,您必须自己添加精美的主题绘图。 通过以上编码,我得到了这个结果:
答案 1 :(得分:2)
我假设您(想)使用默认的DefaultDrawing = True
设置,否则您的问题不存在。
要摆脱焦点矩形,你需要再次绘制它(因为它是一个XOR操作,焦点矩形将消失),或者阻止它被绘制。
使用OnDrawCell
事件再次绘图:
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if gdFocused in State then
DrawFocusRect(StringGrid1.Canvas.Handle, Rect);
end;
完全阻止它绘制,例如通过禁用将焦点设置为StringGrid的可能性来完成。我假设你没有使用它的编辑器,因此不应该给出任何进一步的可用性问题。
type
TStringGrid = class(Vcl.Grids.TStringGrid)
public
function CanFocus: Boolean; override;
end;
function TStringGrid.CanFocus: Boolean;
begin
Result := False;
end;
这实际上是一个有点奇怪的工作解决方案,因为你仍然能够进入控件并且它会一直响应键盘事件。
我无法使用此代码重现您的剪辑问题(此处为XE2):
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if gdSelected in State then
begin
StringGrid1.Canvas.Brush.Color := $00940A4B;
StringGrid1.Canvas.FillRect(Rect);
StringGrid1.Canvas.Font.Style := [fsBold];
StringGrid1.Canvas.Font.Color := clHighlightText;
StringGrid1.Canvas.TextOut(Rect.Left + 3, Rect.Top + 5,
StringGrid1.Cells[ACol, ARow]);
end;
end;
Rect
将是正确的 CellRect
。剪辑效果是由其他地方的其他因素造成的。
但是,如果XE8的源代码中存在虚假的+4
,例如Tom Brunberg mentions,这很容易被-4
克服,那么这显然是一个错误,应该报告。