Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Проблема с TImage


Автор: amt 23.1.2012, 21:30
Всем доброе время суток!
Начал осваивать C++. До этого работа в VB6.
Там для любого сонтрола можно установить индек, например, Image1(0)? Image1(1) и т.д
Это очень удобно, так как позволяет в цикле обрабатывать свойства семейства  Image1, различая каждый из них по индексу.

Подскажите, плиз, можноли сделать это в C++ и если можно, о как?
У меня не получилось.

Заранее благодарен

Добавлено через 12 минут и 18 секунд
Мне наверное надо в Bilder
Модераторы, перенесите, плиз.

Автор: bsa 24.1.2012, 10:30
Цитата(amt @  23.1.2012,  22:30 Найти цитируемый пост)
Начал осваивать C++.

ты начал осваивать не С++, а C++ Builder. Это совершенно разные вещи (отличия такие же, как basic и visual basic).
Цитата(amt @  23.1.2012,  22:30 Найти цитируемый пост)
Подскажите, плиз, можноли сделать это в C++ и если можно, о как?

в С++ это сделать можно, если написать свой собственный класс. В твоем случае различать можно по названию (Image->Name).

Автор: xvr 24.1.2012, 11:17
Можно перебрать все компоненты на форме - проперти Controls и ControlCount. Дальше разбираться какие из них Image'и (например через dynamic_cast<TImage*>(...) ). Если надо как то отличить сами Image'и друг от друга, то можно пощупать их имена (проперть Name) или задать какие то значения в проперти Tag (он специально для этого предназначен)


Автор: amt 24.1.2012, 18:44
Так я и начал делать

Объявил массив TControl *arrTmg[5]

Дальше в цикле юзаю Controls формы и если его класс TImage делаю

TControl *ChildeControl;

