0

使用伪函数进行子类化:

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并设置ResultHTCLIENT 我们有鼠标响应时,但是,由于我的错误和错误的子类化,如果没有设置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 并在 newWProc 中拦截 Message.Msg == WM_NCHITTEST
时,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


 }
4

1 回答 1

1

这是一个令人困惑的问题 - 您的代码示例不是 C++ 并没有帮助。

set Control DefWndProc to SubClass.lpfnWndProc

例如,不是 C++ 函数中的一行。你能显示你的实际代码吗?

我可以猜测您要做什么:您是否要对窗口(可能是表单?)进行子类化,以便在单击鼠标时移动它?如果是这样,您不需要执行任何原始 Windows API 样式的子类化,就像您使用GetWindowLong. 在 C++ Builder 中,VCL 是围绕 Windows API 的面向对象的包装器,您可以通过以下两种更简洁的方式之一来执行此操作:

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

Delphi 中的#1 示例(但您应该能够轻松地将其转换为 C++)在Embarcadero 文档中关于 WndProc 的子类化

#2 的一个例子,最干净的 OO 版本,在这里,它实际上也展示了如何做你想做的事情:C++Builder: Create a TForm with BorderStyle bsNone that is但是可移动和可调整大小

鉴于您似乎想要做的事情,我建议您使用#2。

于 2013-04-03T13:36:03.533 回答