所有组件都接受所有消息,但如果一个组件没有指定的消息处理程序,它什么也不做
如果你想发现 VCL 组件是否对某些 Windows 消息有特殊的处理程序,你必须查看 VCL 源代码,这些源代码通常由 C++Builder 提供(XE 和 XE2 的 Starter Edition 除外)。
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 :-)
顺便说一句。在我的 CBuilder5 的 VCL 源目录中简单搜索 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 中调用它。
最好为 TMemo 定义和分配 NewWndProc 并将旧的 WindowProc 存储在包含您的组件的表单中,这样您就不需要从 TMemo 制作新的继承组件。因此,在表单中定义TWndMethod OldWndProc 并在表单中添加以下内容,例如OnCreate() 处理程序
TWndMethod OldWndProc = MyMemo->WindowProc;
MyMemo->WindowProc = NewWndProc;
您还可以通过不将某些消息传递给 OldWndProc 来防止触发预定义的处理程序。请注意,如果您阻止处理敏感的系统消息(如 WM_CREATE),您将收到错误。