Bayesean Blog - Desktop, Mobile and IOT Developer Blog


Delphi VCL Buttons in DBGrid

Posted on 1st Nov 2018 in Delphi VCL


btnheader3.png

There has been a trend for cloud based applications to show the Delete and Edit buttons in the grid. So a quick search on the net revealed that very little information on how to create a Styled Working Button in a Standard VCL DBGrid was to be found. So here is a development prototype that could be implemented in your application.

So how should this Styled Button appear and function in the DBGrid:-

  • Must be visible but inactive in state on all non- focused rows of the DBGrid.
  • Also focused when the row is focused.
  • Become a fully functional standard button i.e. makes uses all button events.
  • Be able to reflect the style of the Application and update to any live style change.

Take a look at how the buttons are seamlessly integrated in the DBGrid below. Then read on how to quickly implement this in to your DBGrid.   

buttons.gif 

IDE

This has been created with Delph 10.2 and it is backwards compatible to XE3. You will need to reload the specific styles and set the clientdataset to re-open the client.cds file.

In this example, the client.cds file example is used as the dataset and a clientdataset is dropped onto the form. Right click the clientdataset component and click on load from MyBase to select a CDS or XML db. We a re mimicking a DB by using a  client.cds database. Once selected, the data is live.

Add a datasource and a DBGrid. Link the Datasource1 to the Clientdataset and set the DBGrid1 ‘s Datasource to the datasource1 component to show the data in the DBgrid1.

As the button will not be connecting to a Datasource it will require an inactive data column to be added. (No connected data Field). Double Click on the DBGrid1 to show the Editing DBGrid1 .columns. Populate the fields with the AddFieldsbtn at the top(3rd from left).

Click on the AddNew Column(1st from left) to add the new field-less column. Now in the column’s properties in the Object Inspector, change the Title to ‘Edit ‘and set the Alignment to ‘taCenter’.

Drop a button on the DBGrid and set the button in the Object inspector’ Visible to False’.

button14.png

Now that we have completed this stage we can continue with the coding of the project.

Code Setup

 On the Form object inspector add the event OnCreate and ‘procedure FormCreate’ is created.

The steps that need to be followed:-

  • Set the buttons parent to DBGrid1.
  • Set the Caption to ‘Edit’.
  • Set the button’s controlstyle to ‘csClickEvents’. This will ensure that the button’s events messages are processed to the form.

 

This would be repeated if another button were added.

//set up the button
 button1.Parent:= dbgrid1;
 button1.Caption:= 'Edit';
 button1.ControlStyle:= button1.ControlStyle +[csClickEvents];

This would be repeated if another button was added.

To correctly position the button on the DBGrid we will need the exact x,y coordinates of the cell in the column. As the standard DBGrid does not have this functionality straight out, fortunately TCustomGrid does. To access the class  we need to add it to the unit as below.

type
TModDbGrid = class(TCustomGrid)
 end;

To keep this modular in nature we will create a separate drawing procedure for the Button. If you add more buttons then this procedure can be called for as many button’s that you wish to add to your grid. Create the following procedure and declare it in the forms’ Private declarations section.

procedure Buttondrawcolumncell
(Sender: TObject;Button:Tbutton;Btncaption:string;
Datacol,YourCol: Integer; Column: TColumn; Grid: TDBGrid;
const Rect: TRect; State: TGridDrawState);

And this is done in two main steps:-

Step 1 Add the inactive button style,

Step 2 Add the active styled button.

 Adding the Inactive Button

 For the first step we draw an inactive button on each row. To do this we will use the style services and procedure Drawframecontrol’. We draw the button as inactive by using  ‘DFCS_INACTIVE or DFCS_ADJUSTRECT’. The Text is also drawn as ‘sfButtonTextdisabled’ .This will ensure that the text color matches the style. The call ’ TDBGrid(Sender).DefaultDrawColumnCell(R, DataCol, Column, State)’  will ensure that the grid is redrawn within the ‘Rect’ named  R then placed in the coordinate position for each row determined by the datacol selected.

 Here is the code for this routine.

var
R,DataRect: TRect;
 style: DWORD;
 FButtonCol :integer;
 FCellDown:TGridCoord;
 begin
    R := rect;
    inflaterect(R,-1,-1);
    //Set up Button
    if (not (gdFixed in State)) and (DataCol = YourCol) then
  begin
    if styleservices.Enabled then
    TDBGrid(Sender).Canvas.Brush.Color := styleservices.GetStyleColor(scButtonDisabled)
    else
    TDBGrid(Sender).Canvas.Brush.Color := clbtnface;

    style := DFCS_INACTIVE or DFCS_ADJUSTRECT;
    DrawFrameControl( grid.Canvas.Handle, r, DFC_BUTTON, style );
     TDBGrid(Sender).DefaultDrawColumnCell(R, DataCol, Column, State);
     TDBGrid(Sender).Canvas.Brush.Style:= bsclear;
     if styleservices.enabled then
      TDBGrid(Sender).Canvas.Font.Color  := Styleservices.GetStyleFontColor(sfButtonTextdisabled)
      else
     TDBGrid(Sender).Canvas.Font.Color  := clblack;

     DrawText(Grid.Canvas.Handle, PChar(BtnCaption), -1, r, DT_CENTER );
     TDBGrid(Sender).DefaultDrawColumnCell(R, DataCol, Column, State);
  end;

Adding the Real Button

Here we make the button visible on the DBGrid and position the button in the active row. To do this we need to identify the DBGrid1 dataset’s ‘Recno’ and ‘record count’.

We now make use of the Class CustomGrid’s function ‘CellRect’ to get the exact (x,y) coordinates  of the cell. The TRect named Datarect’s position of the button is set and finally the button is made visible.

 

if grid.DataSource.DataSet.RecNo <= grid.DataSource.DataSet.recordcount  then
 begin
  if (not (gdFixed in State)) and (DataCol = YourCol) then
  begin
     DataRect := TModDbGrid(grid).CellRect((YourCol+1),TModDbGrid(grid).row);
     Inflaterect(datarect,-1,-1);
     button.Width:= Datarect.Width;
     button.left := (DataRect.right - button.width) ;
     button.top := DataRect.top ;
     button.height := (DataRect.bottom-DataRect.top);
     button.visible:= true;
        end;
  end;

Now that the procedure has been completed, create the DBGrid1 ‘s  ‘onDrawColumnCell ‘ event and add the button’s draw procedure ‘ButtondrawColumnCell’.

 

ButtondrawColumnCell(Sender,Button1,'Edit',Datacol,6,Column,DBgrid1,Rect,State);

As we have the Class CustomGrid exposed then we can re-color the background of the unused space in the grid. Add the following code here.

//Change color if the white space below the grid to same as background

 TModDBGrid(sender).FInternalColor:= styleservices.GetStyleColor(scCategoryPanelGroup);

Back on the Form, click on the button to add the Button1Click event and add the following code.

procedure TForm4.Button1Click(Sender: TObject);
begin
  showmessage('Edit this row');
  end;

Now you are ready to compile and enjoy your new refreshed DBGrid with a shiny working button.

Licence MIT.

Feel free to download a working example from the Bayesean-Blog Github Repository…

Download Code

 

Happy Coding

Greg

 

 

                                                                                                                                                          


Lauro      Commented   5 months ago Reply

Congratulations on the Code! This example can be used in DBGrid to make the Tree feature. | Customers A | -Sales $ 100.00

Add a Comment

9+5

Recent News

Delphi A Professional VCL DBGrid Part Four
Delphi A Professional VCL DBGrid Part Three
Delphi A Professional VCL DBGrid Part Two
Delphi A Professional VCL DBGrid Part One
Delphi VCL Buttons in DBGrid
Two Helper Apps for Delphi LibUSB
Delphi Libusb Library Introduction
Delphi Object directly to a Json string in a REST Client

Categories

Bootstrap 4
Delphi VCL
Delphi FMX
Ajax
Bootstrap 3
CSS
XE4>Delphi > XE4
Delphi < XE4
PHP

Archives

June 2019

Delphi A Professional VCL DBGrid Part Four

May 2019

Delphi A Professional VCL DBGrid Part Three

April 2019

Delphi A Professional VCL DBGrid Part Two

March 2019

Delphi A Professional VCL DBGrid Part One

November 2018

Delphi VCL Buttons in DBGrid

October 2018

Two Helper Apps for Delphi LibUSB

September 2018

Delphi Libusb Library Introduction

August 2018

Delphi Object directly to a Json string in a REST Client
Delphi using Environment Variables in your App

July 2018

Delphi FMX Leaflet Plotter using OSM Maps

June 2018

C2PAS32 Convertor Application
C to Delphi Open Source Convertors Shootout
Delphi command-line programs with DOSCommand

May 2018

Delphi PDF Embedded viewer with PDF.js

March 2018

Delphi FMX - Changing TCharacter to TCharHelper
Make Your Delphi App POP using Javascript!

January 2018

Delphi FMX Dashboard using Chart.JS
Delphi FMX Form Docking

December 2017

PHP Slim REST Server & Delphi Auth Part 5

November 2017

Delphi FMX REST Client App Part 4

October 2017

Delphi VCL REST Pricing Client App Part 3

September 2017

Delphi REST VCL Client Basic Auth Part 2B

August 2017

Delphi REST Client Part 2A
PHP PDO REST Server Part 1

July 2017

PHP REST Server and Delphi Client Intro

June 2017

Delphi SQLite Encryptor-Decryptor Tool
Updating Applications Manifest using Delphi

May 2017

Create a Visual IP Address Geolocation with PHP

March 2017

PHP Downloader using Countdown timer
PHP File Downloader from a Inbox Selection

February 2017

Javascript Image-File Uploader with ThumbViewer

January 2017

Morris Charts and PHP-PDO

December 2016

CSS to create a functional Toggle Button