Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/25: Рейтинг темы: голосов - 25, средняя оценка - 4.56
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906

Динамическое изменение имени объекта

01.06.2012, 12:00. Показов 4752. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Господа, возникла необходимость динамической подмены имени графического объекта формы, созданного статически.
То есть на форме находится множество однотипных объектов и к каждому из них нужно применить одно и то же действие. К примеру существует десять кнопок и десять соответствующих им панелей. И при нажатии на Button1 изменяется свойство Panel1, при нажатии Button2 соответственно то же самое свойство Panel2 и так далее. Всего таких пар объектов много, и не охота в обработчик каждой кнопки запихивать здоровый кусок кода, одинакового для всех, и отличающийся только на номер кнопки (объекта). А просто написать функцию, в которую передавать единственный параметр - имя нажатой кнопки (или просто номер ее).

Что-то типа того:
C++
1
2
3
4
Form1->Panel1->Visible = false;
 
NameObject = "Panel1";
Form1->NameObject->Visible = false;
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.06.2012, 12:00
Ответы с готовыми решениями:

Динамическое изменение имени компонента
Доброго времени суток! Помогите решить проблему: возникла необходимость изменять свойство нескольких однотипных компонентов сразу, но...

Создание собственного VCL компонента. Динамическое изменение количества колонок в зависимости от размера объекта
Доброго времени суток всем. Решил при создании своего компонента на основе TStringGrid инкапсулировать в него ряд свойств. Хочется...

Динамическое создание объекта, вызывающего функцию
Типичное динамическое создание объектов: TImage *myImage; myImage = new TImage(Form1); Пробую сделать так: TImage *myObject; ...

18
Автор FAQ
 Аватар для -=ЮрА=-
6614 / 4256 / 401
Регистрация: 08.08.2009
Сообщений: 10,325
Записей в блоге: 24
01.06.2012, 12:34
SatanaXIII, форма, консоль - всё это имеет дескриптор окна HWND а по этому дескриптору можно изменить его заголовок с помощью SetWindowText
Подробно о данной функции здесь http://vsokovikov.narod.ru/New... owtext.htm
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
01.06.2012, 16:12  [ТС]
-=ЮрА=-, большое спасибо за ответ, почитал про SetWindowText, но не совсем то.

Изменить заголовок формы легко:
C++
1
2
3
4
HWND hWnd;
hWnd = Form1->Handle;
char *STR="New";
SetWindowText(hWnd,STR);
Изменить свойство Caption у объекта Panel тоже:
C++
1
2
3
4
5
HWND hWnd;
hWnd = Form1->Panel1->Handle;
char *STR="New";
SetWindowText(hWnd,STR);
Form1->Panel1->Refresh();
А вот к примеру у объекта Shape нету свойства Handle.
А я хочу приблизительно следующее:
C++
1
2
3
4
5
6
7
8
9
10
...
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TransmitBNumber(1);
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
TransmitBNumber(2);
}
...
где
C++
1
2
3
4
5
void TransmitBNumber(int i)
{
//какие-то действия получения Shape[i]
Form1->Shape[i]->Visible = true;
}
А Shape[i] это уже конкретно Shape1, если i==1; Shape2, если i==2 и т.д.

Не по теме:

Прошу прощения за билдер.

0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
05.06.2012, 10:43  [ТС]
Не работает.
C++
1
2
3
4
5
AnsiString NameObj;
NameObj = (Form1->Edit1->Text);
TShape* SenderSh;
SenderSh->Name = NameObj;
SenderSh->Visible = true;
0
Автор FAQ
 Аватар для -=ЮрА=-
