private:
DYNAMIC void __fastcall MouseUp (TMouseButton Button, Classes::TShiftState Shift, int X, int Y);
__published:
__property OnMouseUp;
....
void __fastcall Tclassname::MouseUp (TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
if ( OnMouseUp != NULL ) OnMouseUp ( this, Button, Shift, X, Y );
}
Обработка сообщений в своей компоненте
Не понимаю как описывать реакцию компоненты на сообщения Windows.
В интернете куча примеров на Delphi. Пробовал переписывать на С.
Не получается.
Нашёл, что надо переопределять уже объявленные методы.
Например, для события OnMouseUp, пишут что надо делать так:
Код:
Пример с мышью - работает, а вот с "фокусом" - OnEnter / OnExit - НЕТ!
Пытаюсь в переопределённом методе Paint() отслеживать состояние "фокус" и по разному рисовать на Canvas но никакой реакции.
Мой компонент наследован от TCustomControl.
Просьба:
1) объяснить
2) указать на грамотное и полное изложения материала, примеры на С
Спасибо.
Цитата: nikipelovav
Не понимаю как описывать реакцию компоненты на сообщения Windows.
...
Нашёл, что надо переопределять уже объявленные методы.
Например, для события OnMouseUp, пишут что надо делать так:
Код:
private:
DYNAMIC void __fastcall MouseUp (TMouseButton Button, Classes::TShiftState Shift, int X, int Y);
__published:
__property OnMouseUp;
....
void __fastcall Tclassname::MouseUp (TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
if ( OnMouseUp != NULL ) OnMouseUp ( this, Button, Shift, X, Y );
}
DYNAMIC void __fastcall MouseUp (TMouseButton Button, Classes::TShiftState Shift, int X, int Y);
__published:
__property OnMouseUp;
....
void __fastcall Tclassname::MouseUp (TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
if ( OnMouseUp != NULL ) OnMouseUp ( this, Button, Shift, X, Y );
}
Если событие уже "прикручено" в родителе, то это правильное решение. Только я бы сделал так:
Код:
void __fastcall Tclassname::MouseUp (TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
/*if ( OnMouseUp != NULL ) OnMouseUp ( this, Button, Shift, X, Y );*/
TControl::MouseUp (Button, Shift, X, Y);
}
{
/*if ( OnMouseUp != NULL ) OnMouseUp ( this, Button, Shift, X, Y );*/
TControl::MouseUp (Button, Shift, X, Y);
}
Цитата: nikipelovav
Пример с мышью - работает, а вот с "фокусом" - OnEnter / OnExit - НЕТ!
что не выходит? код?
Цитата: GIZMO
Если событие уже "прикручено" в родителе, то это правильное решение. Только я бы сделал так:
что не выходит? код?
Код:
void __fastcall Tclassname::MouseUp (TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
/*if ( OnMouseUp != NULL ) OnMouseUp ( this, Button, Shift, X, Y );*/
TControl::MouseUp (Button, Shift, X, Y);
}
{
/*if ( OnMouseUp != NULL ) OnMouseUp ( this, Button, Shift, X, Y );*/
TControl::MouseUp (Button, Shift, X, Y);
}
что не выходит? код?
Вариант 1
Код:
DYNAMIC void __fastcall DoEnter (void);
DYNAMIC void __fastcall DoExit (void);
void __fastcall Tmyclass::DoEnter (void)
{
if ( OnEnter != NULL ) OnEnter ( this );
или здесь что-то другое нужно?
}
void __fastcall Tmyclass::DoExit (void)
{
if ( OnExit != NULL ) OnExit ( this );
или здесь что-то другое нужно?
}
DYNAMIC void __fastcall DoExit (void);
void __fastcall Tmyclass::DoEnter (void)
{
if ( OnEnter != NULL ) OnEnter ( this );
или здесь что-то другое нужно?
}
void __fastcall Tmyclass::DoExit (void)
{
if ( OnExit != NULL ) OnExit ( this );
или здесь что-то другое нужно?
}
Вариант 2
Код:
private:
bool FFocused;
HIDESBASE MESSAGE void __fastcall WMSetFocus (Messages::TWMSetFocus &Message); //
HIDESBASE MESSAGE void __fastcall WMKillFocus (Messages::TWMKillFocus &Message); //
public:
virtual void __fastcall Paint(void);
void __fastcall Tmyclass::WMSetFocus(Messages::TWMSetFocus &Message)
{
FFocused = true;
Repaint();
}
void __fastcall Tmyclass::WMKillFocus(Messages::TWMKillFocus &Message)
{
FFocused = false;
Repaint();
}
в методе рисования пытаюсь учесть "фокус"
void __fastcall Tmyclass::Paint()
{
TRect R = ClientRect;
pCanvas->Brush->Color = clLime;
pCanvas->FillRect(R);
pCanvas->TextOut( 10, 10, "exit" );
if (FFocused)
{
pCanvas->Brush->Color = clRed;
pCanvas->FillRect(R);
pCanvas->TextOut( 10, 20, "enter" );
pCanvas->DrawFocusRect(R);
}
}
bool FFocused;
HIDESBASE MESSAGE void __fastcall WMSetFocus (Messages::TWMSetFocus &Message); //
HIDESBASE MESSAGE void __fastcall WMKillFocus (Messages::TWMKillFocus &Message); //
public:
virtual void __fastcall Paint(void);
void __fastcall Tmyclass::WMSetFocus(Messages::TWMSetFocus &Message)
{
FFocused = true;
Repaint();
}
void __fastcall Tmyclass::WMKillFocus(Messages::TWMKillFocus &Message)
{
FFocused = false;
Repaint();
}
в методе рисования пытаюсь учесть "фокус"
void __fastcall Tmyclass::Paint()
{
TRect R = ClientRect;
pCanvas->Brush->Color = clLime;
pCanvas->FillRect(R);
pCanvas->TextOut( 10, 10, "exit" );
if (FFocused)
{
pCanvas->Brush->Color = clRed;
pCanvas->FillRect(R);
pCanvas->TextOut( 10, 20, "enter" );
pCanvas->DrawFocusRect(R);
}
}
Что ни пробовал - всегда рисует компоненту в одном состоянии!
в объекте указываем, что хотим получать сообщения "пришел/ушел фокус" и цепляем пару новых обработчиков.
Код:
[hpp-file] // указаны только добавляемые поля
class TMyCustomControl : public TCustomControl
{
protected:
TNotifyEvent FOnGetFocus;
TNotifyEvent FOnLostFocus;
MESSAGE void __fastcall WMSetFocus (TWMSetFocus &Message);
MESSAGE void __fastcall WMKillFocus (TWMKillFocus &Message);
// как вариант покороче - без cpp части
// MESSAGE void __fastcall WMSetFocus (TWMSetFocus &Message) { if (FOnGetFocus) FOnGetFocus(this); };
// MESSAGE void __fastcall WMKillFocus (TWMKillFocus &Message) { if (FOnLostFocus) FOnLostFocus(this); };
public:
__published:
__property TNotifyEvent OnGetFocus = {read=FOnGetFocus, write=FOnGetFocus};
__property TNotifyEvent OnLostFocus = {read=FOnLostFocus, write=FOnLostFocus};
// собственно, "заказ сообщений"
#pragma warn -inl
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_SETFOCUS, TWMSetFocus, WMSetFocus);
VCL_MESSAGE_HANDLER(WM_KILLFOCUS, TWMKillFocus, WMKillFocus);
END_MESSAGE_MAP (TCustomControl);
#pragma warn .inl
};
[cpp-file]
MESSAGE void __fastcall TMyCustomControl::WMSetFocus (TWMSetFocus &Message)
{
if (FOnGetFocus) FOnGetFocus(this);
}
//---------------------------------------------------------------------------
MESSAGE void __fastcall TMyCustomControl::WMKillFocus (TWMKillFocus &Message)
{
if (FOnLostFocus) FOnLostFocus(this);
}
//---------------------------------------------------------------------------
class TMyCustomControl : public TCustomControl
{
protected:
TNotifyEvent FOnGetFocus;
TNotifyEvent FOnLostFocus;
MESSAGE void __fastcall WMSetFocus (TWMSetFocus &Message);
MESSAGE void __fastcall WMKillFocus (TWMKillFocus &Message);
// как вариант покороче - без cpp части
// MESSAGE void __fastcall WMSetFocus (TWMSetFocus &Message) { if (FOnGetFocus) FOnGetFocus(this); };
// MESSAGE void __fastcall WMKillFocus (TWMKillFocus &Message) { if (FOnLostFocus) FOnLostFocus(this); };
public:
__published:
__property TNotifyEvent OnGetFocus = {read=FOnGetFocus, write=FOnGetFocus};
__property TNotifyEvent OnLostFocus = {read=FOnLostFocus, write=FOnLostFocus};
// собственно, "заказ сообщений"
#pragma warn -inl
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_SETFOCUS, TWMSetFocus, WMSetFocus);
VCL_MESSAGE_HANDLER(WM_KILLFOCUS, TWMKillFocus, WMKillFocus);
END_MESSAGE_MAP (TCustomControl);
#pragma warn .inl
};
[cpp-file]
MESSAGE void __fastcall TMyCustomControl::WMSetFocus (TWMSetFocus &Message)
{
if (FOnGetFocus) FOnGetFocus(this);
}
//---------------------------------------------------------------------------
MESSAGE void __fastcall TMyCustomControl::WMKillFocus (TWMKillFocus &Message)
{
if (FOnLostFocus) FOnLostFocus(this);
}
//---------------------------------------------------------------------------
Цитата: Zor
как правильно:
в объекте указываем, что хотим получать сообщения "пришел/ушел фокус" и цепляем пару новых обработчиков.
в объекте указываем, что хотим получать сообщения "пришел/ушел фокус" и цепляем пару новых обработчиков.
Код:
[hpp-file] // указаны только добавляемые поля
class TMyCustomControl : public TCustomControl
{
protected:
TNotifyEvent FOnGetFocus;
TNotifyEvent FOnLostFocus;
MESSAGE void __fastcall WMSetFocus (TWMSetFocus &Message);
MESSAGE void __fastcall WMKillFocus (TWMKillFocus &Message);
// как вариант покороче - без cpp части
...
class TMyCustomControl : public TCustomControl
{
protected:
TNotifyEvent FOnGetFocus;
TNotifyEvent FOnLostFocus;
MESSAGE void __fastcall WMSetFocus (TWMSetFocus &Message);
MESSAGE void __fastcall WMKillFocus (TWMKillFocus &Message);
// как вариант покороче - без cpp части
...
Спасибо, попробую. А как в этом варианте учитываются стандартные, для работы с "фокусом", методы DoEnter, DoExit и события OnEnter, OnExit ?
Никак. Вместо них два новых. Можете назвать их DoEnter/DoExit - кто помешает?
Цитата: nikipelovav
Пытаюсь в переопределённом методе Paint() отслеживать состояние "фокус" и по разному рисовать на Canvas но никакой реакции.
Если дело только в этом, то может проще сделать - TCustomControl::Paint() + TWinControl::Focused() ?
Необходимо для визуального компонента (TTreeView) назначить горячие клавиши (Ctrl+Ins, Ins, Ctrl+V, Ctrl+C и т.д.)
Для этого тоже надо создавать обработчик WM_* сообщений или можно проще?
а разве OnKey events в Treeview уже отменили