{"id":97,"date":"2007-05-12T13:58:13","date_gmt":"2007-05-12T11:58:13","guid":{"rendered":" http:\/\/www.nsonic.de\/blog\/2007\/05\/adding-a-combobox-to-a-cell\/"},"modified":"2007-05-12T13:58:15","modified_gmt":"2007-05-12T11:58:15","slug":"adding-a-combobox-to-a-cell","status":"publish","type":"post","link":"https:\/\/www.nsonic.de\/blog\/2007\/05\/adding-a-combobox-to-a-cell\/","title":{"rendered":"Adding a ComboBox to a cell"},"content":{"rendered":"<p><em>> I am using Delphi 2.0.  I have a TStringGrid.  In one of the columns, I want<br \/>\n> the cells to act as ComboBoxes; i.e. each of the cells in that column would<br \/>\n> have a small down arrow button which, when clicked, would show a<br \/>\n> drop-down list from which the user could choose an item for the cell.<br \/>\n><br \/>\n> Any ideas on how I would go about this?  Thanks.<br \/>\n><br \/>\n<\/em><br \/>\nthere are several approaches here. A very simple one would just display a<br \/>\ngenuine combobox on top of the cell when the user clicks on the cell. If you<br \/>\nwant to see an arrow button in the cell in this scenario you would have to<br \/>\ndraw it yourself in an OnDrawCell event.<br \/>\n<!--more--><br \/>\nAttach a combobox to a stringgrid column<\/p>\n<p>[code lang=&#8221;delphi&#8221;]unit Unit1;<\/p>\n<p>interface<\/p>\n<p>uses<br \/>\n  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br \/>\n  StdCtrls, Grids;<\/p>\n<p>type<br \/>\n  TForm1 = class(TForm)<br \/>\n    StringGrid1: TStringGrid;<br \/>\n    ComboBox1: TComboBox;<br \/>\n    procedure ComboBox1Exit(Sender: TObject);<br \/>\n    procedure FormCreate(Sender: TObject);<br \/>\n    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;<br \/>\n      var CanSelect: Boolean);<br \/>\n  private<br \/>\n    { Private declarations }<br \/>\n    Procedure CMDialogKey( Var msg: TCMDialogKey );<br \/>\n      message CM_DIALOGKEY;<br \/>\n  public<br \/>\n    { Public declarations }<br \/>\n  end;<\/p>\n<p>var<br \/>\n  Form1: TForm1;<\/p>\n<p>implementation<\/p>\n<p>{$R *.DFM}<\/p>\n<p>procedure TForm1.CMDialogKey(var msg: TCMDialogKey);<br \/>\nbegin<br \/>\n  If Activecontrol = Combobox1 Then Begin<br \/>\n    If msg.CharCode = VK_TAB Then Begin<br \/>\n      \/\/ set focus back to the grid and pass the tab key to it<br \/>\n      stringgrid1.setfocus;<br \/>\n      stringgrid1.perform( WM_KEYDOWN, msg.charcode, msg.keydata );<br \/>\n      \/\/ swallow this message<br \/>\n      msg.result := 1;<br \/>\n      Exit;<br \/>\n    End;<br \/>\n  End;<br \/>\n  inherited;<br \/>\nend;<\/p>\n<p>procedure TForm1.ComboBox1Exit(Sender: TObject);<br \/>\nbegin<br \/>\n  with sender as TCombobox do begin<br \/>\n    hide;<br \/>\n    if itemindex >= 0 then<br \/>\n      with stringgrid1 do<br \/>\n        cells[ col, row ] := items[itemindex];<br \/>\n  end;<br \/>\nend;<\/p>\n<p>procedure TForm1.FormCreate(Sender: TObject);<br \/>\nbegin<br \/>\n  combobox1.visible := false;<br \/>\nend;<\/p>\n<p>procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,<br \/>\n  ARow: Integer; var CanSelect: Boolean);<br \/>\nvar<br \/>\n  R: TRect;<br \/>\n  org: TPoint;<br \/>\nbegin<br \/>\n  With Sender As TStringgrid Do<br \/>\n    If (ACol = 2) and (ARow >= FixedRows) Then Begin<br \/>\n      \/\/ entered the column associated to the combobox<br \/>\n      \/\/ get grid out of selection mode<br \/>\n      perform( WM_CANCELMODE, 0, 0 );<br \/>\n      \/\/ position the control on top of the cell<br \/>\n      R := CellRect( Acol, Arow );<br \/>\n      org:= Self.ScreenToClient( ClientToScreen( R.topleft ));<br \/>\n      With combobox1 do begin<br \/>\n        setbounds( org.X, org.Y, r.right-r.left, height );<br \/>\n        itemindex := Items.IndexOf( Cells[ acol, arow ] );<br \/>\n        Show;<br \/>\n        BringTofront;<br \/>\n        \/\/ focus the combobox and drop down the list<br \/>\n        SetFocus;<br \/>\n        DroppedDown := true;<br \/>\n      end;<br \/>\n    End;<br \/>\nend;<\/p>\n<p>end.<br \/>\n[\/code]<br \/>\nWith a little modification the TStringgrid class can also be made to actually<br \/>\nparent a combonent. You need to modify the way it handles WM_COMMAND for this:<\/p>\n<p>[code lang=&#8221;delphi&#8221;]unit ControlStringgrid;<\/p>\n<p>interface<\/p>\n<p>uses<br \/>\n  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br \/>\n  Grids;<\/p>\n<p>type<br \/>\n  TControlStringgrid = class(TStringgrid)<br \/>\n  private<br \/>\n    { Private declarations }<br \/>\n    Procedure WMCommand( var msg: TWMCommand ); message WM_COMMAND;<br \/>\n  protected<br \/>\n    { Protected declarations }<br \/>\n  public<br \/>\n    { Public declarations }<br \/>\n  published<br \/>\n    { Published declarations }<br \/>\n  end;<\/p>\n<p>procedure Register;<\/p>\n<p>implementation<\/p>\n<p>procedure Register;<br \/>\nbegin<br \/>\n  RegisterComponents(&#8216;PBGoodies&#8217;, [TControlStringgrid]);<br \/>\nend;<\/p>\n<p>{ TControlStringgrid }<\/p>\n<p>procedure TControlStringgrid.WMCommand(var msg: TWMCommand);<br \/>\nbegin<br \/>\n  If EditorMode and ( msg.Ctl = InplaceEditor.Handle ) Then<br \/>\n    inherited<br \/>\n  Else<br \/>\n    If msg.Ctl <> 0 Then<br \/>\n      msg.result :=<br \/>\n        SendMessage( msg.ctl, CN_COMMAND,<br \/>\n                     TMessage(msg).wparam,<br \/>\n                     TMessage(msg).lparam );<br \/>\nend;<\/p>\n<p>end.<br \/>\n[\/code]<br \/>\nUsing this grid you can create a combobox as child of the grid, which has the<br \/>\nadvantage that it will scroll with the grid while visible.<\/p>\n<p>Peter Below (TeamB)<\/p>\n<p>[tags]Delphi, Components, StringGrid[\/tags]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>> I am using Delphi 2.0. I have a TStringGrid. In one of the columns, I want > the cells to act as&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":""},"categories":[11],"tags":[90,75,94],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p71Tml-1z","_links":{"self":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts\/97"}],"collection":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/comments?post=97"}],"version-history":[{"count":0,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/posts\/97\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/media?parent=97"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/categories?post=97"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nsonic.de\/blog\/wp-json\/wp\/v2\/tags?post=97"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}