Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
28 / 24 / 10
Регистрация: 26.04.2015
Сообщений: 307

Дочерние формы (не MDI) и STL::List

22.08.2016, 23:53. Показов 3747. Ответов 63
Метки list (Все метки)

Студворк — интернет-сервис помощи студентам
Хай всем, нашёл тему по форуму, близкую к моей задаче:
Динамическое создание и удаление компонентов.,
но возник вопрос, корректно ли использование того кода для компонентов формы
C++
1
2
3
4
5
6
7
8
void __fastcall TfmSendFile::FormCreate(TObject *Sender)
{
    sbtDel = new TsButton(fmSendFile);
    sbtDel->OnClick = sbtDelClick;
 
    Number = 0;
    vLabel.push_back(new TsLabel(fmSendFile));
...
непосредственно к самой форме? (у меня в программе - список указателей дочерних окон главной формы). И ещё, как удалять из списка эти указатели?
Unit1.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//===========================================================================
#include <vcl.h>
#include <list.h>
#pragma hdrstop
#include "Unit1.h"
 
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
    list<TForm1*> myList; 
 
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    frm_2 = NULL; //(TForm*) - указатель на дочернюю форму
    ed = NULL;    //(TEdit*) - указатель на Edit этой формы
}
//===========================================================================
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   
//    if ( frm_2 == NULL )
    {
    frm_2 = new TForm( this );            
//  frm_2->Parent = this;
    frm_2->Top = (ClientHeight - frm_2->Height)*0.50; 
    frm_2->Left = (ClientWidth - frm_2->Width)*0.50;
    
//  frm_2->ActiveControl = NULL;
    ::SetParent( frm_2->Handle, Handle ); 
    frm_2->OnClose = &Form2Close;         
    frm_2->Show();                       
 
        ed = new TEdit( frm_2 );           
    ed->Parent = frm_2;
        ed->Top = 20;                         
    ed->Left = 30;
    ed->Font->Style = TFontStyles() << fsBold;    
    }
//--------------------------
    myList.push_back(new TForm1(frm_2)); // <--- вот это интересует в сравнении с темой про компоненты
