Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.07.2008, 15:49   #1
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию Событие для динамически созданной Button

Здравствуйте, уважаемые форумчане, ниже приведен код функции создающей динамически форму, лэйблу и кнопки заданного количества. Вообще попытка сделать чтото вроде собственного MessageBox-а только с произвольным количеством кнопок, потому желательно, чтобы возращался номер нажатой кнопки. Создание и освобождение вроде происходит правильно, кстати, если в коде, что-то покажется не оптимальным или не красивым пишите, исправлю, с удовольствием воспользуюсь вашим советом. Основная суть вопроса заключается в описании процедуры нажатия на кнопку, созданную динамически, вернее, как прилепить эту процедуру к событию кнопки OnClick. Если есть более разумные решения этого вопроса, пишите пожалуйста. Требуется, чтобы процедура возращала номер нажатой кнопки.


Собственно код:
Код:
function GetButton(Text: PAnsiChar; Caption :PAnsiChar; Count: Byte): Byte;
var GetForm: ^TForm;
    GetLabel: ^TLabel;
    mButton: array of ^TButton;
    bLeft: smallint;
    i: smallint;
begin
bLeft:=16;
SetLength(mButton, Count);
GetMem(GetForm, sizeof(getForm));
GetForm^:=TForm.Create(nil);
GetForm.Width:=140*Count+27;
GetForm.Height:=120;
GetForm.Position:=poDesktopCenter;
GetForm.Name:='GetForm';
GetForm.Caption:=Caption;
GetForm.Enabled:=True;

GetMem(GetLabel, sizeof(GetLabel));
GetLabel^:=TLabel.Create(GetForm^);
GetLabel.Name:='GetLabel';
GetLabel.Parent:=GetForm^;
GetLabel.Top:=24;
GetLabel.Left:=16;
GetLabel.Font.Size:=12;
GetLabel.Font.Color:=clBlack;
GetLabel.Font.Name:='CyrillicGoth';
GetLabel.Caption:=Text;

for i:=0 to Count-1 do
    begin
      GetMem(mButton[i], sizeof(mButton[i]));
      mButton[i]^:=TButton.Create(GetForm^);
      mButton[i].Name:='Button_'+IntToStr(i);
      mButton[i].Parent:=GetForm^;
      mButton[i].Caption:=IntToStr(i);
      mButton[i].Width:=119;
      mButton[i].Height:=28;
      mButton[i].Left:=bLeft;
      inc(bLeft, 124);
      mButton[i].Top:=50;
      mButton[i].Font.Size:=14;
      mButton[i].Font.Name:='CyrillicGoth';
      mButton[i].Font.Color:=clBlack;
      mButton[i].Caption:=mButton[i].Name;
      mButton[i].Enabled:=True;
      mButton[i].Visible:=True;
    end;
GetForm.Visible:=True;

GetForm.Close;
for i:=0 to Count-1 do
  FreeMem(mButton[i]);
FreeMem(GetLabel);
mButton:=nil;
FreeMem(GetForm)
end;
Спасибо

