RAD Studio VCL Reference
ContentsIndex
PreviousUpNext
Classes.MakeObjectInstance Function

Allocates a block of memory to be used by an instance of a class.

Pascal
function MakeObjectInstance(AMethod: TWndMethod): Pointer;
C++
void * MakeObjectInstance(TWndMethod AMethod);

Call MakeObjectInstance to obtain memory to associate with an instance of a class.  

This can be particularly useful when using classes that do not have a Windows handle but need to receive Windows Messages. MakeObjectInstance registers a message handling function into the Windows Message Processing Chain, effectively trapping the Windows Messages. This way the messages sent to the parent window are redirected and processed by the correct function.  

C++ Examples: 

 

/*
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 decendents
of TWinControl.  MakeObjectInstance is used here to allocate
a block of memory for the class object.  Then we 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.
This example was furnished by Robert Dunn and nicely described
at: http://home.att.net/~robertdunn/Papers/MethodCallbacks.html
Copyright © 1998-2001 Thin Air Enterprises and Robert Dunn.
All rights reserved.
*/
class TMyComponent : public TComponent
{
protected:
  void* FNewWndProcInst;
  void* FOldWndProcInst;
  virtual void __fastcall MyWndProc(Messages::TMessage& Msg);
public:
  __fastcall TMyComponent(TComponent* Owner);
  __fastcall ~TMyComponent(void);
};

__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
{
}

// 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... (your needs may differ)
  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)
{
  // Do whatever you want with the message before calling
  // (or not calling) the 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(
    (int(__stdcall*)()) FOldWndProcInst, Form1->Handle,
    msg.Msg, msg.WParam, msg.LParam);
  // do whatever 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;

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  mycomp = new TMyComponent(this);
  oldMsg.Msg = 0;
  oldMsg.WParam = 0;
  oldMsg.LParam = 0;
}

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
  delete mycomp;
}

 

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!