Dynamic Trigger Function - c++

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.

Related

Subclassing an edit control from a user defined class/pointer-to-member-function

I think I've fallen in the same trap as many before me where I try to impose a nice OO methodology on win32 API programming. No MFC, no AFX, I'm not even using VC++, I'm using C::B with gcc.
I think what I'm trying to do is impossible, but since MFC exists (although I'm not using it) there must be some way.
I've created a class to contain several window controls. It implements handlers for WM_CREATE and WM_COMMAND, and keeps track of all the associated data around my small group of controls (ID codes and HWNDs).
It works great for buttons, static controls, even light GDI methods, but it all breaks down when I try to subclass an edit control.
Really, I just want to capture the "enter" key, but as anybody who's been down that road before will attest, when an edit control has focus, the parent window doesn't receive WM_KEYDOWN or WM_COMMAND, we are left to implement our own proc. Super lame.
OK, so subclassing an edit control is fine, if the editProc is global or static. I know that is because SetWindowLongPtr needs a function address, and that concept is nebulous for a member function.
So the object of my class is declared as "static" inside the parent WndProc. But the function is not "static" because then I wouldn't have access to non-static data members (completely defeating the purpose of this exercise). I'm hoping that because the objest is itself static, I should be able to properly define the address of one of its member functions.
Readers that have tried this before will either have given up and used MFC or something else, or perhaps have found a clever work-around.
I'll let this sample code do the rest of the talking: (simplified - will not compile as such)
/**** myprogram.c ****/
#include "MyControlGroup.h"
int winMain(){ // etc... }
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// object is static becuse it only needs to be initialized once
static MyControlGroup myControl;
if (msg == WM_CREATE)
myControl.onWMCreate(hWnd);
else if (msg == WM_COMMAND)
myControl.onWMCommand( wParam, lParam );
else if (msg == WM_DESTROY)
PostQuitMessage(0);
return DefWindowProcW(l_hWnd, l_msg, l_wParam, l_lParam);
}
The header file for my class:
/**** MyControlGroup.h ****/
class MyControlGroup
{
private:
HWND m_hWndParent;
HWND m_hWndEditBox;
int m_editBoxID;
public:
MyControlGroup();
void onWMCreate(HWND);
void onWMCommand(WPARAM, LPARAM);
// want to find a way to pass the address of this function to SetWindowLongPtr
LRESULT myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
...and the implementation:
/**** MyControlGroup.cpp ****/
static int staticID = 1;
MyControlGroup::MyControlGroup()
{
m_editBoxID = staticID++;
}
void MyControlGroup::onWMCreate(HWND hWnd)
{
// My control group has buttons, static controls, and other stuff which are created here with CreateWindowW. It also has an edit control:
m_hWndEditBox = CreateWindowW(L"EDIT", L"initial text", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 150, 20, hWnd, (HMENU)m_editBoxID, NULL, NULL);
/*
To subclass the edit control, I need a pointer to my customized proc. That means I
need a pointer-to-member-function, but SetWindowLongPtr needs a pointer to global or
static function (__stdcall or CALLBACK, but not __thiscall).
*/
// I'd like to do something like this, adapted from a great write-up at
// http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
LERSULT (MyControlGroup::*myEditProcPtr)(HWND, UINT, WPARAM, LPARAM);
myEditProcPtr = &MyControlGroup::myEditProc;
// Up to now it compiles ok, but then when I try to pass it to SetWindowLongPtr, I get
// an "invalid cast" error. Any ideas?
SetWindowLongPtr(m_hWndEditBox, GWLP_WNDPROC, (LPARAM)myEditProcPtr);
}
void MyControlGroup::onWMCommand(WPARAM wParam, LPARAM lParam){ /* process parent window messages. Editboxes don't generate WM_COMMAND or WM_KEYDOWN in the parent :''( */}
LRESULT MyControlGroup::myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// process messages like IDOK, WM_KEYDOWN and so on in the edit control
}
Even once I get this done, I'll still need to figure out a way to pass the address of the parent WndProc to myEditProc for the return value, but until I get past this there is no point in worrying about that.
Thanks in advance for reading!
myEditProc needs to be a static function.
Once you've done that you can pass the address of the function directly without going through the intermediate variable:
static LRESULT myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
...
SetWindowLongPtr(m_hWndEditBox, GWLP_WNDPROC, (LPARAM)myEditProc);
To access your class data from the static function, you can save it in the userdata field of the edit control, e.g.:
// before sub-classing the control
SetWindowLongPtr(m_hWndEditBox, GWLP_USERDATA, (LPARAM)this);
// in the sub-class procedure
MyControlGroup* pThis = (MyControlGroup*)GetWindowLongPtr(m_hWndEditBox, GWLP_USERDATA);
But as #K-ballo suggested, SetWindowSubclass is definitely the way to do this unless you want compatibility with pre-XP. It handles the sub-classing procedure for you automatically, lets you associate a userdata pointer (e.g. this) that is automatically passed to the sub-class procedure, and safely handles removing the sub-class at the end.

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)

How to use DialogBoxParam?

I have a pre-made template resource dialog, and I want to use DialogBoxParam to display it, but I can't find any good examples over the internet. The dialog is a simple login dialog, so can someone explain how to build my lpDialogFunc and what to put in dwInitParam?
You've tagged this question as C++, but havn't specified any particular framework (such as ATL or MFC).
So, in the spirit of providing a c++ / OOP answer to the question, without using a framework, the first thing to do is to create a class to wrap the dialog box, as well as provide a way for the dialog proc to reliably retrieve the pointer to the class. The windows API is a C API and cannot call class members directly so it is necessary to create static methods that can then retrieve the classes this pointer from somewhere.
class MyDialog {
HWND _dlg;
public:
int RunModal(HINSTANCE resModule, UINT resId,HWND parent){
return DialogBoxParam(resModule,MAKEINTRESOURCE(resId),parent,&StaticDialogProc,(LPARAM)this);
}
protected:
static INT_PTR CALLBACK StaticDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam){
MyDialog* self;
if(uMsg == WM_INITDIALOG){
self = (MyDialog*)lParam;
self->_dlg = hwndDlg;
SetWindowLongPtr(hwndDlg,DWLP_USER,lParam);
}
else
self = (MyDialog*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
if(self)
return self->DialogProc(uMsg,wParam,lParam);
return FALSE;
}
virtual UINT_PTR DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam){
switch(uMsg){
case WM_INITDIALOG:
OnInitDialog();
break;
case WM_COMMAND:
OnCommand(LOWORD(wParam),HIWORD(wParam),(HWND)lParam);
break;
default:
return FALSE;
}
return TRUE;
}
virtual void OnInitDialog(){
}
virtual void OnCommand(int id, USHORT notifyCode,HWND control){
EndDialog(_hdlg,id);
}
};
Now, there are hundreds of window messages that Windows can send to a dialog. Add handlers for each message to DialogProc and call a specific virtual function so derived classes can handle the message differently by overriding the virtual.
The critical messages to handle are usually WM_INITDIALOG which is sent as soon as the dialog is created, so is an ideal time to initialize any controls on the dialog - to populate drop down controls, or SetWindowText to initielize text boxes with default values.
and WM_COMMAND, which is sent by controls like buttons, when they are clicked, passing in their id, and this is where you would handle the OK and CANCEL buttons.
Once DialogBoxParam returns, the dialog and all its child controls has been destroyed, so you would typically extract all the input fields in the OnCommand handler and store them in class members before calling EndDialog.
Another use case for the second part of the question: "what to put in dwInitParam"?
If you prefer OO programming and do not want to use the global scope for your dialog box, you can pass this to the formal parameter dwInitParam.
Obtaining a pointer to the caller:
template< typename CallerT >
inline CallerT *GetDialogCaller(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (WM_INITDIALOG != uMsg) {
// Retrieves information about the specified window.
// 1. A handle to the window and, indirectly, the class to which the window belongs.
// 2. Retrieves the user data associated with the window.
return reinterpret_cast< CallerT * >(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
}
CallerT * const caller = reinterpret_cast< CallerT * >(lParam);
// Changes an attribute of the specified window.
// 1. A handle to the window and, indirectly, the class to which the window belongs.
// 2. Sets the user data associated with the window.
// 3. The replacement value.
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, reinterpret_cast< LONG_PTR >(caller));
return caller;
}
Delegating the message to the caller:
class Widget {
public:
static INT_PTR CALLBACK DialogProcDelegate(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
// Retrieve a pointer to the instance of Widget
// that called DialogBoxParam.
Widget * const widget = GetDialogCaller< Widget>(hwndDlg, uMsg, wParam, lParam);
// Delegate the message handling.
return widget->DialogProc(hwndDlg, uMsg, wParam, lParam);
}
INT_PTR Show() const {
return DialogBoxParam(nullptr, MAKEINTRESOURCE(IDD_WIDGET_SETTINGS), nullptr, DialogProcDelegate, reinterpret_cast< LPARAM >(this));
}
private:
INT_PTR DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
// Note that this method is not affected by our approach,
// i.e. this method will still receive a WM_INITDIALOG.
switch (uMsg) {
...
}
return FALSE;
}
};
The alternative puts the caller in global scope and is restricted to a single caller for all dialog boxes.
you can do something like this. The dwInitParam Specifies the value to pass to the dialog box in the lParam parameter of the WM_INITDIALOG message. You can pass any value or simply pass NULL
INT_PTR CALLBACK editDlg(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG:
return 1;
break;
}
return 0;
}
if(DialogBoxParam(hInst,MAKEINTRESOURCE(IDD_EDIT),hwndMain,editDlg,NULL)==IDOK)
{
}

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() {
...
}

Implement user activity logger in old application?

How to go about implementing a user activity logger in MFC application.To get to know what are all the features are used most in an existing application.
You can override the windows procedure of your application window:
class CMyMainWindow {
void LogUsageData(UINT message);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
LogData(message);
return CWnd::WindowProc(message, wParam, lParam); // route message to message map
}
}
Note that the task is not so trivial: LogUsageData should discard most messages, focusing only on the ones defined in the message map.
However, this should be a good place to start.