Delphi XE4中不可选中的动态创建的TCheckBox

Delphi XE4中不可选中的动态创建的TCheckBox,delphi,Delphi,我想创建一个属性编辑器,因为TValueListEditor不支持很多东西。因此,当用户输入单元格时,我使用了TStringGrid和其他控件。当我为布尔值放置TCheckBox时,动态创建的TCheckBox是不可选中的。onClick事件处理程序没有被单击触发(网格被触发),而TCheckBox的标题失去了不透明度。我把它的父母放在前面。此时,我还使用了TEdit和TComboBox控件,它们工作正常。有人可以帮助以预期的方式使用它吗 下面是一个重现这种情况的示例 考绩制度: dfm: ob

我想创建一个属性编辑器,因为
TValueListEditor
不支持很多东西。因此,当用户输入单元格时,我使用了
TStringGrid
和其他控件。当我为布尔值放置
TCheckBox
时,动态创建的
TCheckBox
是不可选中的。
onClick
事件处理程序没有被单击触发(网格被触发),而
TCheckBox
的标题失去了不透明度。我把它的父母放在前面。此时,我还使用了
TEdit
TComboBox
控件,它们工作正常。有人可以帮助以预期的方式使用它吗

下面是一个重现这种情况的示例

考绩制度:

dfm:

object Form1: TForm1
  Left = 358
  Top = 183
  Caption = 'Form1'
  ClientHeight = 601
  ClientWidth = 854
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object StringGrid1: TStringGrid
    Left = 120
    Top = 72
    Width = 320
    Height = 120
    TabOrder = 0
  end
  object CheckBox1: TCheckBox
    Left = 192
    Top = 128
    Width = 97
    Height = 17
    Caption = 'Static checkbox'
    TabOrder = 1
  end
end

这不适用于复选框,因为字符串网格会拦截
WM_命令
消息的处理。单击复选框时,会向其父级(即字符串网格)发送
WM_命令
通知。“Vcl.Grids”的
TCustomGrid.WMCommand
中的网格检查通知是否来自其inplace编辑器,否则将丢弃消息

您可以修改网格上消息的处理以更改行为。一种方法是导出一个新控件。例如

type
  TStringGrid = class(vcl.grids.TStringGrid)
  protected
    procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
  end;

  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    ....

...

procedure TStringGrid.WMCommand(var Message: TWMCommand);
var
  Control: TWinControl;
begin
  inherited;
  Control := FindControl(Message.Ctl);
  if Assigned(Control) and (Control <> InplaceEditor) then
    Control.Perform(Message.Msg, MakeWParam(Message.ItemID, Message.NotifyCode),
        Message.Ctl);
end;
类型
TStringGrid=class(vcl.grids.TStringGrid)
受保护的
程序WMCommand(var消息:TWMCommand);消息WM_命令;
结束;
TForm1=类(TForm)
StringGrid1:TStringGrid;
....
...
过程TStringGrid.WMCommand(var消息:TWMCommand);
变量
控制:双控制;
开始
继承;
控件:=FindControl(Message.Ctl);
如果分配了(控制)和(控制InplaceEditor),则
Control.Perform(Message.Msg、MakeWParam(Message.ItemID、Message.NotifyCode),
Message.Ctl);
结束;
然后,
OnClick
将启动。您不需要
BringToFront
,它可以在同级控件之间工作



关于不透明度,它是复选框的默认外观。您可以通过在表单本身上放置一个与标签重叠的复选框来验证这一点。

您到底需要什么
TValueListEditor
无法处理的内容
TStringGrid
不是为承载子控件而设计的,它自己的内置单元格编辑器除外。只需使用网格的
OnDrawCell
事件,根据需要在单元格上绘制复选框的图像,然后使用网格的
OnMouseDown/Up
事件来“切换”单元格的检查状态,您的运气可能会更好。您可以使用网格的
对象
属性来跟踪状态数据。@RemyLebeau。可折叠的复合值、活动的内联编辑器(TEdit、TCOMBOX、TCECKBOX和自定义组件)。我想内联使用很多组件类型。你最好找一个第三方属性编辑器来处理所有这些内容,并且可以在运行时使用。仅使用默认的VCL组件将很难实现这一点。FWIW将复选框放置在面板上会更简单,并有助于单击和不透明度。事件处理问题已解决。谢谢。但是透明标题不是TCheckBox的默认行为。我将静态的一个放在示例中以说服它。静态控件的标题首先覆盖其背景,然后写入文本。应该有一个属性影响控件的绘制。(我在文档中没有找到任何内容)您的TPanel建议也解决了我的其他问题。这是个好主意。再次非常感谢!:)
type
  TStringGrid = class(vcl.grids.TStringGrid)
  protected
    procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
  end;

  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    ....

...

procedure TStringGrid.WMCommand(var Message: TWMCommand);
var
  Control: TWinControl;
begin
  inherited;
  Control := FindControl(Message.Ctl);
  if Assigned(Control) and (Control <> InplaceEditor) then
    Control.Perform(Message.Msg, MakeWParam(Message.ItemID, Message.NotifyCode),
        Message.Ctl);
end;