【问题标题】:Dynamic Trigger Function动态触发功能
【发布时间】:2015-03-23 20:56:46
【问题描述】:

我目前正在尝试制作一个完全动态的 EventHandler 几个小时。但是,无论我尝试什么似乎都行不通。

下面是 EventHandler 应该做什么的简图:

EventHandler<EventName>::Add (void* listener);

EventHandler<EventName>::Trigger(...);

通过Add 方法添加的每个事件都被安全地保存在本地 std::vector 中。到目前为止一切顺利,直到此为止,一切都很好而且很清楚。我们创建一个模板和简单的触发函数。

然而,现在问题来了,Trigger 函数。为了更好地理解,这个 EventHandler 触发了从 Native C++ Code 到 CLI Code 的函数。

要触发 CLI 功能,我需要:

  • void* 地址(正常)
  • 参数(不正确)

在 Trigger() 函数内部,我想有这样的代码:

//WndProc Example Event
reinterpret_cast<void(__stdcall *)(HWND, UINT, WPARAM, LPARAM)>(clrVoidPtr)(hwnd, msg, wParam, lParam);

但是...这不是动态的(因为 args 是在内部定义的)。我想用实际 Trigger (...) 方法的参数调用它。我知道我必须使用 va_args 和类似的东西,但即便如此,我似乎也无法从中做出实际的概念证明?

是否有可能拥有一个完全动态的 EventHandler,其中 Trigger 函数接受每个参数并简单地使用它调用适当的函数?

现在我的解决方案是为我拥有的每个事件创建一个事件类,并在触发器函数中定义实际参数,例如:

void WndProcEvent::Trigger(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

...但是由于我将有很多事件,即使我使用宏创建它们也是不可接受的(顺便说一句,调试起来很糟糕...)

感谢您的阅读。

【问题讨论】:

    标签: c++ eventhandler


    【解决方案1】:

    我建议为每个事件类型创建一个简单的对象,该对象定义关联的自定义事件签名并包含用于从通用“(HWND,UINT,WPARAM,LPARAM)”格式映射到自定义签名的代码。例如:

    // 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 不满意(糟糕!)。那主要是因为它是宏汤!。

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 2018-01-19
      • 2021-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多