Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибка доступа к элементу другой формы 
V
    Опции темы
iDeus
Дата 6.10.2011, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Deus vult
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 5.6.2008
Где: Vladivostok

Репутация: нет
Всего: нет



Здравствуйте, помогите пожалуйста разобраться в такой ситуации:

Есть 2 формы, UsersForm и UserAddForm, которые наследуют друг друга. 

На форме UsersForm  лежит заполненный StringGrid. На этой же форме кнопка, по нажатию которой, модально выводится UserAddForm

В UserAddForm сравниваются введенные там данные с данными в StringGrid'е на первой форме. 

Компилятор не выдает ошибок, но при попытке выполнить сравнение выводится ошибка:
user posted image


Обращаюсь к СтрингГриду так:

Код

for(int i = 1; i <= UsersForm->sg_users->RowCount; i++)
                        {
                            if(e_name->Text == UsersForm->sg_users->Cells[1][i]) fl = true;
                        }


В чем может быть проблема? Пробовал переносить TStringGrid *sg_users; в UserAddForm.h из __published в public, так при компиляции вообще пишет, что класс TStringGrid не найден. 

Само собой, правильность индексов элементов СтрингГрида к которым обращаюсь перепроверил.

На всякий случай:

UsersForm.h
Код

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

#ifndef rUsersH
#define rUsersH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Grids.hpp>
#include "PSQLDbTables.hpp"
#include <DB.hpp>
#include <Buttons.hpp>
//---------------------------------------------------------------------------
class TUsersForm : public TForm
{
__published:    // IDE-managed Components
    TStringGrid *sg_users; //собственно тот самый стрингГрид из которого нужно взять данные
    TPSQLQuery *PSQLQuery_Users;
    TBitBtn *bt_add;
    TBitBtn *bt_edit;
    TBitBtn *bt_refresh;
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall bt_addClick(TObject *Sender);

private:    // User declarations
public:        // User declarations
    __fastcall TUsersForm(TComponent* Owner);



    int RowCount; //количество строк которые нам понадобятся

    void HideRight();        //спрятать вправо
    void HideLeft();       //спрятать влево
    void HideUp();         //спрятать вверх
    void HideDown();       //спрятать вниз

    void ShowRight();      //показать справа
    void ShowLeft();       //показать слева
    void ShowUp();         //показать сверху
    void ShowDown();       //показать снизу
};
//---------------------------------------------------------------------------
extern PACKAGE TUsersForm *UsersForm;
//---------------------------------------------------------------------------
#endif


UserAddForm.h
Код

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

#ifndef rUserAddH
#define rUserAddH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TUserAddForm : public TForm
{
__published:    // IDE-managed Components
    TGroupBox *GroupBox1;
    TLabel *Label1;
    TLabel *Label2;
    TEdit *e_name;
    TEdit *e_pass;
    TLabel *lb_ok;
    TLabel *Label4;
    TComboBox *cb_level;
    TLabel *Label5;
    TButton *bt_add;
    TButton *bt_cancel;
    TMemo *m_comment;
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall bt_cancelClick(TObject *Sender);
    void __fastcall bt_addClick(TObject *Sender);
private:    // User declarations
public:        // User declarations
    __fastcall TUserAddForm(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TUserAddForm *UserAddForm;
//---------------------------------------------------------------------------
#endif

PM MAIL ICQ Skype GTalk   Вверх
artsb
Дата 6.10.2011, 10:49 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Цитата(iDeus @  6.10.2011,  09:58 Найти цитируемый пост)
Обращаюсь к СтрингГриду так:

Вы делаете цикл по строкам от 1 до UsersForm->sg_users->RowCount. А это не правильно.
Индексы идут от 0 до (UsersForm->sg_users->RowCount - 1).
Если вам нужно просто пропустить первую строку (если это шапка таблицы, например), то:
Код

for(int i = 1; i < UsersForm->sg_users->RowCount; i++)
{
     if(e_name->Text == UsersForm->sg_users->Cells[1][i])
          fl = true;
}


Добавлено через 4 минуты и 26 секунд
И зачем вам бежать по всем записям, если вы изменяете один единственный флаг.
Лучше так:
Код

bool blnIsChanged = false;
//...
for(int i = 1; i < UsersForm->sg_users->RowCount; i++)
{
     if(e_name->Text != UsersForm->sg_users->Cells[1][i])
     {
          blnIsChanged = true;
          break;
     }
}

if(blnIsChanged)
{
// были внесены изменения
}


Это сообщение отредактировал(а) artsb - 6.10.2011, 10:51


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
iDeus
Дата 6.10.2011, 11:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Deus vult
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 5.6.2008
Где: Vladivostok

Репутация: нет
Всего: нет



artsb, исправил, как вы сказали, но это не помогло. 

похоже проблема все-таки с доступом к СтрингГриду. проверил это так:
добавил перед циклом 

ShowMessage(UsersForm->sg_users->Cells[1][1]);

в результате увидел туже самую ошибку. 

Более того, подобная ошибка выводится если, пробоваться обращаться к компоненту PSQLQuery, который как и СтрингГрид лежит на первой форме. (стрингрид заполняется из результата запроса к Pg)

Может какая-то ошибка в наследовании? 

В первой форме я наследую вторую:

Код

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

#include <vcl.h>
#pragma hdrstop

#include "rUsers.h"
#include "rMain.h"
#include "rStart.h"
#include "rUserAdd.h"   <- вот вторая форма
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "PSQLDbTables"
#pragma resource "*.dfm"


Во второй - первую:

Код

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

#include <vcl.h>
#pragma hdrstop

#include "rUserAdd.h"
#include "rMain.h"
#include "rUsers.h"  <- вот первая
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "PSQLDbTables"
#pragma resource "*.dfm"


Вот код функции, где все происходит (кнопка на второй форме)
Код

void __fastcall TUserAddForm::bt_addClick(TObject *Sender)
{
    //добавление нового пользователя
    //проверяем на заполненность обязательных полей
    if((e_name->Text.Length() > 0) && (e_pass->Text.Length() > 0))
        {
            //проверяем выбранли уровень
            if(cb_level->Text != "...")
                {
                    //проверяем уникальность имени
                    bool fl = false; // такое же имя НЕ встречается

                    ShowMessage(UsersForm->sg_users->Cells[1][1]); // получается ли вообще получить значение из СтрингГрида

                    for(int i = 1; i < UsersForm->sg_users->RowCount; i++)
                        {
                            if(e_name->Text == UsersForm->sg_users->Cells[1][i])
                                {
                                    fl = true;
                                    break;
                                }
                        }
                    if(fl == false)
                        {
                            //добавляем запись в базу данных
                            //ShowMessage("добавляем запись в базу данных");
                            //MainForm->Cursor = crSQLWait;
                            //Screen->Cursor = crSQLWait;
                            ShowMessage("Добавляем запись в БД");

                        }
                    else
                        {
                            //найденно такое же имя
                            ShowMessage("найденно такое же имя");
                        }
                }
            else
                {
                    //не выбран уровень
                    ShowMessage("не выбран уровень");
                }
        }
    else
        {
            //не заполденны имя или пароль
            ShowMessage("не заполденны имя или пароль");
        }

}

PM MAIL ICQ Skype GTalk   Вверх
artsb
Дата 6.10.2011, 11:30 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



iDeus, а попробуйте так:
Код

ShowMessage(UsersForm->sg_users->RowsCount);

Плюс, можете поставить точку останова на эту строку и посмотреть валидны ли указатели UsersForm и sg_users.

Тут естьдва варианта, ИМХО:
1. В СтрингГриде нет записей.
2. Вы убрали форму UsersForm из списка автосоздаваемых. Потом создаёте эту форму отдельно, но всё ещё обращаетесь по указателю UsersForm, который, естественно, не валиден.

Попробуйте ещё вместо строчки
Цитата
ShowMessage(UsersForm->sg_users->Cells[1][1]);

написать так:
Код

TUsersForm *frm;
frm = dynamic_cast<TUsersForm *>(this->Owner);
if(frm)
{
  ShowMessage(frm->sg_users->Cells[1][1]);
}



--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
iDeus
Дата 6.10.2011, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Deus vult
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 5.6.2008
Где: Vladivostok

Репутация: нет
Всего: нет



Цитата

iDeus, а попробуйте так:
ShowMessage(UsersForm->sg_users->RowsCount);


Приводит к той же ошибке. 

Да, вы совершенно правы, форма убрана из автосоздаваемых и создается отдельно, из предыдущей формы. 
Код

        TUsersForm* UsersForm;
    UsersForm = new TUsersForm(Application);


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

ShowMessage(UsersForm->sg_users->Cells[1][1]);

на 
Код

TUsersForm *frm;
frm = dynamic_cast<TUsersForm *>(this->Owner);
if(frm)
{
  ShowMessage(frm->sg_users->Cells[1][1]);
}

но это ни к чему не привело. Условие if(frm) не выполняется, а если вынести ShowMessage(frm->sg_users->Cells[1][1]); за if, то это приводит к появлению все той же ошибки. 

user posted image

СтрингГрид не пуст. 

Может я не верно понял, что нужно сделать с dynamic_cast, что все заработало?
PM MAIL ICQ Skype GTalk   Вверх
artsb
Дата 6.10.2011, 14:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Вы при создании формы UserAddForm также указываете Owner'ом Application?

Если да, то тогда у вас два пути:
1. Передавать указатель на форму UsersForm в конструктор UserAddForm. И далее использовать его.
2. Создавать форму UserAddForm так:
Код

TUserAddForm * UserAddForm;
UserAddForm = new TUserAddForm(this);

и потом делать как я уже писал:
Код

TUsersForm *frm;
frm = dynamic_cast<TUsersForm *>(this->Owner);
if(frm)
{
  ShowMessage(frm->sg_users->Cells[1][1]);
}



--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
iDeus
Дата 6.10.2011, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Deus vult
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 5.6.2008
Где: Vladivostok

Репутация: нет
Всего: нет



artsb, большое спасибо. Все заработало. 

При создании UserAddForm, указал владельцем this, а дальше через 
Код

TUsersForm *frm;
frm = dynamic_cast<TUsersForm *>(this->Owner);


Еще раз спасибо. 
PM MAIL ICQ Skype GTalk   Вверх
artsb
Дата 7.10.2011, 08:06 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Кстати, совсем забыл, есть же ещё третий вариант smile
- При создании формы UsersForm использовать глобальный указатель, т.е. это
Код

TUsersForm* UsersForm;
UsersForm = new TUsersForm(Application);

заменить на:
Код

UsersForm = new TUsersForm(Application);

И теперь в форме UserAddForm использовать указатель UsersForm как обычно.

Просто у вас получилось так: есть глобальный указатель на форму TUsersForm - UsersForm. Он объявлен в конце .h-ника с описанием формы.
Но вы объявили ЛОКАЛЬНЫЙ указатель с таким же именем. Вот и получилось, что вы не "видели" эту форму в UserAddForm.

Это сообщение отредактировал(а) artsb - 7.10.2011, 08:07


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.1168 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.