Can I use member function as first argument to EnumWindows [duplicate] - c++

This question already has answers here:
how to pass a non static-member function as a callback?
(8 answers)
Closed 9 years ago.
Can I use member function as first argument to EnumWindows? I don't see any workaround in this case even with boost::bind.

Given this normal callback function:
BOOL CALLBACK EnumWindowsProc(HWND wnd, LPARAM lParam);
You can invoke EnumWindows using lParam to pass it a pointer to your class:
EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(this));
In EnumWindowsProc you can simply call member function (casting lParam to your class type). Like this:
BOOL CALLBACK EnumWindowsProc(HWND wnd, LPARAM lParam)
{
return reinterpret_cast<MyClass*>(lParam)->EnumWindows(wnd);
}
If you don't want to make your class method public you can:
Pack a struct to contain both class instance and pointer to member.
Use a library for delegates.
Use boost std:bind (in this case it'll work well because you do it on your own class member, it has not to be __stdcall).
Whatever you will use you can find more details in this post here on SO.

EnumWindows takes a callback that looks like this
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam);
You cannot use either a member function or a lambda that has a capture. You do this instead.
typedef std::function<bool(HWND hwnd)> func_type;
BOOL CALLBACK MyEnumProc(HWND hwnd, LPARAM lparam)
{
auto& func = *reinterpret_cast<func_type*>(lparam);
if(func(hwnd))return TRUE;
else return FALSE;
}
You would use it like this
auto f = std::make_shared<func_type>(std::bind(&mymemberfunction,this));
EnumWindows(MyEnumProc,reinterpret_cast<LPARAM>(f.get()));
//Make sure to keep the shared_ptr around until you are done enumerating

Related

Why does a virtual function call from constructor work sometimes but not others?

The general rule of thumb is not to call a virtual function from a constructor because it can lead to unpredictable behavior. So why does it work sometimes?
I recently wrote a couple of base classes with pure virtual functions, and accidentally included an indirect call to those functions in the constructor. I realized my mistake and corrected it, but one of them worked while the other did not.
Here's the definition of the class that worked:
template <typename TWindow>
class dialog_base
{
static INT_PTR CALLBACK dlg_proc_internal
(HWND,
UINT,
WPARAM,
LPARAM);
protected:
dialog_base
(const LPCWSTR templateName,
const HWND parent)
{
CREATESTRUCT create;
create.lpCreateParams = this;
m_hwnd = CreateDialogParam(
hinstance_, templateName, parent, dlg_proc_internal,
reinterpret_cast<LPARAM>(&create));
}
HWND m_hwnd;
virtual INT_PTR CALLBACK dlg_proc
(UINT,
WPARAM,
LPARAM) = 0;
public:
virtual ~dialog_base()
{
DestroyWindow(m_hwnd);
}
HWND GetHandle() const;
void show() const;
};
In this class, the DialogBoxParam function calls dlg_proc_internal, passing the WM_NCCREATE message:
template <typename TWindow>
INT_PTR dialog_base<TWindow>::dlg_proc_internal
(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
dialog_base<TWindow>* pThis;
if (msg == WM_NCCREATE)
{
pThis = static_cast<dialog_base<TWindow>*>(reinterpret_cast<
CREATESTRUCT*>(lParam)->lpCreateParams);
SetLastError(0);
if (!SetWindowLongPtr(
hWnd, GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(pThis)) && GetLastError() != 0)
return 0;
}
else
{
pThis = reinterpret_cast<dialog_base<TWindow>*>(
GetWindowLongPtr(hWnd, GWLP_USERDATA));
}
return pThis
? pThis->dlg_proc(msg, wParam, lParam)
: DefWindowProc(hWnd, msg, wParam, lParam);
}
This function retrieves the pointer passed as the last argument to CreateDialogParam and stores it in the window so that it can be retrieved again in later calls to the function.
It then mistakenly calls the pure virtual function dlg_proc instead of returning -- and appears to work just fine through the constructor of a child class.
I created a different class which was almost identical, except that it called CreateWindowEx instead of CreateDialogParam. The pointer argument was passed in much the same way, and used to call the pure virtual function. This time, it failed as one might expect. So what's the difference between the two situations?
EDIT:
Perhaps I should clarify. I'm not asking "Why can't I call virtual members from a constructor?". I'm asking about why the process of resolving virtual members before the object is constructed can sometimes create situations in which an error does not occur, and the correct function is called.
Calling a virtual function from a constructor has perfectly predictable behavior in C++, just like it has perfectly predictable behavior in .Net and Java. However, it's not the same behavior.
In C++, virtual functions dispatch on the type of the object at the moment of calling. Some other languages will use the intended type of object. Both are viable choices, both have risks, but since this is a C++ question I'll focus on the C++ risk.
In C++, virtual functions can be pure virtual. dlg_proc in the question is such a pure virtual function. These are declared in the base class, but not (necessarily) defined there. Trying to call a function that you did not define is Undefined Behavior. Compilers are entirely free to do whatever they like.
One possible implementation is that a compiler just calls a random other function. This could be remove(filename). It might also be the override from a derived class. But there are a million other possible results, including crashes and hangs. So we don't try to predict what happens, and just say: don't call pure virtual functions from ctors.
Footnote:
You can actually provide a body for a pure virtual function; the language allows it.
CreateDialog...() (and DialogBox...()) does not pass its dwInitParam parameter value to your message procedure via WM_(NC)CREATE. It is passed via WM_INITDIALOG instead, which you are not handling. Only CreateWindow/Ex() passes its lpParam parameter values to the message procedure via WM_(NC)CREATE. This is documented behavior!
But more importantly, you are manually passing a CREATESTRUCT to CreateDialogParam(). That is not necessary, especially since you are not handling that extra CREATESTRUCT in your WM_NCCREATE handler. When the system issues WM_(NC)CREATE to a window, the lParam passed to CreateWindow/Ex() gets wrapped in a system-provided CREATESTRUCT. So, even if CreateDialogParam() were to pass its dwInitParam as the lParam to CreateWindowEx() (which is not documented behavior, BTW), you still wouldn't be obtaining your dialog_base* pointer correctly inside your message procedure, as you are not handling that 2 separate CREATESTRUCTs could be present. So, your code has undefined behavior when using the pThis pointer for any reason, since you are not passing that pointer value into your message procedure correctly.
You need to pass your this pointer directly to CreateDialogParam() without wrapping it, and you need to handle WM_INITDIALOG instead of WM_NCCREATE. Then your virtual method should behave as expected (ie, it will not dispatch to a derived class, since WM_INITDIALOG is being handled within the context of the base class constructor).
Also, DO NOT call DefWindowProc() in your message procedure (or derived overrides) when using CreateDialog...() (or DialogBox...()). This is specifically stated in the DialogProc documentation:
Although the dialog box procedure is similar to a window procedure, it must not call the DefWindowProc function to process unwanted messages. Unwanted messages are processed internally by the dialog box window procedure.
Try this instead:
template <typename TWindow>
class dialog_base
{
static INT_PTR CALLBACK dlg_proc_internal(HWND, UINT, WPARAM, LPARAM);
protected:
dialog_base(LPCWSTR templateName, HWND parent)
{
m_hwnd = CreateDialogParamW(hinstance_, templateName, parent, dlg_proc_internal, reinterpret_cast<LPARAM>(this));
}
HWND m_hwnd;
virtual INT_PTR CALLBACK dlg_proc(UINT, WPARAM, LPARAM) = 0;
public:
virtual ~dialog_base()
{
DestroyWindow(m_hwnd);
}
HWND GetHandle() const;
void show() const;
};
template <typename TWindow>
INT_PTR dialog_base<TWindow>::dlg_proc_internal (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
dialog_base<TWindow>* pThis;
if (msg == WM_INITDIALOG)
{
pThis = reinterpret_cast<dialog_base<TWindow>*>(lParam);
// you CANT cancel dialog creation here when
// using CreateDialog...(), only when using
// DialogBox...()! So, no point in doing any
// error checking on SetWindowLongPtr()...
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis));
// no point in trying to call pThis->dlg_proc()
// here since it won't be dispatched to derived
// classes anyway...
return TRUE; // or FALSE, depending on your needs...
}
pThis = reinterpret_cast<dialog_base<TWindow>*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
if (!pThis) return FALSE;
return pThis->dlg_proc(msg, wParam, lParam);
}

