Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ADOQuery на дочерней форме при использовании MDI


Дева ©   (2005-11-09 21:24:00) 

При написании программы в Delphi с использованием MDI у меня возникла трудность. Последовательность действий при отладки:
Запускаю приложение. Используя меню (MainMenu) "Файл->новый" Создаю дочернюю форму (модуль users). На ней располагается DBGrid с данными ADOQuery. Все работает нормально, данные из базы данных отображаются (В режиме только для чтения).
Надо добавить запись. Для этого использую еще одну форму, в которую вводятся данные. Вызываю её с помощью всплывающего меню (PopupMenu). ПКМ -> новая запись. Эта форма имеет FormStyle = fsNormal. На ней расположено три текстовых поля (TEdit), и две кнопки (TButton). При нажатии на кнопку "Хорошо" передаю дочерней форме параметры - данные, которые необходимо внести в таблицу. Просто запускается процедура, принадлежащая модулу users, со входными параметрами)

procedure TFormUsers.PNewUser(NameUser, FIOUser, PasswUser: String);
begin
ADOQueryUsers.Insert;
ADOQueryUsers.FieldByName('NameUser').AsString:=NameUser;
ADOQueryUsers.FieldByName('FIO').AsString:=FIOUser;
ADOQueryUsers.FieldByName('PasswordUser').AsString:=PasswUser;
ADOQueryUsers.Post;
end;

NameUser, FIOUser, PasswUser получены из трех текстовых полей

Данные передаются, но вот запрос их обрабатывать отказывается. Запрос вообще работать отказывается. Выскакивает сообщение

Project Mpark.exe raised exception class EAccessViolation with message 'Access violation at address 004A9A56 in module 'Mpark.exe'. Read of address 000002F8'. Process stopped. Use Step or Run to continue

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


sniknik   (2005-11-17 13:32:00) [1]

> ButtonOk.ModalResult:=mrOk;//Вот присваиваю значение mrOk
ну так все правильно, перевое присвоение кнопке, на второе кнопка "сработала"

вообще убери в дизайне у кнопки резалт (поставь ModalResult = mrNone), и везде где есть присвоения, раз уж сам по кнопке делаеш, единственное в кнопке завершение по резулту делай. ->

procedure TDlgClientForm.ButtonOkClick(Sender: TObject);
begin
if Length(Edit1.Text) <> 13 then
 begin
    ShowMessage('длина должна быть равна 13');
    Edit1.SetFocus;
 end else
 begin
    Cl1:=Edit1.Text;
    Cl2:=Edit2.Text;
     ModalResult:= mrOk;//не кнопке заметь
 end;
end;


Игорь Шевченко   (2005-11-17 13:23:00) [2]


> Помогите, пожалуйста!! Совсем не могу понять. Я вызываю
> методом ShowModal форму, на которой расположена кнопка Ok.
>  Изначально ModalResult = mrNone, это нужно для того, чтобы
> закрытие формы и выполнение дальнейшего кода происходило
> лишь в том случае, когда данные в полях TEdit соответствовали
> требованиям, тогда ModalResult устанавливается в значение
> mrOk. Но тут у меня проблема - при выполнении всех требований
> нажимаю на кнопку хорошо и ничего не происходит, приходится
> нажимать второй раз


1. У кнопки поставить ModalResult = mrOk
2. Написать обработчик события ButtonClick
if not УспешнаяПроверка then
  ModalResult := mrNone


Дева   (2005-11-17 13:20:00) [3]

Помогите, пожалуйста!! Совсем не могу понять. Я вызываю методом ShowModal форму, на которой расположена кнопка Ok. Изначально ModalResult = mrNone, это нужно для того, чтобы закрытие формы и выполнение дальнейшего кода происходило лишь в том случае, когда данные в полях TEdit соответствовали требованиям, тогда ModalResult устанавливается в значение mrOk. Но тут у меня проблема - при выполнении всех требований нажимаю на кнопку хорошо и ничего не происходит, приходится нажимать второй раз. Тогда все происходит так, как должно было происходить. Почему? Где моя ошибка
модуль Client

procedure TFormClient.EditPMClick(Sender: TObject);
begin
with DlgClientForm do
 begin
   Edit1.Text:=ADOQueryClient.Fields.Fields[1].AsString;
   Edit2.Text:=ADOQueryClient.Fields.Fields[2].AsString;
   ButtonOk.ModalResult:=mrNone;//устанавливаю значение ModalResult
 end;
