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

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

问题描述

我在第一列的字符串网格( TStringGrid )中放置复选框( TCheckBox 复选框显示精细,位置正确,当鼠标悬停在它们上方时,通过发光来响应。当我点击它们,但是,他们不切换。他们对点击作出反应,并突出显示,但最终,实际的 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:

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.

EDIT

我做了一个简短的测试,我在表单上放置了一个常规的 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?

推荐答案

TStringGrid WMCommand 处理程序不允许子控件处理消息(InplaceEdit除外)。

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

因此,您可以使用一个插入类(基于 Peter Under 的代码)或通过手,因为一些人已经建议。下面是插入类的代码:

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天全站免登陆