TStringGrid 实现下拉框比较常见的思路是在TSringGrid中嵌入一个TComboBox ,
思路虽然简单,但开发起来却很麻烦,而且有时会出现不愿看到的效果。
还有一种更巧的方法,是Delphi未公开的。

先看两个Delphi提供的VCL:

TInplaceEdit 是Delphi 提供的一个未公开的控件,只能内嵌于TCustomGrid
         中使用,TStringGrid 单元格的编辑功能就是由该控件实现的。

TInplaceEditList 是TInplaceEdit的子控件,该控件实现了下拉框和带省略号
         的按钮的功能,也是只能在TCustomGrid 中使用。
         OnEditButtonClick 事件,按钮按下时触发该事件。
         OnGetPickListitems 事件,下拉框弹出前触发该事件,在该事件的处
         理中可以改变下拉框的内容。

TEditStyle =(esSimple, esEllipsis, esPickList)。
         编辑器类型,esSimple 普通类型,esEllipsis 带省略号按钮类型,
         esPickList 下拉框类型。
         
TCustomGrid ,看一下它的两个protected函数:
       FInplaceEdit: TInplaceEdit;
         FInplaceEdit 是TCustomGrid的编辑器。
         
       Function GetEditStyle(ACol, ARow: Longint): TEditStyle; dynamic;
       获取给定单元格的编辑器属性。
       
       Function CreateEditor: TInplaceEdit; virtual;
       TCustomGrid  创建编辑器。
       
       TCustomGrid 只对这两个函数作了最基本的实现,其源代码如下:
            
      function TCustomGrid.CreateEditor: TInplaceEdit;
      begin
                  Result := TInplaceEdit.Create(Self);
      end;
            
      function TCustomGrid.GetEditStyle(ACol, ARow: Longint): TEditStyle;
      begin
           Result := esSimple;
      end;

TStringGrid 没有改变这两个函数,因此TStringGrid没法用TInplaceEditList
      实现下拉框功能 。
      
      
实现原理:
      TStringGird 第一次进入编辑状态前由CreateEditor 创建编辑器,在编辑器
      显示前会访问TCustomGrid.GetEditStyle 函数,并由该函数的返回值决定编
      辑器类型。对于TInplaceEditList而言,如果GetEditStype 返回esEllipsis ,
      就是具有按钮功能的编辑器,如果返回值是esPickList ,就是下拉框类型的编
      辑器,并在显示之前触发OnGetPickListitems事件。因此在TStringGrid的子控
      件中重新实现这两个函数,首先使CreateEditor创建的编辑器为TinplaceEditList
      型的,然后在GetEditSyle函数中引出OnGetEditStyle事件,在应用环境中决定编
      辑的类型。

unit DropListGrid;

interface

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

type
  TOnGetEditStyle = procedure(ACol, ARow: Integer;var EditStyle:TEditStyle) of Object;
  TOnGridEditButtonClick=procedure(Sender:TObject;ACol,ARow:Integer)of Object;
  TDropListGrid = class(TStringGrid)
  private
    { Private declarations }
    FButtonWidth: Integer;
    FDropDownRows: Integer;
    FOnEditButtonClick: TOnGridEditButtonClick;
    FOnGetPickListitems: TOnGetPickListItems;
    FOnGetEditStyle: TOnGetEditStyle;
    procedure setFButtonWidth(const Value: Integer);
    procedure setFDropDownRows(const Value: Integer);
    procedure SetFOnEditButtonClick(const Value: TOnGridEditButtonClick);
    procedure SetFOnGetPickListitems(const Value: TOnGetPickListItems);
    procedure SetOnGetEditStyle(const Value: TOnGetEditStyle);
    procedure ButtonClick(Sender: TObject);
    procedure GetPickListitems(ACol, ARow: Integer; Items: TStrings) ;

