Здравствуйте, _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();
};
};
Здравствуйте, 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;
При наборе текста в этом эдите в Events log чудненько появляются строчки "Changed!". То есть все работает, как и должно быть. Видимо, проблема где-то в вашем коде.
Здравствуйте, Flamer, Вы писали:
F>При наборе текста в этом эдите в Events log чудненько появляются строчки "Changed!". То есть все работает, как и должно быть. Видимо, проблема где-то в вашем коде.
Если Parent форма, то у меня тоже работает (Change() и вызывает обработчик OnChange), а вот если грид, то начинается катавасия: CN_COMMAND не приходит, а именно оно вызывает Change(), когда в edit'е что-то меняется. Я просто думал, что там какие-то тонкости есть, которые я не учел.
Здравствуйте, _pk_, Вы писали:
F>>При наборе текста в этом эдите в Events log чудненько появляются строчки "Changed!". То есть все работает, как и должно быть. Видимо, проблема где-то в вашем коде.
__>Если Parent форма, то у меня тоже работает (Change() и вызывает обработчик OnChange), а вот если грид, то начинается катавасия: CN_COMMAND не приходит, а именно оно вызывает Change(), когда в edit'е что-то меняется. Я просто думал, что там какие-то тонкости есть, которые я не учел.
Ага. Ну тогда у меня такое предложение: ведь никто нам не мешает посубклассить оконную процедуру нашего эдита. И уж там-то точно можно узнать, что и как происходит. В смысле, анализировать нужные нам сообщения и делать свое черное дело.
Здравствуйте, _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 и начинают писать собственные подобные компоненты...
Здравствуйте, Sergei I. Gorelkin, Вы писали:
SIG>Проблема в процедуре TCustomGrid.WMCommand(). Разработчики посчитали, что на гриде не может быть других контролов, кроме ее собственного InplaceEdit, и не стали вызывать inherited метод, т.е. TWinControl.WMCommand(). А именно там ищется контрол, handle которого передан в WM_COMMAND, и вызывается его Perform(CN_COMMAND, ...) SIG>Таким образом, если у контрола (Parent is TCustomGrid) = true, то CN_COMMAND ему никогда не придет. И это одна из причин, по которым многие очень громко ругаются на гриды из VCL и начинают писать собственные подобные компоненты...
Здравствуйте, _pk_, Вы писали:
__>Покопавшись в коде, обнаружил, что не приходит CN_COMMAND. __>Как только делаю Parent'а формой, CN_COMMAND начинает нормально работать.
Насколько я помню, я когда-то подобную проблему (не такую, но похожую) решил, размещая edit не на гриде, а на панели, размещенной на гриде. Попробуйте, вдруг поможет.
Здравствуйте, 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;