Поместите TCheckBox в TStringGrid в Delphi
Я хочу поставить TCheckBox
внутри TStringGrid
в Delphi в каждой ячейке определенного столбца. Я использую Delphi 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
дескриптор темы между событиями рисования ячейки. Но принцип здесь.
http://privat.rejbrand.se/stringcheck1.png http://privat.rejbrand.se/stringcheck2.png
Чего здесь не хватает, так это функции для изменения состояния флажков. Возможно, вы захотите переключить состояние в OnClick
обработчик. Если вы действительно серьезны, вам также следует реагировать на движение мыши и отображать эффект наведения мыши на флажки, если доступны темы.
РЕДАКТИРОВАНИЕ синим цветом: чтобы переключить состояние флажка, этот ответ объясняет, как вы можете использовать Invalidate
метод.
Не пытайтесь разместить фактический TCheckBox
контроль внутри TStringGrid
, Используйте сетку OnDrawCell
событие с Win32 API DrawFrameControl()
вместо этого, чтобы нарисовать изображение элемента управления CheckBox внутри каждой ячейки по мере необходимости. Вы можете использовать OnClick/OnMouse...
события с сеткой Objects[][]
свойство для отслеживания проверенного состояния каждой ячейки при необходимости. Я считаю, что это намного проще в управлении, так как TStringGrid
не был предназначен для размещения реальных элементов управления.
Я использую виртуальную сетку под названием ExGridView Романа Мочалова, которая поддерживает флажки.
Мой собственный модифицированный форк GridView, портированный для Unicode и т. Д., С именем TExGridView вместо TGridView и с демонстрацией флажков, находится здесь как битовая корзина как /wpostma/exgridview.
Компонент ExGridView имеет свойство Checkbox в инспекторе свойств, которое должно быть установлено в значение true. Затем необходимо настроить свойства столбца таким образом, чтобы тип столбца имел тип флажка, установленный на флажок или переключатель. Затем вы должны реализовать обратный вызов события GetCheckState. Посмотрите демоверсию, включенную в проект bitbucket.
Первоначальный источник этого кода был здесь, но он не может быть использован в последних версиях. Моя версия BitBucket протестирована и работает с Delphi 2007, 2009 и всеми версиями, актуальными на 2016 год (Delphi 10 Seattle).