子类化VCL的后代TWinControl
Subclassing descendant of VCL TWinControl
使用伪函数创建子类:
CreateSpecialHandle(TWinControl *Control, const TCreateParams &Params, const AnsiString SubClass)
{
......;
set Control DefWndProc to SubClass.lpfnWndProc
set Control WindowHandle from CreateWindowEx
......;
subclass(TWinControl *Control);
}
subclass(TWinControl *Control)
{
......;
oldWProc = (void*)GetWindowLong(Control->Handle, GWL_WNDPROC);
oldDefWProc = (void*)(Control->DefWndProc);
oldWindowProc = Control->WindowProc;
MakeObjectInstance(newWProc) for SetWindowLong
MakeObjectInstance(newDefWProc) for Control->DefWndProc
Control->WindowProc = newWindowProc;
......;
}
现在,我们有了子类控件的意外行为。WM_NCHITTEST
结果0,等等…
例如,当newWProc
拦截WM_NCHITTEST
时,将Result
设置为HTCLIENT
我们有鼠标响应,但是,如果没有将msg.result
设置为1的msg.msg WM_NCHITTEST
我的错误和错误的子类化后果,我们还需要手动处理什么?
-
newWProc
回调oldWProc
-
newDefWProc
回调oldDefWProc
-
newWindowProc
呼叫oldWindowProc
我们是否必须子类化父控件的子类化控件?
此外,发送WM_GETTEXT
结果与空缓冲区。
显然,我们做错了什么。我们需要解释,
提前感谢大家
更新:
in TDCEdit:public TCustomEdit overriding CreateWindowHandle
void __fastcal CreateWindowHandle(const TCreateParams &Params)
{
CreateSpecialHandle(this,Params,TEXT("EDIT"));
}
void CreateSpecialHandle(TWinControl *Control,const TCreateParams &Params, AnsiString SubClass)
{
...
Control->WindowHandle = CreateWindowEx(...,"EDIT",....);
....
subclass(Control);
}
subclass(TWinControl* Control)
{
......;
oldWProc = (void*)GetWindowLong(Control->Handle, GWL_WNDPROC);
oldDefWProc = (void*)(Control->DefWndProc);
oldWindowProc = Control->WindowProc;
MakeObjectInstance(newWProc) for SetWindowLong
MakeObjectInstance(newDefWProc) for Control->DefWndProc
Control->WindowProc = newWindowProc;
......;
}
现在,当我使用TDCEdit和拦截消息。Msg == WM_NCHITTEST
newWProc消息。结果为0,并在所有消息处理链中保持0。
注意,子类TCustomEdit是我们需要子类化
的其他控件之一。在项目中,我们尝试使用相同的子类(TWinControl*)函数。
这是newWProc的一部分,还有几行关注问题
void __fastcall TControlWrapper::newWProc(Messages::TMessage &Message)
{
if(Message.Msg == WM_NCHITTEST ) // TEST
if(Message.Result == 0)
Message.Result=1;//<- WHY I NEED TO DO THIS
if( Message.Msg == WM_DESTROY) {
HandleWMDestroy(Message);
return;
}
CallWindowProcW( (int(__stdcall*)())oldWProc,
Handle, Message.Msg, Message.WParam,
Message.LParam);
if(Message.Msg == WM_NCHITTEST )
if(Message.Result == 0)Message.Result=1;//<- OR THIS
}
这是一个令人困惑的问题-它没有帮助,你的代码示例不是c++。
set Control DefWndProc to SubClass.lpfnWndProc
例如,在c++函数中不是一行。你能显示你的实际代码吗?
我可以猜测你想做什么:你是否试图子类化一个窗口(也许是一个窗体?),以便它在鼠标点击时移动?如果是这样,你不需要做任何原始的Windows api风格的子类化,你似乎在做GetWindowLong
的方式。在c++ Builder中,VCL是一个围绕Windows API的面向对象的包装器,您可以通过以下两种更简洁的方式之一来实现:
- 创建一个新的
- 创建
TWinControl
的后代类(如果您正在使用表单,您已经有一个)并实现虚拟方法WndProc
。
WindowProc
并设置它;这是一个指向新窗口过程的属性,你可以简单地调用旧窗口过程;#1的一个例子,在Delphi(但你应该能够很容易地将其转换为c++)是在Embarcadero文档中子类化WndProc。
一个例子#2,最干净的OO版本,在这里,这实际上显示了如何做你想做的事情:c++ Builder:创建一个带有BorderStyle bsNone的TForm,但仍然是可移动和可调整大小
考虑到你似乎想要做的事情,我建议你用#2。
- 需要在后代 .h 文件中重新声明被覆盖的函数
- 如何更改可检查的QPushButton后代的背景颜色
- 如果后代类没有非静态成员或析构函数,我是否需要虚拟析构函数
- 删除boost ::线程后代
- 如何从基类调用后代函数
- C++检查对象是否是给定超类的后代
- 当后代需要不同的参数列表时,我应该如何在基类中定义抽象方法
- 这个问题叫什么?如果通过基类型传递结构,则后代类型中的字段在方法中不可用
- 如何编写对树中节点的后代进行计数的迭代DFS
- XPATHNavigator的编译函数中的"后代"是什么意思?
- 在CDialog的后代中没有调用OnInitDialog
- c++中指向对象及其后代的指针
- 如何将模板参数限制为模板化接口的专门化的后代
- 是否有std::vector的后代可以合并和排序?
- 子类化VCL的后代TWinControl
- LCA后代节点
- 在非直接后代中可访问的受保护成员