//--------------------------
}
//---------------------------------------------------------------------------
 
 
void __fastcall TForm1::Form2Close(TObject *Sender, TCloseAction &Action)
{
    if (ed!=NULL)
        delete ed;     
    ed = NULL;     
 
    if (frm_2!=NULL)   
        delete frm_2;
    frm_2 = NULL;     
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::WndProc(TMessage &Message)
{
    static bool isAppActive = true;
 
    switch(Message.Msg)
    {
        case WM_NCACTIVATE:
            Message.WParam = isAppActive;
            Message.Result = DefWindowProc(this->Handle, Message.Msg, Message.WParam, Message.LParam);
            break;
 
        case WM_ACTIVATEAPP:
            isAppActive = (Message.WParam != 0);
            LPARAM lp = 0L;
            this->Perform(WM_NCACTIVATE, 0, lp);
            Message.Result = 0;
            return;
    }
    TForm::WndProc(Message); // interited
}
//---------------------------------------------------------------------------
Unit1.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//===========================================================================
#ifndef     Unit1H
#define     Unit1H
 
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
 
//---------------------------------------------------------------------------
class   TForm1 : public TForm
{
__published:    // IDE-managed Components
    TButton *Button1;
    TEdit *Edit1;
    void __fastcall Button1Click(TObject *Sender);
 
private:    // User declarations
    TForm* frm_2;    
    void __fastcall TForm1::Form2Close(TObject *Sender, TCloseAction &Action);  
    TEdit* ed;    
 
protected:
        void __fastcall WndProc(TMessage &Message);
 
public:     // User declarations
    __fastcall  TForm1(TComponent* Owner); 
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif  //(Unit1H)
//===========================================================================
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
22.08.2016, 23:53
Ответы с готовыми решениями:

Работа с MDI и Дочерние формы
Здравствуйте у меня вопрос, есть 2 формы,главная и дочерняя. Дочерняя выводится через StripMenu. Когда я вывожу не одну дочернюю, а...

MDI вместо закрытия главной формы закрываются дочерние
Собственно есть главная &quot;MainForm&quot; и несколько дочерних, генерируемых динамически, у обоих типов форм есть обработчик закрытия. Проблема в...

Как сделать что бы дочерние формы в MDI application delphi сразу не открывались при запуске программы
Здравствуйте, как сделать что бы дочерние формы в MDI application delphi сразу не открывались при запуске программы, а открывались после...

63
28 / 24 / 10
Регистрация: 26.04.2015
Сообщений: 307
24.08.2016, 02:57  [ТС]
аап теме!
Если нечётко выразился в топике - мне нужно создать по нажатию TForm1::Button1 динамические компоненты-объекты дочерние формы (сделано) и при закрытии любой их них - удалялся бы нужный указатель на эту форму. Как я понял, для создание нескольких компонентов и потом их произвольного удаления лучше использовать STL::List, в котором элементами будут указатели на объекты-формы.
адреса дочерних форм проверил - в list записываются (по дебагу до этого не мог увидеть )
C++
1
2
3
4
5
6
myList.push_back(new TForm1(frm_2)); 
    list<TForm1*>::iterator i;
    list<TForm1*>::iterator iter = myList.begin();
    list<TForm1*>::iterator iter_end = myList.end(); 
    for (i = iter; i != iter_end; i++)
    ShowMessage(AnsiString().sprintf("%p",*i));
Но как в коде запрограммировать удаление нужного указателя и разрушение объекта, при закрытии любой дочерней формы? Как мне знать, что если я вызову срабатывание TForm1::Form2Close, закрыв напр. 3-ю дочернюю форму из 5-и созданных, то в STL::List удалится именно 3-й элемент? - через *Sender -
C++
1
TForm1 * frm = dynamic_cast<TForm*>( Sender );
?
P.S.: очень нужна помощь с этими вопросами! + любые замечания по коду, если там есть косяки, а они скорее всего есть)
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 06:50
Wolver, 1 если сами хотите управлять временем жизни формы подавайте в её конструктор 0. 2 если хотите удалить её из списка при закрытии то в OnClose формы перебирайте список и как найдёте элемент равный this удалите его
0
 Аватар для SmittWesson
236 / 196 / 21
Регистрация: 04.06.2014
Сообщений: 1,309
24.08.2016, 07:13
Цитата Сообщение от Wolver Посмотреть сообщение
И ещё, как удалять из списка эти указатели?
Командой delete но и это - DOS-овский вариант. В принципе, сборщик мусора винды, за Вас всё сделает (они предусмотрели этот вариант. Защита от говнокодеров). Но по-нашим, не писанным программёрским правилам, лучше свой мусор убирать самим.
Не там чисто, где убирают, а там, где не сорят. Ай-м сорри
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 07:41
SmittWesson, кстати хороший вопрос - из списка то мы удалимся, а кто вызовет delete? Думаю надо глянуть есть ли у формы какой нибудь флажок типа удалить при закрытии
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
24.08.2016, 07:49
Цитата Сообщение от Wolver Посмотреть сообщение
Но как в коде запрограммировать удаление нужного указателя и разрушение объекта, при закрытии любой дочерней формы?
Разве нельзя при закрытии дочерней формы выполнить delete this; ?
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 07:56
d7d1cd, можно, главное что бы после того метода где вы это сделаете (закрытие приводит к вызову нескольких методов) не вызывалось ещё чего нибудь
0
 Аватар для SmittWesson
236 / 196 / 21
Регистрация: 04.06.2014
Сообщений: 1,309
24.08.2016, 08:01
Цитата Сообщение от vxg Посмотреть сообщение
из списка то мы удалимся, а кто вызовет delete? Думаю надо глянуть есть ли у формы какой нибудь флажок типа удалить при закрытии
Делит включать нужно, но уже не в обязательном порядке. Я пробовал открывать объекты, не закрывая делитом. Через некоторое время, включается системный процесс, ща на вскидку не вспомню,(давненько экспериментировал). Машину подвесил секунд на 30. Потом проверяю области оперативки, а там от мною созданных процессов ничего и не осталось. Вот, собственно и вся проблема. Т.е. Если не хочешь подвесить машину у юзверя, применяй Делит. Если тебе - пофиг, можно и не ставить. Вот только если вызовов много, твоей говнонопрогой мало кто пользоваться рискнёт. Я однажды столкнулся с такой шнягой. Открывался объект в рекурсии, но не удалялся (скопипастил где-то). Через пол-часа работы, машина подвисала намертво (минут на 15). Блин, а нужно то было всего в код вставит делит!
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 08:09
d7d1cd, вроде так - в FormClose приходит Action и если присвоить ему caFree форма сама удалится при закрытии
0
 Аватар для SmittWesson
236 / 196 / 21
Регистрация: 04.06.2014
Сообщений: 1,309
24.08.2016, 08:19
Цитата Сообщение от vxg Посмотреть сообщение
FormClose приходит Action и если присвоить ему caFree форма сама удалится при закрытии
Совершенно верно. В Дебилдере, так оно и есть. Я не об этом. Action, там по-умолчанию встроен. Правда, мало кто ним пользуется на прямую (и я в том числе). Я, собственно, о создаваемых объектах типа
C++
1
2
int xren = new int(xren); 
delete xren.
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 08:33
SmittWesson, у человека есть в коде делит, он знает о его существовании по определению так как использует нью
0
 Аватар для SmittWesson
236 / 196 / 21
Регистрация: 04.06.2014
Сообщений: 1,309
24.08.2016, 09:42
И Гидэ Мопасан. Не вижу. Может у мня проблемы со зрением?
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 10:07
SmittWesson, 55-я строка Unit1.cpp - убийство дочерней динамической при закрытии родительской. Кстати эдит убивать не нужно если вы в его конструктор подали форму на которой он лежит - его убьёт сама форма в своём деструкторе
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
24.08.2016, 10:09
Цитата Сообщение от Wolver Посмотреть сообщение
для создание нескольких компонентов и потом их произвольного удаления лучше использовать STL::List, в котором элементами будут указатели на объекты-формы
Не трогай ты эту унсафе штутку под названием std. потому как кода грохнешь frm_2 она при этом грохнет и Edit которым владеет. А такая наглость приведет к крешу контейнера stl который об этом ничего не знает. В VCL уже есть свой набор умных контейнеров с слежением за состоянием объекта. любой компонет при своем удалении удаляет всех при создании кого он был указан Owner-ом. при этом при вешнем удалении любого из дочерних компонентов отслеживает это и удаляет его из своих списков владения и обработки.
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 10:14
Fulcrum_013, 1 что за ренегатство про табу на std)? 2 человек не хочет ждать смерти владельца, а создавать и убивать в полёте, поэтому owner должен быть 0 (у форм но не у контролов)
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
24.08.2016, 11:05
Цитата Сообщение от vxg Посмотреть сообщение
1 что за ренегатство про табу на std)?
Это там в комитете сборище ренегатов которое пихает в стандарт всякий говнокод вместо уже 20 лет как назревших расширений синтаксиса.
Цитата Сообщение от vxg Посмотреть сообщение
2 человек не хочет ждать смерти владельца, а создавать и убивать в полёте, поэтому owner должен быть 0 (у форм но не у контролов)
Только STL для этого не нужна. Ну кинь эти компоненты в панель (ну или любой потомок TComponent Owner-ом сделай, кстати если невидимый нужен можно просто экземпляр TComponent создать как контейер со слежением) потом этот компонент грохни когда не нужон стал. зато все гарантированно safe без всякой дополнительной обвязки (все слежение за жизненным циклом уже под капотом). А если вообще вся форма грохается так и подавно.

