![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как правильно осовбодить контролы на StringGrid
Nil © (2007-12-12 14:05:00)Создаю контролы так:
procedure TForm3.FormCreate(Sender: TObject);
var
B: TButton;
P: TPanel;
I, J, CurRow: Integer;
begin
for I := 1 to 10 do
begin
StringGrid1.RowCount:=i;
P:=TPanel.Create(Panel1);
P.Parent:=Self;
P.Width:=50;
P.Height:=24;
P.Visible:=False;
B := TButton.Create(P);
B.Parent:=Self;
B.Caption:='0-'+IntToStr(i);
B.Width:=20;
B.Height:=20;
B.Top:=2;
B.Left:=2;
B.Visible:=True;
B.Name:='But0'+IntToStr(i);
P.InsertControl(B);
B := TButton.Create(P);
B.Parent:=Self;
B.Caption:='1-'+IntToStr(i);
B.Width:=20;
B.Height:=20;
B.Top:=2;
B.Left:=24;
B.Visible:=True;
B.Name:='But1'+IntToStr(i);
P.InsertControl(B);
StringGrid1.Cells[0,i-1]:='Button'+IntToStr(i);
StringGrid1.Objects[0,i-1] := P;
end;
end;
procedure TForm3.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
B: TButton;
P: TPanel;
begin
if StringGrid1.Objects[ACol, ARow] is TControl then P:=(StringGrid1.Objects[ACol,ARow] as TPanel) else P:=nil;
if not (gdFixed in State) and (P is TPanel) then
begin
P.Left:=StringGrid1.Left+Rect.Left+Rect.Right-P.Width+Panel1.Left;
P.Top:=StringGrid1.Top+Rect.Top+Panel1.Top+4;
P.Visible:=True;
end;
end;
procedure TForm3.StringGrid1VerticalScroll(Sender: TObject);
begin
StringGrid1.Refresh;
end;
при закрытии приложения получаю EInvalidPointer: Invalid pointer operation..
идея в том чтобы сделать родителем всех динамически созданных контролов TPanel, который кинул на форму в design time. как я понимаю, при закрытии приложения, всё что связано с этой панелью должно правильно освободиться, включая всех детей этой панели. но похоже что то пошло не так:) подскажите пож в чём проблема и как это правильнее организовать
заранее благодарен
Nil (2007-12-13 16:35:00) [1]Спасибо большое! Получилось всё гораздо проще чем я думал
DiamondShark (2007-12-12 16:24:00) [2]
> нужно принаведении курсора на кнопочку, поменять его вид.
> . может ещё какая чудо функция есть?)
Положение курсора отслеживается в собитии OnMouseMove.
Попадание курсора в ячейку определяется MouseToCell
Вид курсора определяется свойством Cursor
А чудо состоит в нужной комбинации операторов.
Anatoly Podgoretsky (2007-12-12 16:10:00) [3]> Nil (12.12.2007 16:00:07) [7]
Эта мегафункция называется Cursor
Anatoly Podgoretsky (2007-12-12 16:09:00) [4]> Nil (12.12.2007 16:00:07) [7]
Nil (2007-12-12 16:00:00) [5]а вот ещё подскажи пож, нужно принаведении курсора на кнопочку, поменять его вид.. может ещё какая чудо функция есть?)
Nil (2007-12-12 15:58:00) [6]пасибо отдельное большое! я первый раз слышу о MouseToCell. надо почаще в хелп нырять и смотреть что вообще бывает:) так гораздо проще. с контролами уже пол дня ковыряюсь, сначала не мог создать, теперь не могу разрушить)
ещё раз пасиба!
DiamondShark (2007-12-12 15:45:00) [7]
> Nil (12.12.07 15:17) [4]
> получается предлагаешь переписать TButton?:)
Я предлагаю воспользоваться уже предоставленными возможностями грида по кастом отрисовке и событиями мыши.
Впрочем, если этот кнопочкастый грид -- новаторская интерфейсная находка, то я бы написал компонент, наследник грида. Глядишь, ещё бы где пригодился.
Но для разовой работы вполне достаточно событий.
> эта задача займёт в разы больше времени и сил
Да ты ж ещё не пробовал.
Вот, смотри.
type
TForm1 = class(TForm)
...
private
FPushed: boolean;
...
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if (ACol = 2) and (ARow = 2) then
begin
if FPushed then
DrawFrameControl(StringGrid1.Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_PUSHED or DFCS_ADJUSTRECT)
else
DrawFrameControl(StringGrid1.Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_ADJUSTRECT);
if gdFocused in State then
begin
InflateRect(Rect, -1, -1);
DrawFocusRect(StringGrid1.Canvas.Handle, Rect);
end;
end
end;
procedure TForm1.StringGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
col, row: Integer;
r: TRect;
begin
StringGrid1.MouseToCell(X, Y, col, row);
FPushed := (col = 2) and (row = 2);
r := StringGrid1.CellRect(2, 2);
InvalidateRect(StringGrid1.Handle, @r, false);
end;
procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
FPushed := false;
StringGrid1.Invalidate;
end;
Пока для лучшей красоты желательно поставить DefaultDrawing = false.
Но это три минуты лабания до отправки ответа.
Вполне обнадёживающий результат. А если потратить столько же времени, сколько потратил до сих пор ты?
Так что не надо про разы.
> это прогрммулина с полностью нарисованным нестандартным
> интерфейсом
Ну так и рисуй его.
Зачем пихать батоны, куда они не лезут.
Nil (2007-12-12 15:17:00) [8]получается предлагаешь переписать TButton?:) зачем, когда за меня уже постарался борланд? эта задача займёт в разы больше времени и сил.. да и постоянно смотреть на OnMouseMove и определять над какой строкой она сейчас находится, это будет очень ресурсоёмкая задача, а как по другому узнать над какой именно ячейкой находится указатель я не знаю. мне кажется так будет намного проще, т.к. мне нужен не просто OnClick, а это будут картинки для которых мне будет нужен OnMouseEnter OnMouseLeave OnMouseUp OnMouseDown.
это прогрммулина с полностью нарисованным нестандартным интерфейсом, в этом и непрятность
DiamondShark (2007-12-12 15:03:00) [9]
> при таком подходе?
У тебя подход наизнанку вывернут.
У тебя ведь исходная задача не "правильно освободить", а "напихать кнопочек в грид". Так ведь?
Всё остальное -- следствие выбранного тобой, как тебе показалось, "лёгкого" решения.
А следствия не заставили себя ждать, ага? Как подгнать кнопочку под ячейку? Как подогнать кнопочку под скрол? Теперь вот, как освободить.
А если б ты чуть-чуть остановился, ты бы додумался, что тебе нет нужды запихивать в грид столько реальных кнопочек, сколько там ячеек. Тем более, что часть кнопочек всё равно не видна.
Тебе надо лишь чтобы в ячейках было что-то выглядящеекак кнопочки, и ведущее себякак кнопочки.
А для этого достаточно отрисовки и реакции на мышь.
Nil (2007-12-12 14:52:00) [10]тогда если правильно понял, то если для панелек которые создаю укажу владельца, например форму на которой stringgrid лежит, то при совобождении формы освободятся и всё панельки которыми она владеет?
сделал так:
procedure TForm3.FormCreate(Sender: TObject);
var
B: TButton;
P: TPanel;
I, J, CurRow: Integer;
begin
for I := 1 to 10 do
begin
StringGrid1.RowCount:=i;
P:=TPanel.Create(Form3);
P.Parent:=Self;
P.Width:=50;
P.Height:=24;
P.Visible:=False;
B := TButton.Create(P);
B.Parent:=P;
B.Caption:='0-'+IntToStr(i);
B.Width:=20;
B.Height:=20;
B.Top:=2;
B.Left:=2;
B.Visible:=True;
B.Name:='But0'+IntToStr(i);
B := TButton.Create(P);
B.Parent:=P;
B.Caption:='1-'+IntToStr(i);
B.Width:=20;
B.Height:=20;
B.Top:=2;
B.Left:=24;
B.Visible:=True;
B.Name:='But1'+IntToStr(i);
StringGrid1.Cells[0,i-1]:='Button'+IntToStr(i);
StringGrid1.Objects[0,i-1] := P;
end;
end;
EInvalidPointer не вываливается, теперь вопрос правильно ли всё освободится (панельки, кнопки которые на этих панельках) при таком подходе?
Kolan (2007-12-12 14:08:00) [11]> идея в том чтобы сделать родителем всех динамически созданных
> контролов TPanel
> всё что связано с этой панелью должно правильно освободиться
Нет. Родитель(Parent) это одно. Owner(владелец) другое. Освободится все чем владеет панель.