Я использую совершенно другой способ выполнения задания ... Создайте целый блок, просто чтобы добавить метод к ExtCtrls.TControlCollection
, не касаясь блока ExtCtrls
(первый взлом), и заставьте такой метод использовать InternalSetLocation
(второй взлом) ). Я также объясняю оба взлома в этом посте.
Тогда мне нужно только добавить такой модуль в секцию использования реализаций (до объявления gridpanel) и вызвать созданный мною метод ... очень простой в использовании.
Вот как я это делаю, шаг за шагом:
- Я включил в проект такой модуль, который я создал для такой работы (добавить файл)
- Я добавляю к своему интерфейсу TForm раздел, использующий такой блок (или где он мне нужен)
- Я использую свой метод
AddControlAtCell
вместо ExtCtrls.TControlCollection.AddControl
Вот блок, который я создал для такой работы, сохраните его как unitTGridPanel_WithAddControlAtCell
:
unit unitTGridPanel_WithAddControlAtCell;
interface
uses
Controls
,ExtCtrls
;
type TGridPanel=class(ExtCtrls.TGridPanel)
private
public
procedure AddControlAtCell(AControl:TControl;AColumn:Integer;ARow:Integer); // Add Control on specifed cell, if there already exists a Control it will be deleted
end;
implementation
uses
SysUtils
;
type
THackControlItem=class(TControlItem); // To get internal access to InternalSetLocation procedure
procedure TGridPanel.AddControlAtCell(AControl:TControl;AColumn:Integer;ARow:Integer);
var
TheControlItem:TControlItem; // To let it be added in a specified cell, since ExtCtrls.TControlCollection.AddControl contains multiply BUGs
begin // Add Control on specifed cell, if there already exists a Control it will be deleted
if (-1<AColumn)and(AColumn<ColumnCollection.Count) // Cell with valid Column
and // Cell inside valid range
(-1<ARow)and(ARow<RowCollection.Count) // Cell with valid Row
then begin // Valid cell, must check if there is already a control
if (Nil<>ControlCollection.ControlItems[AColumn,ARow]) // Check if there are any controls
and // A control is already on the cell
(Nil<>ControlCollection.ControlItems[AColumn,ARow].Control) // Check if cell has a control
then begin // There is already a control, must be deleted
ControlCollection.Delete(ControlCollection.IndexOf(ControlCollection.ControlItems[AColumn,ARow].Control)); // Delete the control
end;
TheControlItem:=ControlCollection.Add; // Create the TControlItem
TheControlItem.Control:=TControl(AControl); // Put the Control in the specified cell without altering any other cell
THackControlItem(ControlCollection.Items[ControlCollection.IndexOf(AControl)]).InternalSetLocation(AColumn,ARow,False,False); // Put the ControlItem in the cell without altering any other cell
end
else begin // Cell is out of range
raise Exception.CreateFmt('Cell [%d,%d] out of range on ''%s''.',[AColumn,ARow,Name]);
end;
end;
end.
Надеюсь, комментарии достаточно четкие, пожалуйста, прочитайте их, чтобы понять, почему и как я это делаю.
Затем, когда мне нужно добавить элемент управления в сеточную панель в указанной ячейке, я делаю следующий простой вызов:
TheGridPanel.AddControlAtCell(TheControl,ACloumn,ARow); // Add it at desired cell without affecting other cells
Очень, очень простой пример добавления вновь созданного TCheckBox во время выполнения в конкретную ячейку может выглядеть следующим образом:
// AColumn is of Type Integer
// ARow is of Type Integer
// ACheckBox is of Type TCheckBox
// TheGridPanel is of Type TGridPanel
ACheckBox:=TCheckBox.Create(TheGridPanel); // Create the Control to be added (a CheckBox)
ACheckBox.Visible:=False; // Set it to not visible, for now (optimization on speed, e tc)
ACheckBox.Color:=TheGridPanel.Color; // Just to use same background as on the gridpanel
ACheckBox.Parent:=TheGridPanel; // Set the parent of the control as the gridpanel (mandatory)
TheGridPanel.AddControlAtCell(ElCheckBox,ACloumn,ARow); // Add it at desired cell without affecting other cells
ElCheckBox.Visible:=True; // Now it is added, make it visible
ElCheckBox.Enabled:=True; // And of course, ensure it is enabled if needed
Обратите внимание, что я использую эти два хака:
type THackControlItem
позвольте мне получить доступ к методу InternalSetLocation
.
type TGridPanel=class(ExtCtrls.TGridPanel)
позвольте мне добавить метод к ExtCtrls.TGridPanel
, даже не касаясь (не нуждаясь в источнике ExtCtrls
)
Важно: Также обратите внимание, что я упомянул, что необходимо добавить модуль к использованию интерфейса каждой формы, где вы хотите использовать метод AddControlAtCell
; то есть для обычных людей, продвинутые люди могут также создать другой модуль и т. д. «концепция» состоит в том, чтобы использовать модуль перед использованием до объявления GridPanel, где вы хотите его использовать ... пример: если GridPanel помещается во время разработки в форму ... он должен продолжать реализацию такой единицы формы.
Надеюсь, это поможет кому-то еще.