6614 / 4256 / 401
Регистрация: 08.08.2009
Сообщений: 10,325
Записей в блоге: 24
05.06.2012, 14:52
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Не работает.
SatanaXIII, и эдитБокс и статик текст и комбобокс - это всё окна т.е. они имеют HWND и к ним применим SetWindowText. Получить дескриптор конкретного контрола можно либо через GetDlgItem(hParent,IDC_EDIT); либо напрямую m_(имя нашего контрола).GetWindow()->m_hWnd;
Чесн слово что там у тебя не выходит, никак не могу понять
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
05.06.2012, 16:32  [ТС]
Цитата Сообщение от -=ЮрА=-
...и эдитБокс и статик текст и комбобокс - это всё окна...
-=ЮрА=-, бесспорно, но я в данный момент про Shape. Графический, точнее геометрический объект и не окно. Я никак не пойму как это все можно к нему применить.
0
05.06.2012, 17:08

Не по теме:

SatanaXIII, не работаю в формах к сожалению:pardon:

0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
05.06.2012, 18:38
SatanaXIII, ну, дык, сделай массив указателей на свои контролы.
C++
1
2
3
4
5
TShape *shapes[] = { Shape1, Shape2, Shape3, Shape4 };
// ...
for(size_t i = 0; i < sizeof(shapes) / sizeof(shapes[0]); i++){
  shapes[i]->Visible = true;
}
0
Я Фоюмчанин ? дааааа)
 Аватар для ivan.-94
213 / 204 / 23
Регистрация: 02.06.2012
Сообщений: 1,424
Записей в блоге: 12
05.06.2012, 19:41
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Изменить заголовок формы легко:
Цитата Сообщение от SatanaXIII Посмотреть сообщение
C++
1
2
3
4
HWND hWnd;
hWnd = Form1->Handle;
char *STR="New";
SetWindowText(hWnd,STR);
Меняем заголовок формы.
C++
1
2
3
4
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Form1->Caption = " New FORM1 ";
}
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Изменить свойство Caption у объекта Panel тоже:
Цитата Сообщение от SatanaXIII Посмотреть сообщение
C++
1
2
3
4
5
HWND hWnd;
hWnd = Form1->Panel1->Handle;
char *STR="New";
SetWindowText(hWnd,STR);
Form1->Panel1->Refresh();
Меняем свойство Caption у объекта TPanel.
C++
1
2
3
4
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Form1->Panel1->Caption = " New PANEL1";
}
Цитата Сообщение от SatanaXIII Посмотреть сообщение
А вот к примеру у объекта Shape нету свойства Handle.
А собственно говоря какой текст вы хатели увидеть на компоненте TShape? И зачем этому компоненту свойствоHandle?
0
Я Фоюмчанин ? дааааа)
 Аватар для ivan.-94
213 / 204 / 23
Регистрация: 02.06.2012
Сообщений: 1,424
Записей в блоге: 12
05.06.2012, 20:14
Цитата Сообщение от BRcr Посмотреть сообщение
SatanaXIII, ну, дык, сделай массив указателей на свои контролы.
C++
1
2
3
4
5
TShape *shapes[] = { Shape1, Shape2, Shape3, Shape4 };
// ...
for(size_t i = 0; i < sizeof(shapes) / sizeof(shapes[0]); i++){
  shapes[i]->Visible = true;
}
Да но не проще ли зделать так?

C++
1
2
3
4
5
6
7
8
9
10
11
    for(int i=0;i<5;i++){
        Panel[i] = new TPanel(this);
        Panel[i]->Parent = Form1;
        Panel[i]->Show();
        Panel[i]->Left = 10;
        Panel[i]->Width = 100;
        Panel[i]->Top = Panel[i]->Width/2*i+5;
        Panel[i]->Tag = i;
        Panel[i]->Name="Panel"+(AnsiString)i;
        Panel[i]->Caption="Panel"+(AnsiString)i;
    }
Вложения
Тип файла: rar mass TPanel.rar (3.4 Кб, 11 просмотров)
0
Я Фоюмчанин ? дааааа)
 Аватар для ivan.-94