protected                     //TInplaceEditList
    { Protected declarations }
     function CreateEditor: TInplaceEdit;override;
     function GetEditStyle(ACol, ARow: Longint): TEditStyle; override;
  public
    { Public declarations }
     destructor Destroy; override;
  published
    { Published declarations }
    property ButtonWidth: Integer read FButtonWidth write setFButtonWidth;
    property DropDownRows: Integer read FDropDownRows write setFDropDownRows;
    property OnEditButtonClick: TOnGridEditButtonClick read FOnEditButtonClick
      write SetFOnEditButtonClick;
    property OnGetPickListitems: TOnGetPickListItems read FOnGetPickListitems
      write SetFOnGetPickListitems;
    property OnGetEditStyle:TOnGetEditStyle read FOnGetEditStyle write SetOnGetEditStyle;

end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('SelfVcl', [TDropListGrid]);
end;

{ TDropListGrid }

procedure TDropListGrid.ButtonClick(Sender: TObject);
begin
   if Assigned(FOnEditButtonClick) then
      FOnEditButtonClick(Self,Col,Row);
end;

function TDropListGrid.CreateEditor: TInplaceEdit;
begin
   Result := TInplaceEditList.Create(Self);
   result.Parent:=Self;
   with TInplaceEditList(result)do
   begin
      Font:=Self.Font;
      if FButtonWidth>0 then
         ButtonWidth:= FButtonWidth;
      if FDropDownRows>0 then
         DropDownRows:=FDropDownRows;
      OnEditButtonClick:=ButtonClick;
      OnGetPickListitems:=GetPickListitems;
   end;

end;

destructor TDropListGrid.Destroy;
begin
   if InplaceEditor<>nil then
      if TInplaceEditList(InplaceEditor).PickListLoaded then
         TInplaceEditList(InplaceEditor).PickList.Items.Clear;
   inherited;
end;

function TDropListGrid.GetEditStyle(ACol, ARow: Integer): TEditStyle;
begin
   result:=inherited GetEditStyle(ACol, ARow);
   if Assigned(FOnGetEditStyle) then
      FOnGetEditStyle(ACol,ARow,result);
end;

procedure TDropListGrid.GetPickListitems(ACol, ARow: Integer;
  Items: TStrings);
begin
   if Assigned(FOnGetPickListitems) then
      FOnGetPickListitems(ACol,ARow,Items);
end;

procedure TDropListGrid.setFButtonWidth(const Value: Integer);
begin
  FButtonWidth := Value;
  if InplaceEditor<>nil then
     TInplaceEditList(InplaceEditor).ButtonWidth:=Value;
end;

procedure TDropListGrid.setFDropDownRows(const Value: Integer);
begin
  FDropDownRows := Value;
  if InplaceEditor<>nil then
     TInplaceEditList(InplaceEditor).DropDownRows:=Value;
end;

procedure TDropListGrid.SetFOnEditButtonClick(const Value: TOnGridEditButtonClick);
begin
  FOnEditButtonClick := Value;
end;

procedure TDropListGrid.SetFOnGetPickListitems(
  const Value: TOnGetPickListItems);
begin
  FOnGetPickListitems := Value;

end;

procedure TDropListGrid.SetOnGetEditStyle(const Value: TOnGetEditStyle);
begin
   FOnGetEditStyle := Value;
end;

end.

==============下面是我生成SelVcl的过程

1、在delphi中新建一个component

2、将以上代码张贴到新建单元中

3、编译生成一个Pas文件在Lib目录下

4、通过install component加入到SelVcl

5、新建一个工程,在SelVcl页中使用该控件

6、设置属性:goEditing:=true;

7、在OnGetEditStyle事件中写EditStyle:= esPickList;

调试可以看到,在点击网格进入编辑状态后,就会显示下列按钮