From Stilet: Собственно код у нас оформляется тегом [code] по кнопке (#). Прошу запомнить.

Последний раз редактировалось Stilet; 23.07.2008 в 16:03.
Dogmat вне форума Ответить с цитированием
Старый 23.07.2008, 16:05   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Ну как как?

Код:
...................
mButton[i].OnClick:=Button1Click;
....................
procedure TForm1.Button1Click(Sender: TObject);
begin
//
end;
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 23.07.2008, 16:37   #3
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Спасибо, постараюсь запомнить, а так я пробовал, не получалось... сейчас нашёл ошибку, нужно было:
Код:
mButton[i].OnClick:=FormMain.Button1.OnClick;
Спасибо, вопрос закрыт
Dogmat вне форума Ответить с цитированием
Старый 24.07.2008, 10:33   #4
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Вынужден вернуться к вопросу.

На данный момент всё создается, событие к кнопкам привязано, вопрос вот в чём, имеем процедуру, которая собственно и создает форму, компоненты и их свойства. Имеем процедуру представляющую собой метод обработки события OnClick всех кнопок формы.

Код:

Тип создаваемой динамически формы:
Код:
type
  TGetForm = class(TForm)
    GetLabel: TLabel;
    procedure GetButton_Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
Сама процедура создания:
Код:
procedure GetButtons(Text: PAnsiChar; Caption :PAnsiChar; Count: Byte);
var
  GetForm: ^TGetForm;
  mButton: array of TButton;
  bLeft: smallint;
  i: smallint;
begin
bLeft:=16;
SetLength(mButton, Count);

GetMem(GetForm, sizeof(GetForm));
GetForm^:=TGetForm.CreateNew(nil);
GetForm.Width:=124*Count+32;
GetForm.Height:=120;
GetForm.Position:=poDesktopCenter;
GetForm.Name:='GetForm';
GetForm.Caption:=Caption;
GetForm.GetLabel:=TLabel.Create(GetForm^);
GetForm.GetLabel.Name:='GetLabel';
GetForm.GetLabel.Parent:=GetForm^;
GetForm.GetLabel.Top:=24;
GetForm.GetLabel.Left:=16;
GetForm.GetLabel.Font.Size:=12;
GetForm.GetLabel.Font.Color:=clBlack;
GetForm.GetLabel.Font.Name:='CyrillicGoth';
GetForm.GetLabel.Caption:=Text;

for i:=0 to Count-1 do
    begin
      mButton[i]:=TButton.Create(GetForm^);
      mButton[i].Name:='Button_'+IntToStr(i);
      mButton[i].Parent:=GetForm^;
      mButton[i].Caption:=IntToStr(i);
      mButton[i].Width:=119;
      mButton[i].Height:=28;
      mButton[i].Left:=bLeft;
      inc(bLeft, 124);
      mButton[i].Top:=50;
      mButton[i].Font.Size:=14;
      mButton[i].Font.Name:='CyrillicGoth';
      mButton[i].Font.Color:=clBlack;
      mButton[i].Caption:=mButton[i].Name;
      mButton[i].Tag:=i;
      mButton[i].OnClick:=GetForm.GetButton_Click
    end;
GetForm.Visible:=True;

FreeMem(GetForm);
mButton:=nil
end;
Реакция на OnClick (mButton[i].OnClick:=GetForm.GetButton_Click):
Код:
procedure TGetForm.GetButton_Click(Sender: TObject);
begin
ShowMessage(IntToStr((Sender as TButton).Tag));
(((Sender as TButton).Parent) as TForm).Close
end;
Вопросы:
1. Освобождение памяти: в GetButtons, в конце, происходит освобождение формы и динамического массива, при этом форма с экрана не исчезает пока ее не закроешь и все mButton[i] правильно реагируют на OnClick, объясните пожалуйста почему так происходит и правильно ли высвобождается память таким образом. Проблема заключалась в том, что процедура выполняется полность и если сразу высвободить память и закрыть форму пользователь просто не успеет нажать на Button, потом убрал Close, оказалось, что форма остается функционировать до закрытия. Это на руку, просто не могу понять почему происходит так.

P.s. после закрытия формы, повторные попытки сделать ее видимой выдают ошибку - получается всё правильно высвобождается? Вопрос почему не сразу.

2. В GetButton_Click ShowMessage выдает номер нажатой кнопки после чего закрывает форму. Необходимо этот номер передать переменной в процедуре, которая вызывает GetButtons, единственное что приходит на ум это выделить под это дело глобальную переменную, но что-т мне это не очень нравится. Хотелось бы что-то вроде MessageBox сделать, чтобы выдавал нормально номер нажатой кнопки, проблема опять же в том что GetButtons выполняется и закрывается по идее сразу (если я правильно понимаю), можно ее описать как функцию но как Result-у передать номер нажатой кнопки из GetButton_Click? Посоветуйте пожалуйста.

3. + ко всему вышеперечисленному, думаю добавить название кнопок, в голову опять таки лезит только массив названий размером в количество кнопок, или можно строку с символами-разделителями, но тоже не уверен что не найдется более оптимального решения, всё кажется грубоватым, посоветуйте пожалуйста если есть идеи.

Обобщенно хочется более человечески организовать эту идею, если есть надумки. как реализовать это более корректно, проще, буду только рад, не поленюсь переделать...

Спасибо

Последний раз редактировалось Dogmat; 24.07.2008 в 10:57.
Dogmat вне форума Ответить с цитированием
Старый 24.07.2008, 11:17   #5
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Цитата:
Сообщение от Dogmat Посмотреть сообщение
1. Освобождение памяти: в GetButtons, в конце, происходит освобождение формы и динамического массива, при этом форма с экрана не исчезает пока ее не закроешь и все mButton[i] правильно реагируют на OnClick, объясните пожалуйста почему так происходит и правильно ли высвобождается память таким образом. Проблема заключалась в том, что процедура выполняется полность и если сразу высвободить память и закрыть форму пользователь просто не успеет нажать на Button, потом убрал Close, оказалось, что форма остается функционировать до закрытия. Это на руку, просто не могу понять почему происходит так.
1. freeMem(GetForm); - в Вашем примере это не освобождение формы, а освобождение памяти под указатель, который создан вызовом getMem. getMem/freeMem здесь лишнее. Тип TForm это уже указатель. Пример создания формы:

Код:
var F:TForm2;
begin
   F := TForm2.Create(nil);
2. Освобождение динамического массива не вызывает дестрактора его элементов. Поэтому кнопки нормально работают. Динамический массив в данном случае также не нужен.

Код:
var B:TButton;
begin
   F := TForm2.Create(nil);

   for ... begin
       B := TButton.Create(F);   // Владелец кнопки форма - она и будет ее освобождать
       B.Parent := F;
       B.OnClick := Button2Click;
   end;

   F.Show;
Цитата:
P.s. после закрытия формы, повторные попытки сделать ее видимой выдают ошибку - получается всё правильно высвобождается? Вопрос почему не сразу.
Вы наверное использовали GetForm, поэтому не работает. Простенький пример:

Код:
// TForm2 - пустая форма в другом модуле

var F:TForm2;
// Эта кнопка создает форму
procedure TForm1.Button1Click(Sender: TObject);
var B:TButton;
begin
   F := TForm2.Create(nil);

   B := TButton.Create(F);
   B.Parent := F;
   B.OnClick := Button2Click;

   F.Show;
end;

// Эта кнопка закрывает форму
procedure TForm1.Button2Click(Sender: TObject);
begin
   F.Close
end;

// Эта кнопка открывает форму повторно
procedure TForm1.Button3Click(Sender: TObject);
begin
   F.Show;
end;
Close не удаляет форму. Для удаления нужно вызвать free.

Цитата:
2. В GetButton_Click ShowMessage выдает номер нажатой кнопки после чего закрывает форму. Необходимо этот номер передать переменной в процедуре, которая вызывает GetButtons, единственное что приходит на ум это выделить под это дело глобальную переменную, но что-т мне это не очень нравится. Хотелось бы что-то вроде MessageBox сделать, чтобы выдавал нормально номер нажатой кнопки, проблема опять же в том что GetButtons выполняется и закрывается по идее сразу (если я правильно понимаю), можно ее описать как функцию но как Result-у передать номер нажатой кнопки из GetButton_Click? Посоветуйте пожалуйста.
Непонятно, что Вы пытаетесь сделать. Почему GetButtons должна вызываться по нажатию кнопки из формы, которая уже создана вызовом этой же процедуры. При чем здесь result ?

Цитата:
3. + ко всему вышеперечисленному, думаю добавить название кнопок, в голову опять таки лезит только массив названий размером в количество кнопок, или можно строку с символами-разделителями, но тоже не уверен что не найдется более оптимального решения, всё кажется грубоватым, посоветуйте пожалуйста если есть идеи.

Обобщенно хочется более человечески организовать эту идею, если есть надумки. как реализовать это более корректно, проще, буду только рад, не поленюсь переделать...
Во-первых название GetButtons создание формы с кнопками. Так и называйте. Названия кнопок можно передать как массив. Тогда и количество кнопок не понадобится.

Код:
procedure CreateFormWithButtons(Captions : array of String);
var F:TForm2;
    i:integer;
    B:TButton;
begin
   F := TForm2.Create(nil);
   for i:=low(Captions) to high(Captions) do begin
      B := TButton.Create(F);
      B.Caption := Captions[i];
      //...
   end;
end;
alexBlack вне форума Ответить с цитированием
Старый 24.07.2008, 11:34   #6
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Цитата:
Непонятно, что Вы пытаетесь сделать. Почему GetButtons должна вызываться по нажатию кнопки из формы, которая уже создана вызовом этой же процедуры. При чем здесь result ?
Видимо я не точно описал.
GetButtons вызывается по нажатию на кнопку находящейся на главной форме и создает GetForm с кнопками, нужно чтобы возвращался номер нажатой кнопки, в этом вся задумка.
А в остальном большое спасибо, так и сделаю.
Dogmat вне форума Ответить с цитированием
Старый 24.07.2008, 11:43   #7
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Цитата:
Сообщение от Dogmat Посмотреть сообщение
Видимо я не точно описал.
GetButtons вызывается по нажатию на кнопку находящейся на главной форме и создает GetForm с кнопками, нужно чтобы возвращался номер нажатой кнопки, в этом вся задумка.
А в остальном большое спасибо, так и сделаю.
Тогда:
- ShowModal чтобы в GetButtons дождаться закрытия формы или
- глобальная переменная, как Вы и писали выше или
- можно установить для GetForm событие, которое будет вызываться по нажатию кнопки. А само событие будет методом вызывающей формы.

Последний раз редактировалось alexBlack; 24.07.2008 в 11:46.
alexBlack вне форума Ответить с цитированием
Старый 24.07.2008, 12:15   #8
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Можно поподробней о варианте с ShowModal, в справке почитал не совсем понятно, как он мне поможет, можно маленький примерчик?
Dogmat вне форума Ответить с цитированием
Старый 24.07.2008, 12:44   #9
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Всё, понял, проверил на простом примере, а у меня ошибку выдает, может быть GetForm не нравится, дальше сам разберусь

Большое вам спасибо
Dogmat вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
button blackstersl Общие вопросы Delphi 7 29.08.2008 15:31
Button... Черничный Общие вопросы Delphi 4 10.06.2008 01:34
Рисование на форме созданной на WinApi N!ckeL Win Api 3 30.04.2008 19:02
События, выполняемые во время работы созданной компоненты Denager Общие вопросы Delphi 13 22.04.2008 16:48
Как выпонить действия по двойному слику на созданной таблице Tiolic Общие вопросы Delphi 2 21.06.2007 09:53