213 / 204 / 23
Регистрация: 02.06.2012
Сообщений: 1,424
Записей в блоге: 12
06.06.2012, 03:32
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Господа, возникла необходимость динамической подмены имени графического объекта формы, созданного статически.
То есть на форме находится множество однотипных объектов и к каждому из них нужно применить одно и то же действие. К примеру существует десять кнопок и десять соответствующих им панелей. И при нажатии на Button1 изменяется свойство Panel1, при нажатии Button2 соответственно то же самое свойство Panel2 и так далее. Всего таких пар объектов много, и не охота в обработчик каждой кнопки запихивать здоровый кусок кода, одинакового для всех, и отличающийся только на номер кнопки (объекта). А просто написать функцию, в которую передавать единственный параметр - имя нажатой кнопки (или просто номер ее).

Что-то типа того:
C++
1
2
3
4
Form1->Panel1->Visible = false;
 
NameObject = "Panel1";
Form1->NameObject->Visible = false;
По моему примеру что я вам выше бросал можно написать функцию.

C++
1
2
3
4
void Form1::Funk(int i)
{
    TLabel[i]->Caption="New Caption Label"+IntToStr(i);
}
Только если у вас заданное количество кнопок и компонентов TLabel почему не написать
просто
C++
1
    TLabel[i]->Caption="New Caption Label"+IntToStr(i);
,где i = 1..n, n=количество кнопок и компонентов TLabel
0
Практикантроп
 Аватар для nick42
4841 / 2726 / 534
Регистрация: 23.09.2011
Сообщений: 5,798
06.06.2012, 10:02
А не проще ли применить общий обработчик для всех кнопок по типу... __
C++
1
2
3
4
5
6
7
8
9
10
11
void __fastcall TForm1::Button1Click(TObject *Sender)
{
     TObject *mO;
     int p=0;
     for (int i=1;i<99;i++)
       if (((TButton *)Sender)->Name == "Button"+IntToStr(i))
       {  p=i; break;  }
     if (p>0)
       if ((mO=FindComponent("Panel"+IntToStr(p)))>0)
          ((TPanel *)mO)->Color = clGray ;
}
2
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
07.06.2012, 13:34  [ТС]
Цитата Сообщение от ivan.-94 Посмотреть сообщение
А собственно говоря какой текст вы хатели увидеть на компоненте TShape? И зачем этому компоненту свойствоHandle?
В том то и дело.
Всякие вот эти вот это было к разговору про SetWindowText.


Цитата Сообщение от ivan.-94 Посмотреть сообщение
Да но не проще ли зделать так?

C++
1
2
3
4
5
6
7
8
9
10
11
    for(int i=0;i<5;i++){
        Panel[i] = new TPanel(this);
        Panel[i]->Parent = Form1;
        Panel[i]->Show();
        Panel[i]->Left = 10;
        Panel[i]->Width = 100;
        Panel[i]->Top = Panel[i]->Width/2*i+5;
        Panel[i]->Tag = i;
        Panel[i]->Name="Panel"+(AnsiString)i;
        Panel[i]->Caption="Panel"+(AnsiString)i;
    }
Нет не проще, так как объекты не создаются динамически. Для внимательно читающих:
Цитата Сообщение от SatanaXIII Посмотреть сообщение
...возникла необходимость динамической подмены имени графического объекта формы, созданного статически.
Размещая их динамически, я застрелюсь каждому прописывать свойства - они у всех разные. Хотя бы те же координаты. Просто на форму набросать и потянуть за углы по проще.


Вот! Вот что я имел ввиду.
Цитата Сообщение от BRcr Посмотреть сообщение
SatanaXIII, ну, дык, сделай массив указателей на свои контролы.
C++
1
2
3
4
5
TShape *shapes[] = { Shape1, Shape2, Shape3, Shape4 };
// ...
for(size_t i = 0; i < sizeof(shapes) / sizeof(shapes[0]); i++){
  shapes[i]->Visible = true;
}

