[SOLVED] Disable CheckBox on TStringGrid lazarus / 21-General ---------------------------------------------------------------------- pmesquita · 2021-03-11 14:12 Staff, I have a TStringGrid with a cbsCheckboxColumn column but I need to hide or disable the CheckBox on specific lines based on a check ... If (AValue = 'Yes') The Disable or Hide; Does anyone know how to proceed? I've tried: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i TCheckBox (StringGrid1.Objects [0, 2]). Visible: = False; however gives access violation ---------------------------------------------------------------------- wp · 2021-03-11 16:28 The checkboxes in stringgrids are not "real" checkboxes but "faked" to display checkbox images. I don't know how to hide the checkbox in some specific cells, but here is a solution how to a make cells readonly: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.StringGrid1SelectCell(Sender: TObject; aCol, aRow: Integer;  var CanSelect: Boolean);begin  if (ACol=1) and (ARow=1) then    StringGrid1.Options := StringGrid1.Options - [goEditing]  else    StringGrid1.Options := StringGrid1.Options + [goEditing];end; Hmmm, not a very nice solution, because the disabled cell is not drawn in some disabled style. Another possibility is to provide customdrawn bitmaps. I took a screenshot of a simple grid with checkboxes and used a graphics program to cut out the checkbox images of the three states. These images were saved as separate bmp files. Then I increased the brightness of these images by a good fraction (75%) to mimic disabled checkboxes - they were saved as well. Theses images were loaded into my demo application (see attachment) at program start (and destroyed at program end). Finally I wrote a handler for the OnUserCheckboxBitmap event where I selected the bitmap according to the Checkbox state provided as parameter. BTW, when you include an empty bitmap you can also simulate a hidden checkbox this way. ---------------------------------------------------------------------- pmesquita · 2021-03-11 17:38 Quote from: wp on March 11, 2021, 05:28:58 pmThe checkboxes in stringgrids are not "real" checkboxes but "faked" to display checkbox images. I don't know how to hide the checkbox in some specific cells, but here is a solution how to a make cells readonly: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.StringGrid1SelectCell(Sender: TObject; aCol, aRow: Integer;  var CanSelect: Boolean);begin  if (ACol=1) and (ARow=1) then    StringGrid1.Options := StringGrid1.Options - [goEditing]  else    StringGrid1.Options := StringGrid1.Options + [goEditing];end; Hmmm, not a very nice solution, because the disabled cell is not drawn in some disabled style. Another possibility is to provide customdrawn bitmaps. I took a screenshot of a simple grid with checkboxes and used a graphics program to cut out the checkbox images of the three states. These images were saved as separate bmp files. Then I increased the brightness of these images by a good fraction (75%) to mimic disabled checkboxes - they were saved as well. Theses images were loaded into my demo application (see attachment) at program start (and destroyed at program end). Finally I wrote a handler for the OnUserCheckboxBitmap event where I selected the bitmap according to the Checkbox state provided as parameter. BTW, when you include an empty bitmap you can also simulate a hidden checkbox this way. I didn't know that the CheckBoxes were just images. So in this case, I can use the OnDrawCell event to draw a box simulating that the CheckBox is hidden as in the example. However I did not understand the reason that when running the processor it is constantly 25% ---------------------------------------------------------------------- wp · 2021-03-11 23:17 Quote from: pmesquita on March 11, 2021, 06:38:05 pmHowever I did not understand the reason that when running the processor it is constantly 25% This is because you are writing to a cell during painting. When you change a cell, the grid (or at least the changed cell) is repainted. But when you do this during paint, another repaint is triggered which triggers yet another repaint etc. When you want to mark the cells with the invisible checkmarks by some text such as 'Hide' as in your example you must do this outside the painting cycle, for example when the grid is populated. ---------------------------------------------------------------------- pmesquita · 2021-03-12 13:16 Quote from: wp on March 12, 2021, 12:17:08 amQuote from: pmesquita on March 11, 2021, 06:38:05 pmHowever I did not understand the reason that when running the processor it is constantly 25% This is because you are writing to a cell during painting. When you change a cell, the grid (or at least the changed cell) is repainted. But when you do this during paint, another repaint is triggered which triggers yet another repaint etc. When you want to mark the cells with the invisible checkmarks by some text such as 'Hide' as in your example you must do this outside the painting cycle, for example when the grid is populated. I understand the reason .. However I created the HideCheckBox procedure and after popularizing the Grid I call the procedure but the CheckBox is still drawn instead of putting the same code in OnDraw .. any suggestions? I don't usually work with canvas so I'm kind of figuring out how it works. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Procedure HideCheckBox(ACol, ARow: Integer);Var  LCellRect: TRect; Begin  Form1.StringGrid1.Cells[ACol, aRow]:= 'Hide';  LCellRect:= Form1.StringGrid1.CellRect(ACol, ARow);  Form1.StringGrid1.Canvas.FillRect(LCellRect); End; ---------------------------------------------------------------------- wp · 2021-03-12 14:44 No, you must not paint in the HideCheckbox procedure because the OS decides when painting will occur rather than you. You are only allowed to paint within the related procedures (OnPaint, OnDrawCell, or similar): Remove the StringGrid.Canvas.FillRect from the procedure and replace it by a StringGrid1.Invalidate -- this instructs the grid to repaint itself at next occasion. (In fact, this is not even necessary because the grid requests a repaint automatically whenever a cell changes). Since you had marked the invisible cells by text 'Hide' you only must make sure that this information is evaluated when repainting is done: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;  aRect: TRect; aState: TGridDrawState);Var  LCellRect: TRect;begin  if StringGrid1.Cells[ACol, ARow] = 'Hide') then  begin    LCellRect:= StringGrid1.CellRect(ACol, ARow);    StringGrid1.Canvas.FillRect(LCellRect);  end;end; A note on the HideCheckbox procedure: Why don't you make it a method of TForm1? In this case it would work also when Form1 is named differently: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Procedure TForm1.HideCheckBox(ACol, ARow: Integer);Var  LCellRect: TRect;begin  StringGrid1.Cells[ACol, aRow]:= 'Hide';end; Note: I did not test this code, there may be typos here and there... ---------------------------------------------------------------------- pmesquita · 2021-03-12 15:18 Quote from: wp on March 12, 2021, 03:44:47 pmNo, you must not paint in the HideCheckbox procedure because the OS decides when painting will occur rather than you. You are only allowed to paint within the related procedures (OnPaint, OnDrawCell, or similar): Remove the StringGrid.Canvas.FillRect from the procedure and replace it by a StringGrid1.Invalidate -- this instructs the grid to repaint itself at next occasion. (In fact, this is not even necessary because the grid requests a repaint automatically whenever a cell changes). Since you had marked the invisible cells by text 'Hide' you only must make sure that this information is evaluated when repainting is done: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;  aRect: TRect; aState: TGridDrawState);Var  LCellRect: TRect;begin  if StringGrid1.Cells[ACol, ARow] = 'Hide') then  begin    LCellRect:= StringGrid1.CellRect(ACol, ARow);    StringGrid1.Canvas.FillRect(LCellRect);  end;end; A note on the HideCheckbox procedure: Why don't you make it a method of TForm1? In this case it would work also when Form1 is named differently: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Procedure TForm1.HideCheckBox(ACol, ARow: Integer);Var  LCellRect: TRect;begin  StringGrid1.Cells[ACol, aRow]:= 'Hide';end; Note: I did not test this code, there may be typos here and there... Worked perfectly... Now I understand, I didn't know that only in the events you mentioned is allowed to work with the canvas .. good to know ... Thank you very much for your help .. and long live Lazarus ---------------------------------------------------------------------- pmesquita · 2021-03-12 15:20 Quote from: wp on March 12, 2021, 03:44:47 pmA note on the HideCheckbox procedure: Why don't you make it a method of TForm1? In this case it would work also when Form1 is named differently: I was too lazy to declare in the private of the form ...