Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.06.26;
Скачать: CL | DM;

Вниз

---|Ветка была без названия|---   Найти похожие ветки 

 
Avreliy   (2003-05-30 16:30) [0]

Здравствуйте мастера! (вкратце: FireBird->D7->BDE->DBGrid)
Есть подчинённая таблица и один из столбцов объявлен так:
SUMM Numeric(9,2)(он же - TableESUMM). При внесении данных без всякой самодеятельности (без попыток переприсвоить) - всё срабатывает. А вот, если я после серии проверок желаю изменить вносящиеся данные (в проц-ре OnChange), например, таким образом
TableESUMM.Value := 100 * TableESUMM.Value,
то Д7 выдаёт Debugger Fault Notification: "access violation at 0Xxxxxxxx: write of address 0Xyyyyyyy".
Когда я пытаюсь изменить данные этого поля через запрос, напр.,
QueryESUMM.Value := 100,
то всё срабатывает. В чём ошибка?


 
AlexSerp ©   (2003-05-30 16:57) [1]

Обычно access violation выдает Делфи. Проблема не в данных.
Я получал access violation, только тогда, когда пытался обратиться к несозданной или освобожденной переменной/объекту.
Других ошибок с access violation у меня не было.


 
Соловьев ©   (2003-05-30 17:00) [2]


> данные (в проц-ре OnChange),

а не пробовал при Edit


 
Avreliy   (2003-05-30 17:06) [3]

> AlexSerp ©
Дело в том, что у меня уже есть существующий нединамический объект, а динамические объекты я не создавал.


 
Sandman25 ©   (2003-05-30 17:09) [4]

Похоже, что происходит рекурсивный вызов обработчика OnChange, пока значение TableESUMM.Value не выйдет за пределы максимально возможного.


 
Avreliy   (2003-05-30 17:26) [5]

> Sandman25
А как может происходить вызов, если я его в обработчике не указываю?
> Соловьев
Ведь такого обработчика не существует для TField-объектов?
Т.е. советуешь использовать AfterEdit для TTable?


 
Zacho ©   (2003-05-30 17:31) [6]


> Avreliy (30.05.03 17:26)

Изменение значения поля в OnChange приводит к вызову OnChange .. и поехало - бесконечная рекурсия.
Используй TField.OnSetText - он для этого и придуман.


 
Sandman25 ©   (2003-05-30 18:03) [7]

2 Avreliy

procedure TableOnChange(...);
begin
Table.OnChange := nil;
try
TableESUMM.Value := 100 * TableESUMM.Value;
finally
Table.OnChange := TableOnChange;
end;


 
Zacho ©   (2003-05-30 18:14) [8]


> Sandman25 © (30.05.03 18:03)

Зачем ??? Ведь есть OnSetText.


 
Avreliy   (2003-05-30 18:21) [9]

Если я использую TField.OnSetText, то игнорируется OnValidate и вдобавок после попытки ввести данные они исчезают.
Если использовать просто OnValidate, то вводимые данные тоже будут исчезать.


 
Sandman25 ©   (2003-05-30 18:24) [10]

2 Zacho

Может пригодиться. В данном случае, возможно, и не нужно.


 
Zacho ©   (2003-05-30 18:27) [11]


> Sandman25 © (30.05.03 18:03)

И еще дополнение: работать твой пример все равно не будет. Правильно было бы так:
procedure TMyForm.MyTableMyFieldChange(Sender:TField);
var
tmpOnChange:TFieldNotifyEvent;
begin
tmpChange:=Sender.OnChange;
Sender.OnChange:=nil;
try
Sender.Value:=...;
finally
Sender.OnChange:=tmpOnChange;
end;
end;

Только зачем такое извращение ?


 
Sandman25 ©   (2003-05-30 18:28) [12]

2 Zacho

Вспомнил одну программку по вводу ТТН, где при изменении пользователем цены с НДС нужно было устанавливать цену без НДС, а при изменении цены без НДС устанавливать цену с НДС.


 
Avreliy   (2003-05-30 18:30) [13]

> Sandman25
Не совсем понял твой код???
Ведь у TTable нет обработчика OnChange.
И что такое Table.OnChange?


 
Zacho ©   (2003-05-30 18:33) [14]


> Avreliy (30.05.03 18:21)

Значит, как-то не так используешь OnSetText, у меня проблем не было.
А OnValidate предназначен исключительно для того, чтобы вызвать Exception если введенные данные не прошли проверку.


 
Sandman25 ©   (2003-05-30 18:33) [15]

>Zacho © (30.05.03 18:27)

Я обычно ставил обработчик на DataSource.OnDataChange.
Для него и пример привел, только не в тему :)


 
Sandman25 ©   (2003-05-30 18:37) [16]

>Avreliy (30.05.03 18:30)

См.Zacho © (30.05.03 18:27), а еще лучше
Zacho © (30.05.03 17:31) ибо Sandman25 © (30.05.03 18:33)
Прошу прощения за нежеланное запутывание


 
Zacho ©   (2003-05-30 18:44) [17]


> Sandman25 © (30.05.03 18:33)

Да дело не столько в теме, сколько в том, что Table.OnChange := TableOnChange - неправильно. Возможно, ты все-таки имел в виду не процедуру, а метод ? :-)



 
Avreliy   (2003-05-30 18:44) [18]

> Zacho © (30.05.03 18:33)
В том-то и дело, что он не вызывает Exception.
Вводимые данные попросту исчезают из поля ввода, абсолютно игнорируясь.


 
Sandman25 ©   (2003-05-30 18:54) [19]

Zacho © (30.05.03 18:44)

Естественно метод. Ошибся.
procedure TForm1.DataSource1OnChange(Sender:TObjoect; Field:TField); Примерно так надо было... вроде :)

PS. Я сегодня встал в полпятого утра и хочу спать, а с работы уйти не могу - работаю до 19-00 по мск. Вот и приходится лазить по форуму, чтобы не уснуть. Ничего, через пару минут наконец-то пойду домой :)
Счастливо!


 
Sandman25 ©   (2003-05-30 18:55) [20]

Не, вот так :)
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);


 
Zacho ©   (2003-05-30 19:00) [21]


> Avreliy (30.05.03 18:44)

Exception должен вызывать ты сам в OnValidate. Или ты о чем-то другом ?


 
Avreliy   (2003-05-30 19:34) [22]

В OnValidate я анализирую состояние переменных и в случае чего генерирую исключительную ситуацию. Например, анализирую на предмет возможного ввода отрицательного значения.
А вот после его ввода(отриц. зн-ния) поле ввода снова, как ни в чём и не бывало, оказывается пустым и исключительная ситуация не генерируется.
И ещё. Ведь OnSetText предназначен скорее для работы с текстом, чем для работы с числовыми переменными. И как-то бессмысленно работать со свойством Text вместо Value.
Или с этим обработчиком нужно работать по-другому?
Если код из OnChange просто перебросить в OnSetText, то данные после ввода исчезают.


 
Zacho ©   (2003-05-30 20:01) [23]


> Avreliy (30.05.03 19:34)

Честно признаюсь, потребность в OnGetText/OnSetText последний раз возникала у меня довольно давно, и было это на Дельфи 3 :-)
Но помню, что никаких проблем не возникало. Приведи свой код обработчика OnSetText.
Как вариант - попробуй TDataSet.BeforePost


 
Avreliy   (2003-05-30 20:52) [24]

