Re[8]: OnChange
От: Sergei I. Gorelkin Россия  
Дата: 04.12.04 07:49
Оценка: 50 (6)
Здравствуйте, _pk_, Вы писали:

__>>Если Parent форма, то у меня тоже работает (Change() и вызывает обработчик OnChange), а вот если грид, то начинается катавасия: CN_COMMAND не приходит, а именно оно вызывает Change(), когда в edit'е что-то меняется. Я просто думал, что там какие-то тонкости есть, которые я не учел.


Проблема в процедуре TCustomGrid.WMCommand(). Разработчики посчитали, что на гриде не может быть других контролов, кроме ее собственного InplaceEdit, и не стали вызывать inherited метод, т.е. TWinControl.WMCommand(). А именно там ищется контрол, handle которого передан в WM_COMMAND, и вызывается его Perform(CN_COMMAND, ...)
Таким образом, если у контрола (Parent is TCustomGrid) = true, то CN_COMMAND ему никогда не придет. И это одна из причин, по которым многие очень громко ругаются на гриды из VCL и начинают писать собственные подобные компоненты...
OnChange
От: _pk_ Россия  
Дата: 03.12.04 18:55
Оценка:
Есть класс-наследник TCustomEdit.
В нем пишу в private procedure InternalChange(Sender: TObject);
и в конструкторе делаю OnChange := InternalChange;

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

Parent и Owner у этого edit'а — TDBGrid.

Покопавшись в коде, обнаружил, что не приходит CN_COMMAND.
Как только делаю Parent'а формой, CN_COMMAND начинает нормально работать.

В чем может быть проблема?
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re: OnChange
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 03.12.04 19:01
Оценка:
Здравствуйте, _pk_, Вы писали:

__>Есть класс-наследник TCustomEdit.

__>В нем пишу в private procedure InternalChange(Sender: TObject);
__>и в конструкторе делаю OnChange := InternalChange;

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


А переопределить метод Change не судьба?

TCustomEdit::Change

Generates an OnChange event.

DYNAMIC void __fastcall Change(void);

Description

Applications do not call the Change method directly. It is triggered automatically by Windows events. Change is exposed as a protected method so that derived classes can make additional responses when the text changes beyond invoking the OnChange event handler. If Derived classes that override the Change method do not call the TCustomEdit method, the OnChange event handler will not be called.


Т.е.:
class TMyEdit : public TCustomEdit
{
 typedef TCustomEdit inherited;

private:
    DYNAMIC void __fastcall Change(void)
    {
     // делаем, что надо
     inherited::Change();
    };
};


Непопулярен хелп у народа, ох непопулярен...
... << RSDN@Home 1.1.3 stable >>
Re[2]: OnChange
От: _pk_ Россия  
Дата: 03.12.04 19:28
Оценка:
Здравствуйте, Flamer, Вы писали:

F>А переопределить метод Change не судьба?


F>Непопулярен хелп у народа, ох непопулярен...


Туда тоже управление не попадает, CN_COMMAND не приходит же!
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[3]: OnChange
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 03.12.04 20:07
Оценка:
Здравствуйте, _pk_, Вы писали:


F>>А переопределить метод Change не судьба?

__>Туда тоже управление не попадает, CN_COMMAND не приходит же!

Что-то с трудом верится... Давайте-ка посмотрим полный код компонента и как компонент используется, а уже потом будем думать
... << RSDN@Home 1.1.3 stable >>
Re[4]: OnChange
От: _pk_ Россия  
Дата: 03.12.04 20:18
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Что-то с трудом верится... Давайте-ка посмотрим полный код компонента и как компонент используется, а уже потом будем думать


TSearchEdit = class(TCustomEdit)
private
  FGrid: TCustomDBGridEx;
  FColumn: TColumnEx;
  procedure SetColumn(const Value: TColumnEx);
  procedure WMKillFocus(var Message: TMessage); message WM_KILLFOCUS;
  procedure InternalChange(Sender: TObject);
protected
  procedure CreateParams(var AParams: TCreateParams); override;
  procedure Locate;
  procedure KeyPress(var Key: Char); override;
public
  constructor Create(AOwner: TCustomDBGridEx); reintroduce; virtual;
  property Column: TColumnEx read FColumn write SetColumn;
end;
    
{ TSearchEdit }

constructor TSearchEdit.Create(AOwner: TCustomDBGridEx);
begin
  inherited Create(AOwner);
  OnChange := InternalChange;
  FGrid := AOwner;
  FreeNotification(FGrid);
  Parent := FGrid;
  BorderStyle := bsNone;
end;

procedure TSearchEdit.CreateParams(var AParams: TCreateParams);
begin
  inherited;
  AParams.Style := AParams.Style or WS_BORDER;
end;

procedure TSearchEdit.InternalChange(Sender: TObject);
begin
  Locate;
end;

procedure TSearchEdit.KeyPress(var Key: Char);
begin
  inherited;
  if Key = Chr(VK_ESCAPE) then
  begin
    Key := #0;
    PostMessage(FGrid.Handle, WMU_KILLME, 0, 0);
  end;
end;

procedure TSearchEdit.Locate;
begin
  with FGrid.DataLink.DataSet do
    if Active then
      try
        Locate(Column.FieldName, Text, [loCaseInsensitive, loPartialKey]);
      except
      end;
end;

procedure TSearchEdit.SetColumn(const Value: TColumnEx);
var R: TRect;
begin
  if FColumn = Value then
    Exit;
  FColumn := Value;
  R := FGrid.CellRect(FColumn.Index + 1, 0);
  Left := R.Left - 1;
  Top := R.Top - 1;
  Height := R.Bottom - R.Top + 2;
  Width := R.Right - R.Left + 2;
  Text := FColumn.Field.AsString;
  SetFocus;
