Динамическое создание TButton в TListview - неправильный подход.
Во-первых, вы должны понимать, что TListview - это обертка для общего элемента управления Microsoft (ComCtl32), и что размещение TButton там динамически во время выполнения - плохой хак. Что бы вы сделали, например, если бы пользователь изменил размер формы так, чтобы появилось ровно 3,5 кнопки? как вы собираетесь зажать кнопку, чтобы половина ее была видна? Или вы бы сделали частичные строки, не имеющие видимой кнопки? Вы действительно уверены, что справитесь со всеми странностями, которые могут произойти, когда пользователь прокручивает колесико мыши, и вам нужно динамически на ходу восстанавливать элементы управления? Вы не должны генерировать элементы управления и освобождать их в процедурах рисования или при нажатии мышкой вниз или вверх.
Если вы действительно хотите, чтобы там была кнопка, вам нужны два состояния изображения: не нажатое и нажатое изображение, которое вы рисуете владельцем в правильном месте, когда сфокусирована правильная ячейка. И наведением мыши, в этой области вы обнаруживаете щелчок
однако, если вы настаиваете, то я бы сделал это:
- Создайте кнопку или кнопки один раз, динамически, в начале программы, и сделайте каждую кнопку видимой или невидимой по мере необходимости.
- Показать или скрыть элементы массива button-or-button-control-массив, вместо того, чтобы выделять их, скрывать вместо освобождения, когда у вас слишком много кнопок.
Ваше изображение показывает одну кнопку на строку, поэтому предположим, что вам понадобится массив из примерно 30 кнопок, созданный во время выполнения и сохраненный в массиве управления (TList или Array of TButton)
Типичный пример сетки с кнопками, нарисованными владельцем, в каждой строке, эти кнопки рисуются внутри ячеек, и при нажатии кнопки мыши при необходимости кнопка рисуется в нижнем или верхнем состоянии:
Но чтобы рисовать каждый элемент, по одной строке за раз, я должен был получить код владельца-кнопки и нарисовать кнопку в каждой ячейке.
Владелец рисует код:
// ExGridView1:TExGridView from https://sites.google.com/site/warrenpostma/
procedure TForm1.ExGridView1DrawCell(Sender: TObject; Cell: TExGridCell;
var Rect: TRect; var DefaultDrawing: Boolean);
var
btnRect:TRect;
ofs:Integer;
caption:String;
tx,ty:Integer;
Flags,Pressed: Integer;
DC:HDC;
begin
if Cell.Col = 1 then begin
DC := GetWindowDC(ExGridView1.Handle);
with ExGridView1.Canvas do
begin
Brush.Color := clWindow;
Rectangle(Rect);
caption := 'Button '+IntToStr(cell.Row);
Pen.Width := 1;
btnRect.Top := Rect.Top +4;
btnRect.Bottom := Rect.Bottom -4;
btnRect.Left := Rect.left+4;
btnRect.Right := Rect.Right-4;
Pen.Color := clDkGray;
if FMouseDown=Cell.Row then
begin
Flags := BF_FLAT;
Pressed := 1;
end else begin
Flags := 0;
Pressed := 0;
end;
Brush.Color := clBtnFace;
DrawEdge(DC, btnRect, EDGE_RAISED, BF_RECT or BF_MIDDLE or Flags);
Flags := (btnRect.Right - btnRect.Left) div 2 - 1 + Pressed;
PatBlt(DC, btnRect.Left + Flags, btnRect.Top + Flags, 2, 2, BLACKNESS);
PatBlt(DC, btnRect.Left + Flags - 3, btnRect.Top + Flags, 2, 2, BLACKNESS);
PatBlt(DC, btnRect.Left + Flags + 3, btnRect.Top + Flags, 2, 2, BLACKNESS);
Font.Color := clBtnText;
Font.Style := [fsBold];
tx := btnRect.left + ((btnRect.Right-btnRect.Left) div 2) - (TextWidth(Caption) div 2);
ty := btnRect.Top + 2;
TextOut(tx,ty,caption);
end;
DefaultDrawing := false;
end;
end;
Существует другой код, не показанный выше, для управления мышью вниз и мышью вверх, чтобы выяснить, когда нажимается кнопка. Я могу загрузить полный пример кода куда-нибудь, если вы хотите.