Александр Лейн дата публикации 26-12-2005 06:59 | КАТЕГОРИЯ | | БИБЛИОТЕКА.VCL.TInplaceEdit.Ошибка процедуры Hide | | ПРОДУКТ | | Delphi | | ПЛАТФОРМА | | Windows |
Неправильно обновляется редактор ячейки гридов (компонентов-наследников TCustomGrid). Эффект наблюдался в среде Delphi5, Delphi7, для компонентов: TDBGrid, TStringGrid, а также для TDBGridEh из библиотеки EhLib версии 2.5.
Эффект можно наблюдать при следующих обстоятельствах:
- Открывается форма с DBGrid со стандартными настройками.
- В DBGrid активизируется редактор ячейки (EditorMode = True, мигает курсор редактирования).
- Форма закрывается так, чтобы редактор ячейки не терял фокус, например нажатием на "крест" в верхнем правом углу формы, или по ALT+F4.
- DataSet, связанный с DBGrid обновляется (закрывается, модифицируются параметры, например SQL, открывается снова).
- Форма открывается второй раз.
- Редактор ячейки отображает старые данные.
Пример:
procedure TForm1.Button2Click(Sender: TObject);
var
ds : TClientDataSet;
f : TForm;
g : TDBGrid;
s : TDataSource;
begin
ds := TClientDataSet.Create(self);
with ds.FieldDefs.AddFieldDef do
begin
Name := 'Q';
DataType := ftString;
Size := 30;
end;
ds.CreateDataSet;
s := TDataSource.Create(self);
s.DataSet := ds;
f := TForm.Create(self);
g := TDBGrid.Create(self);
g.Parent := f;
g.Visible := true;
g.DataSource := s;
f.Caption := 'Введите строку и закройте окно';
f.ShowModal;
{Вводим какую нибудь строку в ячейку таблицы, не нажимая Enter,
и закрываем окно}
ds.Close;
ds.CreateDataSet;
f.Caption := 'Это пустая таблица!';
f.ShowModal;
{Видим в таблице старую строку, хотя на самом деле таблица пуста}
end;
Причина ошибка — процедура TInplaceEdit.Hide из модуля Grids:
procedure TInplaceEdit.Hide;
begin
if HandleAllocated and IsWindowVisible(Handle) then
begin
Invalidate;
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_HIDEWINDOW or SWP_NOZORDER or
SWP_NOREDRAW);
if Focused then Windows.SetFocus(Grid.Handle);
end;
end;
Функция IsWindowVisible возвращает значение False, если не видимо окно, в котором находится InplaceEdit, поэтому функция SetWindowPos не отрабатывается и InplaceEdit не скрывается.
- Вначале отображать форму с гридом, и только потом формировать для него данные. Недостатки: это невозможно осуществить, если форма отображается модально.
- Формировать данные по событию OnActivate формы.
Недостатки: иногда данные удобно формировать в другом модуле.
- Создавать форму динамически, а после закрытия освобождать.
Недостатки: время создания формы может быть большим и ее лучше создавать один раз за время работы программы.
- Установить опцию dgAlwaysShowEditor:
DBGrid1.Options := DBGrid1.Options+[dgAlwaysShowEditor];
- На одно из событий формы OnActivate, OnCloseQuery, OnClose, OnHide прописать код:
DBGrid1.EditorMode := False;
- Изменить исходный текст модуля Grids.pas, закомментировав вызов IsWindowVisible:
procedure TInplaceEdit.Hide;
begin
if HandleAllocated {and IsWindowVisible(Handle)} then
begin
Invalidate;
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_HIDEWINDOW or SWP_NOZORDER or
SWP_NOREDRAW);
if Focused then Windows.SetFocus(Grid.Handle);
end;
end;
Полной уверенности правильности данной модификации Grids.pas у меня нет, но ошибок в среде Delphi5 после модификации у меня не было. Недостатки: необходимость модификации исходного модуля для каждой версии Delphi.
[TCustomGrid] [TStringGrid] [TDBGrid] [TInplaceEdit] [Интерфейс. Компоненты и формы] [Редактирование записи в таблице] [Режимы Visible и Enabled]
Обсуждение материала [ 11-04-2009 22:29 ] 3 сообщения |