| 
| 
 | Вопрос # 4 532/ вопрос открыт / | 
 |  Всех приветствую.Вопрос возможно нубовский, но тем не менее
 проблема состоит в том что я програмно создаю много кнопок на форме, попутно занося указатели на них в связный список. После этого я пытаюсь удалить первую созданную кнопку, в результате получаю ошибку обращения к памяти, почему не понимаю.
 Если ктото знает как решить проблему отпишите пожалуста.
 
 P.S. про dispose знаю, но это не помогает в моей проблеме, и потом еще думаю что если не уничтожить панель, то возможны утечки памяти.
 Приложение:Переключить в обычный режим unit Unit1; interface uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls; type  TForm1 = class(TForm)    Button1: TButton;    procedure FormClick(Sender: TObject);    procedure Button1Click(Sender: TObject);    procedure FormCreate(Sender: TObject);   private    { Private declarations }  public    { Public declarations }  end; type MyFerst = recordnum: integer;next: Pointer;End; type TMyElement = recordprev: Pointer;button: TButton;next: Pointer;End; type MyElementP = ^TMyElement; var  Form1: TForm1;  MyButton: TButton;  i:integer;     implementation {$R *.dfm}  procedure TForm1.FormClick(Sender: TObject);varALeft, ATop, AWidth, AHeight: Integer;MyPoint: TPoint;p:pointer;BeginWindows.GetCursorPos(MyPoint);AWidth := 75;AHeight := 25;ALeft := MyPoint.X-Form1.Left-5;ATop := MyPoint.Y-Form1.Top-35; i:=i+1;  Ferst.num:=i;   Begin Ferst.next:=Pointer(ElementP); Element:=ElementP^; Element.prev:=@Ferst; End  Begin Element.next:=Pointer(ElementP); p:=@Element; Element:=ElementP^; Element.prev:=p; End;  Element.next:=nil; MyButton:=Element.button;MyButton.Parent:=Form1;MyButton.Name:='ButtonN'+IntToStr(i);  end; procedure TForm1.Button1Click(Sender: TObject);beginElementP:=MyElementP(Ferst.next);Element:=ElementP^;MyButton:=Element.button; end; procedure TForm1.FormCreate(Sender: TObject);begin Ferst.next:=nil;end; end.
|  |   Вопрос задал: SOA (статус: Посетитель)Вопрос отправлен: 24 августа 2010, 18:14
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Вадим К Здравствуйте, SOA!Вообще то я рекомендовал бы взять TList и не заниматься изобретением велосипедов. Там просто.
 вначале создам
 list := TList.create;
 
 добавляем
 list.add(button);
 
 удаляем по индексу
 but := TButton(list[i]);
 but.free;
 list.delete(i);
 
 удалим list в конце работы
 list.free;
 правда перед этим не забываем почистить оставшиеся элементы.
 
 
 Если по коду, то тут есть базовое недопонимание. Оно в строках
 Element:=ElementP^;
 Element.prev:=@Ferst;
 
 В первой строке объект копируется, это же запись.
 и когда в следующей строке делается присваивание, то исходный объект, куда указывает ElementP^ не изменяется! И так как указатель указывает неведомо куда, получаем в лоб.
 нужно первую строку выкинуть, а в второй писать так
 ElementP^.prev:=@Ferst;
 
|  | Ответ отправил: Вадим К (статус: Академик)Время отправки: 24 августа 2010, 18:39
 Оценка за ответ: 5
 Комментарий к оценке: Спасибо за разъяснения, если сделать так как вы написали, то все работает. |  
 Мини-форум вопросаВсего сообщений: 25; последнее сообщение — 13 октября 2014, 23:07; участников в обсуждении: 5. Страницы: [1] [2] [Следующая »]  