Большое спасибо, BRcr. Все работает замечательно, но только в потоке главной формы. При создании параллельного потока повисает на глушняк. Какие-то проблемы с созданием массива ссылок на объекты, размещенные в другой форме. Линкуется два часа, а потом виснет. Что-то вот ему не нравится из потока обращаться. Не в курсе в чем подвох?
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
07.06.2012, 14:08
Долгая линковка - по меньшей мере странно, что-то где-то зацикливается...
Подвисать может из-за отсутствия в потоке Synchronize(). Непонятно, в общем, код в студию.
0
Я Фоюмчанин ? дааааа)
 Аватар для ivan.-94
213 / 204 / 23
Регистрация: 02.06.2012
Сообщений: 1,424
Записей в блоге: 12
07.06.2012, 16:24
Цитата Сообщение от SatanaXIII Посмотреть сообщение
C++
1
sizeof(shapes) / sizeof(shapes[0]
может быть здесь какая то проблема. Попробуйте вместо этого написать конкретное число.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
08.06.2012, 16:32  [ТС]
То, что предложил nick42 прям самое то! Волшебно. Еще бы все это вынести в отдельный поток. Скажем, чтобы при нажатии на кнопку динамически создавался поток, и по прошествии некоторого времени, уничтожался. И для каждой кнопки свой.

Вся моя задача сводится к тому, чтобы подсвечивать на форме некоторое время сектора произвольной формы, размеров и расположения (отсюда и статическое их создание). Время подсвечивания (попросту видимости Shape-ов) так же задается произвольно. Так же может быть нажато несколько кнопок по очереди, что значит, что подсвечиваться должны произвольное количество секторов одновременно. И чтобы основная форма не зависала на эти несколько секунд и пихаю все это дело в поток.
Вот как-то так.

Старый код уже заломал, так что в студию его тяжело. Теперь вот в тот же поток пытаюсь запихать nick42-ю придумку. Получается следующее:

У всех кнопок на свойство OnClick вешаю событие
C++
1
2
3
4
void __fastcall TFormTabl::BMesto1Click(TObject *Sender)
{
CaptureBName(Sender);
}
Функция CaptureBName имеет следующий вид:
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
void __fastcall TFormTabl::CaptureBName(TObject *Sender)
{
FormPlan->Show(); // Показать форму, содержащую картинку с секторами.
 
int mm=0;
 
     TObject *mO; // Указатель на переменную типа объект (заготовка для любого объекта)
     int p=0;
     for (int i=1;i<VsegoKnopok;i++)
       if (((TButton *)Sender)->Name == "BMesto"+IntToStr(i)) // Если имя указателя на объект типа кнопка равно BMesto[i]
       {  p=i; break;  } 
     if (p>0) // Если есть хоть одно совпадение
       if ((mO=FindComponent("LMesto"+IntToStr(p)))>0) // Найти объект с названием LMesto[p] и поместить в mO указатель на него.
         { 
         while(mm<((TLabel *)mO)->Caption.Length()) // У меня рядом с каждой кнопкой расположен лейбл, в котором написано название нужного сектора
                                                    // вида A/1, A/2, B/1, D,12 и т.д. Из них я парсю название нужного сектора (Shape-а) убирая слеш. 
           {                          //mm++;
           if( (((TLabel *)mO)->Caption[++mm]!='/') )
             {
             sKovsh[p].NameSector += ((TLabel *)mO)->Caption[mm]; // В структуре sKovsh храню в том числе и имя сектора.
             }
           }
           sKovsh[p].BeginFlash = true; // Так же в структуре лежит флаг активации подсветки
         }
       }
}
В соседнем модуле лежит код потока:
C++
1
2
3
4
5
6
7
8
9
10
11
12
.h
 
