Advertisement
hamacker

DBGrid Tunado - com zebra, sort, altura de linha, ....

Apr 6th, 2016
377
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 11.37 KB | None | 0 0
  1. unit interceptor_TDBGrid;
  2.  
  3. // Esta é uma classe interceptadora que acrescenta funcionalidades ao DBGrid.
  4. // Como usar: basicamente voce coloca a unit interceptor_TDBGrid na uses de seu form
  5. //   (tem que ser posterior a DBGrids, Grids para não haver problemas) e não precisa de
  6. //   mais nada, magicamente seus DGGrids herdarão as features abaixo:
  7. // Zebra: o famoso cor sim e cor não ;-)
  8. // LinesPerRow: Quantidade de linhas para acomodar melhor campos memos e strings longas
  9. // Campo de Imagem: Qualquer imagem suportada pelo TGraphicField será exibido.
  10. // Faz a ordenação ao clicar no titulo da coluna, também ao passar o mouse pelo titulo
  11. //    das colunas, o cursor  modifica-se para HandPoint para indicar uma ação disponível
  12. // Se quer desativar as personalizações que essa classe de interceptação faz, então use:
  13. //   dbgrid1.DoAll:=false; // volta a ser um DBGrid comum
  14. // Se for trabalhar com memos ou strings longas com quebra de linhas então defina:
  15. //   dbgrid1.LinesPerRow:=3; // 3 linhas de altura
  16. // Zebrar um grid é o default, mas você pode personalizar as cores ou até desligar a zebra:
  17. //   dbgrid1.ColorPair:=$00EFEDED;
  18. //   dbgrid1.ColorOdd:=$00D3D3D3;
  19. //   dbgrid1.ColorFont:=clWhite;
  20. //   dbgrid1.ColorSelection:=clWebCornFlowerBlue;
  21. //   dbgrid1.Zebra:=true;
  22. // Todo: Capacitar o TitleClick para fazer a ordenação também em ClientDataset, atualmente
  23. //   só faz em Datasets baseado em Firedac (FDQuery e FDMemTable)
  24. // By Hamacker (sirhamacker [em] gmail.com)
  25.  
  26. interface
  27.  
  28. uses
  29.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls,
  30.   ExtCtrls, Menus, RegularExpressions, StrUtils, VCL.DBGrids, VCL.Grids, Data.DB, FireDAC.Comp.Client;
  31.  
  32. type
  33.   TDBGrid = class(Vcl.DBGrids.TDBGrid)
  34.   private
  35.     FColorPair: TColor;
  36.     FColorOdd: TColor;
  37.     FColorFont: TColor;
  38.     FColorForSelection: TColor;
  39.     FZebra:Boolean;
  40.     FLinesPerRow: Integer;
  41.     FBoldForSelection: Boolean;
  42.     FDoAll: Boolean;
  43.     FSendKeyDownTo:TWinControl;
  44.     procedure SetLinesPerRow (Value: Integer);
  45.     function ReverseColorBW(BackGroundColor : TColor):TColor;
  46.     procedure OrdenarGrid(Column: TColumn);
  47.     procedure SetDoAll(const Value: Boolean);
  48.   protected
  49.     procedure DrawColumnCell(const Rect: TRect; DataCol: Integer;
  50.       Column: TColumn; State: TGridDrawState); override;
  51.     procedure TitleClick(Column: TColumn); override;
  52.     procedure  LayoutChanged; override;
  53.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  54.   public
  55.     constructor Create(AOwner: TComponent); override;
  56.  published
  57.     property LinesPerRow: Integer  read FLinesPerRow write SetLinesPerRow default 1;
  58.     property ColorPair:TColor read FColorPair write FColorPair;
  59.     property ColorOdd:TColor read FColorOdd write FColorOdd;
  60.     property ColorFont:TColor read FColorFont write FColorFont;
  61.     property ColorSelection:TColor read FColorForSelection write FColorForSelection;
  62.     property Zebra:Boolean read FZebra write FZebra;
  63.     property BoldForSelection:Boolean read FBoldForSelection write FBoldForSelection;
  64.     property DoAll:Boolean read FDoAll write SetDoAll;
  65.     //property OnDrawColumnCell;
  66.     //property OnTitleClick;
  67.   end;
  68.  
  69.  
  70. implementation
  71.  
  72.  
  73. { TDBGrid }
  74. constructor TDBGrid.Create(AOwner: TComponent);
  75. begin
  76.   inherited ;
  77.   FColorPair:=$00EFEDED;
  78.   FColorOdd:=$00D3D3D3;
  79.   FColorFont:=clWhite;
  80.   FColorForSelection:=clWebCornFlowerBlue;
  81.   FZebra:=true;
  82.   FBoldForSelection:=true;
  83.   FLinesPerRow:=1;
  84.   FDoAll:=true;
  85. end;
  86.  
  87. procedure TDBGrid.TitleClick(Column: TColumn);
  88. begin
  89.   if Assigned(OnTitleClick) then
  90.   begin
  91.     inherited OnTitleClick(Column);
  92.     Invalidate;
  93.   end
  94.   else
  95.   begin
  96.     OrdenarGrid(Column);
  97.   end;
  98. end;
  99.  
  100. procedure TDBGrid.MouseMove(Shift: TShiftState; X, Y: Integer);
  101. var
  102.   pt: TGridcoord;
  103. begin
  104.   pt:= MouseCoord(x, y);
  105.  
  106.   if pt.y=0 then
  107.     Cursor:=crHandPoint
  108.   else
  109.     Cursor:=crDefault;
  110.   inherited MouseMove(Shift,X, Y);
  111. end;
  112.  
  113. // A ordenação está preparada para usar Firedac, outro tipo de componente não terá qualquer efeito
  114. procedure TDBGrid.OrdenarGrid(Column: TColumn);
  115.   procedure BoldTitle;
  116.   var i:Integer;
  117.   begin
  118.     for i:=0 to Pred(Self.Columns.Count)
  119.       do  Self.Columns[i].Title.Font.Style:=[];
  120.     Column.Title.Font.Style:=[fsBold];
  121.   end;
  122. begin
  123.   try
  124.     if Column.Grid.DataSource.DataSet is TFDQuery then
  125.     begin
  126.       if not(Column.Field.FieldKind in [fkData, fkInternalCalc]) then
  127.       begin
  128.         Application.MessageBox(pChar('Campo ['+Column.FieldName+'] calculado.' + #13#10 + 'Não é possivel ordenação.'), pChar('Erro:'),MB_OK+MB_ICONERROR);
  129.         exit;
  130.       end;
  131.       if TFDQuery(Column.Grid.DataSource.DataSet).IndexFieldNames = Column.FieldName then
  132.       begin
  133.         TFDQuery(Column.Grid.DataSource.DataSet).IndexFieldNames := Column.FieldName + ':d';
  134.         BoldTitle;
  135.       end
  136.       else
  137.       begin
  138.         TFDQuery(Column.Grid.DataSource.DataSet).IndexFieldNames := Column.FieldName;
  139.         BoldTitle;
  140.       end;
  141.     end
  142.     else
  143.       if Column.Grid.DataSource.DataSet is TFDMemTable then
  144.       begin
  145.         if TFDMemTable(Column.Grid.DataSource.DataSet).IndexFieldNames = Column.FieldName then
  146.         begin
  147.           TFDMemTable(Column.Grid.DataSource.DataSet).IndexFieldNames := Column.FieldName + ':d';
  148.           BoldTitle;
  149.         end
  150.         else
  151.         begin
  152.           TFDMemTable(Column.Grid.DataSource.DataSet).IndexFieldNames := Column.FieldName;
  153.           BoldTitle;
  154.         end;
  155.       end;
  156.   except
  157.     on E: Exception
  158.       do Application.MessageBox(pChar(e.Message), pChar('Erro:'),MB_OK+MB_ICONERROR);
  159.   end;
  160. end;
  161.  
  162. // ReverseColorBW: Retorna uma cor branca ou preta que faz contraste com a cor especificada.
  163. // Com isso posso garantir que não importa a cor que use com o Brush, sempre terei a cor
  164. // da fonte fazendo contraste.
  165. function TDBGrid.ReverseColorBW(BackGroundColor : TColor):TColor;
  166. const
  167.  cHalfBrightness = ((0.3 * 255.0) + (0.59 * 255.0) + (0.11 * 255.0)) / 2.0;
  168. var
  169.  Brightness : double;
  170. begin
  171.  with TRGBQuad(BackGroundColor)
  172.    do BrightNess := (0.3 * rgbRed) + (0.59 * rgbGreen) + (0.11 * rgbBlue);
  173.  if (Brightness>cHalfBrightNess)
  174.    then result := clblack
  175.    else result := clwhite;
  176. end;
  177.  
  178. procedure TDBGrid.SetDoAll(const Value: Boolean);
  179. begin
  180.   if Value <> FDoAll then
  181.   begin
  182.     FDoAll := Value;
  183.     LayoutChanged;
  184.   end;
  185. end;
  186.  
  187. procedure TDBGrid.SetLinesPerRow(Value: Integer);
  188. begin
  189.   if Value <> FLinesPerRow then
  190.   begin
  191.     FLinesPerRow := Value;
  192.     LayoutChanged;
  193.   end;
  194. end;
  195.  
  196. procedure TDBGrid.LayOutChanged;
  197. var
  198.   PixelsPerRow, PixelsTitle, I: Integer;
  199. begin
  200.   inherited LayOutChanged;
  201.  
  202.   Canvas.Font := Font;
  203.   PixelsPerRow := Canvas.TextHeight('Wg') + 3;
  204.   if dgRowLines in Options then
  205.     Inc (PixelsPerRow, GridLineWidth);
  206.  
  207.   Canvas.Font := TitleFont;
  208.   PixelsTitle := Canvas.TextHeight('Wg') + 4;
  209.   if dgRowLines in Options then
  210.     Inc (PixelsTitle, GridLineWidth);
  211.  
  212.   // set number of rows
  213.   RowCount := 1 + (Height - PixelsTitle) div (PixelsPerRow * FLinesPerRow);
  214.  
  215.   // set the height of each row
  216.   DefaultRowHeight := PixelsPerRow * FLinesPerRow;
  217.   RowHeights [0] := PixelsTitle;
  218.   for I := 1 to RowCount - 1 do
  219.     RowHeights [I] := PixelsPerRow * FLinesPerRow;
  220.  
  221.   // send a WM_SIZE message to let the base component recompute
  222.   // the visible rows in the private UpdateRowCount method
  223.   PostMessage (Handle, WM_SIZE, 0, MakeLong(Width, Height));
  224. end;
  225.  
  226. procedure TDBGrid.DrawColumnCell (const Rect: TRect; DataCol: Integer;
  227.   Column: TColumn; State: TGridDrawState);
  228. var
  229.   Bmp: TBitmap;
  230.   OutRect: TRect;
  231.   bDone:Boolean;
  232.   DefAlign:Integer;
  233. begin
  234.   if (not FDoAll) and Assigned(OnDrawColumnCell) then
  235.   begin
  236.     inherited DrawColumnCell(Rect, DataCol, Column, State);
  237.     Invalidate;
  238.     Exit;
  239.   end;
  240.   if (FDoAll) then
  241.   begin
  242.  
  243.     if (gdSelected in state) then
  244.     begin
  245.       Canvas.Brush.Color := FColorForSelection;
  246.       Canvas.Font.Color := ReverseColorBW(FColorForSelection);
  247.       if FBoldForSelection
  248.         then Canvas.Font.Style:=[fsBold];
  249.     end
  250.     else
  251.     begin
  252.       if Odd(DataSource.Dataset.RecNo)
  253.         then Canvas.Brush.Color := FColorPair
  254.         else Canvas.Brush.Color := FColorOdd;
  255.       if FBoldForSelection
  256.         then Canvas.Font.Style:=[];
  257.       //inherited;
  258.       if Assigned(OnDrawColumnCell)
  259.         then OnDrawColumnCell(Self, Rect, DataCol, Column, State);
  260.     end;
  261.  
  262.     // limpa a area
  263.     Canvas.FillRect (Rect);
  264.     // copy the rectangle
  265.     OutRect := Rect;
  266.     // restringir a saida
  267.     InflateRect (OutRect, -2, -2);
  268.     bDone:=false;
  269.     DefAlign:=DT_LEFT;
  270.     if Column.Field.Alignment=taLeftJustify then DefAlign:=DT_LEFT;
  271.     if Column.Field.Alignment=taRightJustify then DefAlign:=DT_RIGHT;
  272.     if Column.Field.Alignment=taCenter then DefAlign:=DT_CENTER;
  273.  
  274.     if (not bDone) and (Column.Field is TGraphicField) then
  275.     begin
  276.       Bmp := TBitmap.Create;
  277.       try
  278.         Bmp.Assign (Column.Field);
  279.         Canvas.StretchDraw (OutRect, Bmp);
  280.       finally
  281.         Bmp.Free;
  282.       end;
  283.       bDone:=true;
  284.     end;
  285.  
  286.     if (not bDone) and (Column.Field is TMemoField) then
  287.     begin
  288.       DrawText (Canvas.Handle, PChar (Column.Field.AsString),
  289.         Length (Column.Field.AsString), OutRect, dt_WordBreak or dt_NoPrefix);
  290.       bDone:=true;
  291.     end;
  292.  
  293.     // String
  294.     if (not bDone) and ((Column.Field is TStringField) ) then
  295.     begin
  296.       //DrawText (Canvas.Handle, PChar (Column.Field.DisplayText),
  297.       //  Length (Column.Field.DisplayText), OutRect,
  298.       //  dt_vcenter or DefAlign or dt_SingleLine or dt_NoPrefix);
  299.       DrawText (Canvas.Handle, PChar (Column.Field.DisplayText),
  300.         Length (Column.Field.DisplayText), OutRect, dt_WordBreak or dt_NoPrefix);
  301.  
  302.       bDone:=true;
  303.     end;
  304.  
  305.     // valores numericos - a direita
  306.     if (not bDone) and (
  307.        (Column.Field is TBCDField) or
  308.        (Column.Field is TCurrencyField) or
  309.        (Column.Field is TFloatField)) then
  310.     begin
  311.       DrawText (Canvas.Handle, PChar (Column.Field.DisplayText),
  312.         Length (Column.Field.DisplayText), OutRect,
  313.         dt_vcenter or DT_RIGHT or dt_SingleLine or dt_NoPrefix);
  314.       bDone:=true;
  315.     end;
  316.  
  317.     // inteiros - centralizados
  318.     if (not bDone) and (
  319.        (Column.Field is TIntegerField) or
  320.        (Column.Field is TSmallintField) or
  321.        (Column.Field is TLargeintField) or
  322.        (Column.Field is TWordField)) then
  323.     begin
  324.       DrawText (Canvas.Handle, PChar (Column.Field.DisplayText),
  325.         Length (Column.Field.DisplayText), OutRect,
  326.         dt_vcenter or DT_CENTER or dt_SingleLine or dt_NoPrefix);
  327.       bDone:=true;
  328.     end;
  329.  
  330.     // data e hora - centralizados
  331.     if (not bDone) and (
  332.        (Column.Field is TDateField) or
  333.        (Column.Field is TTimeField) or
  334.        (Column.Field is TDateTimeField)) then
  335.     begin
  336.       DrawText (Canvas.Handle, PChar (Column.Field.DisplayText),
  337.         Length (Column.Field.DisplayText), OutRect,
  338.         dt_vcenter or DT_CENTER or dt_SingleLine or dt_NoPrefix);
  339.       bDone:=true;
  340.     end;
  341.  
  342.     // Para todos os demais tipos desenha-se uma linha simples verticalmente centralizada
  343.     if (not bDone) then
  344.     begin
  345.       DrawText (Canvas.Handle, PChar (Column.Field.DisplayText),
  346.         Length (Column.Field.DisplayLabel), OutRect,
  347.         dt_vcenter or DefAlign or dt_SingleLine or dt_NoPrefix);
  348.       bDone:=true;
  349.     end;
  350.  
  351.   end;
  352. end;
  353.  
  354. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement