我目前正在尝试几个小时来制作一个完全动态的EventHandler。但是,无论我尝试什么似乎都行不通。
以下是EventHandler应该做的快速图表:
EventHandler<EventName>::Add (void* listener);
EventHandler<EventName>::Trigger(...);
由Add
方法添加的每个事件都在本地std :: vector中进行安全保护。到目前为止一直很好,直到这一切,一切都很好,非常清楚。我们创建了一个模板和简单的触发函数。
然而,现在问题是Trigger
功能。为了更好地理解,此EventHandler触发从Native C ++ Code到CLI Code的功能。
要触发CLI功能,我需要:
在Trigger()函数中,我想要这样的代码:
//WndProc Example Event
reinterpret_cast<void(__stdcall *)(HWND, UINT, WPARAM, LPARAM)>(clrVoidPtr)(hwnd, msg, wParam, lParam);
然而......这不是动态的(因为args是在里面定义的)。我想用实际的Trigger (...)
方法中的参数来调用它。我知道我必须和va_args
类似,但即使如此,我似乎也不可能从中做出一个真实的概念证明吗?
甚至可以拥有一个完全动态的EventHandler,其中Trigger函数接受每个参数并简单地用它调用适当的函数?
现在我的解决方案是为我拥有的每个事件创建一个事件类,并在Trigger函数中定义实际参数,例如:
void WndProcEvent::Trigger(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
...但是因为我会有很多事件,即使我使用宏来创建它们,这对我来说是不可接受的(调试btw很糟糕......)
感谢您的阅读。
答案 0 :(得分:2)
我建议为每个定义关联自定义事件签名的事件类型创建一个简单对象,并包含从通用'(HWND,UINT,WPARAM,LPARAM)'格式到自定义签名的映射代码。 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;
我实际上为一个项目做了类似的事情,但是使用'sigc ++' 因为我对使用MFC / ATL不满意(哎呀!)。这主要是因为它是一个宏观汤!。
希望有所帮助。