Question |
How do make one of my VCL class member-functions act as a Win32 callback function? |
Answer |
This problem is a lot easier to solve than most people think. Most of the time, you will see
callbacks implemented either as static members or global functions with the class instance pointer set as
extra data (to the window or lParam or whatever). The VCL provides two undocumented functions that are
designed to do exactly what we want: use member-functions as callbacks. Those functions are
MakeObjectInstance and FreeObjectInstance. Example://---------Function Protypes from Forms.hpp---------------- //extern PACKAGE void * __fastcall MakeObjectInstance(Controls::TWndMethod Method); //extern PACKAGE void __fastcall FreeObjectInstance(void * ObjectInstance); //--------------------------------------------------------- //------------------------------Unit1.h-------------------------------------- //--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components void __fastcall FormClick(TObject *Sender); private: // User declarations void *oldproc; void *newproc; void __fastcall myproc(TMessage &msg); public: // User declarations __fastcall TForm1(TComponent* Owner); __fastcall ~TForm1(); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif //-----------------------End Unit1.h----------------------------------------- //-----------------------Unit1.cpp------------------------------------------- //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { newproc = MakeObjectInstance(myproc); oldproc = (void *)SetWindowLong(Handle,GWL_WNDPROC,(LONG)newproc); } //--------------------------------------------------------------------------- __fastcall TForm1::~TForm1() { SetWindowLong(Handle,GWL_WNDPROC,(LONG)oldproc); FreeObjectInstance(newproc); } //--------------------------------------------------------------------------- void __fastcall TForm1::myproc(TMessage &msg) { if (msg.Msg == WM_LBUTTONUP) ShowMessage("click"); msg.Result = CallWindowProc((FARPROC)oldproc,Handle,msg.Msg,msg.WParam,msg.LParam); } void __fastcall TForm1::FormClick(TObject *Sender) { ShowMessage("click_event"); } //--------------------------------------------------------------------------- //-----------------------End Unit1.cpp--------------------------------------- |
Last Modified: 17-NOV-00