Posted on 1st Nov 2018 in Delphi VCL
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:-
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.
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’.
Now that we have completed this stage we can continue with the coding of the project.
On the Form object inspector add the event OnCreate and ‘procedure FormCreate’ is created.
The steps that need to be followed:-
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’.
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
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.
Feel free to download a working example from the Bayesean-Blog Github Repository…
August 2019Delphi Delimited String to Fields
June 2019Delphi A Professional VCL DBGrid Part Four
May 2019Delphi A Professional VCL DBGrid Part Three
April 2019Delphi A Professional VCL DBGrid Part Two
March 2019Delphi A Professional VCL DBGrid Part One
November 2018Delphi VCL Buttons in DBGrid
October 2018Two Helper Apps for Delphi LibUSB
September 2018Delphi Libusb Library Introduction
August 2018Delphi Object directly to a Json string in a REST Client
July 2018Delphi FMX Leaflet Plotter using OSM Maps
June 2018C2PAS32 Convertor Application
May 2018Delphi PDF Embedded viewer with PDF.js
March 2018Delphi FMX - Changing TCharacter to TCharHelper
January 2018Delphi FMX Dashboard using Chart.JS
December 2017PHP Slim REST Server & Delphi Auth Part 5
November 2017Delphi FMX REST Client App Part 4
October 2017Delphi VCL REST Pricing Client App Part 3
September 2017Delphi REST VCL Client Basic Auth Part 2B
August 2017Delphi REST Client Part 2A
July 2017PHP REST Server and Delphi Client Intro
June 2017Delphi SQLite Encryptor-Decryptor Tool
May 2017Create a Visual IP Address Geolocation with PHP
March 2017PHP Downloader using Countdown timer
January 2017Morris Charts and PHP-PDO
December 2016CSS to create a functional Toggle Button