Delphi XE4中无法取消动态创建的TCheckBox选项框

3
我想创建一个属性编辑器,因为很多东西不受TValueListEditor的支持。所以我使用了一个TStringGrid和其他控件放置在它上面,当用户输入单元格时会出现。当我为布尔值放置一个TCheckBox时,动态创建的TCheckBox无法勾选。onClick事件处理程序不会被点击触发(网格会被触发),而TCheckBox的标题失去了其不透明度。我设置了它的父级并将其带到前面。此时我也使用了TEdit和TComboBox控件,它们工作正常。有人可以帮助我按预期方式使用它吗?
这里是一个重新创建情况的示例。 pas:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids,
  StdCtrls;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    CheckBox1: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    procedure onCheckBoxClicked( sender_ : TObject );
  public
    { Public declarations }
    fCheckBox : TCheckBox;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.onCheckBoxClicked( sender_ : TObject );
begin
  if ( TCheckBox( sender_ ).checked ) then
    TCheckBox( sender_ ).caption := 'true'
  else
    TCheckBox( sender_ ).caption := 'false';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  fCheckBox := TCheckBox.create( NIL );
  fCheckBox.Parent := stringGrid1;
  fCheckBox.caption := 'Dynamic checkbox';
  fCheckBox.left := 70;
  fCheckBox.top := 30;
  fCheckBox.onClick := onCheckBoxClicked;
  fCheckBox.BringToFront;
  stringgrid1.cells[1,1] := 'fgfgfgfgfgf';
  stringgrid1.cells[1,2] := 'fgfgfgfgfgf';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  fCheckBox.Free;
end;

end.

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

TValueListEditor 无法处理什么问题? TStringGrid 不适合托管子控件,除了它自己的原地单元格编辑器。您可以尝试使用网格的 OnDrawCell 事件来绘制所需单元格上的 复选框 图像,然后使用网格的 OnMouseDown/Up 事件来“切换”单元格的选中状态。您可以使用网格的 Objects 属性来跟踪状态数据。 - Remy Lebeau
很多东西。可折叠的复合值、活跃的内联编辑器(TEdit、TComboBox、TCheckBox和自定义组件)。我想在内联中使用很多种组件。 - SOLID Developper
最好找一个第三方属性编辑器来处理所有这些东西,并且可以在运行时使用。只使用默认的VCL组件,你会很难完成这个任务。 - Remy Lebeau
1个回答

4

由于字符串网格截取了WM_COMMAND消息的处理,因此此方法不适用于复选框。单击复选框时,会向其父级(即字符串网格)发送WM_COMMAND通知。在“Vcl.Grids”中的TCustomGrid.WMCommand中,网格检查通知是否来自其原地编辑器,否则将丢弃该消息。

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

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;

然后触发OnClick事件。你不需要使用BringToFront,它适用于兄弟控件。


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


1
就此而言,将复选框放置在面板上会更简单,并有助于点击和不透明度。 - Sertac Akyuz
事件处理问题已解决,非常感谢。但是透明标题不是TCheckBox的默认行为。我在示例中放置了静态控件来证明它。静态控件的标题首先覆盖其背景,然后再写入文本。应该有一个属性来影响控件的绘制。(我在文档中没有找到任何信息) - SOLID Developper
您的 TPanel 推荐解决了我的另一个问题。这是个好主意。再次感谢您! :) - SOLID Developper
@sertac,我只是在OnDrawCell事件中使用了一对12x12 PNG图像进行呈现,但我很好奇 - 你的将复选框放置在面板上的建议是如何工作的? - rossmcm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接