返回介绍

20.2 更改事件处理机制

发布于 2025-03-08 15:27:59 字数 1711 浏览 0 评论 0 收藏 0

在通常情况下,wxWidgets 将事件发送到产生这个事件的窗口(或者别的事件处理器).对于命令事件,还将以特定的方式遍历整个窗口继承树(详情参考附录 H,"wxWidgets 的事件处理机制") 来处理.举例来说,如果你点击工具条上的任何一个工具按钮,产生的事件将首先发送给这个工具按钮的事件表处理,然后是包含这个工具条的 frame 窗口的时间表,然后是整个应用程序类的事件表.通常情况下,这样的作法是满足要求的,但是如果有时候,你希望超过一个控件都可以使用工具条上的拷贝命令的时候,就会有一些问题,比如,你的主程序中有一个主窗口(假设是一个绘画程序) 和一个文本编辑框,这个文本编辑框可能永远也无法处理工具条上的拷贝命令,因为这个命令并不会调用这个编辑框的事件处理函数.在这种情况下,你可能希望事件能够首先交给当前处于活动状态的控件处理,然后再按照正常的处理顺序执行.这样,如果当前的活动控件内部实现了针对这个事件的处理函数(比如 wxID_COPY),那么这个函数就将被调用,否则就在窗口继承树中向上查找对应的处理函数,直到它找到一个这样的函数.这种命令总是针对当前活动控件的作法会更符合用户的使用习惯。

我们可以通过下面的方法重载主窗口的 ProcessEvent 函数,以便拦截命令事件并将其首先交给当前活动的控件处理,如下所示:

bool MainFrame::ProcessEvent(wxEvent& event)
{
    static wxEvent* s_lastEvent = NULL;
    // 避免死循环
    if (& event == s_lastEvent)
        return false;
    if (event.IsCommandEvent() &&
       !event.IsKindOf(CLASSINFO(wxChildFocusEvent)) &&
       !event.IsKindOf(CLASSINFO(wxContextMenuEvent)))
    {
        s_lastEvent = & event;
        wxControl *focusWin = wxDynamicCast(FindFocus(), wxControl);
        bool success = false;
        if (focusWin)
            success = focusWin->GetEventHandler()
                                ->ProcessEvent(event);
        if (!success)
            success = wxFrame::ProcessEvent(event);
        s_lastEvent = NULL;
        return success;
    }
    else
    {
        return wxFrame::ProcessEvent(event);
    }
}

就目前的情况来看,这种作法在那些当前活动控件可能为一个 wxTextCtrl 控件的时候显的更有用(在大多数平台上), wxWidgets 为这种控件实现了多种内置的命令,包括 wxID_COPY, wxID_CUT, wxID_PASTE, wxID_UNDO 和 wxID_REDO,还实现了一些默认的用户界面行为.不过,你也可以给任意的控件通过实现其派生类的方式增加这些默认的事件处理函数,比如说 wxStyledTextCtrl 控件(参考 examples/chap20/pipedprocess 中的例子,这个例子为 wxStyledTextCtrl 控件提供了这种增强处理)。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文