//вот вызов другой формы с проверкой того, какая кнопка нажата
if DlgClientForm.ShowModal=mrOk then
 begin
 ADOQueryClient.Edit;
 ADOQueryClient.Fields.Fields[1].AsString:=DlgClient.Cl1;
 ADOQueryClient.Fields.Fields[2].AsString:=DlgClient.Cl2;
 ADOQueryClient.Post;
 end;
end;

модуль DlgClient

procedure TDlgClientForm.ButtonOkClick(Sender: TObject);
begin
if Length(Edit1.Text) <> 13 then
       begin
       ShowMessage('длина должна быть равна 13');
       Edit1.SetFocus;
       end
 else
   begin
   ButtonOk.ModalResult:=mrOk;//Вот присваиваю значение mrOk
   Cl1:=Edit1.Text;
   Cl2:=Edit2.Text;
   end;
end;


Дева   (2005-11-16 14:38:00) [4]

Спасибо, у меня уже все работет.
А методы, что Visible, что ShowModal применялись не к дочерней форме, а к той, в которой вводились данные для передачи в дочернюю форму. У нее FormStyle = fsNormal

Код, если уж очень интересно:
(выложу только то, что по делу)

модуль main

//происходит при выборе в меню: Базы данных->Сотрудники
procedure TMusicPark.SotrudMClick(Sender: TObject);
begin
SotrudM.Visible:=false;//для того, чтобы нельзя было запустить еще одно
TFormUsers.Create(Application);//создаю дочернее окно users
end;

модуль users

//PopupMenu новый пользователь
procedure TFormUsers.NewUserClick(Sender: TObject);
begin
//для не-дочернего окна, откуда беру параметры для передачи обратно
//в модуль users
with FormPasswChange do
 begin
//просто "делаю" внешний вид
   Caption:='Новый пользователь';
   LabelOldPassw.Caption:='Имя пользователя';
   EditOldPassw.Text:='';
   EditOldPassw.PasswordChar:=#0;
   LabelNewPassw.Caption:='ФИО';
   EditNewPassw.Text:='';
   EditNewPassw.PasswordChar:=#0;
   LabelRepPassw.Caption:='Пароль';
   EditRepPassw.Text:='';
//вот тут и началась проблема
   Visible:=true;
 end;
end;

//далее выполнение передается в модуль PasswChange

//после ввода данных в поля: нажатие кнопки хорошо
procedure TFormPasswChange.ButtonOkClick(Sender: TObject);
begin
users.FormUsers.NewUser(Edit1.Text, Edit2.Text, Edit3.Text);
end;

//теперь снова в модуль users

procedure TFormUsers.NewUser(Ed1, Ed2, Ed3: String);
begin
//вот это уже отказывается работать
ADOQueryUsers.Insert;
ADOQueryUsers.FieldByName('NameUser').AsString:=Ed1;
ADOQueryUsers.FieldByName('FIO').AsString:=Ed2;
ADOQueryUsers.FieldByName('PasswordUser').AsString:=Ed3;
ADOQueryUsers.Post;
end;

Это было в самом начале. Потом, когда я стала исправлять, я использовала в модуле users глобальные переменные
Ed1, Ed2, Ed3: String;
изменила два метода:
procedure TFormUsers.NewUserClick(Sender: TObject);
procedure TFormPasswChange.ButtonOkClick(Sender: TObject);
и удалила:
procedure TFormUsers.NewUser(Ed1, Ed2, Ed3: String);

получилось

//PopupMenu новый пользователь
procedure TFormUsers.NewUserClick(Sender: TObject);
begin
with FormPasswChange do
 begin
   Caption:='Новый пользователь';
   LabelOldPassw.Caption:='Имя пользователя';
   EditOldPassw.Text:='';
   EditOldPassw.PasswordChar:=#0;
   LabelNewPassw.Caption:='ФИО';
   EditNewPassw.Text:='';
   EditNewPassw.PasswordChar:=#0;
   LabelRepPassw.Caption:='Пароль';
   EditRepPassw.Text:='';
 end;
if FormPasswChange.ShowModal=mrOk then
//происходит в том случае, когда нажата кнопка хорошо
//на форме PasswChange
   begin
     ADOQueryUsers.Insert;
     ADOQueryUsers.FieldByName('NameUser').AsString:=Ed1;
     ADOQueryUsers.FieldByName('FIO').AsString:=Ed2;
     ADOQueryUsers.FieldByName('PasswordUser').AsString:=Ed3;
     ADOQueryUsers.Post;
   end;
end;