end;

procedure TSearchEdit.WMKillFocus(var Message: TMessage);
begin
  inherited;
  PostMessage(FGrid.Handle, WMU_KILLME, 0, 0);
end;
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[5]: OnChange
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 03.12.04 20:37
Оценка:
Здравствуйте, _pk_, Вы писали:

[]

Сорри, в дельфях не силен, но вот минимальный код на Билдере, который работает:

class TMyEdit : public TCustomEdit
{
 typedef TCustomEdit inherited;
private:
    DYNAMIC void __fastcall Change()
    {
      OutputDebugString("Changed!");
      inherited::Change();
    };
 public:
  __fastcall TMyEdit(TComponent* AOwner) : TCustomEdit(AOwner) { }
  __fastcall ~TMyEdit() {}
};

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  TMyEdit* ed = new TMyEdit(this);
  ed->Parent = this;
  ed->Left = 20;
  ed->Top = 200;
  
}
//---------------------------------------------------------------------------


При наборе текста в этом эдите в Events log чудненько появляются строчки "Changed!". То есть все работает, как и должно быть. Видимо, проблема где-то в вашем коде.
... << RSDN@Home 1.1.3 stable >>
Re[6]: OnChange
От: _pk_ Россия  
Дата: 03.12.04 21:02
Оценка:
Здравствуйте, Flamer, Вы писали:

F>При наборе текста в этом эдите в Events log чудненько появляются строчки "Changed!". То есть все работает, как и должно быть. Видимо, проблема где-то в вашем коде.


Если Parent форма, то у меня тоже работает (Change() и вызывает обработчик OnChange), а вот если грид, то начинается катавасия: CN_COMMAND не приходит, а именно оно вызывает Change(), когда в edit'е что-то меняется. Я просто думал, что там какие-то тонкости есть, которые я не учел.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[7]: OnChange
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 03.12.04 22:31
Оценка:
Здравствуйте, _pk_, Вы писали:

F>>При наборе текста в этом эдите в Events log чудненько появляются строчки "Changed!". То есть все работает, как и должно быть. Видимо, проблема где-то в вашем коде.


__>Если Parent форма, то у меня тоже работает (Change() и вызывает обработчик OnChange), а вот если грид, то начинается катавасия: CN_COMMAND не приходит, а именно оно вызывает Change(), когда в edit'е что-то меняется. Я просто думал, что там какие-то тонкости есть, которые я не учел.


Ага. Ну тогда у меня такое предложение: ведь никто нам не мешает посубклассить оконную процедуру нашего эдита. И уж там-то точно можно узнать, что и как происходит. В смысле, анализировать нужные нам сообщения и делать свое черное дело.
... << RSDN@Home 1.1.3 stable >>
Re[9]: OnChange
От: _pk_ Россия  
Дата: 04.12.04 07:53
Оценка:
Здравствуйте, Sergei I. Gorelkin, Вы писали:

SIG>Проблема в процедуре TCustomGrid.WMCommand(). Разработчики посчитали, что на гриде не может быть других контролов, кроме ее собственного InplaceEdit, и не стали вызывать inherited метод, т.е. TWinControl.WMCommand(). А именно там ищется контрол, handle которого передан в WM_COMMAND, и вызывается его Perform(CN_COMMAND, ...)

SIG>Таким образом, если у контрола (Parent is TCustomGrid) = true, то CN_COMMAND ему никогда не придет. И это одна из причин, по которым многие очень громко ругаются на гриды из VCL и начинают писать собственные подобные компоненты...

Присоединяюсь к ругающимся... спасибо!
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re: OnChange
От: Softwarer http://softwarer.ru
Дата: 06.12.04 10:39
Оценка:
Здравствуйте, _pk_, Вы писали:

__>Покопавшись в коде, обнаружил, что не приходит CN_COMMAND.

__>Как только делаю Parent'а формой, CN_COMMAND начинает нормально работать.

Насколько я помню, я когда-то подобную проблему (не такую, но похожую) решил, размещая edit не на гриде, а на панели, размещенной на гриде. Попробуйте, вдруг поможет.
Re[2]: OnChange
От: Olafpalmer Россия  
Дата: 06.12.04 14:26
Оценка:
Здравствуйте, Softwarer, Вы писали:

S>Здравствуйте, _pk_, Вы писали:


__>>Покопавшись в коде, обнаружил, что не приходит CN_COMMAND.

__>>Как только делаю Parent'а формой, CN_COMMAND начинает нормально работать.

S>Насколько я помню, я когда-то подобную проблему (не такую, но похожую) решил, размещая edit не на гриде, а на панели, размещенной на гриде. Попробуйте, вдруг поможет.


Тоже сталкивался с этой проблемой. Помогла легкая правка грида в своем наследнике:

type
...
procedure WMCommand(var msg: TWMCommand); message WM_COMMAND;
...
procedure TMyGrid.WMCommand(var msg: TWMCommand);
begin
  If EditorMode
  then if Assigned(InplaceEditor) and ( msg.Ctl = InplaceEditor.Handle ) Then
    inherited
  Else
    If msg.Ctl <> 0 Then
      msg.result :=
        SendMessage( msg.ctl, CN_COMMAND,
                     TMessage(msg).wparam,
                     TMessage(msg).lparam );
end;
Re[3]: OnChange
От: _pk_ Россия  
Дата: 06.12.04 18:38
Оценка:
Здравствуйте, Olafpalmer, Вы писали:

O>Тоже сталкивался с этой проблемой. Помогла легкая правка грида в своем наследнике:


Примерно также я ее и решил
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.