为什么 TStringGrid 的子控件不能正常工作? [英] Why don't child controls of a TStringGrid work properly?

查看:32
本文介绍了为什么 TStringGrid 的子控件不能正常工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将复选框 (TCheckBox) 放置在第一列的字符串网格 (TStringGrid) 中.复选框显示良好,位置正确,鼠标悬停在它们上方时会发光以响应鼠标.但是,当我单击它们时,它们不会切换.他们对点击做出反应并突出显示,但最终,实际的 Checked 属性不会改变.更令人费解的是,一旦这些值存在,我就没有任何代码更改它们,我什至没有将 OnClick 事件分配给这些复选框.此外,我默认这些复选框未选中,但显示时,它们选中.

I am placing checkboxes (TCheckBox) in a string grid (TStringGrid) in the first column. The checkboxes show fine, positioned correctly, and respond to mouse by glowing when hovering over them. When I click them, however, they do not toggle. They react to the click, and highlight, but finally, the actual Checked property does not change. What makes it more puzzling is I don't have any code changing these values once they're there, nor do I even have an OnClick event assigned to these checkboxes. Also, I'm defaulting these checkboxes to be unchecked, but when displayed, they are checked.

复选框与添加到列表中的每条记录一起创建,并在记录指针内引用,该指针分配给要放置复选框的单元格中的对象.

The checkboxes are created along with each record which is added to the list, and is referenced inside a record pointer which is assigned to the object in the cell where the checkbox is to be placed.

用于单元格突出显示的字符串网格技巧:

String grid hack for cell highlighting:

type
  THackStringGrid = class(TStringGrid); //used later...

包含复选框的记录:

  PImageLink = ^TImageLink;
  TImageLink = record
    ...other stuff...
    Checkbox: TCheckbox;
    ShowCheckbox: Bool;
  end;

复选框的创建/销毁:

function NewImageLink(const AFilename: String): PImageLink;
begin
  Result:= New(PImageLink);
  ...other stuff...
  Result.Checkbox:= TCheckbox.Create(nil);
  Result.Checkbox.Caption:= '';
end;

procedure DestroyImageLink(AImageLink: PImageLink);
begin
  AImageLink.Checkbox.Free;
  Dispose(AImageLink);
end;

向网格添加行:

//...after clearing grid...
//L = TStringList of original filenames
if L.Count > 0 then
  lstFiles.RowCount:= L.Count + 1
else
  lstFiles.RowCount:= 2; //in case there are no records
for X := 0 to L.Count - 1 do begin
  S:= L[X];
  Link:= NewImageLink(S); //also creates checkbox
  Link.Checkbox.Parent:= lstFiles;
  Link.Checkbox.Visible:= Link.ShowCheckbox;
  Link.Checkbox.Checked:= False;
  Link.Checkbox.BringToFront;
  lstFiles.Objects[0,X+1]:= Pointer(Link);
  lstFiles.Cells[1, X+1]:= S;
end;

Grid 的 OnDrawCell 事件处理程序:

Grid's OnDrawCell Event Handler:

procedure TfrmMain.lstFilesDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  Link: PImageLink;
  CR: TRect;
begin
  if (ARow > 0) and (ACol = 0) then begin
    Link:= PImageLink(lstFiles.Objects[0,ARow]); //Get record pointer
    CR:= lstFiles.CellRect(0, ARow); //Get cell rect
    Link.Checkbox.Width:= Link.Checkbox.Height;
    Link.Checkbox.Left:= CR.Left + (CR.Width div 2) - (Link.Checkbox.Width div 2);
    Link.Checkbox.Top:= CR.Top;
    if not Link.Checkbox.Visible then begin
      lstFiles.Canvas.Brush.Color:= lstFiles.Color;
      lstFiles.Canvas.Brush.Style:= bsSolid;
      lstFiles.Canvas.Pen.Style:= psClear;
      lstFiles.Canvas.FillRect(CR);
      if lstFiles.Row = ARow then
        THackStringGrid(lstFiles).DrawCellHighlight(CR, State, ACol, ARow);
    end;
  end;
end;

这是点击时的样子...

Here's how it looks when clicking...

可能是什么原因造成的?它绝对不会更改我代码中任何地方的 Checked 属性.放置在网格中时,复选框本身会产生一些奇怪的行为.

What could be causing this? It's definitely not changing the Checked property anywhere in my code. There's some strange behavior coming from the checkboxes themselves when placed in a grid.

编辑

我做了一个简短的测试,我在表单上放置了一个常规的 TCheckBox.检查/取消检查很好.然后,在表单的 OnShow 事件中,我将复选框的 Parent 更改为该网格.这一次,我得到了相同的行为,点击时不会切换.因此,当 TCheckBox 将另一个控件作为其父控件时,它似乎无法正确响应.如何克服这个问题?

I did a brief test, I placed a regular TCheckBox on the form. Check/unchecks fine. Then, in my form's OnShow event, I changed the Checkbox's Parent to this grid. This time, I get the same behavior, not toggling when clicked. Therefore, it seems that a TCheckBox doesn't react properly when it has another control as its parent. How to overcome this?

推荐答案

TStringGridWMCommand 处理程序不允许子控件处理消息(InplaceEdit 除外).

TStringGrid's WMCommand handler doesn't allow children controls to handle messages (except for InplaceEdit).

所以你可以使用例如插入的类(基于 Peter 下面的代码)或绘制控件用手,正如一些人所建议的那样.下面是插入类的代码:

So you can use e.g. an interposed class (based on code by Peter Below) or draw controls by hands, as some people have adviced. Here is the code of the interposed class:

uses
  Grids;

type
  TStringGrid = class(Grids.TStringGrid)
  private
    procedure WMCommand(var AMessage: TWMCommand); message WM_COMMAND;
  end;

implementation

procedure TStringGrid.WMCommand(var AMessage: TWMCommand);
begin
  if EditorMode and (AMessage.Ctl = InplaceEditor.Handle) then
    inherited
  else
  if AMessage.Ctl <> 0 then
  begin
    AMessage.Result := SendMessage(AMessage.Ctl, CN_COMMAND,
      TMessage(AMessage).WParam, TMessage(AMessage).LParam);
  end;
end;

这篇关于为什么 TStringGrid 的子控件不能正常工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