Добавлено через 21 минуту
А вообще последнее время приходится програмить в основном без VCL так слепил себе пару шаблонов по образу и подобию чтобы не парится со владениями и тп:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
template <class OwnedType>
class TOwner:protected TList<OwnedType,int>{    
private:
   bool FCleaning=false;
protected:
    void Remove(TOwnedObject<TOwner>* Object){
        if (TList::FastDelete(Object->OwnerId))     
            Data[Object->OwnerId]->FOwnerId = Object->OwnerId;              
    };
    TOwner(char *TypeName, int aGrowStep=16) :TList(aGrowStep, TypeName){};
public:
    void Clear(){
        FCleaning = true;
        for (int i = 0; i < Count; i++) if (Data[i]) delete Data[i];
        TList::Clear();
        FCleaning = false;
    };
    ~TOwner(){      
        Clear(); 
    };  
    dR_property(bool, Cleaning)
};
 
template <class OwnerType>
class TOwnedObject{
private:
    friend class TOwner<TOwnedObject<OwnerType>>;
    OwnerType *FOwner = nullptr;
    int FOwnerId = -1;
public:
    TOwnedObject(OwnerType *aOwner) :FOwner(aOwner) { if (Owner) FOwnerId = Owner->Add(this); }
    dR_property(OwnerType *, Owner)
    dR_property(int, OwnerId)
    ~TOwnedObject(){ if (Owner) if (!Owner->Cleaning) Owner->Remove(this); };
};
STL таким премудростям не обучена
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 11:05
Fulcrum_013, 1 гхм)) 2 нет никакого капота - человек хочет к примеру что бы при клике на что-то открывалось окно к примеру свойств и что бы можно было таких окон открыть сколько угодно - при клике он окно создаёт, при закрытии удаляет, если он оставит это дело на владельца окна так и будут плодится пока владелец не умрет либо нужно его побуждать убивать их что ничем не отличается от явного уничтожения
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
24.08.2016, 11:17
Цитата Сообщение от vxg Посмотреть сообщение
если он оставит это дело на владельца окна
Владельцем окна вообще то должон быть TApplication. А у окна по закрытии есть событие OnClose в котором есть параметр Action. если его поставить Action=caFree; окно удалится.

