Delphi 11、VCL、运行时样式属性

blpfk2vs  于 2022-09-21  发布在  其他
关注(0)|答案(2)|浏览(307)

假设我使用Delphi11VCL中的一种样式,并根据该样式绘制了一个DBGrid,则用户可以在应用程序使用期间在一组样式之间切换。

问题1.如何检索单元格将在运行时绘制的颜色值(以及其字体颜色)?

Q2.我必须根据DBGrid的数据集中的一些字段值绘制DBGrid的单元格。使用OnDrawColumnCell很容易,但有些样式确实不能处理客户的含义颜色集:它们真的是不可更改的。之后,我想在运行时更改当前的样式颜色(网格及其字体)。

谢谢你们伙计们。

乔瓦尼

lb3vh1jj

lb3vh1jj1#

问题1:在OnDrawColumnCell事件中,Canvas.Brush.ColorCanvas.Font.Color已经设置为Style值。

Q2:从网格的StyleElements属性中删除seClientseFont,并使用网格的ColorFont.Color属性。

jhkqcmku

jhkqcmku2#

如果你使用主题,那么绘画就以非标准的方式进行。VCL使用StyleHooks绘制带有主题支持的任何控件。如果我们谈论TDBGrid--出于优化的原因,它本身使用了大量的主题绘制,但你总是可以看看源代码来理解它是如何工作的。绘制具有不同样式的单元格的代码的一部分是TCustomDBGrid.DrawCell。我将它的一部分用于我自己的TDBGrid实现,所以这里有部分源代码供您更好地理解:

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;

我在加载组件和更改主题时使用Procedure GenerateBitmap。之后-我使用这个颜色来绘制我的网格,并绘制缓存的位图,并通过缩放来填充单元格背景。是的,我知道这不是一个完整的测试项目,但你可以从它得到你的两个问题的答案。

相关问题