Mega Code Archive

 
Categories / Delphi / VCL
 

To use a combobox instead inplace editor in TStringGrid

Title: to use a combobox instead inplace editor in TStringGrid Question: How can I use a combobox as inplace editor in standard TStringGrid? Answer: I wrote a small app which demonstrates how you can use the some combobox instead standard inplace editor in TStringGrid component. Also in this app you can view how change font and/or alignment for some cells. The form contents as text: object frmMain: TfrmMain Left = 200 Top = 108 Width = 510 Height = 382 Caption = 'Example: TStringGrid advanced using' Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 object StringGrid1: TStringGrid Left = 24 Top = 152 Width = 457 Height = 161 ColCount = 2 DefaultColWidth = 200 DefaultRowHeight = 21 RowCount = 9 TabOrder = 0 OnDrawCell = StringGrid1DrawCell OnSelectCell = StringGrid1SelectCell ColWidths = ( 118 296) end object cbInplaceComboBox: TComboBox Left = 32 Top = 320 Width = 145 Height = 21 Style = csDropDownList ItemHeight = 13 Items.Strings = ( '1 value' '2 value' '3 value' '4 value' '5 value' '6 value' '7 value' '8 value' '9 value') TabOrder = 1 OnChange = cbInplaceComboBoxChange end object btnClose: TButton Left = 416 Top = 320 Width = 75 Height = 25 Cancel = True Caption = '&Close' Default = True TabOrder = 2 OnClick = btnCloseClick end object MemoDescription: TMemo Left = 24 Top = 8 Width = 457 Height = 129 Font.Charset = DEFAULT_CHARSET Font.Color = clNavy Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [fsBold] Lines.Strings = ( 'In this sample I shows how you can:' ' ' '1. change the inplace editor for second column' ' from standard inplace editor to user TComboBox component' ' ' ' view the next procedures:' ' - TfrmMain.FormCreate' ' - TfrmMain.CMDialogKey' ' - TfrmMain.cbInplaceComboBoxChange' ' - TfrmMain.StringGrid1SelectCell' ' ' '2. draw the cell values with different fonts' ' ' ' view the next procedure:' ' - TfrmMain.StringGrid1DrawCell' ' ' '3. change alignment for cells' ' ' ' view the next procedure:' ' - TfrmMain.StringGrid1DrawCell') ParentFont = False ScrollBars = ssVertical TabOrder = 3 end end The pas-file for same form: unit Main; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids; type TfrmMain = class(TForm) StringGrid1: TStringGrid; cbInplaceComboBox: TComboBox; btnClose: TButton; MemoDescription: TMemo; procedure FormCreate(Sender: TObject); procedure cbInplaceComboBoxChange(Sender: TObject); procedure StringGrid1SelectCell(Sender: TObject; Col, Row: Integer; var CanSelect: Boolean); procedure StringGrid1DrawCell(Sender: TObject; Col, Row: Integer; Rect: TRect; State: TGridDrawState); procedure btnCloseClick(Sender: TObject); private { Private declarations } procedure CMDialogKey(var msg: TCMDialogKey); message CM_DIALOGKEY; public { Public declarations } end; var frmMain: TfrmMain; implementation {$R *.DFM} procedure TfrmMain.FormCreate(Sender: TObject); var i: Integer; begin StringGrid1.DefaultRowHeight := cbInplaceComboBox.Height; cbInplaceComboBox.Visible := False; StringGrid1.Cells[0, 0] := 'Row No'; StringGrid1.Cells[1, 0] := 'Values (from Combobox)'; for i := 1 to StringGrid1.RowCount-1 do StringGrid1.Cells[0, i] := IntToStr(i); end; procedure TfrmMain.CMDialogKey(var msg: TCMDialogKey); begin if (ActiveControl = cbInplaceComboBox) then begin if (msg.CharCode = VK_TAB) then begin //set focus back to the grid and pass the tab key to it cbInplaceComboBox.SetFocus; cbInplaceComboBox.Perform(WM_KEYDOWN, msg.CharCode, msg.KeyData); // swallow this message msg.result := 1; Exit; end; end; inherited; end; procedure TfrmMain.cbInplaceComboBoxChange(Sender: TObject); var intRow: Integer; begin inherited; {Get the ComboBox selection and place in the grid} with cbInplaceComboBox do begin intRow := StringGrid1.Row; if (StringGrid1.Col = 2) then StringGrid1.Cells[2, intRow] := Items[ItemIndex] else StringGrid1.Cells[StringGrid1.Col, intRow] := Items[ItemIndex]; Visible := False; end; StringGrid1.SetFocus; end; procedure TfrmMain.StringGrid1SelectCell(Sender: TObject; Col, Row: Integer; var CanSelect: Boolean); var R: TRect; begin if ((Col = 1) and (Row 0)) then begin {Size and position the combo box to fit the cell} R := StringGrid1.CellRect(Col, Row); R.Left := R.Left + StringGrid1.Left; R.Right := R.Right + StringGrid1.Left; R.Top := R.Top + StringGrid1.Top; R.Bottom := R.Bottom + StringGrid1.Top; {Show the combobox} with cbInplaceComboBox do begin Left := R.Left + 1; Top := R.Top + 1; Width := (R.Right + 1) - R.Left; Height := (R.Bottom + 1) - R.Top; ItemIndex := Items.IndexOf(StringGrid1.Cells[Col, Row]); Visible := True; SetFocus; end; end; CanSelect := True; end; procedure TfrmMain.StringGrid1DrawCell(Sender: TObject; Col, Row: Integer; Rect: TRect; State: TGridDrawState); const AlignFlags: array [TAlignment] of Integer = (DT_LEFT or DT_VCENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX, DT_RIGHT or DT_VCENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX, DT_CENTER or DT_VCENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX); var s: string; begin inherited; with Rect do begin Left := Left + 2; Top := Top + 2; Right := Right - 5 end; s := StringGrid1.Cells[Col, Row]; if (Row = 0) and (Col begin StringGrid1.Canvas.Font.Style := StringGrid1.Canvas.Font.Style + [fsBold]; StringGrid1.Canvas.Brush.Color := StringGrid1.FixedColor; StringGrid1.Canvas.FillRect(Rect); DrawText(StringGrid1.Canvas.Handle, PChar(s), Length(s), Rect, AlignFlags[taCenter]); end else if (Col = 0) and (Row 0) and (Row begin StringGrid1.Canvas.FillRect(Rect); DrawText(StringGrid1.Canvas.Handle, PChar(s), Length(s), Rect, AlignFlags[taRightJustify]); end; end; procedure TfrmMain.btnCloseClick(Sender: TObject); begin Close end; end. PS: you can download this app from hotinfo page on my site. The direct link: http://www.geocities.com/mshkolnik/FAQ/strgrid.zip (120K)