class ThreadPosition : public TThread
{
private:
        void __fastcall LoopPosition();
protected:
        void __fastcall Execute();
public:
        __fastcall ThreadPosition(bool CreateSuspended);
        TObject *mO1; // Опять пытаюсь создать указатель
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.cpp
 
void __fastcall ThreadPosition::Execute()
{
do
{
 Synchronize(LoopPosition);
}
while(!Terminated);
}
 
void __fastcall ThreadPosition::LoopPosition()
{
for(int n=1; n<VsegoKnopok; n++) // Перебор всех кнопок
{
  if(FormTabl->sKovsh[n].BeginFlash) // Если n-ная кнопка нажата
    {
         ((TShape *)mO1)->Name = FormTabl->sKovsh[n].NameSector; // В FormTabl объявлена структура sKovsh
         ((TShape *)mO1)->Visible = !(((TShape *)mO1)->Visible);
    }
}
И вот на 18 строчке происходит практически то же самое, что и в предыдущем случае. То есть все работает без проблем. Не виснет, основная форма работает, кнопки нажимаются, но как только доходит до 18 строки поток наглухо виснет.

Добавлено через 22 часа 27 минут
Пардон.
Не вот так
C++
1
2
3
4
5
  if(FormTabl->sKovsh[n].BeginFlash) // Если n-ная кнопка нажата
    {
         ((TShape *)mO1)->Name = FormTabl->sKovsh[n].NameSector; // В FormTabl объявлена структура sKovsh
         ((TShape *)mO1)->Visible = !(((TShape *)mO1)->Visible);
    }
а вот так будет вернее
C++
1
2
3
4
5
6
  if(FormTabl->sKovsh[n].BeginFlash)
    {
       if ((mO1=FindComponent(FormTabl->sKovsh[n].NameSector))>0)
         //((TShape *)mO1)->Name = FormTabl->sKovsh[n].NameSector;
         ((TShape *)mO1)->Visible = !(((TShape *)mO1)->Visible);
    }
Ругается. Говорит
[C++ Error] ThreadPosition.cpp(43): E2268 Call to undefined function 'FindComponent'

Хотя FindComponent объявлена в Classes.hpp, подключаемом по умолчанию как и в основной форме, так и в потоке.
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
08.06.2012, 18:00
FindComponent - метод класса формы в данном случае(наследуется, начиная с TComponent).
Поэтому так, если надо искать на FormTabl:
C++
1
mO1 = FormTabl->FindComponent( FormTabl->sKovsh[n].NameSector )
1
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
09.06.2012, 14:02  [ТС]
Точно!
Цитата Сообщение от BRcr Посмотреть сообщение
FindComponent - метод класса формы в данном случае(наследуется, начиная с TComponent).
Поэтому так, если надо искать на FormTabl
Все работает превосходно. Всем большое спасибо.

Добавлено через 4 часа 12 минут
Вдогонку. А можно ли пересчитать все однотипные объекты на форме? Или как-нибудь устроить перебор оных. Просто интересно.
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
09.06.2012, 14:56
C++
1
2
3
4
5
size_t count = 0;
for( size_t i = form->ComponentCount - 1; i >= 0; --i ) {
  if ( form->Components[i]->ClassNameIs( "TLabel" ) ) ++count;
}
ShowMessage( String( count ) + " labels counted." );
Еще свойство Controls есть, если что...
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.06.2012, 14:56
Помогаю со студенческими работами здесь

Получение указателя на метод объекта по его имени
Доброго времени суток. Как получить метод объекта имея в строковой переменной его имя, по аналогии с WinAPI - GetProcAddress? Пример: ...

Динамическое изменение фильтра
я кинул на форму grid и radioGrub мне нужно сделать динамический изменений фильтраий через событий onrepertfilter...прописать код!!!я...

Как задать динамическое изменение имени параметра
Здравствуйте, помогите, пожалуйста советом. Есть три вектора разной длины А1, А2, А3. Теперь я хочу в цикле поочередно к ним обращаться...

Динамическое изменение положения объекта
Ребят, как ПРОГРАММНО сделать то, что в делфи 7 делается так: ПКМ по объекту-управление-переслать назад?

Не работает динамическое изменение объекта
Привет. Вот создал типа калькулятор с динамикой. А не работает. Помогите мне найти ошибку. Вот код: &lt;!DOCTYPE html&gt; ...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru