Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не срабатывает TEdit.OnChange 
V
    Опции темы
chikistbuch
Дата 19.10.2013, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Всем привет. Изменение данных в ячейках DBGrid'а делаю через обычный TEdit, чтобы контролировать что вводит пользователь. ChangeCell Вызывается при двойном нажатии на ячейку DBGrid'а. События описанные в Edit.OnKeyPress, Edit.OnExit хорошо работают, а вот Edit.OnChange не обрабатывается. Т.е. всё что написано в EditChange попросту не выполняется. Чё за нах??
Код

procedure TForm1.ChangeCell(Sender: TObject); //прорисовывает EDIT для измнения значений в DBGrid
var
  Edit: TEdit;
begin
  Edit:=TEdit.Create(TDBGrid(Sender));
  Edit.Name:='DBEdit';
  Edit.Top:=DBSelectedCellRect.Top-2;
  Edit.Left:=DBSelectedCellRect.Left;
  Edit.Width:=DBSelectedCellRect.Right - DBSelectedCellRect.Left;
  Edit.Text:=TDBGrid(Sender).SelectedField.AsString;//Заполняем edit
  Edit.OnChange:=EditChange;
  Edit.OnKeyPress:=EditKeyPress;
  Edit.OnExit:=EditExit;
  Edit.Parent:=TDBGrid(Sender);
  Edit.SetFocus;
end;


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

procedure TForm1.EditChange(Sender: TObject);
var
  i: word;
  value, typ: string;
begin
  typ:=getAS(TDBGrid(TEdit(Sender).Parent).SelectedField.FieldName, 4);
  if typ='real' then begin

    value:=TEdit(Sender).Text;
    if value='' then TEdit(Sender).Color:=clWindow else begin
      for i:=1 to length(value) do begin
        if NOT (strtoint(value[i]) in [0..9]) OR NOT (value[i]=',') then begin
          TEdit(Sender).Color:=$00A3A7FA;
          exit;
        end;

      end;
    end;
  end;
end;

Код

procedure TForm1.EditKeyPress(Sender: TObject; var Key: Char); //edit для label'ов
var
  sql, NumberComponent: string;
begin
  if Key = #13 then begin //если нажат enter
    Key := #0;//чтобы не звенело
    if TEdit(Sender).Name='DBEdit' then begin //если это EDIT для изменения данных в ячейке таблице, то сохраняем изменения
      TDBGrid(TEdit(Sender).Parent).DataSource.DataSet.Edit;//переводим Dataset  в режим редактирования
      TDBGrid(TEdit(Sender).Parent).SelectedField.Value:=RoundEx(strtofloat(TEdit(Sender).Text), 3); //округляем и сохраняем
      TDBGrid(TEdit(Sender).Parent).DataSource.DataSet.Post;//сохраняет вставленную или отредактированную запись в БД
      TDBGrid(TEdit(Sender).Parent).SetFocus;
    end
    else begin // а если это edit для названия выходов (Label'ов)? nj
      if TEdit(Sender).Text<>'' then begin
        NumberComponent:=getNumberComponent(TEdit(Sender).Name);
        TLabel(getComponent('DBGridLabel'+NumberComponent, TEdit(Sender).Parent, 1)).Caption:=TEdit(Sender).Text; //присваиваем label значение edit
        sql:='UPDATE '+add_kav(G_PROJECT_NAME+'_exit', 1)+' SET exit_name='+add_kav(TEdit(Sender).Text, 2)+' WHERE id='+NumberComponent;
        form1.sql_execute(form1.UniQuery3, sql);
        TEdit(Sender).Parent.SetFocus;
        //PostMessage(Form1.Handle, WM_DeleteMyComponent, integer(Sender), 0);//удаляем компоент
       end;
    end;
  end;
  if Key = #27 then begin //если нажат escape
    Key := #0;//чтобы не звенело
    TDBGrid(TEdit(Sender).Parent).SetFocus;
  end;
end;

Код

procedure TForm1.EditExit(Sender: TObject);
begin
  PostMessage(Form1.Handle, WM_DeleteMyComponent, integer(Sender), 0);//удаляем компоент
end;

PM MAIL   Вверх
Poseidon
Дата 19.10.2013, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

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



Тут только отладчик скажет в чем же дело. Есть подозрения, что typ все-такие не равен 'real', но это только догадки. Возможно событие не назначено конкретному компоненту, как вариант. 

Создай тестовый проект с воспроизводящейся этой ошибкой и выложи весь проект сюда, посмотрим.


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
chikistbuch
Дата 20.10.2013, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Poseidon @  19.10.2013,  23:52 Найти цитируемый пост)
Есть подозрения, что typ все-такие не равен 'real'

До этого даже не доходит. Т.е. если я ставлю BREAK (BREAKPOINT), то при запуске проги на нём не происходит остановка выполнения кода:
user posted image
А события описанные:
Код

  Edit.OnKeyPress:=EditKeyPress;
  Edit.OnExit:=EditExit;

Выполняются. хз
PM MAIL   Вверх
БелАмор
Дата 20.10.2013, 09:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



OnChange не вызывается из-за назначения Parent'ом грида.
С причиной не разбирался.
Если назначить Parent'ом форму (Self), то OnChange нормально вызывается.
В данном случае не вижу препятствий сделать именно так,
нужно будет только пересчитать координаты.

PM   Вверх
chikistbuch
Дата 20.10.2013, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(БелАмор @ 20.10.2013,  09:15)
Если назначить Parent'ом форму (Self), то OnChange нормально вызывается.

Код

Edit:=TEdit.Create(self);

Нифига, всё равно не обрабатывается OnChange!
PM MAIL   Вверх
Akella
Дата 20.10.2013, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

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



Для начала почитай про owner и parent.  что это и с чем едят, различия и т.д.
PM MAIL   Вверх
chikistbuch
Дата 20.10.2013, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Akella @ 20.10.2013,  14:51)
Для начала почитай про owner и parent.  что это и с чем едят, различия и т.д.

Akella, спасибо! Почитал вот эту статью и вроде бы как понял, что "компонент-родитель должен уметь принимать и обрабатывать сообщения от системы Windows". Походу DBGrid не отлавливает OnChange вот и ничего не получалось.
Вот работающий код:
Код

procedure TForm1.ChangeCell(Sender: TObject); //прорисовывает EDIT для измнения значений в DBGrid
var
  Edit: TEdit;
begin
  Edit:=TEdit.Create(Form1);
  Edit.Name:='DBEdit';
  Edit.Top:=DBSelectedCellRect.Top+TDBGrid(Sender).Top;
  Edit.Left:=DBSelectedCellRect.Left++TDBGrid(Sender).Left+2;
  Edit.Width:=DBSelectedCellRect.Right - DBSelectedCellRect.Left;
  Edit.Text:=TDBGrid(Sender).SelectedField.AsString;//Заполняем edit
  Edit.OnChange:=EditChange;
  Edit.OnKeyPress:=EditKeyPress;
  Edit.OnExit:=EditExit;
  Edit.Parent:=TPanel(Sender).Parent;
  Edit.SetFocus;
end;


В принципе БелАмор говорил это же, только я его не понял )))

Это сообщение отредактировал(а) chikistbuch - 20.10.2013, 17:42
PM MAIL   Вверх
Akella
Дата 20.10.2013, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

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



Цитата(chikistbuch @  20.10.2013,  12:24 Найти цитируемый пост)
Edit:=TEdit.Create(self);

Это означает, что ты указал владельца, а не родителя, т.е. именно владелец (self - форма) будет уничтожать компоненту "Edit", когда сам будет помирать.
PM MAIL   Вверх
Poseidon
Дата 20.10.2013, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

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



