MakeObjectInstance (C++)
Description
This example uses the MakeObjectInstance function to subclass a form's WinProc for the purpose of trapping Windows messages. This needs to be done for components that are not decendants of TWinControl. MakeObjectInstance is used here to allocate a block of memory for the class object. Then you fill the memory with the machine code necessary to jump to a unique class object member function, and then use the address of that block of memory as the callback address.
Code
class TMyComponent : public TComponent
{
protected:
void* FNewWndProcInst;
void* FOldWndProcInst;
virtual void __fastcall MyWndProc(Messages::TMessage& Msg);
public:
__fastcall TMyComponent(TComponent* Owner);
__fastcall ~TMyComponent(void);
};
// This is the constructor. Create the instance callback and
// save it to FNewWndProcInst and save the old window proc to
// FOldWndProcInst. Subclass the form.
//
__fastcall TMyComponent::TMyComponent(TComponent* Owner)
: TComponent(Owner), FOldWndProcInst(0), FNewWndProcInst(0)
{
// If the owner is a form, the following code fragment is valid:
TForm* form = dynamic_cast<TForm*>(Owner);
if (form)
{
FNewWndProcInst = MakeObjectInstance(MyWndProc);
FOldWndProcInst = (void*) ::SetWindowLong(
form->Handle, GWL_WNDPROC, (LONG) FNewWndProcInst);
if (!FOldWndProcInst) { /* error */ };
}
// Other initialization
}
// This is the destructor. Restore the original WndProc and
// free the instance callback.
//
__fastcall TMyComponent::~TMyComponent(void)
{
if (FNewWndProcInst)
{
(void*)SetWindowLong(
Form1->Handle, GWL_WNDPROC, (LONG) FOldWndProcInst);
FreeObjectInstance(FNewWndProcInst);
}
}
// This is the callback method; in this example, it is used
// to filter messages to the underlying Windows control.
//
TMessage oldMsg;
void __fastcall TMyComponent::MyWndProc(Messages::TMessage& msg)
{
// You can perform any action with the message before calling
// (or not calling) the original WndProc() to handle
// the message call to the original WndProc.
// Note that, if you have instantiated multiple objects
// of this class, then you are actually chaining back to
// MyWndProc() in each earlier instantiation, until you
// get back to the original WndProc.
msg.Result = CallWindowProc(
(long(__stdcall*)(HWND__*, unsigned int, unsigned int, long)) FOldWndProcInst, Form1->Handle,
msg.Msg, msg.WParam, msg.LParam);
// You can perform any action you want after the original WndProc() has handled the message.
if (oldMsg.Msg != msg.Msg)
{
Form1->ListBox1->Items->Add(
"Message recieved: Msg: " + IntToStr((int)msg.Msg) + " WParam: " +
IntToStr((int)msg.WParam) + " LParam: " + IntToStr((int)msg.LParam));
oldMsg = msg;
}
}
TMyComponent *mycomp;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
mycomp = new TMyComponent(this);
oldMsg.Msg = 0;
oldMsg.WParam = 0;
oldMsg.LParam = 0;
}
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete mycomp;
}
Uses
- System.Classes.MakeObjectInstance ( fr | de | ja )
- System.Classes.FreeObjectInstance ( fr | de | ja )