Friday, May 09, 2025

Editing check boxes in a DBGrid

I wrote1 a few weeks ago about how to make certain fields editable in a data grid. As I wrote towards the end of the blog, The flags are shown as checkboxes drawn on the grid, but when they are edited, their real nature is disclosed - they have one of the values 0 or 1. The user has to enter the appropriate value in order to change the state of the checkbox.

This has nagged me somewhat; it would be better that the user simply press the space bar in order to toggle a flag's value. When I sat down to try and solve this problem a few weeks ago by using the grid's OnKeyPress method, I asked myself how do I know which column is being edited? Today I discovered the answer to that question: the function dbgrid1.selectedfield.FieldName tells me the column's name. Once I had this, some fiddling around gave me the following code (this is after a few iterations):

procedure TDoStatus.DBGrid1KeyPress(Sender: TObject; var Key: Char); var s: string; Procedure SetFieldValue (f: TSmallintField); var n: integer; begin qDoStatus.Edit; n:= f.asinteger; if n = 0 then f.asinteger:= 1 else f.asinteger:= 0; qDoStatus.Post; end; begin if key = ' ' then begin s:= dbgrid1.selectedfield.FieldName; if s = 'FUTURE' then SetFieldValue (qDoStatusFuture) else if s = 'MEETING' then SetFieldValue (qDoStatusMeeting) else if s = 'COPYCONTACT' then SetFieldValue (qDoStatusCopyContact) else if s = 'CLOSED' then SetFieldValue (qDoStatusClosed) else exit; // this stupid code gets the grid to redraw itself if qDoStatus.Eof then begin qDoStatus.Prior; qDoStatus.Next; end else begin qDoStatus.Next; qDoStatus.Prior; end; end
end;

This does indeed work, although it's not perfect. First of all, the user can still type 0, 1 or anything else for that matter, and my code doesn't prevent that despite my attempts at doing so. Maybe I should add the end 'else key = #0'. If the user does type 0 or 1, then nothing happens, so at least that's good. Secondly, I don't like the code at the end with the prior/next calls; this seems extravagant, but a call to 'refresh' may do the same fiddling around. Finally, it would be nice if I could make this more abstract by passing a global function the name of the query, although it's not clear at the moment how I would use selectedfield.fieldname. 

Today I was concentrating on writing code that works correctly; I'm sure that tomorrow it will be clear how to turn this localised code (similar code appears in another unit) into something more abstract and global.

Internal links
[1] 1916



This day in history:

Blog #Date TitleTags
7309/05/2007Killarney Boys Of PleasureSoundclick, Folktronix, Lunasa
35809/05/2011Running a database query which automates Word in a background threadProgramming, Delphi, Office automation, Threads
47909/05/2012Early footage of The BandThe Band, Youtube
58209/05/2013More sleep analysisCPAP
84009/05/2015Preparing for Florence (2)Holiday, Florence, Italy
102809/05/2017ZingersPersonal, Films
131509/05/2020DBA news in May: it's getting very near the endDBA
161509/05/2023Two weeks of ErythritolHealth, Erythritol

No comments: