Ne said:
The first question is about coding a callback on Windows. In a class of
callback function, the function has to be static. Now the problem is that
from within this function, no non-static members can be accessed or invoked.
Seems like the only way is to change all the members to static.
Not at all.
I'd like to hear your opinions on such change.
It would kind of defeat the object of having a class if you made all the
functions static. You might as well have a bunch of global functions and
variables.
Here's how you should do it, this only works of the callback accepting
function is well designed. Fortunately in Windows most of them are.
I'll illustrate with the Windows API call EnumWindows, but this technique is
widely applicable.
The EnumWindows function requires a callback of the form
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
This is what you must supply (although the name is up to you obviously), it
cannot be a member function, strictly speaking in cannot even be a static
member function although many compilers accept this. Suppose you want to
callback a method called addWindow in a WindowList class. Here's what you do
class WindowList
{
bool addWindow(HWND win);
};
BOOL CALLBACK EnumWindowsGlue(HWND hwnd, LPARAM lParam)
{
return reinterpret_cast<WindowList*>(lParam)->addWindow(hwnd);
};
WindowList myWindowList;
EnumWindows(EnumWindowsGlue, reinterprest_cast<LPARAM>(&myWindowList));
The way you pass the object you want to call a method on as a parameter to
EnumWindows and the way that parameter is recieved by the callback function
is the trick. The callback function is just a 'glue' that lets you attach
the member function to the EnumWindows routine.
Most Windows APIs have similar features, usually the extra parameter is
defined as LPVOID which is a bit more portable and means you only need one
static_cast instead of two reinterpret_cast's. (For the benefit of
non-Windows users, LPARAM is typedef'd as long, and LPVOID is typedef'd as
void*.
john