type
TForm2 = class(TForm)
Button1: TButton;
DBGrid1: TDBGrid;
private
{ Private declarations }
function ColorFilter(AColor: TColor): TColor;
function FillBMPGradient(var ABMP: TBitmap; ACol1, ACol2: TColor; AWidth,
AHeight: integer; AVertical: Boolean = true): Boolean;
public
{ Public declarations }
procedure GenerateBitmap;
function GrayScaleColor(AColor: TColor): TColor;
end;
uses
Vcl.Themes, VCL.GraphUtil;
//in real life this is field of class, but to simplify - i move it to VAR
var
//Lot of precached bitmaps for future drawing of cell background
FParLine, FNParLine, FSelLine, FGroupCell,
FSelCell, FFixedLine, FGutter,
FFixedSortCol, FSelGutter : TBitmap;
//lot of precached colors
FTitleFontColor, FSelectedFontColor, FCellFontColor,
FBorderCellColor, FBorderSelCellColor, FBorderTitleCellColor,
FBorderGutterCellColor, FBackGrountColor : TColor;
//function for make color gray
function TForm2.GrayScaleColor(AColor: TColor): TColor;
var
xGray : byte;
begin
xGray := Round((0.299 * GetRValue(AColor)) + (0.587 * GetGValue(AColor)) + (0.114 * GetBValue(AColor)));
Result:= RGB(xGray, xGray, xGray);
end;
//function make colors gray of not, depends of Enable property of Grid
function TForm2.ColorFilter(AColor : TColor) : TColor;
begin
if not Enabled then begin
Result := GrayScaleColor(AColor)
end else begin
Result := AColor;
end;
end;
function TForm2.FillBMPGradient(var ABMP: TBitmap; ACol1,
ACol2: TColor; AWidth, AHeight: integer; AVertical: Boolean): Boolean;
begin
ACol1 := ColorFilter(ACol1);
ACol2 := ColorFilter(ACol2);
if not Assigned(ABMP) then
ABMP := TBitmap.create();
if (AWidth <> 0) and (AWidth <> ABMP.Width) then
ABMP.Width := AWidth;
if (AHeight <> 0) and (AHeight <> ABMP.Height) then
ABMP.Height := AHeight;
if AVertical then
Vcl.GraphUtil.GradientFillCanvas(ABMP.Canvas, ACol1, ACol2, ABMP.Canvas.ClipRect, gdVertical)
else
Vcl.GraphUtil.GradientFillCanvas(ABMP.Canvas, ACol1, ACol2, ABMP.Canvas.ClipRect, gdHorizontal);
end;
//this procedure generate bitmaps cache
procedure TForm2.GenerateBitmap;
const
CFixedStates: array[Boolean, Boolean] of TThemedGrid = (
(tgFixedCellNormal, tgFixedCellPressed),
(tgFixedCellHot, tgFixedCellPressed));
CFixedGradientStates: array[Boolean, Boolean] of TThemedGrid = (
(tgGradientFixedCellNormal, tgGradientFixedCellPressed),
(tgGradientFixedCellHot, tgGradientFixedCellPressed));
CFixedClassicStates: array[Boolean, Boolean] of TThemedGrid = (
(tgClassicFixedCellNormal, tgClassicFixedCellPressed),
(tgClassicFixedCellHot, tgClassicFixedCellPressed));
CNormalStates: array[Boolean] of TThemedGrid = (
tgCellNormal, tgCellSelected);
CNormalGradientStates: array[Boolean] of TThemedGrid = (
tgGradientCellNormal, tgGradientCellSelected);
CNormalClassicStates: array[Boolean] of TThemedGrid = (
tgClassicCellNormal, tgClassicCellSelected);
var
LStyle: TCustomStyleServices;
LColor : TColor;
LDetails: TThemedElementDetails;
FUseStyle : boolean;
xCol1, xCol2 : TColor;
function UseTheme : boolean;
begin
Result := FUseStyle;
end{function UseTheme};
procedure MyDraw(var ABitmap : TBitmap; ADetails : TThemedElementDetails; AWidth : integer = 160; AHeight : integer = 16);
var
i : integer;
begin
if not Assigned(ABitmap) then begin
ABitmap := TBitmap.Create;
ABitmap.SetSize(AWidth, AHeight);
i := SaveDC(ABitmap.Canvas.Handle);
try
LStyle.DrawElement(ABitmap.Canvas.Handle, LDetails, Rect(0, 0, AWidth, AHeight));
finally
RestoreDC(ABitmap.Canvas.Handle, i);
end{finally};
end{if};
end;
begin
////////////////////
//Fill Bitmap
LStyle := StyleServices;
FUseStyle := (not LStyle.IsSystemStyle) and LStyle.Enabled and (seClient in DBGrid1.StyleElements);
if UseTheme then begin
if not LStyle.GetElementColor(LStyle.GetElementDetails(tgCellNormal), ecTextColor, FCellFontColor) or
(FCellFontColor = clNone) then
FCellFontColor := clHighlightText;
if not LStyle.GetElementColor(LStyle.GetElementDetails(tgCellSelected), ecTextColor, FSelectedFontColor) or
(FSelectedFontColor = clNone) then
FSelectedFontColor := clHighlightText;
if not LStyle.GetElementColor(LStyle.GetElementDetails(tgFixedCellNormal), ecTextColor, FTitleFontColor) or
(FTitleFontColor = clNone) then
FTitleFontColor := clHighlightText;
end else begin
FCellFontColor := clBlack;//clBlack;
FSelectedFontColor := clWhite;
FTitleFontColor := clBlack;//clBlack;
end{if..else};
//FFixedSortCol
if UseTheme then begin
LDetails := LStyle.GetElementDetails(CFixedStates[true{(gdHotTrack in AState)},true{ (gdPressed in AState)}]);
MyDraw(FFixedSortCol, LDetails);
end else begin
xCol1 := B1a0a1bE0FCFC;
xCol2 := B1a0a1b9EF3F3;
FillBMPGradient(FFixedSortCol, xCol1, xCol2, 16, 16);
end{if..else};
//Fixed line
if UseTheme then begin
LDetails := LStyle.GetElementDetails(CFixedStates[false{(gdHotTrack in AState)},false{ (gdPressed in AState)}]);
MyDraw(FFixedLine, LDetails);
LStyle.GetElementColor(LStyle.GetElementDetails(tgFixedCellNormal), ecBorderColor, FBorderTitleCellColor);
FBorderGutterCellColor := FBorderTitleCellColor;
end else begin
xCol1 := B1a0a1bC8EDFB;
xCol2 := B1a0a1bABDFF3;
FBorderTitleCellColor := rgb(200, 170, 105);
FBorderGutterCellColor := (B1a0a1bD6D6D6);
FillBMPGradient(FFixedLine, xCol1, xCol2, 19, 19, true); //B1a0a1bD7FFE7
end{if..else};
//FParLine
if UseTheme then begin
LDetails := LStyle.GetElementDetails(CNormalStates[false {(gdSelected in AState) and (goDrawFocusSelected in FOptions)}]);
if LStyle.GetElementColor(LDetails, ecFillColor, LColor) and (LColor <> clNone) then
xCol1 := LColor;
xCol1 := GetShadowColor(xCol1, 10);
xCol2 := xCol1;
FillBMPGradient(FParLine, xCol1, xCol2, 16, 16, true);
end else begin
xCol1 := B1a0a1bf5f5f5;
xCol2 := B1a0a1bf5f5f5;
FillBMPGradient(FParLine, xCol1, xCol2, 16, 16, true); //B1a0a1bFEFAF5
end{if..else};
//FNParLine
if UseTheme then begin
LDetails := LStyle.GetElementDetails(CNormalStates[false {(gdSelected in AState) and (goDrawFocusSelected in FOptions)}]);
if LStyle.GetElementColor(LDetails, ecFillColor, LColor) and (LColor <> clNone) then
xCol1 := LColor;
xCol2 := xCol1;
FillBMPGradient(FNParLine, xCol1, xCol2, 16, 16, true);
end else begin
FillBMPGradient(FNParLine, clWhite, clWhite, 16, 16, true); //B1a0a1bFEFAF5
end{if..else};
//FSelLine
if UseTheme then begin
LDetails := LStyle.GetElementDetails(CNormalStates[false {(gdSelected in AState) and (goDrawFocusSelected in FOptions)}]);
if LStyle.GetElementColor(LDetails, ecFillColor, LColor) and (LColor <> clNone) then
xCol1 := LColor;
xCol1 := GetShadowColor(xCol1, 40);
xCol2 := xCol1;
FillBMPGradient(FSelLine, xCol1, xCol2, 16, 16, true);
end else begin
FillBMPGradient(FSelLine, B1a0a1bE6E1D5, B1a0a1bE6E1D5, 16, 16, true); //B1a0a1bFEFAF5
end{if..else};
//sel cell
if UseTheme then begin
LDetails := LStyle.GetElementDetails(CNormalStates[true {(gdSelected in AState) and (goDrawFocusSelected in FOptions)}]);
MyDraw(FSelCell, LDetails, 300, 21);
end else begin
FillBMPGradient(FSelCell, B1a0a1b796951, B1a0a1b796951, 16, 16, true);
end{if..else};
FillBMPGradient(FGroupCell,
B1a0a1bE1AB80,
B1a0a1bE1AB80,
16,
16,
true
);
//FGutter
if UseTheme then begin
LDetails := LStyle.GetElementDetails(CFixedStates[false, false]);
MyDraw(FGutter, LDetails);
end else begin
FillBMPGradient(FGutter, B1a0a1bEBEBEB, B1a0a1bDBDBDB, 16, 16, true);
end{if..else};
if UseTheme then begin
LDetails := LStyle.GetElementDetails(CFixedStates[true, false]);
MyDraw(FSelGutter, LDetails, 21, 21);
end else begin
FillBMPGradient(FSelGutter, B1a0a1bFFF3D7, B1a0a1bF0966A, 16, 16, true);
end{if..else};
//all is done ;)
////////////////////
end;
2条答案
按热度按时间lb3vh1jj1#
问题1:在
OnDrawColumnCell
事件中,Canvas.Brush.Color
和Canvas.Font.Color
已经设置为Style值。Q2:从网格的
StyleElements
属性中删除seClient
和seFont
,并使用网格的Color
和Font.Color
属性。jhkqcmku2#
如果你使用主题,那么绘画就以非标准的方式进行。VCL使用StyleHooks绘制带有主题支持的任何控件。如果我们谈论TDBGrid--出于优化的原因,它本身使用了大量的主题绘制,但你总是可以看看源代码来理解它是如何工作的。绘制具有不同样式的单元格的代码的一部分是TCustomDBGrid.DrawCell。我将它的一部分用于我自己的TDBGrid实现,所以这里有部分源代码供您更好地理解:
我在加载组件和更改主题时使用Procedure GenerateBitmap。之后-我使用这个颜色来绘制我的网格,并绘制缓存的位图,并通过缩放来填充单元格背景。是的,我知道这不是一个完整的测试项目,但你可以从它得到你的两个问题的答案。