为StringGrid Cell增加ComboBox功能

I have a TStringGrid.  In one of the columns, I want
> the cells to act as ComboBoxes; i.e. each of the cells in that column would
> have a small down arrow button which, when clicked, would show a
> drop-down list from which the user could choose an item for the cell.

there are several approaches here. A very simple one would just display a
genuine combobox on top of the cell when the user clicks on the cell. If you
want to see an arrow button in the cell in this scenario you would have to
draw it yourself in an OnDrawCell event.

Attach a combobox to a stringgrid column

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    ComboBox1: TComboBox;
    procedure ComboBox1Exit(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
  private
    { Private declarations }
    Procedure CMDialogKey( Var msg: TCMDialogKey );
      message CM_DIALOGKEY;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.CMDialogKey(var msg: TCMDialogKey);
begin
  If Activecontrol = Combobox1 Then Begin
    If msg.CharCode = VK_TAB Then Begin
      // set focus back to the grid and pass the tab key to it
      stringgrid1.setfocus;
      stringgrid1.perform( WM_KEYDOWN, msg.charcode, msg.keydata );
      // swallow this message
      msg.result := 1;
      Exit;
    End;
  End;
  inherited;
end;

procedure TForm1.ComboBox1Exit(Sender: TObject);
begin
  with sender as TCombobox do begin
    hide;
    if itemindex >= 0 then
      with stringgrid1 do
        cells[ col, row ] := items[itemindex];
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  combobox1.visible := false;
end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
var
  R: TRect;
  org: TPoint;
begin
  With Sender As TStringgrid Do
    If (ACol = 2) and (ARow >= FixedRows) Then Begin
      // entered the column associated to the combobox
      // get grid out of selection mode
      perform( WM_CANCELMODE, 0, 0 );
      // position the control on top of the cell
      R := CellRect( Acol, Arow );
      org:= Self.ScreenToClient( ClientToScreen( R.topleft ));
      With combobox1 do begin
        setbounds( org.X, org.Y, r.right-r.left, height );
        itemindex := Items.IndexOf( Cells[ acol, arow ] );
        Show;
        BringTofront;
        // focus the combobox and drop down the list
        SetFocus;
        DroppedDown := true;
      end;
    End;
end;

end.

With a little modification the TStringgrid class can also be made to actually
parent a combonent. You need to modify the way it handles WM_COMMAND for this:

unit ControlStringgrid;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids;

type
  TControlStringgrid = class(TStringgrid)
  private
    { Private declarations }
    Procedure WMCommand( var msg: TWMCommand ); message WM_COMMAND;
  protected
    { Protected declarations }
  public
    { Public declarations }
  published
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('PBGoodies', [TControlStringgrid]);
end;

{ TControlStringgrid }

procedure TControlStringgrid.WMCommand(var msg: TWMCommand);
begin
  If EditorMode and ( msg.Ctl = InplaceEditor.Handle ) Then
    inherited
  Else
    If msg.Ctl <> 0 Then
      msg.result :=
        SendMessage( msg.ctl, CN_COMMAND,
                     TMessage(msg).wparam,
                     TMessage(msg).lparam );
end;

end.

Using this grid you can create a combobox as child of the grid, which has the
advantage that it will scroll with the grid while visible.

Peter Below (TeamB)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值