TStringGrid 实现下拉框的更多相关文章

  1. jquery实现下拉框多选

    一.说明 本文是利用EasyUI实现下拉框多选功能,在ComboxTree其原有的基础上对样式进行了改进,样式表已上传demo,代码如下 二.代码 <!DOCTYPE html PUBLIC & ...

  2. 利用js取到下拉框中选择的值

    现在的需求是:下拉框中要是选择加盟商让其继续选择学校,要是选择平台管理员则不需要选择学校.隐藏选择下拉列表. 选择枚举值: /// <summary> /// 平台角色 /// </ ...

  3. jquery禁用下拉框

    禁用下拉框 //下拉框禁用 $("select").each(function () { $("#" + this.id).attr("disable ...

  4. [原创]自己动手实现React-Native下拉框控件

    因项目需要,自己动手实现了一个下拉框组件,最近得空将控件独立出来开源上传到了Github和npm. Github地址(求Star 求Star 求Star 

  5. ajax 多级联动 下拉框 Demo

    写了ajax实现级联下拉框,考虑常用,并且级联个数随不同业务个数不同,于是就整理了一下,实现了 ajax + N级联动 下拉框的效果 效果图 HTML 代码 <h2> 省级联动</h ...

  6. jquery Combo Select 下拉框可选可输入插件

    Combo Select 是一款友好的 jQuery 下拉框插件,在 PC 浏览器上它能模拟一个简单漂亮的下拉框,在 iPad 等移动设备上又能回退到原生样式.Combo Select 能够对选项进行 ...

  7. struts-hibernate-ajax完成区县和街道级联下拉框功能(二补充使用json解析list结果集,ajax循环json层级处理)

    针对<struts-hibernate-ajax完成区县和街道级联下拉框功能>进行补充,上一篇中,要在action中拼接JSON格式字符串,很容易手抖.直接用json处理一下转成json格 ...

  8. asp.net MVC4 表单 - 下拉框

    1.下拉框代码方式 控制器内构建下拉项目: List<SelectListItem> list = new List<SelectListItem>(); list.Add(n ...

  9. Jquery制作--美化下拉框

    平常我们用的原生select下拉框,大部分样式没办法修改,导致在不同的浏览器里面会跟设计图的风格大相径庭.所以为了能让它美化起来,就用JQ模拟了一个下拉框,可以随意定义样式.原生的下拉框也保留在div ...

随机推荐

  1. 分组取前N记录(转)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 经常看到问题,如何取出每组的前N条记录.方便大家参考于是便把常见的几种解法列出于下. 问题:有表 如下,要求取出各班前两名(允许并列第二)Tabl ...

  2. IT类影视

    1.爱奇艺 代码(The Code) 2.爱奇艺 操作系统革命(Revolution OS) 3.爱奇艺 互联网之子 4.爱奇艺 深网

  3. WPF ItemControl的源与选择项问题

    具体场景: datagrid的行中有个combox 每个行是一个实例A 每个行中的SelectedItem是实例A的一个属性B 我希望实现datagrid的复制Command,具体做法是A序列化反序列 ...

  4. java-items

    类名Items package entity; //商品类 public class Items { private int id; // 商品编号 private String name; // 商 ...

  5. 【dart学习】-- dart 安装开发环境

    前言 说明下:本人只有window和mac,所以安装实践只有这两种,其他的自行尝试.简介:Dart是谷歌开发的计算机编程语言,后来被Ecma (ECMA-408)认定为标准 [1] .它被用于web. ...

  6. JavaWeb开发中遇到的错误:org.apache.catalina.core.StandardWrapperValve invoke

    org.apache.catalina.core.StandardWrapperValve invoke 今天写代码,竟然接连遇到这个异常好几次.debug几个小时才弄明白,晕. 上网找了些拼凑下做个 ...

  7. AcWing 202. 最幸运的数字 (欧拉定理)打卡

    8是中国的幸运数字,如果一个数字的每一位都由8构成则该数字被称作是幸运数字. 现在给定一个正整数L,请问至少多少个8连在一起组成的正整数(即最小幸运数字)是L的倍数. 输入格式 输入包含多组测试用例. ...

  8. (转)OpenFire源码学习之十八:IOS离线推送

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43458213 IOS离线推送 场景: 如果您有iOS端的APP,在会话聊天的时候,用户登 ...

  9. JAVA导出excel如何设置表头跨行或者跨列,跪求各位大神了

    sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 0));// 开始行,结束行,开始列,结束列.只能是POI了吧?java还有其他方法吗?

  10. 广度优先搜索(Breadth First Search)

    Date:2019-07-03 14:29:02 走完一层的所有房间,再走下一层,用队列实现 算法实现 /*--------------------------模版------------------ ...