[SOLVED] How TO: Create a combobox that displays brush styles lazarus / 39-Graphics ---------------------------------------------------------------------- EganSolo · 2022-03-19 11:32 This thread https://forum.lazarus.freepascal.org/index.php?topic=55595.0 shows very clearly how to create a combobox that displays the pen styles. I tried to adapt it to show the brush styles. Here's a snipet from my code: 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 Tge_StyleBox.DrawBrushItem(const anIndex: integer; ARect: TRect);begin  with cb_Style,Canvas.Brush do  begin    case Items[anIndex] of       'Solid'     : Style := bsSolid;       'Clear'   : Style := bsClear;       'Horizontal': Style := bsHorizontal;     'Vertical'  : Style := bsVertical;       'FDiagonal' : Style := bsFDiagonal;       'BDiagonal' : Style := bsBDiagonal;       'Cross'   : Style := bsCross;       'DiagCross' : Style := bsDiagCross;       'Image'     : Style := bsImage;       'Pattern'   : Style := bsPattern;    end;    Color := clBlack;    Canvas.FillRect(aRect.Left,aRect.Top,aRect.Bottom,aRect.Right div 2);    Canvas.TextOut (ARect.Right div 2 + 10, ARect.Top, Items[anIndex]);  end;end; procedure Tge_StyleBox.cb_StyleDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState);begin If fPenStyle then DrawPenItem(Index,aRect) else DrawBrushItem(Index,aRect);end;  In the above code cb_style is a TComboBox with its style set to csOwnerDrawVariable. When I run this code with fpenStyle set to false, the drop-down list is garbled (see the attached pic). Any suggestion on where I'm going wrong is welcome! Thanks, ---------------------------------------------------------------------- wp · 2022-03-19 11:58 Quote from: EganSolo on March 19, 2022, 12:32:35 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   with cb_Style,Canvas.Brush do The comma in this line seems to be wrong. Because of that, your code affects the canvas of the form rather than the canvas of cb_Style. BTW, there is a similar combobox in TAChart (TChartCombobox). [EDIT] Well, maybe the comma is correct... This is an ugly example of why the "with" syntax is hated by so many... ---------------------------------------------------------------------- Handoko · 2022-03-19 12:21 This works on Lazarus 2.2.0 Linux GTK2: 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.ComboBox1DrawItem(Control: TWinControl; Index: Integer;  ARect: TRect; State: TOwnerDrawState);begin  if not(Control is TComboBox) then Exit;  with (Control as TComboBox), Canvas.Brush do  begin    Color := clDefault;    Canvas.FillRect(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);    case Items[Index] of       'Solid'     : Style := bsSolid;       'Clear'     : Style := bsClear;       'Horizontal': Style := bsHorizontal;       'Vertical'  : Style := bsVertical;       'FDiagonal' : Style := bsFDiagonal;       'BDiagonal' : Style := bsBDiagonal;       'Cross'     : Style := bsCross;       'DiagCross' : Style := bsDiagCross;    end;    Color := clBlack;    Canvas.FillRect(ARect.Left, ARect.Top, ARect.Right div 2, ARect.Bottom);    Color := clDefault;    Canvas.TextOut(ARect.Right div 2 + 10, ARect.Top, Items[Index]);  end;end; But I don't know why bsSolid and bsClear give the same result. ---------------------------------------------------------------------- EganSolo · 2022-03-20 00:18 @wp: Thank you for pointing out that TChart has a similar combobox. I looked at the TChart Palette and I did not find it. I suppose it is present in the code of TChart? It seemed to me that having the bit of code below is a little easier than trying to find the combo box in another package @Handoko: Thank you so much for taking the time to post your code! It helped me understand what I was doing wrong. I used it to further the code a bit more and now, I think, we have something that is satisfactory. Here are the steps to take to make this works: 1. In the Implementation section of your unit add this: 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 Implementationuses LCLType, FPCanvas;  2. Initialize the TCombox box you have added to your form as follows: 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 Tge_StyleBox.LoadBrushStyles;begin  with cb_Style.Items do  begin   Clear;   cb_Style.Style := csOwnerDrawVariable;   Add('Solid'     );   Add('Clear'     );   Add('Horizontal');   Add('Vertical'  );   Add('FDiagonal' );   Add('BDiagonal' );   Add('Cross'     );   Add('DiagCross' );  end;end;  For instance, you can have that method called from the FormCreate or the constructor of a frame. 3. Implement the handle to the OnDraawItem event as follows: 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 Tge_StyleBox.cb_StyleDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState);begin If fPenStyle then DrawPenItem(Index,aRect) else DrawBrushItem(Index,aRect,State);end;  In my case, I am implementing a combo box for pen styles and for fill styles in one frame, but if you only care to draw the styles of the brush, then by all means, simplify the code by moving the code of DrawBrushItem into the event handler directly. 4. Lastly, here is the code to draw the brush styles: 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 Tge_StyleBox.DrawBrushItem(const anIndex: integer; ARect: TRect; State: TOwnerDrawState);begin  with cb_Style,Canvas.Brush do  begin  Color := clDefault;    Canvas.FillRect(aRect);    case Items[anIndex] of       'Solid'     : Style := bsSolid;       'Clear'     : Style := bsClear;       'Horizontal': Style := bsHorizontal;       'Vertical'  : Style := bsVertical;       'FDiagonal' : Style := bsFDiagonal;     'BDiagonal' : Style := bsBDiagonal;       'Cross'     : Style := bsCross;       'DiagCross' : Style := bsDiagCross;    end;    If Style = bsClear    then Color := clDefault    else Color := clRed;     Canvas.Rectangle(aRect.Left,aRect.Top,aRect.Right div 2,aRect.bottom-2);    Color := clDefault;    //If we don't clear the style, it messes up the text out.    Style := bsClear;    If [odSelected,odFocused] * State <> []    then begin      Color := clBlue;      With cb_Style.Canvas.Font do      begin       Color := clWhite;       Style := Style + [fsBold];      end;    end    else    begin      Color := clDefault;      cb_Style.Canvas.Font.Color := clBlack;    end;    Canvas.TextOut (ARect.Right div 2 + 10, ARect.Top, Items[anIndex]);  end;end;  Feel free to change the color of the feel as needed. This code will give the following image below.