For (i=0; i<4; i++) {
     ChildControl=Form1->Controls[i]

Добавлено через 5 минут и 45 секунд
If (ChildeControl->ClasName=="TImage" )
     arrImg[i]=ChildeControl;

Пишу на память поэтому синтаксис может страдать
Но в этом блоке все окей

Далее я в одной из процедур обращаюсь к массиву

делаю цикл и внем указываю arrImg[i]->Top=10;
При запуске выдается ошибка связанная с памятью щас не помню

Не пойму в чем дело


Цитата

ты начал осваивать не С++, а C++ Builder. Это совершенно разные вещи (отличия такие же, как basic и visual basic).


Я просто не в тот топик засунул и дописал про это

Автор: sawfish 25.1.2012, 10:25
Сделайте приведение типа для указателя контрола:
Код

((TImage*)arrImg[i])->Top=10;

Автор: xvr 25.1.2012, 11:36
Вот это arrImg[i]=ChildeControl; неправильно. У вас в массиве arrImg будут дырки. К тому же вы уверены, что у вас на всей форме только 4 контрола?

Автор: amt 25.1.2012, 19:47
Спасибо  За ответы

Цитата

Сделайте приведение типа для указателя контрола:
Выделить всёкод C++ Builder
1:
    
((TImage*)arrImg[i])->Top=10;

Попробую

Я сегодня написаль в отдленой програмке тот код который описывал для фиксированного количества контролов и  все работает именно через массив  arrImg[i]=ChildeControl. 

Вот то что у меня работает отдельно
Код

/---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "string.h"
#include "Controls.hpp"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TControl *arrImg[3];
int *arrInd;
int i;
int cntImg;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall GetCtrlInd(){
TControl *chldCtrl;
cntImg=0;
    for (i = 0; i < Form1->ControlCount; i++) {
        chldCtrl=Form1->Controls[i];
        if (chldCtrl->ClassName()=="TImage")     {
            chldCtrl->Tag=i;
            Form1->ListBox1->Items->Add(chldCtrl->Name);//для проверки
            cntImg=cntImg++;
            arrImg[i]=chldCtrl;
        }
    }

    arrInd = new int[cntImg];

    for (i = 0; i < Form1->ControlCount; i++) {
        chldCtrl=Form1->Controls[i];
        if (chldCtrl->ClassName()=="TImage")     {
            arrInd[chldCtrl->Tag]=chldCtrl->Tag;
        }
    }
}
//---------------------------------------------------------------------------
void __fastcall SetPos(){
int start=20;
int step=51;

    for (i = 0; i < 3; i++) {
        arrImg[i]->Top=start;
        start=start+step;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
GetCtrlInd();
SetPos();
}
//---------------------------------------------------------------------------

А вот в проге где еще уже что-то наворочено и где этот код необходим, он почему-то не работает, функция SetPos вызывает ошибку при выполнении. Помогите плиз!




Цитата

К тому же вы уверены, что у вас на всей форме только 4 контрола?

По этому поводу у меня второй вопрос, который я хотел задать.

Задумка такая что количество контролов будет зависит от настроек пользователя. Как динамически добавлять объекты? Подскажите плиз

Автор: xvr 25.1.2012, 21:42
В строке 32 ошибка - заведите отдельный индекс (не i), и по нему складывайте:
Код

int j=0;
...
       arrImg[j++]=chldCtrl;
...



Цитата(amt @  25.1.2012,  19:47 Найти цитируемый пост)
 Как динамически добавлять объекты?

Код

TImage* my_obj=new TImage(this);
my_obj->Parent=this;
Ну и остальные проперти по вкусу. Вызывать из метода формы TForm1

Автор: amt 26.1.2012, 21:14
xvr? спасибо за ответ (и всем кто откликнулся). 
Только я еще не очень хорошо ориентируюсь в языке

    
Цитата

TImage* my_obj=new TImage(this);
my_obj->Parent=this;


В первой строке вроде всё ясно кроме this
И вторую строку поясните, плиз



Цитата

В строке 32 ошибка - заведите отдельный индекс (не i), и по нему складывайте:


? Это исправить в моей большой проги или в той что выложил? (прсто эта маленькая прога прекрасно работает)


Заранее благодарен

Автор: xvr 27.1.2012, 12:04
Цитата(amt @  26.1.2012,  21:14 Найти цитируемый пост)
В первой строке вроде всё ясно кроме this

this - это объект, от которого вызывается метод. В данном случае - ваша форма

Цитата(amt @  26.1.2012,  21:14 Найти цитируемый пост)
И вторую строку поясните, плиз

Тут вновь созданному объекту говорят, кто у него родитель (в иерархии окон на экране)

Цитата(amt @  26.1.2012,  21:14 Найти цитируемый пост)
Это исправить в моей большой проги или в той что выложил?

В обоих

Цитата(amt @  26.1.2012,  21:14 Найти цитируемый пост)
прсто эта маленькая прога прекрасно работает

Вам просто повезло. Ваши TImage'и лежат первыми среди всех компонентов

А вот это cntImg=cntImg++; вообще непонятно что (точнее понятно - баг). Должно быть либо cntImg=cntImg+1; либо cntImg++;

Автор: amt 27.1.2012, 23:35
xvr, в очередной раз спасибо

Цитата

А вот это cntImg=cntImg++; вообще непонятно что (точнее понятно - баг). Должно быть либо cntImg=cntImg+1; либо cntImg++;


Здесь я имел ввиду увеличение параметра на единицу в каждом шаге цикла.  Просто еще не привык к новому языку и смешал все в кучу.

Цитата

Вам просто повезло. Ваши TImage'и лежат первыми среди всех компонентов


При проверке я действительно Image на форме создал впервую очередь.
А вот на форме в нужной проге вперемежку создавались сонтролы. Видимо это и вызывает ошибку

Буду копать дальше
 smile  smile 

Автор: Dem_max 28.1.2012, 13:18
вот так
Код

    int i = 1;
    while(FindComponent("Button" + AnsiString(i)))
    {
        ((TButton *)FindComponent("Button" + AnsiString(i)))->Enabled = false;
        i++;
    }


Этот код переберет все Button1 до последней, и сделает их не активными, для имэйджев подставь соответствующее имя компонента.

Автор: xvr 28.1.2012, 14:08
Цитата(Dem_max @  28.1.2012,  13:18 Найти цитируемый пост)
Этот код переберет все Button1 до последней,

Этот код не будет работать если изменить имена Button'ов с автогенеренных на что-нибудь более вменяемое

Автор: Dem_max 28.1.2012, 16:36
Цитата(xvr @ 28.1.2012,  14:08)
Цитата(Dem_max @  28.1.2012,  13:18 Найти цитируемый пост)
Этот код переберет все Button1 до последней,

Этот код не будет работать если изменить имена Button'ов с автогенеренных на что-нибудь более вменяемое

Код

    int i = 1;
    while(FindComponent("MySuperPuperButtonExName" + AnsiString(i)))
    {
        ((TButton *)FindComponent("MySuperPuperButtonExName" + AnsiString(i)))->Enabled = false;
        i++;
    }

Автор: xvr 29.1.2012, 12:05
'Более вменяемое' в частности означает, что имена будут осмысленные, а не MySuperPuperButtonExName0/MySuperPuperButtonExName1/MySuperPuperButtonExName2. Ну например - Apply, CancelDlg, LoadFile, ну и т.д.

Автор: Dem_max 29.1.2012, 14:23
Смысла нету присваивать разные имена, если компоненты будут иметь те же свойства и поведение.

Автор: xvr 29.1.2012, 19:43
Цитата(Dem_max @  29.1.2012,  14:23 Найти цитируемый пост)
если компоненты будут иметь те же свойства и поведение. 

А вот это не факт. Неизвестно, для каких компонентов ТС пытается что то изобрести. Возможно, что и для совсем не связанных друг с другом, и с разным поведением.
Вариант с перебором по имени (в виде имя+индекс) действительно хорош для похожих компонентов. Но тогда и именовать компоненты надо с учетом того, что их будут переберать по имени с индексом.
Вариант с пропертью Components не требует какого либо именования, но полностью возлагает на программиста обязанность разбираться с тем, какие компоненты ему попались  smile Этот подход можно применить когда происхождение конкретных компонентов не важно (например при сохранении и восстановлении формы в файл)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)