Добавлено через 7 минут
Цитата Сообщение от vxg Посмотреть сообщение
нет никакого капота
А под капотом то что если его явно извне прибить никому от этого не поплохеет. в отличии от того если оно будет в STL контейнере.
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
24.08.2016, 12:00
Fulcrum_013, caFree присваивать нужно безусловно и об этом сказано. caFree не имеет отношения к владельцу - форма должна удалится даже если владелец 0 - так зачем её обманывать и назначать владельцем того кто так никогда ничего с ней и не сделает? Контейнер (тут он один - список) нужен лишь для хранения указателей. То что мы храним в нем указатель на форму никак не влияет на саму форму. То что мы удаляем указатель ИЗ СПИСКА никак не влияет на форму. Явное удаление формы как сказано выше в данном случае нежелательно и возложено на обработчик закрытия формы при условии присвоения Action значения caFree. Так что же вам тут не нравится? То что вместо TList или вообще TForm[] использовали std::list? Это дело вкуса и к задаче отношения не имеет.
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
24.08.2016, 12:04
Цитата Сообщение от vxg Посмотреть сообщение
использовали std::list?
То что он во первых не нужен а во вторых не сможет нормально обработать удаление формы без явного извлечения из него этой формы вручную
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.08.2016, 12:04
Помогаю со студенческими работами здесь

Дочерние окна MDI
На MDI форме есть кнопка, по нажатию на которую должны выстроиться каскадом все дочерние формы. метод Cascade – выстроить каскадом...

mdi - дочерние окна перетирают друг друга
Здравствуйте форумчане! Сталкнулся с небольшой проблемой для меня. А именно: Написал программу MDI,в каждом окне можно рисовать...

Как настроить соответствие размеров MDI-контейнера и MDI-формы?
Здравствуйте! Я для вкладки &quot;TbpDaSubekt&quot; сделал MDI-форму &quot;FrmTipHran&quot;: FrmTipHran.TopLevel = False FrmTipHran.Parent =...

Работа с STL list + пропись List.h
Здравствуйте! Помогите, пожалуйста, разобраться с STL list. Нужно сделать программу в которой будет содержаться класс Student, прописать...

Чтоб Дочерние формы открывались по иерархии от главной формы
Есть главная форма Form1, Form1 - topmost=true, т.е Form 1 отображается поверх всех окон. Нужно чтоб form2 открывалась не поверх всех окон...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru