使用伪函数进行子类化:
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并拦截Message.Msg == WM_NCHITTEST
时
在newWProc内部,Message.Result为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
}
答案 0 :(得分:1)
这是一个令人困惑的问题 - 您的代码示例不是C ++也无济于事。
set Control DefWndProc to SubClass.lpfnWndProc
例如,不是C ++函数中的一行。你能显示你的实际代码吗?
我可以猜测你正在尝试做什么:你是否试图将一个窗口(可能是一个窗体?)子类化,以便在单击鼠标时它会移动?如果是这样,您不需要执行任何原始Windows API样式的子类化,就像您对GetWindowLong
所做的那样。在C ++ Builder中,VCL是围绕Windows API的面向对象的包装器,您可以通过以下两种更简洁的方式之一来实现:
WindowProc
并进行设置;这是一个指向新窗口过程的属性,您只需调用旧窗口过程; TWinControl
的后代类(如果您使用的是表单,则已有),并实现虚拟方法WndProc
。Delphi中的#1示例(但您应该可以轻松地将其转换为C ++)位于the Embarcadero documentation on subclassing WndProc。
最简洁的OO版本#2的例子就在这里,这实际上也说明了你要做的事情:C++Builder: Create a TForm with BorderStyle bsNone that is nevertheless movable and resizable
鉴于你似乎想做什么,我建议你去#2。