|   | SOA (статус: Посетитель), 25 августа 2010, 07:32 [#1]:Из написанного в ответе я понял, что чтоб работать с переменной Element, надо изменять ее указатель, чтоб он был равен ElementP. Но к сожалению ничего другого, кроме как
 
 ^Element:=Pointer(ElementP);
 
 не придумал, а компилятор ругается на эту конструкцию.
 Я конечно понимаю что скорее всего это нереально, но всетаки вы случайно не знаете как можно изменять указатель переменной в delphi?
 |  
|   | min@y™ (статус: Доктор наук), 25 августа 2010, 09:44 [#2]:Да выкинь ты этот связный список к ядрене фене! Ну нафига тебе такой геморрой? Тебе ж сказали: юзай TList и куча проблем сразу испарится. Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | SOA (статус: Посетитель), 25 августа 2010, 10:28 [#3]:To min@y™: Вместо связного списка сначала хотел использовать динамический массив и вроде бы все работало, но при создании третьей кнопки, непонятно почему возникала ошибка обращения к памяти, из-за чего и было решено использовать связный список, ввиду того что работа будет вестись исключительно через указатели.
 |  
|   | Вадим К (статус: Академик), 25 августа 2010, 10:31 [#4]:Посмотрим на эту конструкцию ^Element:=Pointer(ElementP);
 в ней две ошибки.
 во первых, что такое:
 ^Element
 Такого синтаксиса нет.
 а
 Pointer(ElementP);
 это приведение переменной к безтипному указателю. Смысла особого нет.
 
 
 Цитата (SOA):  но всетаки вы случайно не знаете как можно изменять указатель переменной в delphi А можно словами объяснить детальней, что это такое должно получиться, а то выглядит страшненько. У переменной нет указателя. У переменной есть адрес. Но его изменить в процессе работы нельзя.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | SOA (статус: Посетитель), 25 августа 2010, 10:35 [#5]:Вадим К >У переменной есть адрес. Но его изменить в процессе работы нельзя.
 
 Этого то я и боялся.
 |  
|   | min@y™ (статус: Доктор наук), 25 августа 2010, 10:40 [#6]:Никак не пойму: ты боишься использовать TList, что-ли? Думаешь, слишком сложно, да? На его основе, кстати, можно создать и TButtonList!
  ) Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | SOA (статус: Посетитель), 25 августа 2010, 10:52 [#7]:To min@y™: я не собираюсь, ничего доказывать, или опровергать, не до этого.
 |  
|   | Вадим К (статус: Академик), 25 августа 2010, 10:55 [#8]: Цитата (SOA): Этого то я и боялся. Этого бояться нельзя. это преимущество.
 А вот для реализации того, что хочется, как раз нужны указатели.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | min@y™ (статус: Доктор наук), 25 августа 2010, 11:05 [#9]: Цитата (SOA): я не собираюсь, ничего доказывать, или опровергать, не до этого.  Ты реально хочешь оставить свой связный список, когда есть более эффективные варианты? Серьёзно?
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | Roma_no_off (статус: Посетитель), 25 августа 2010, 22:29 [#10]:А какой смысл пользоваться TList'ми и прочим, когда у формы есть свойство Components? Оно и содержит все, что находится на форме, а узнать, что это конкретно кнопка можно простой конструкцией: 
 if Form1.Components[i] is TButton then ... |  
|   | SOA (статус: Посетитель), 26 августа 2010, 13:38 [#11]:Помогите пожалуста с кодом еще раз, не могу понять почему компилчтор ругается на Self, хотя не должен. 
 unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;
 
type
  TForm1 = class(TForm)
    procedure FormClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
type buttonP = ^TButton;
 
Procedure AddElement(c: TRect);
 
var
  Form1: TForm1;
  NowActive: TButton;
  Button: buttonP;
  i: integer =0 ;
 
implementation
 
{$R *.dfm}
 
Procedure AddElement(c: TRect);
var
Point: TPoint;
AWidth,AHidth,ATop,ALeft: Integer;
Begin
new(Button);
 
Button^:=TButton.Create(Self); // Ругается тут
nowActive:=Button^;
Windows.GetCursorPos(Point);
ALeft:=Point.X-c.Left-5;
ATop:=Point.Y-c.Top-35;
AWidth:=49;
AHidth:=41;
i:=i+1;
NowActive.Name:='hello '+IntToStr(i);
NowActive.Parent:=Self; // Также ругается тут
NowActive.SetBounds(ALeft,ATop,AWidth,AHidth);
 
End;
 
procedure TForm1.FormClick(Sender: TObject);
begin
AddElement(Form1.ClientRect);
end;
 
end. |  
|   | Вадим К (статус: Академик), 26 августа 2010, 14:01 [#12]:Логично, что он ругается. потому что где ему взять self в этой процедуре? По порядку, что такое self ? - это первый неявный параметр любого нестатического метода (не процедуры!)
 То есть на самом деле, метод для обработчика клика кнопки выглядит так
 
 procedure TForm1.FormClick(Self:TForm; Sender: TObject);Просто этот первый параметр скрывается и разруливается компилятором. Self указывает на та экземпляр класса (то есть объект), который "владеет" этим методом. то есть в данном случае это форма.
 
 
 процедура Procedure AddElement(c: TRect); не является методом и поэтому у нее нет первого скрытого параметра. и взяться ему негде. Поэтому наиболее простой способ исправить, это заменить в Procedure AddElement(c: TRect); слово self на form1.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | SOA (статус: Посетитель), 26 августа 2010, 14:05 [#13]:Так ведь он (компилятор) не хочет даже создавать кнопку 
 Button^:=TButton.Create(Self); // Ругается тут
 
 хотя должен.
 |  
|   | Вадим К (статус: Академик), 26 августа 2010, 14:20 [#14]:а зачем все это type buttonP = ^TButton;
 ????
 зачем плодить указатель на ссылку???
 TButton - это просто ссылка, поэтому половина кода бессмыслена.
 
 Procedure AddElement(c: TRect);
var
Point: TPoint;
AWidth,AHidth,ATop,ALeft: Integer;
Button:TButton;
Begin
 
Button:=TButton.Create(form1); 
nowActive:=Button;
Windows.GetCursorPos(Point);
ALeft:=Point.X-c.Left-5;
ATop:=Point.Y-c.Top-35;
AWidth:=49;
AHidth:=41;
i:=i+1;
NowActive.Name:='hello '+IntToStr(i);
NowActive.Parent:=form1;
NowActive.SetBounds(ALeft,ATop,AWidth,AHidth);
 NowActive.visible := true;
End;то  Roma_no_off : в некоторых случаях бывает очень удобно хранить именно свои компоненты так. а то на форме могут быть ещё кнопки...
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | SOA (статус: Посетитель), 26 августа 2010, 14:23 [#15]:Вы правы все так. |  
|   | Вадим К (статус: Академик), 26 августа 2010, 14:29 [#16]:Тяжелое влияние с++ ? Галочка "подтверждения прочтения" - вселенское зло. |  
|   | SOA (статус: Посетитель), 26 августа 2010, 17:16 [#17]:Если вы про связный список, то я его не считаю тяжелым влиянием, наоборот, в свое время он помог мне лучше понять, как обращаться с указателями и зачем они нужны. А если про незнание что такое Self, так это только потому что delphi я преимущественно изучал не по книжкам, а по FAQ и Help.
 |  
|   | Вадим К (статус: Академик), 26 августа 2010, 17:26 [#18]:нет, я имел ввиду создание указателя для ссылки и вообще стиль написания кода. Галочка "подтверждения прочтения" - вселенское зло. |  
|   | SOA (статус: Посетитель), 26 августа 2010, 17:41 [#19]:Указатель для ссылки создавался по примеру help для delphi Help -> New procedure -> Example
 
 В C++ насколько знаю с указателями попроще, там только Pointer используется.(Не надо запоминать какой тип указателя создал для того или иного типа).
 |  
|   | Вадим К (статус: Академик), 26 августа 2010, 17:42 [#20]: Цитата (SOA): В C++ насколько знаю с указателями попроще, там только Pointer используется.(Не надо запоминать какой тип указателя создал для того или иного типа). неправда
   Галочка "подтверждения прочтения" - вселенское зло. |  Страницы: [1] [2] [Следующая »]  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |