Reputation: 657
Using pseudo funcs for subclassing:
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;
......;
}
Now, we have unexpected behavior of subclassed control.
WM_NCHITTEST
result 0, etc...
For example when newWProc
intercepts WM_NCHITTEST
and sets Result
to HTCLIENT
we have mouse response, but, is that not responding without setting msg.result
to 1 for msg.msg WM_NCHITTEST
consequence of my mistake and wrong subclassing, what else we need to handle manually?
newWProc
make callback of oldWProc
newDefWProc
make callback of oldDefWProc
newWindowProc
calls oldWindowProc
Do we have to subclass parent control of subclassed control as well?
Also, sending WM_GETTEXT
results with empty buffer.
Obviously, we are doing something wrong here. We need explanation,
Thank You all in advance
Update:
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;
......;
}
Now, when I use TDCEdit and intercept Message.Msg == WM_NCHITTEST
inside newWProc Message.Result is 0 and stay 0 through all message process chain.
Note that subclassing TCustomEdit is one among other controls we need to subclass
in project and we try to use same subclass(TWinControl*) function for all.
Here is part of newWProc with few more lines to focus on problem
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
}
Upvotes: 0
Views: 717
Reputation: 13590
This is a confusing question - it doesn't help that your code samples are not C++.
set Control DefWndProc to SubClass.lpfnWndProc
is not a line in a C++ function, for example. Can you show your actual code please?
I can make a guess at what you're trying to do: are you trying to subclass a window (perhaps a form?) so that it moves when the mouse is clicked on it? If so, you don't need to do any raw Windows API-style subclassing, the way you appear to be doing with GetWindowLong
. In C++ Builder, the VCL is an object-oriented wrapper around the Windows API, and you can do this in one of two much cleaner ways:
WindowProc
and set it; this is a property pointing to a new window procedure, and you simply call the old one too;TWinControl
(if you're using a form, you already have one) and implement the virtual method WndProc
.An example of #1, in Delphi (but you should be easily able to convert it to C++) is in the Embarcadero documentation on subclassing WndProc.
An example of #2, the cleanest OO version, is here, and this actually shows how to do what you're trying to do, too: C++Builder: Create a TForm with BorderStyle bsNone that is nevertheless movable and resizable
Given what you appear to want to do, I would suggest going with #2.
Upvotes: 1