1. Technology

Drawing a TComboBox: Color Pick List, Font Pick List

Graphical Drop Down List - a Combo Box of Colors; and a True-Type Font Picker.

By

Owner Drawing a Delphi ComboBox

Owner Drawing a Delphi ComboBox

Understanding Owner Drawing in Delphi article introduced custom drawing of VCL controls.

As with menus (menu items), an application can create an owner-drawn combo box to take responsibility for painting list items. An owner-drawn combo box can list/show information other than text strings - usually some graphical elements.

To create an owner-draw combo box, we set its Style property to csOwnerDrawFixed or csOwnerDrawVariable.

If all list items in the combo box are the same height, such as strings or icons, an application can use the csOwnerDrawFixed style.

If list items are of varying height, like bitmaps of different size, an application can use the csOwnerDrawVariable style. In this case the application will receive the WM_MEASUREITEM Windows message and the OnMeasureItem event will be fired for each item - to specify the height of list items in the combo box.

Having done this, Windows no longer draws the control. Instead it sends a WM_DRAWITEM message whenever a portion of the control needs to be repainted. The parent window (form) of an owner-drawn combo box (its owner) then fires the OnDrawItem event when a portion of the combo box needs to be painted.

To demonstrate owner-drawing with combo boxes create a combo box full of colors (two variations) and a combo with true-type fonts showing the actual image of the font.

Color Picker

To create a combo box of colors, first we have to add color names to the Items of the combo box (done in the Form.OnCreate event). All colors (color names) are held in a Colors constant defined as:
 const Colors: array[0..17] of TColor = (clAqua, clBlack, ..., clWhite, clYellow) ;
 
The code used to draw the items is not too complex. We simply retreive the color associated with the item, set it as the color of the canvas and than draw the rectangle in that color. To obtain the string corresponding to the color, we call the ColorToString RTL function.
 procedure TForm1.ColorComboDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState) ;
 begin
  with Control as TComboBox do
  begin
    //draw filled rectangle
    Canvas.Brush.Color := TColor(Colors[Index]) ;
    Canvas.FillRect(Rect) ;
    //draw color name
    Canvas.TextOut(Rect.Left, Rect.Top, ColorToString(Colors[Index]))
  end;
 end; 
Note: The "Additional" VCL palette has the TColorBox which represents a combo box that lets users select a color. Note2: At the time of writing this article, Delphi did not include TColorBox.

Font Picker

Even though it might look that having all the fonts displayed in the combo with the actual image of the font should be hard to code - it is not. I suppose you know that the global Screen variable (TScreen) in its Fonts property holds the face names for all fonts supported by the system (screen fonts).

To fill the font-combo with font names we simply use:

 var
   cnt : integer;
 begin
   for cnt := 0 to Screen.Fonts.Count-1 do
     FontCombo.Items.Add(Screen.Fonts.Strings[cnt]) ;
 end; 
The OnDrawItem handler for the font combo looks like:
 procedure TForm1.FontComboDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState) ;
 begin
  with (Control as TComboBox).Canvas do
  begin
    Font.Name := Screen.Fonts.Strings[Index];
    FillRect(Rect) ;
    TextOut(Rect.Left, Rect.Top, PChar(Screen.Fonts.Strings[Index]))
  end;
 end; 

More ideas...

Many of the Windows Common Controls, such as the list view, tree view, tab control, status bar, etc. are extremely flexible and can be used to replace a variety of custom and owner-drawn controls. For example, a list view can replace a list box that is owner-drawn in order to show a check box next to each item.
Source Code
  1. About.com
  2. Technology
  3. Delphi
  4. Using VCL Components
  5. TComboBox
  6. Drawing a TComboBox: Color Pick List, Font Pick List

©2014 About.com. All rights reserved.