C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
new для окна, описать событие
Лена
Отправлено: 08.11.2006, 17:17


Мастер участка

Группа: Участник
Сообщений: 501



У меня код, который создает форму:
CODE

//показ модального окна при щелчке в гриде
void __fastcall TForm1::DBGrid1EditButtonClick(TObject *Sender)
{
if(Form1->DBGrid1->Fields[0]->IsNull==true || Form1->DBGrid1->Fields[2]->IsNull==true)
   {
    ShowMessage("Поля \"Код\" и \"Доступ\" необходимо заполнить");
    return;
   }
TField * Self;
Self = DBGrid1->SelectedField;
if(Self)
if(Self->FieldName == "man")
  {
   TFormVladelec *FormVladelec = new TFormVladelec(Application);
   FormVladelec->ShowModal();
   delete FormVladelec;
  }
}


После того как окно появилось, мне бы хотелось иметь код в его обработчике события OnResize (или даже в OnShow):

CODE

void __fastcall TFormVladelec::FormResize(TObject *Sender)
{

    if (FormVladelec->Width<680)//ошибка!!!
    {
    FormVladelec->Width = 680;
    }
    if (FormVladelec->Height<480)
    {
    FormVladelec->Height=480;
    }
 
}


Однако такой код генерирует ошибку. Очевидно, окно FormVladelec не до конца создано? Как в таком случае можно вставить мой код в OnResize? Можно отказаться от оператора new, но хочется разобраться. smile.gif

Присоединить изображение

Присоединить изображение

Valdemar
Отправлено: 08.11.2006, 17:37


Мастер участка

Группа: Участник
Сообщений: 433



Если это нужно для ограничения размеров формы, то можно воспользоваться свойством формы Constraints, которое задать дизайн-тайме ну или в процессе выполнения.
Можно еще задать свой обработчик программно:
TFormVladelec->OnResize=твой обработчик
Твоя функция-обработчик должна иметь прототип как у нужного обработчика.
Лена
Отправлено: 08.11.2006, 17:51


Мастер участка

Группа: Участник
Сообщений: 501



Cпасибо.
Наверное лучший способ в моем случае это определить TFormVladelec->OnResize= обработчик
В обработчике планируется добавить код...
В форме, которая будет создана, тоже находиться грид. Я хотела в нем при увелечении формы (при ее растягивании) менять ширину колонок этого грида.
AVC
Отправлено: 08.11.2006, 17:56


Ветеран

Группа: Модератор
Сообщений: 1583



Откуда взялась переменная FormVladelec в TFormVladelec::FormResize? (Вспомните о её области видимости)

Если нет ошибок то все работает нормально. Я этим методом пользуюсь не один год, а формы (кроме первой) создаю через new.
CODE

void __fastcall TF_Main::FormResize(TObject *Sender)
{ FormCheckMinHW (this, 470, 630); }



Перепишите так
CODE

void __fastcall TFormVladelec::FormResize(TObject *Sender)
{

   if (Width<680)//ошибка!!!
   {
   Width = 680;
   }
   if (Height<480)
   {
   Height=480;
   }
 
}

И все станет не место.
Лена
Отправлено: 08.11.2006, 18:13


Мастер участка

Группа: Участник
Сообщений: 501



Да работает. smile.gif
Однако не понятно помему я не могу обратиться через имя объекта...
Разве после FormVladelec->ShowModal(); переменная FormVladelec (имя формы) не существует? ohmy.gif
beginner
Отправлено: 08.11.2006, 23:59


Дежурный стрелочник

Группа: Участник
Сообщений: 44



QUOTE (Лена @ 08.11.2006, 18:13)
Да работает. smile.gif
Однако не понятно помему я не могу обратиться через имя объекта...
Разве после FormVladelec->ShowModal(); переменная FormVladelec (имя формы) не существует? ohmy.gif

FormVladelec имеется, напр. код FormVladelec->Width из FormResize
обращается к ней. Но созданная форма присваивается
другому FormVladelec, который определен в обработчике
DBGrid1EditButtonClick. Т.е. ошибка вызвана определением
нового объекта в DBGrid1EditButtonClick.

Вместо
TFormVladelec *FormVladelec = new TFormVladelec(Application);
нужно просто написать
FormVladelec = new TFormVladelec(Application);

И вместо имени формы можно еще использовать this.



Отредактировано beginner — 09.11.2006, 00:09
AVC
Отправлено: 09.11.2006, 09:59


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (Лена @ 08.11.2006, 17:13)
Однако не понятно помему я не могу обратиться через имя объекта...

Продублирую ответ beginner немного другими словами.
Основное — в данном случае вы НЕ обращаетесь к объекту через его имя, а просто есть переменная — указатель на экземпляр класса.
Так как компилятор пропустил ваш код значит у вас в FormVladelec есть такие строки (их обычно вставляет мастер построения формы)
TFormVladelec *FormVladelec;
и
extern PACKAGE TFormVladelec;
Это объявление глобального указателя на экземпляр формы FormVladelec. Если форма создается автоматически то этот указатель заполняется реальным знчением.
В вашем случае вы кодом
{
TFormVladelec *FormVladelec = new TFormVladelec(Application);
FormVladelec->ShowModal();
delete FormVladelec;
}
перекрыли одноименную глобальную переменную, но в пределах фигурных скобок все правильно (вспомните правила областей видимости переменных),
а вот код из формы FormVladelec
if (FormVladelec->Width<680)
пытается работать с той самой глобальной переменной, определенной в том же модуле формы.

И вообще считаю очень вредным внитри экземпляра класса обращаться к этому же экземпляру через внешнюю переменную. Если хотите подчеркнуть что обращение идет именно к этому экземпляру у вас есть this.

Второе — вы, конечно, можете писать в вызываущей функции
FormVladelec = new TFormVladelec(Application);
Но помните, что это всего лищь одна переменная, и если в ней уже был записан адрес экземпляра ранее созданной формы, то теперь указатель указывает на новый экземпляр. Это не криминально и поправимо, но может доставить несколько приятных и веселых минут при отладке приложения.
Лена
Отправлено: 09.11.2006, 11:21


Мастер участка

Группа: Участник
Сообщений: 501



Спасибо за объяснения. Теперь понятно.


>И вообще считаю очень вредным внутри экземпляра класса обращаться к этому же экземпляру через внешнюю переменную.


Я так делаю, потому что мне удобно набрав стрелочку "->" увидеть подсказку Builder и быстро выбрать нужное свойство. Поэтому я и писала: FormVladelec->"вижу список свойств."
Теперь знаю, что правильнее this->... rolleyes.gif

Вернуться в Вопросы программирования в C++Builder