【问题标题】:Put a TCheckBox inside a TStringGrid in Delphi在 Delphi 的 TStringGrid 中放置一个 TCheckBox
【发布时间】:2011-07-15 10:19:57
【问题描述】:

我想在 Delphi 的某个列的每个单元格中的 TStringGrid 中放置一个 TCheckBox。我正在使用 Delphi XE。

【问题讨论】:

    标签: delphi delphi-xe tstringgrid tcheckbox


    【解决方案1】:

    不要尝试将实际的TCheckBox 控件放置在TStringGrid 中。将网格的 OnDrawCell 事件与 Win32 API DrawFrameControl() 函数一起使用,根据需要在每个单元格内绘制 CheckBox 控件的图像。您可以将OnClick/OnMouse... 事件与网格的Objects[][] 属性一起使用,以根据需要跟踪每个单元格的检查状态。我发现这更容易管理,因为 TStringGrid 不是为托管实际控件而设计的。

    【讨论】:

      【解决方案2】:

      如果启用,您应该绘制自己的复选框,最好使用视觉主题。这是如何做到这一点的简单草图:

      const
        Checked: array[1..4] of boolean = (false, true, false, true);
      
      procedure TForm4.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
        Rect: TRect; State: TGridDrawState);
      const
        PADDING = 4;
      var
        h: HTHEME;
        s: TSize;
        r: TRect;
      begin
        if (ACol = 2) and (ARow >= 1) then
        begin
          FillRect(StringGrid1.Canvas.Handle, Rect, GetStockObject(WHITE_BRUSH));
          s.cx := GetSystemMetrics(SM_CXMENUCHECK);
          s.cy := GetSystemMetrics(SM_CYMENUCHECK);
          if UseThemes then
          begin
            h := OpenThemeData(StringGrid1.Handle, 'BUTTON');
            if h <> 0 then
              try
                GetThemePartSize(h,
                  StringGrid1.Canvas.Handle,
                  BP_CHECKBOX,
                  CBS_CHECKEDNORMAL,
                  nil,
                  TS_DRAW,
                  s);
                r.Top := Rect.Top + (Rect.Bottom - Rect.Top - s.cy) div 2;
                r.Bottom := r.Top + s.cy;
                r.Left := Rect.Left + PADDING;
                r.Right := r.Left + s.cx;
                DrawThemeBackground(h,
                  StringGrid1.Canvas.Handle,
                  BP_CHECKBOX,
                  IfThen(Checked[ARow], CBS_CHECKEDNORMAL, CBS_UNCHECKEDNORMAL),
                  r,
                  nil);
              finally
                CloseThemeData(h);
              end;
          end
          else
          begin
            r.Top := Rect.Top + (Rect.Bottom - Rect.Top - s.cy) div 2;
            r.Bottom := r.Top + s.cy;
            r.Left := Rect.Left + PADDING;
            r.Right := r.Left + s.cx;
            DrawFrameControl(StringGrid1.Canvas.Handle,
              r,
              DFC_BUTTON,
              IfThen(Checked[ARow], DFCS_CHECKED, DFCS_BUTTONCHECK));
          end;
          r := Classes.Rect(r.Right + PADDING, Rect.Top, Rect.Right, Rect.Bottom);
          DrawText(StringGrid1.Canvas.Handle,
            StringGrid1.Cells[ACol, ARow],
            length(StringGrid1.Cells[ACol, ARow]),
            r,
            DT_SINGLELINE or DT_VCENTER or DT_LEFT or DT_END_ELLIPSIS);
        end;
      end;
      

      当然,在实际场景中,Checked 数组不是常量,您可能希望在单元格绘制事件之间保存s 指标和h 主题句柄。但原理就在这里。

      这里缺少的是一个改变复选框状态的函数。您可能希望在OnClick 处理程序中切换状态。如果您真的很认真,您还希望响应鼠标的运动,并在主题可用时在复选框上显示鼠标悬停效果。

      由蓝色编辑:切换复选框状态this answer 解释了如何使用Invalidate 方法。

      【讨论】:

      • Andreas 您介意我借用该代码并将其放入 JVCL 字符串网格吗?这将是一个很好的补充。
      • @Warren P:随意使用代码。 @Ken:抱歉,无法抗拒!
      • 谢谢,它可以工作,在 JVCL Grid 上有这个会很好
      • @AndreasRejbrand 如果我们想管理自己的onclick,是否意味着我们要重复这个过程,还是什么?我们如何检查绘制主题的状态?请给我一个提示。
      • @AndreasRejbrand 感谢您提供这个很棒的解决方案。 ∞+1
      【解决方案3】:

      我使用 Roman Mochalov 的名为 ExGridView 的虚拟网格,它支持复选框。

      我自己修改的 GridView 分支,移植到 Unicode 等,命名为 TExGridView,而不是 TGridView,并且带有复选框的演示在 bitbucket here 上作为 /wpostma/exgridview。

      ExGridView 组件在属性检查器中有一个 Checkbox 属性,该属性必须设置为 true,然后您必须设置 Column 属性,以便 Column 将复选框类型设置为复选框或单选按钮。然后您必须实现 GetCheckState 事件回调。请参阅 bitbucket 项目中包含的演示。

      此代码的原始来源是 here,但它不能在最新版本上构建。我的 bitbucket 版本已经过测试,可与 Delphi 2007、2009 以及截至 2016 年的所有最新版本(Delphi 10 Seattle)一起使用。

      【讨论】:

      • 如何从 Roman Mochalov 的 ExGridView 中添加 CheckBox 到 GridView 上???
      • @WarrenP 我使用 TMS AdvStringGrid,但它是否支持其复选框的灰色状态(我不这么认为)?我如何管理自己的灰色复选框?我可以用某种方式给它上色吗?
      • 为什么不问 TMS?他们很好地支持他们的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多