Цитата(chikistbuch @  20.10.2013,  17:40 Найти цитируемый пост)
Edit.Parent:=TPanel(Sender).Parent;
Очень интересный подход, особенно если учесть, что Sender - это TDBGrid. Почему бы просто не указать там Form1 или Self, тем более что вся эта индийская конструкция все-равно вернет именно это?



--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
БелАмор
Дата 21.10.2013, 00:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(Poseidon @  20.10.2013,  20:23 Найти цитируемый пост)
Цитата(chikistbuch @  20.10.2013,  17:40 )
Edit.Parent:=TPanel(Sender).Parent;

Очень интересный подход, особенно если учесть, что Sender - это TDBGrid. Почему бы просто не указать там Form1 или Self, тем более что вся эта индийская конструкция все-равно вернет именно это?

Насколько я понял, у автора грид лежит на панели и он хотел указать родителем именно панель.
Процитированный вариант работать будет, однако в нём заложена логическая ошибка, хотя и не приводящая к фактической.
Думаю, стоит этот момент разобрать хотя бы кратко.

1. Как уже сказали, Sender здесь ссылается на грид (объект типа TDBGrid).
2. Ошибки компиляции в этом месте не возникает потому, что приведение типа производится жёсткое, без проверки реального типа объекта, а компилятору в случае жёсткого приведения по-барабану что к чему приводить и каковы будут последствия.
3. Во время выполнения программы ошибки в этом месте не возникает потому, что и TPanel, и TDBGrid наследуют свойство Parent от их дальнего общего предка TControl. Обращение к необщему свойству привело бы к ошибке. Приведение с проверкой Edit.Parent:=(Sender as TPanel).Parent также привело бы к ошибке. Правильным вариантом было бы приведение либо к TDBGrid, либо к любому его предку вплоть до TControl.
4. Если Sender в процедуре используется многократно, то логично завести локальную переменную нужного типа (здесь - TDBGrid или предка), один раз присвоить ей значение (причём лучше с проверкой типа, через as) и вместо TDBGrid(Sender).Parent спокойно писать g.Parent
5. Edit:=TEdit.Create(Form1); - это опять-же, грубейшая логическая ошибка, в частном случае не приводящая к фактической.
  TForm1 - класс. Экземпляров класса (объектов) в общем случае может быть много. Form1 - это переменная-указатель (4 или 8 байт), которая может указывать только на один экземпляр формы. А может и не указывать вообще никуда. А все формы класса TForm1 должы работать, сколько бы их ни было создано. И работать со своими данными. Короче, правильным вариантом записи было бы Edit:=TEdit.Create(Self); Разберитесь что такое Self.
6. Посмотрите статью: Жизнь и смерть в режиме run-time

Ваша процедура с указанными исправлениями могла бы выгледеть примено так:

Код

procedure TForm1.ChangeCell(Sender: TObject);
var
  Edit: TEdit;
  g: TDBGrid;  // Добавлено
begin
  g := Sender as TDBGrid;  // Добавлено
  Edit:=TEdit.Create(Self);  // Form1 ---> Self
  Edit.Name:='DBEdit';
  Edit.Top:=DBSelectedCellRect.Top+g.Top;
  Edit.Left:=DBSelectedCellRect.Left+g.Left+2;
  Edit.Width:=DBSelectedCellRect.Right - DBSelectedCellRect.Left;
  Edit.Text:=g.SelectedField.AsString;
  Edit.OnChange:=EditChange;
  Edit.OnKeyPress:=EditKeyPress;
  Edit.OnExit:=EditExit;
  Edit.Parent:=g.Parent;  // TPanel(Sender) ---> g
  Edit.SetFocus;
end;


PM   Вверх
Zadnica
Дата 21.10.2013, 09:03 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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




Модератор: Сообщение скрыто.

PM MAIL   Вверх
chikistbuch
Дата 21.10.2013, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



БелАмор, вот это разжевал! И не поленился столько писать!! Зачёт и спасибо  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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