有没有办法使用普通的 ASCII 字符(如逗号)作为 wxWidgets 菜单加速器?

发布于 2024-12-14 11:21:19 字数 267 浏览 0 评论 0原文

我想要一些菜单项来显示普通键的加速器,例如空格键或逗号键,但我希望 wxWidgets 自己制作这些加速器(因为这样它们就不能在程序中的任何地方使用过,包括编辑框之类的地方)。

不幸的是,wxWidgets 坚持始终将其在该列中识别的任何内容放入其控制下的加速器中,并简单地删除其无法识别的任何内容。

我正在寻找某种方法来将任意文本放入加速器列(我认为不存在,我查看了源代码),或者获取用于菜单的加速器表,以便我可以自己修改一下(还没找到)。有人能指出我正确的方向吗?

I want a few menu entries that show accelerators that are normal keys, like the space-bar or comma key, but I don't want wxWidgets to make those accelerators itself (because then they can't be used anywhere in the program, including in things like edit boxes).

Unfortunately, wxWidgets insists on always making anything it recognizes in that column into an accelerator under its control, and simply erases anything it doesn't recognize.

I'm looking for some way to either put arbitrary text into the accelerator column (which I don't think exists, I've looked at the source code), or get 'hold of the accelerator table used for the menus so I can modify it myself (haven't found it yet). Can anyone point me in the right direction?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ζ澈沫 2024-12-21 11:21:19

你可以尝试wxKeyBinder。它允许您将热键绑定到命令(通常是菜单条目),轻松保存/加载/添加/删除/修改......

You can try wxKeyBinder. It allows you to bind hotkeys to commands (usually menu entries), save/load/add/remove/modify ... them easily

痕至 2024-12-21 11:21:19

我找不到直接访问菜单加速键的方法,但修改加速菜单文本也可以。这是我想出的代码:

在头文件中:

class accel_t {
    public:
    // If idcount == -1, idlist must be null or terminated with a -1 entry.
    accel_t(): mMenu(0) { }
    accel_t(wxMenuBar *m, int *idlist = 0, int idcount = -1);
    void reset(wxMenuBar *m, int *idlist = 0, int idcount = -1);
    void restore() const;
    void remove() const;

    private: //
    struct accelitem_t {
        accelitem_t(int _id, wxAcceleratorEntry _key): id(_id), hotkey(_key) { }
        int id;
        wxAcceleratorEntry hotkey;
    };
    typedef std::vector<accelitem_t> data_t;

    void noteProblemMenuItems(wxMenu *m);
    static bool isProblemAccelerator(wxAcceleratorEntry *a);

    wxMenuBar *mMenu;
    data_t mData;
};

在 cpp 文件中:

accel_t::accel_t(wxMenuBar *m, int *idlist, int idcount) {
    reset(m, idlist, idcount);
}

void accel_t::reset(wxMenuBar *m, int *idlist, int idcount) {
    mMenu = m;
    mData.clear();
    if (idlist == 0) {
        for (int i = 0, ie = m->GetMenuCount(); i != ie; ++i)
            noteProblemMenuItems(m->GetMenu(i));
    } else {
        if (idcount < 0) {
            int *i = idlist;
            while (*i != -1) ++i;
            idcount = (i - idlist);
        }

        for (int *i = idlist, *ie = i + idcount; i != ie; ++i) {
            wxMenuItem *item = mMenu->FindItem(*i);
            if (item) {
                wxAcceleratorEntry *a = item->GetAccel();
                if (a != 0) mData.push_back(accelitem_t(*i, *a));
            }
        }
    }
}

bool accel_t::isProblemAccelerator(wxAcceleratorEntry *a) {
    if (a == 0) return false;
    int flags = a->GetFlags(), keycode = a->GetKeyCode();

    // Normal ASCII characters, when used with no modifier or Shift-only, would
    // interfere with editing.
    if ((flags == wxACCEL_NORMAL || flags == wxACCEL_SHIFT) &&
        (keycode >= 32 && keycode < 127)) return true;

    // Certain other values, when used as normal accelerators, could cause
    // problems too.
    if (flags == wxACCEL_NORMAL) {
        if (keycode == WXK_RETURN ||
            keycode == WXK_DELETE ||
            keycode == WXK_BACK) return true;
    }

    return false;
}

void accel_t::noteProblemMenuItems(wxMenu *m) {
    // Problem menu items have hotkeys that are ASCII characters with normal or
    // shift-only modifiers.
    for (size_t i = 0, ie = m->GetMenuItemCount(); i != ie; ++i) {
        wxMenuItem *item = m->FindItemByPosition(i);
        if (item->IsSubMenu())
            noteProblemMenuItems(item->GetSubMenu());
        else {
            wxAcceleratorEntry *a = item->GetAccel();
            if (isProblemAccelerator(a))
                mData.push_back(accelitem_t(item->GetId(), *a));
        }
    }
}

void accel_t::restore() const {
    if (mMenu == 0) return;
    for (data_t::const_iterator i = mData.begin(), ie = mData.end(); i != ie;
        ++i)
    {
        wxMenuItem *item = mMenu->FindItem(i->id);
        if (item) {
            wxString text = item->GetItemLabel().BeforeFirst(wxT('\t'));
            wxString hotkey = i->hotkey.ToString();
            if (hotkey.empty()) {
                // The wxWidgets authors apparently don't expect ASCII
                // characters to be used for accelerators, because
                // wxAcceleratorEntry::ToString just returns an empty string for
                // them. This code deals with that.
                int flags = i->hotkey.GetFlags(), key = i->hotkey.GetKeyCode();
                if (flags == wxACCEL_SHIFT) hotkey = wx("Shift-") + wxChar(key);
                else hotkey = wxChar(key);
            }
            item->SetItemLabel(text + '\t' + hotkey);
        }
    }
}

void accel_t::remove() const {
    if (mMenu == 0) return;
    for (data_t::const_iterator i = mData.begin(), ie = mData.end(); i != ie;
        ++i)
    {
        wxMenuItem *item = mMenu->FindItem(i->id);
        if (item) {
            wxString text = item->GetItemLabel().BeforeFirst(wxT('\t'));
            item->SetItemLabel(text);
        }
    }
}

最简单的使用方法是像平常一样创建菜单栏,并放置所有加速键(包括有问题的加速键),然后创建一个其中的 accel_t 项目如下所示:

// mProblemAccelerators is an accel_t item in the private part of my frame class.
// This code is in the frame class's constructor.
wxMenuBar *menubar = _createMenuBar();
SetMenuBar(menubar);
mProblemAccelerators.reset(menubar);

它将识别并记录造成问题的加速键。最后,根据需要调用 removerestore 函数,以删除或恢复有问题的加速键。每当我打开需要进行标准编辑的窗口时,我都会通过传递到框架的消息来调用它们。

I couldn't find a way to access the menu's accelerator keys directly, but modifying the accelerator menu text works just as well. Here's the code I came up with:

In a header file:

class accel_t {
    public:
    // If idcount == -1, idlist must be null or terminated with a -1 entry.
    accel_t(): mMenu(0) { }
    accel_t(wxMenuBar *m, int *idlist = 0, int idcount = -1);
    void reset(wxMenuBar *m, int *idlist = 0, int idcount = -1);
    void restore() const;
    void remove() const;

    private: //
    struct accelitem_t {
        accelitem_t(int _id, wxAcceleratorEntry _key): id(_id), hotkey(_key) { }
        int id;
        wxAcceleratorEntry hotkey;
    };
    typedef std::vector<accelitem_t> data_t;

    void noteProblemMenuItems(wxMenu *m);
    static bool isProblemAccelerator(wxAcceleratorEntry *a);

    wxMenuBar *mMenu;
    data_t mData;
};

In a cpp file:

accel_t::accel_t(wxMenuBar *m, int *idlist, int idcount) {
    reset(m, idlist, idcount);
}

void accel_t::reset(wxMenuBar *m, int *idlist, int idcount) {
    mMenu = m;
    mData.clear();
    if (idlist == 0) {
        for (int i = 0, ie = m->GetMenuCount(); i != ie; ++i)
            noteProblemMenuItems(m->GetMenu(i));
    } else {
        if (idcount < 0) {
            int *i = idlist;
            while (*i != -1) ++i;
            idcount = (i - idlist);
        }

        for (int *i = idlist, *ie = i + idcount; i != ie; ++i) {
            wxMenuItem *item = mMenu->FindItem(*i);
            if (item) {
                wxAcceleratorEntry *a = item->GetAccel();
                if (a != 0) mData.push_back(accelitem_t(*i, *a));
            }
        }
    }
}

bool accel_t::isProblemAccelerator(wxAcceleratorEntry *a) {
    if (a == 0) return false;
    int flags = a->GetFlags(), keycode = a->GetKeyCode();

    // Normal ASCII characters, when used with no modifier or Shift-only, would
    // interfere with editing.
    if ((flags == wxACCEL_NORMAL || flags == wxACCEL_SHIFT) &&
        (keycode >= 32 && keycode < 127)) return true;

    // Certain other values, when used as normal accelerators, could cause
    // problems too.
    if (flags == wxACCEL_NORMAL) {
        if (keycode == WXK_RETURN ||
            keycode == WXK_DELETE ||
            keycode == WXK_BACK) return true;
    }

    return false;
}

void accel_t::noteProblemMenuItems(wxMenu *m) {
    // Problem menu items have hotkeys that are ASCII characters with normal or
    // shift-only modifiers.
    for (size_t i = 0, ie = m->GetMenuItemCount(); i != ie; ++i) {
        wxMenuItem *item = m->FindItemByPosition(i);
        if (item->IsSubMenu())
            noteProblemMenuItems(item->GetSubMenu());
        else {
            wxAcceleratorEntry *a = item->GetAccel();
            if (isProblemAccelerator(a))
                mData.push_back(accelitem_t(item->GetId(), *a));
        }
    }
}

void accel_t::restore() const {
    if (mMenu == 0) return;
    for (data_t::const_iterator i = mData.begin(), ie = mData.end(); i != ie;
        ++i)
    {
        wxMenuItem *item = mMenu->FindItem(i->id);
        if (item) {
            wxString text = item->GetItemLabel().BeforeFirst(wxT('\t'));
            wxString hotkey = i->hotkey.ToString();
            if (hotkey.empty()) {
                // The wxWidgets authors apparently don't expect ASCII
                // characters to be used for accelerators, because
                // wxAcceleratorEntry::ToString just returns an empty string for
                // them. This code deals with that.
                int flags = i->hotkey.GetFlags(), key = i->hotkey.GetKeyCode();
                if (flags == wxACCEL_SHIFT) hotkey = wx("Shift-") + wxChar(key);
                else hotkey = wxChar(key);
            }
            item->SetItemLabel(text + '\t' + hotkey);
        }
    }
}

void accel_t::remove() const {
    if (mMenu == 0) return;
    for (data_t::const_iterator i = mData.begin(), ie = mData.end(); i != ie;
        ++i)
    {
        wxMenuItem *item = mMenu->FindItem(i->id);
        if (item) {
            wxString text = item->GetItemLabel().BeforeFirst(wxT('\t'));
            item->SetItemLabel(text);
        }
    }
}

The easiest way to use it is to create your menu-bar as normal, with all accelerator keys (including the problematic ones) in place, then create an accel_t item from it something like this:

// mProblemAccelerators is an accel_t item in the private part of my frame class.
// This code is in the frame class's constructor.
wxMenuBar *menubar = _createMenuBar();
SetMenuBar(menubar);
mProblemAccelerators.reset(menubar);

It will identify and record the accelerator keys that pose problems. Finally, call the remove and restore functions as needed, to remove or restore the problematic accelerator keys. I'm calling them via messages passed to the frame whenever I open a window that needs to do standard editing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文