//кнопка хорошо
procedure TFormPasswChange.ButtonOkClick(Sender: TObject);
begin
users.Ed1:=EditOldPassw.Text;
users.Ed2:=EditNewPassw.Text;
users.Ed3:=EditRepPassw.Text;
end;

Соответственно кнопке хороша задала ModalResult = mrOk


sniknik   (2005-11-15 09:11:00) [5]

p.s. если же это все относится к нормальной форме в MDI приложении, то все одно описание как, что у него происходит описано непонятно, гда вызывается (событие/порядок имеют значение) в общем без кода не разберешся.


sniknik   (2005-11-15 09:01:00) [6]

Германн ©   (15.11.05 01:54) [8]
> Nikolay. А по-русски если?

а что непонятного?
сделай MDI Application и попробуй установить свойство формы, у которой стиль fsMDIChild, Visible в false например (в true смысла нет она показывается сразу после создания). потом проверь выполни метод ShowModal (хотя и безсмысленно).
в обоих случаях получиш ошибку, неприменимо это к чилдам.
и тем не менее Дева ©   (14.11.05 22:46) [5] утверждает что ему помог переход с одного на другое.... ???
вывод? здесь он говорит про чилдформы, пытается с ними работать (-> ActiveMDIChild), хотя реально использует другие. пусть покажет что в его понятиях дочерняя форма. код. ведь совершенно ясно, что при таких пробелах, его словесное описание проблемы - совершенная лажа, не отражает действительности.


Германн   (2005-11-15 01:54:00) [7]

2 sniknik ©   (15.11.05 00:59) [7]
Nikolay. А по-русски если?
"сначала бы определились про, что разговор... код, желательно с коментариями, что, чем именно ты назаваеш, просто позарез необходим."

Имхо, лучше пить и молчать, чем не пить и жевать!
Прими и проч. :-)


sniknik   (2005-11-15 00:59:00) [8]

> на дочерней форме при использовании MDI
> как-то надо использовать свойство ActiveMDIChild
> Просто использовала метод ShowModal...

???
сомнительно чтото. также как и "использование Visible", не применимо это к MDI дочерним окнам.

сначала бы определились про, что разговор... код, желательно с коментариями, что, чем именно ты назаваеш, просто позарез необходим.


Плохиш   (2005-11-14 23:51:00) [9]


> Дева ©   (14.11.05 22:46) [5]
> Не подскажете, почему использование Visible не предпочтительно?

В общем случае утверждение ложно.
А у тебя так и осталась ошибка в 17й строке, как Игорь Шевченко в [3] намекал и эта ошибка скоро опять всплывёт.


Дева   (2005-11-14 22:46:00) [10]

Ладно, всем спасибо. Я этот вопрос решила. Просто использовала метод ShowModal вместо того, чтобы использовать Visible (как я это сделала сначала).
Не подскажете, почему использование Visible не предпочтительно?


Slym   (2005-11-10 16:23:00) [11]

Лучше так-
procedure TFormUsers.NewUser(Sender:TObject);
var UserEdit:TUserEdit;
begin
 UserEdit:=TUserEdit.Create(nil);
 try
   if UserEdit.ShowModal=IDOK then
   begin
     ADOQueryUsers.Insert;
     try
       ADOQueryUsers.FieldByName('NameUser').AsString:=UserEdit.NameUser.Text;
       ADOQueryUsers.FieldByName('FIO').AsString:=UserEdit.FIOUser.Text;
       ADOQueryUsers.FieldByName('PasswordUser').AsString:=UserEdit.PasswUser.Text;
       ADOQueryUsers.Post;
     except
       ADOQueryUsers.Cancel;
       raise;
     end;
   end;
 finally
   UserEdit.Free;
 end;
end;


Игорь Шевченко   (2005-11-10 16:05:00) [12]

Дева ©   (10.11.05 14:57) [2]

А код, как это делается, можно посмотреть ?


Дева   (2005-11-10 14:57:00) [13]

Не совсем. Из дочерней формы методом Visible я вызываю окно для ввода данных, т. е. другой модуль. Из этого модуля введенные данные я возвращаю в дочернюю форму. Очевидно, я неверно использую процедуру дочерней формы или вызываю форму для ввода данных. Мне кажется, что здесь как-то надо использовать свойство ActiveMDIChild, только я не знаю как. Не подскажите?


Игорь Шевченко   (2005-11-09 22:59:00) [14]


> Read of address 000002F8'


Сдается мне, какая-то форма не создана, а на нее ссылаются по имени глобальной переменной.

Я угадал ?


Наверх

Титульная страница Поиск, карта сайта Написать письмо