I have two classes defined as:
class Control
{
private:
std::vector<int> Info;
public:
Control(..);
virtual ~Control();
LRESULT __stdcall SubClass(HWND Window, UINT Msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
};
class Button: public Control
{
//...
};
Control::Control(..)
{
SetWindowSubclass(..., SubClass, ...); //Need to pass member function as callback..
}
LRESULT __stdcall Control::SubClass(HWND Window, UINT Msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
//Use "Info" data member in here.. thus I cannot have static callback in order to use it.
}
And so I came up with:
class Control
{
private:
std::vector<int> Info;
static LRESULT __stdcall SetCallback(void* ThisPtr) {return static_cast<Control*>(ThisPtr)->SubClass;};
public:
//all the same stuff..
};
Control::Control(..)
{
SetWindowSubclass(..., SetCallback, ...);
}
But the above throws a whole bunch of errors. Is there anyway to either have my static callback access other datamembers OR have my callback non-static? I do not want to have to do something like the following for every instance created (which I've seen as suggestions all over the internet):
Control F;
F.SetCallback(&F::SubClass, &F); //Externally sets member as callback which I don't want.
I'm trying to keep everything in the constructor or the class itself.
The following shows how to pass calls to the freestanding message handler function, on to a member function of your C++ object.
It's a lot of code, but normally you would abstract this away in some reusable module, and the most basic stuff is just the little class
gui::api_level::window_subclasser_t
.I haven't shown very much error handling, and neither does this code support programmatic destruction of the C++ object via external
delete
(I think the sane way to do this is to justDestroyWindow
the API level window and let that propagate up to self-destruction of the C++ object, but it's many years since last time I did this).To compile this with Visual C++ 11.0, define the preprocessor symbol
IS_DELETED
as nothing.This is probably the most common question when it comes to Win32 API UI programming. See:
http://msdn.microsoft.com/en-us/library/windows/desktop/ff381400(v=vs.85).aspx
Basically the trick is to call SetWindowLongPtr with GWLP_USERDATA as the first parameter and this as the second. Then in the WindowProc callback use GetWindowLongPtr to get it from the HWND.