Dynamic Trigger Function

I am currently trying since several hours to make a completely dynamic EventHandler. But, whatever I try seems to not work.
Here is a quick diagram of what the EventHandler should do:
EventHandler<EventName>::Add (void* listener);
EventHandler<EventName>::Trigger(...);
Every Event that gets added by the Add method, gets safed in a local std::vector. So far so good, until this, everything is fine and pretty clear. We create a template and the simple trigger function.
However, now comes the issue, the Trigger function. To give a better understanding, this EventHandler triggers functions from Native C++ Code to CLI Code.
To trigger the CLI function, I need:
void* address (OK)
arguments (not OK)
Inside the Trigger() function, I'd like to have to such code:
//WndProc Example Event
reinterpret_cast<void(__stdcall *)(HWND, UINT, WPARAM, LPARAM)>(clrVoidPtr)(hwnd, msg, wParam, lParam);
However... this is not dynamic (because the args are defined inside). I want to call it with the arguments from the actual Trigger (...) method. I know I have to work with va_args and similar, but even that, it seems impossible to me to make an actual Proof of Concept out of this?
Is it even possible to have a completely dynamic EventHandler, where the Trigger function accepts every argument and simply calls the appropriate function with it?
Right now my solution is to create a Event Class for each Event that I have and define the actual parameters in the Trigger function, as example:
void WndProcEvent::Trigger(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
... but since I will have a lot of events, this is not acceptable to me even if I create them by using macros (which are horrible to debug btw...)
Thank you for reading.
I would suggesting creating a simple object for each event type that defines the associated custom event signature and contains code for mapping from generic '(HWND, UINT, WPARAM, LPARAM)' format to custom signature. e.g:
// incomplete!
typedef void(WindowsCall *)(HWND, UINT, WPARAM, LPARAM);
struct OnClickEvent
{
public:
typedef void (CustomCall *)(HWND, int x, int y);
static void Invoke(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, CustomCall customCall)
{
// invoke custom call here!
...
}
};
template<string EventName, typename Invoker>
class EventHandler
{
typedef std::vector<Invoker::CustomCall> Listeners;
Listeners m_Listeners;
void Add(Invoker::CustomCall customCall)
{
m_Listeners.Add(customCall);
}
void Trigger(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
for (Listeners::iterator it = m_Listeners.begin();
it != m_Listeners.end();
++it)
Invoker::invoke(hwnd, msg, wparam, lparam, (*it));
}
// etc
...
};
// e.g Use
EventHandler<"OnClick", OnClickEvent> onClickHandler;
I actually did a similar thing for a project eons ago but used 'sigc++'
as I was not satisfied with using MFC/ATL (yuck!). Thats mainly because it was a macro soup!.
Hope that helps.

map of method pointers, compiler says it they don't take any arguements

this class is much larger, but i'll just post the offending code.
template<class T>
class BaseWindow : public IWindow
{
typedef void(T::*HandlerPtr)(WPARAM, LPARAM)
public:
LRESULT CALLBACK BaseWindow<T>::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
// various stuff
private:
void AddHandler(long id, HandlerPtr func);
private:
std::map<long, void(T::*)(WPARAM, LPARAM)> m_MessageHandlers;
}
template<class T>
void BaseWindow<T>::AddHandler(long id, HandlerPtr func)
{
m_MessageHandler.insert(std::pair<long, HandlerPtr>(id, func));
}
template<class T>
LRESULT CALLBACK Dapper32::BaseWindow<T>::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if(m_MessageHandlers.count(msg) == 1)
{
auto it = m_MessageHandlers.find(msg);
it->second(wparam, lparam); // <-- error here for all template instantiations
return 0;
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
Here's a little background. For fun and practice, i'm making a win32 wrapper since it seems like a fun, lengthy project to tackle. After a bit of a deliberation, i decided that i preferred a system of storing message handlers in maps rather than each message getting there own virtual function, or worse even, working with a giant switch statement. What the goal here is, you derive from this BaseWindow class and then the template parameter is that derived class. Something like
class MyWindow : public BaseWindow<MyWindow>
then you make private methods that will handle a specific message, and then call the AddHandler function passing in the message id, and then a pointer to that method. Easy as cake, and i've verified that they are entered into the map correctly. However, in the BaseWindow class, i get the error:
error C2064: term does not evaluate to a function taking 2 arguments
I find this odd because every place i pass around the pointer, the declaration certainly does take two arguments. When i remove the parentheses and arguements to make it look like:
it->second;
it compiles and runs, and of course, none of the handlers are called, but how can it even compile when a function pointer with two parameters is invoked without taking an arguement list? something is fishy and frankly i don't get it. Do any of you brilliant minds have any insight into this?
You need to do this:
(it->second)(wparam, lparam); // note parens
Can't remove the question so i guess i'll exlain how i solved it. got rid of the method pointers altogether, used std::functions in the map, and then used std::bind in the add handler function calls. much easier to work with system and method pointers are harder to store in a map together.
Try this code:
(*this.*(it->second))(wparam , lparam)

EnumWindows Pointer error

I'm getting a weird error trying to EnumWindows to a function inside a class. Here's my code
EnumWindows(&ConsoleDetector::EnumWindowsProc, NULL);
BOOL CALLBACK ConsoleDetector::EnumWindowsProc(HWND wnd, LPARAM lParam)
{
char className[200];
GetClassName(wnd, className, 200);
if (strcmp(className, "ConsoleWindowClass"))
m_result.push_back(wnd);
return TRUE;
}
Here's the error im getting:
ConsoleDetector.cpp:30: error: cannot convert 'BOOL (ConsoleDetector::*)(HWND__*, LPARAM)' to 'BOOL (*)(HWND__*, LPARAM)' for argument '1' to 'BOOL EnumWindows(BOOL (*)(HWND__*, LPARAM), LPARAM)'
Using MingW.
Thanks for help.
You are passing an instance method. You need to pass a plain function rather than a method bound to an instance.
It has to be declared like this:
BOOL CALLBACK EnumWindowsProc(HWND wnd, LPARAM lParam)
Pass the instance of the ConsoleDetector to the lParam parameter of EnumWindows and it will in turn be passed to your callback.
Like this:
BOOL CALLBACK EnumWindowsProc(HWND wnd, LPARAM lParam)
{
ConsoleDetector cd = static_cast<ConsoleDetector*>(lParam);
//do stuff with cd and wnd
}
ConsoleDetector *cd = ...
EnumWindows(EnumWindowsProc, static_cast<LPARAM>(cd));
You can't use the windows callback function with class member functions in c++. Only static class functions or non class functions are allowed.
How should the EnumWindows function kown the instance of a class? You can only supply a function pointer, not an instance pointer to EnumWindows

Is it possible to give a top-level function access to an object's members in C++?

So I'm writing some wrapper classes for GUI programming in Win32. I'm starting with a Window class, and so far it contains a MainLoop method that is basically a clone of the standard Win32 WinMain function. That way, one can do something like this:
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow) {
Window *win = new Window();
// Do all your widget creation and add it to the window object...
return win->MainLoop(hInst, hPrev, szCmdLine, nCmdShow);
}
Inside the window object's MainLoop method, it must create the new Win32 window by setting its lpfnWndProc member. This member, as any Win32 programmer knows, is a function pointer to a specifically defined WndProc function. The problem is, if I were to create a WndProc function, I would need access to that window object's members (so that it knew what to draw on the window, etc.). This leaves me two options (that I know of):
I can define WndProc at the top level, but that cuts off access to the object's members.
I can define it as a class method, but then it's not the exact function type that lpfnWndProc asks for, so I can't set it!
Can anyone help me unravel this catch-22?
You could also make it a static member function. :)
Anyways, a solution depends on if you need only one window or if you need multiple windows.
First a solution for single windows:
// in .h
class Window{
public:
static LRESULT WINAPI MessageProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT InternalMessageProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// ...
};
// in .cpp
#include "Window.h"
Window* global_window = 0;
Window::Window(/*...*/){
if(!global_window)
global_window = this;
else
// error or exception... or something else
}
LRESULT WINAPI Window::MessageProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
return global_window->InternalMessageProc(hWnd, msg, wParam, lParam);
}
Now if you want to allow multiple windows, use a std::map (or if your compiler supports std::unordered_map).
Edit: This solution comes with some subtle problems. As #Ben Voigt points out in his comment, you get a chicken and egg problem as the MessageProc is called inside of CreateWindow(Ex), but only after the CreateWindow(Ex) call you have the window handle. Here's a solution based on Ben's next comment (thanks!):
// Window.h stays the same
// in .cpp
#include "Window.h"
#include <map>
std::map<HWND, Window*> window_map;
Window* currently_created_window = 0;
Window::Window(){
currently_created_window = this;
window_handle = CreateWindow(/*...*/);
}
LRESULT WINAPI Window::MessageProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
// if the key 'hWnd' doesn't exist yet in the map
// a new key-value pair gets created and the value gets value-initialized
// which, in case of a pointer, is 0
if(window_map[hWnd] == 0){
// window doesn't exist yet in the map, add it
window_map[hWnd] = currently_created_window;
}
window_map[hWnd]->InternalMessageProc(hWnd, msg, wParam, lParam);
}
Be cautious though, as the above example isn't thread-safe. You need to mutex-lock the creation of the window:
Window::Window(/*...*/){
Lock lock_it(your_mutex);
currently_created_window = this;
window_handle = CreateWindow(/*...*/);
lock_it.release();
// rest of the initialization
}
The above should do for the thread-safety (I hope).
You need to create window map and when you create new window just add it to this global map. You can use simple linked list instead of course.
map<HWND, Window *> wndmap;
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
Window *pWnd = wndmap [hwnd];
....
}
WndProc cannot be an instance member function, because Windows will not pass any hidden this parameter. It can be namespace scope or a static member.
One simple solution is to use a map<HWND, Window*> to find the object, and then forward parameters to a method on the object.
Note that WndProc can maintain the map itself, since CreateWindow provides an opaque user parameter that shows up in WM_CREATE which is useful for carrying the Window *, and then you remove the entry in WM_DESTROY.
Define your WndProc as a static class member - this will then be compatible (for all compilers I'm aware of) with non-member function pointer, such as those used in Win32 programming.
But I have to say that this is a bit of a waste of time - there are a zillion Windows class libraries out there, and I don't think the world really needs another one.
Sounds you need to declare the function without defining it. That's what prototypes are for.
class Object;
void f(Object* o);
class Object {
public:
...
void some_method() {
... &f ...
}
void another_method() {
...
}
...
};
void f(Object* o) {
...
o->another_method();
...
}
The other way around might also be possible.
class Object {
public:
...
void some_method();
void another_method();
...
};
void f(Object* o) {
...
o->another_method();
...
}
void Object::some_method() {
... &f ...
}
void Object::another_method() {
...
}