delphi - 为什么 TStringGrid 的子控件不能正常工作?

标签 delphi checkbox mouseevent delphi-xe2 tstringgrid

我将复选框 (TCheckBox) 放置在第一列的字符串网格 (TStringGrid) 中。复选框显示良好,位置正确,并且在将鼠标悬停在其上方时通过发光来响应鼠标。然而,当我单击它们时,它们不会切换。它们对点击使用react并突出显示,但最终,实际的 Checked 属性并没有改变。更令人费解的是,我没有任何代码来更改这些值,我什至也没有为这些复选框分配 OnClick 事件。另外,我默认这些复选框未选中,但在显示时,它们已选中

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

用于单元格突出显示的字符串网格黑客:

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 事件处理程序:

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;

这是点击时的样子...

Reacts to Mouse Click but Doesn't Change

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

编辑

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

最佳答案

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

所以你可以使用例如正如一些人所建议的那样,插入一个类(基于 code by Peter Below )或手动绘制控件。这是插入类的代码:

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;

关于delphi - 为什么 TStringGrid 的子控件不能正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11719454/

相关文章:

拖动期间释放鼠标时忽略 JavaScript mouseUp 事件

delphi - 未声明的标识符 TEncoding delphi7

javascript - 如何一次禁用网页上的所有复选框?

javascript - 使用索引从复选框中提取值

c# - 事件 "While Button is Pressed"

javascript - 使用 jQuery 为元素设置动画并调用 stop()

Delphi 5 编译器错误返回接口(interface)指针而不是返回值

delphi - 如何将方法指针作为窗口消息参数发送?

delphi - 串口连接超过6个设备有限制吗?

android - 检查是否选中了任何复选框