if (ANSILowerCase(taEMDETAILRISETYPE.Value) = "ххххх") then begin
if quJob.Active then quJob.Close;
quJob.ParamByName("JOBTYPE").Value := taEMDETAILJOBTYPE.Value;
quJob.Open;
if (taEMPLOYEEGRADETYPE.IsNull) then
taEMDETAILSUMM.Value := taEMDETAILSUMM.Value * (quJobCOEFF.Value / 100)
else begin
if quGrade.Active then quGrade.Close;
quGrade.ParamByName("GRADETYPE").Value := taEMPLOYEEGRADETYPE.Value;
quGrade.Open;
taEMDETAILSUMM.Value := quGradeGRADESUM.Value * (quJobCOEFF.Value / 100)
end
end
else taEMDETAILSUMM.Value := taEMDETAILSUMM.Value
--------------------------------------------------
ta -таблицы, qu -запросы.
taEMDETAILSUMM.Value, quGradeGRADESUM.Value - TBCDField
quJobCOEFF.Value - TInteger


 
Zacho ©   (2003-05-30 21:21) [25]


> Avreliy (30.05.03 20:52)

Насколько я понял, это обработчик OnSetText именно поля taEMDETAILSUMM ?
Тогда можно попробовать следующее:
1. else taEMDETAILSUMM.Value := taEMDETAILSUMM.Value - убрать, все равно бессмысленно.
2. taEMDETAILSUMM.Value := taEMDETAILSUMM.Value * (quJobCOEFF.Value / 100) заменить на Sender.Value :=StrToFloat(Text) * (quJobCOEFF.Value / 100)

И, если не получится, как насчет обработки в BeforePost ?


 
Zacho ©   (2003-05-30 21:26) [26]


> Avreliy (30.05.03 20:52)

И, в догонку, это случаем не lookup поле?


 
Avreliy   (2003-05-30 21:41) [27]

1. Это не lookup поле.
2. taEMDETAILSUMM.Value := taEMDETAILSUMM.Value * (quJobCOEFF.Value / 100) заменить на
Sender.Value :=StrToFloat(Text) * (quJobCOEFF.Value / 100) -
не помогает.
3. В BeforePost ещё не успел.


 
Zacho ©   (2003-05-30 22:14) [28]


> Avreliy (30.05.03 21:41)
> 2. taEMDETAILSUMM.Value := taEMDETAILSUMM.Value * (quJobCOEFF.Value
> / 100) заменить на
> Sender.Value :=StrToFloat(Text) * (quJobCOEFF.Value / 100)
> не помогает.

Странно. То ли я уже хорошенько забыл, как работает OnSetText, то ли в D7 он работает как-то по другому. То ли дело вообще в чем-то другом.
Попробуй сделать нужные тебе действия в BeforePost.
Похоже, больше ничем не могу помочь. :(


 
Avreliy   (2003-05-30 22:15) [29]

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


 
Zacho ©   (2003-05-30 22:35) [30]


> Avreliy (30.05.03 22:15)

Тогда попробуй разобраться с OnSetText. Imho, это самый правильный способ.
В крайнем случае - Zacho © (30.05.03 18:27) , но это все же изврат.
P.S. А почему BDE ? Старый проект ? Если есть возможность перейти на FIBPlus или IBX - крайне рекомендую.


 
Avreliy   (2003-05-30 22:48) [31]

Дело в том, что это мой первый проект БД...
и весьма вероятно, что последний с использованием BDE...
Если помнишь, мы уже говорили на эту тему.
Но в любом случае, спасибо за содействие.


 
Zacho ©   (2003-05-30 23:05) [32]


> Avreliy (30.05.03 22:48)
> Если помнишь, мы уже говорили на эту тему.

Уже забыл, что именно с тобой :(
Удачи !



Страницы: 1 вся ветка

Текущий архив: 2003.06.26;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.169 c
7-84774
Anonimus
2003-04-17 11:15
2003.06.26
Перезагрузка......


4-84845
Xeon
2003-04-26 08:15
2003.06.26
Работа с реестром


3-83968
andrey__
2003-05-27 15:25
2003.06.26
Нужно определить фиксированную часть в <B>TDBGrid </B>


14-84606
Silentium!
2003-06-09 12:36
2003.06.26
Адресная книга


3-83987
Ann
2003-05-30 10:36
2003.06.26
DBNavigator