gpt4 book ai didi

c++ - VCL TWinControl 的子类化后代

转载 作者:行者123 更新时间:2023-11-28 07:41:29 25 4
gpt4 key购买 nike

使用伪函数进行子类化:

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 for 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


}

最佳答案

这是一个令人困惑的问题 - 您的代码示例不是 C++ 也无济于事。

set Control DefWndProc to SubClass.lpfnWndProc
例如,

不是 C++ 函数中的一行。您可以显示您的实际代码吗?

我可以猜测您要做什么:您是否正在尝试子类化一个窗口(也许是一个窗体?),以便在单击鼠标时它会移动?如果是这样,您不需要执行任何原始 Windows API 样式的子类化,就像您使用 GetWindowLong 所做的那样。在 C++ Builder 中,VCL 是围绕 Windows API 的面向对象的包装器,您可以通过以下两种更简洁的方法之一来实现:

  1. 创建一个新的WindowProc并设置它;这是一个指向新窗口过程的属性,您也只需调用旧窗口过程即可;
  2. 创建 TWinControl 的后代类(如果您使用的是表单,您已经有一个)并实现虚拟方法 WndProc

#1 的一个示例,在 Delphi 中(但您应该可以轻松地将其转换为 C++)在 the Embarcadero documentation on subclassing WndProc 中.

#2 的一个例子,最干净的 OO 版本,在这里,它实际上也展示了如何做你想做的事情:C++Builder: Create a TForm with BorderStyle bsNone that is nevertheless movable and resizable

鉴于您似乎想做的事情,我建议您选择 #2。

关于c++ - VCL TWinControl 的子类化后代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15770417/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com