我想在某个列的每个单元格中放入TCheckBox
一个在 Delphi 中的内部。TStringGrid
我正在使用德尔福 XE。
3 回答
如果启用,您应该绘制自己的复选框,最好使用视觉主题。这是如何做到这一点的简单草图:
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
处理程序中切换状态。如果您真的很认真,您还希望响应鼠标的运动,并在主题可用时在复选框上显示鼠标悬停效果。
由蓝色编辑:要切换复选框状态,此答案说明了如何使用Invalidate
方法。
不要试图TCheckBox
在TStringGrid
. OnDrawCell
而是使用带有 Win32 API函数的网格事件,DrawFrameControl()
根据需要在每个单元格内绘制 CheckBox 控件的图像。您可以根据需要使用OnClick/OnMouse...
带有网格Objects[][]
属性的事件来跟踪每个单元格的选中状态。我发现这更容易管理,因为TStringGrid
它不是为托管真正的控件而设计的。
我使用 Roman Mochalov 的名为ExGridView的虚拟网格,它支持复选框。
我自己修改的 GridView 分支,移植为 Unicode 等,命名为 TExGridView,而不是 TGridView,并且带有复选框的演示在 bitbucket 上作为 / wpostma /exgridview。
ExGridView 组件在属性检查器中有一个 Checkbox 属性,该属性必须设置为 true,然后您必须设置 Column 属性,以便 Column 将复选框类型设置为复选框或单选按钮。然后您必须实现 GetCheckState 事件回调。请参阅 bitbucket 项目中包含的演示。
这段代码的原始来源在这里,但它不能在最近的版本上构建。我的 bitbucket 版本已经过测试,可与 Delphi 2007、2009 以及截至 2016 年的所有最新版本(Delphi 10 Seattle)一起使用。