Все компоненты принимают все сообщения, но если компонент не имеет назначенного обработчика сообщений, он просто ничего не делает
Если вы хотите узнать, есть ли у компонента VCL специальный обработчик для определенного сообщения Windows, вам нужно изучить источники VCL, которые обычно предоставляются в C ++ Builder (кроме версий XE и XE2 для начинающих).
VCL-источники расположены в% CBuilderDir% \ Sources \ VCL (глядя на мой CBuilder5 / 6)
Источники написаны на Delphi, но не составит труда найти все, что нам нужно.
Во-первых, вам нужно найти определение вашего целевого класса. Вы можете искать по всему каталогу исходного кода VCL файл со строкой, похожей на
TMemo = Class
(для вашего примера с TMemo)
Откройте файл, в котором вы нашли свой класс (обычно это будет stdctrls.pas или controls.pas - там находятся самые полезные компоненты), перейдите к строке с определением класса и прокрутите немного вниз, пока не найдете группу процедуры, похожие на
procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
... и так далее. Эти процедуры вызываются в ответ на определенные сообщения, идентификаторы которых предоставляются после определения процедуры.
Если у класса есть процедура для определенного сообщения, то он дает на него некоторый ответ.
Обработчики сообщений наследуются в delphi, поэтому, если вы не нашли обработчик для вашего сообщения, вы можете посмотреть на базовые классы и их обработчики сообщений. Чтобы обнаружить полную иерархию классов, вы можете просто заглянуть в файл справки или снова посмотреть определение класса TMemo = class (TCustomMemo)
и взять имя родительского класса из фигурных скобок.
Затем вы можете повторить поиск обработчика сообщений для всех родительских классов, пока не достигнете TObject
: -)
Кстати. Простой поиск в директории источника VCL моего CBuilder5 любого присутствия EM_LINESCROLL
Я понял, что ни один компонент VCL не обрабатывает его.
Если вам нужно только обеспечить специальное взаимодействие для определенного сообщения, не пытаясь выяснить, есть ли у компонента уже есть обработчики сообщений или нет, вы можете просто переопределить метод WindowProc
вашего компонента. У всех потомков TControl
есть этот метод.
Этот метод обрабатывает все сообщения, полученные компонентом, и вы можете добавить ответ к дополнительным системным или пользовательским сообщениям здесь.
void __fastcall TMyForm::NewWndProc(Messages::TMessage &Message)
{
if (Message.Msg == EM_LINESCROLL)
// Do something special for this message
else OldWndProc(Message);
}
Единственное, что вам нужно сделать, это сохранить значение старого WindowProc, чтобы вызвать его в NewWndProc после того, как вы все сделаете.
Лучше определить и назначить NewWndProc
и сохранить старое WindowProc
для TMemo в форме, содержащей ваш компонент, так что вам не придется возиться с созданием нового унаследованного компонента из TMemo
. Итак, определите TWndMethod OldWndProc
в форме и поместите следующее, например, в форму OnCreate()
handler
TWndMethod OldWndProc = MyMemo->WindowProc;
MyMemo->WindowProc = NewWndProc;
Также вы можете предотвратить запуск предопределенных обработчиков, не передавая определенные сообщения в OldWndProc. Будьте осторожны, если вы запретите обработку разумных системных сообщений (например, WM_CREATE), вы получите ошибки.