Dynamically disabling wxMenuItem when on item has been clicked

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
ChronoGraff
Knows some wx things
Knows some wx things
Posts: 42
Joined: Wed Apr 22, 2015 5:42 pm

Dynamically disabling wxMenuItem when on item has been clicked

Post by ChronoGraff »

My question is how do I disable a menu item when I click a certain menu item and vice versa?

When CreatePopupMenu() is called each wxMenuItem is added to the vector, however, it seems that CreatePopupMenu() is called each time I click on the taskbar icon. This is giving me the illusion that menu_item->Enable(false) is not working but what seems to be happening is the actual wxMenu is simply being rebuilt each time I click the taskbar.

Is there a way to disable a menu item dynamically and have it remain disabled until a process or another item is clicked?

Again many thanks.

Code: Select all

std::vector<wxMenuItem *> menu_items;

Code: Select all

wxMenu *
SystemTray::CreatePopupMenu()
{
    menu_items.clear();
    menu = new wxMenu;

    scheduled = menu->Append(PU_SCHED_TIMEOUT, _("&Scheduled break log"));
    menu_items.push_back(scheduled);

    notify = menu->Append(PU_NOTIFY, _("N&otify brief timeout"));
    menu_items.push_back(notify);

    requested = menu->Append(PU_REQUEST, _("&Request time away"));
    menu_items.push_back(requested);
    
    menu->AppendSeparator();

    resume = menu->Append(PU_RESUME, _("&Resume work"));
    resume->Enable(false);

    menu->AppendSeparator();
    menu->Append(PU_DAILY_TASKS, _("&View today's tasks"));
    menu->Append(PU_SCAN_WORKSTATION, _("&Scan for illegal applications"));

    /* OSX has built-in quit menu for the dock menu, but not for the status item */
    #if defined (__WXOSX__)
    if (OSXIsStatusItem())
    #endif
    {
        menu->AppendSeparator();
        menu->Append(PU_EXIT, _("E&xit"));
    }

    return menu;
}
When I click the menu item, naturally I pass the address of the pointer to the wxMenuItem.

Code: Select all

Bind(wxEVT_MENU, [=](wxCommandEvent & e) {
        show_scheduled_timeout();
        disable_timeout_menu_items(*scheduled);
    }, PU_SCHED_TIMEOUT);
I loop over each item, and check the pass address with the addresses stored in the vector.

Code: Select all

void
SystemTray::disable_timeout_menu_items(wxMenuItem & current_item)
{
    for (auto item : menu_items)
    {
        std::cout << &current_item << " " << &(*item) << std::endl;

        if (&current_item != &(*item))
        {
            std::cout << item->IsEnabled() << std::endl;
            // if (item->IsEnabled())
            // {
            // item->Enable(false);
            // }
        }
    }
}
Terminal output (1 = enabled, there are 3 menu items), the address on the left is that which is current_item

Code: Select all

0x7ff06b64de40 0x7ff06b548630
1
0x7ff06b64de40 0x7ff06b64de40
0x7ff06b64de40 0x7ff06b60f0c0
1
coderrc
Earned some good credits
Earned some good credits
Posts: 141
Joined: Tue Nov 01, 2016 2:46 pm

Re: Dynamically disabling wxMenuItem when on item has been clicked

Post by coderrc »

instead of menuItem->enable try menu->enable
eg

Code: Select all

resume = menu->Append(PU_RESUME, _("&Resume work"));
menu->Enable(PU_RESUME, false);
Edit:
Never mind, I think I misunderstood the question.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Dynamically disabling wxMenuItem when on item has been clicked

Post by doublemax »

If you want to disable a menu item in a taskbaricon menu, you need to do it while you create it in CreatePopupMenu(). The menu will be deleted when closed.
Use the source, Luke!
ChronoGraff
Knows some wx things
Knows some wx things
Posts: 42
Joined: Wed Apr 22, 2015 5:42 pm

Re: Dynamically disabling wxMenuItem when on item has been clicked

Post by ChronoGraff »

doublemax wrote:If you want to disable a menu item in a taskbaricon menu, you need to do it while you create it in CreatePopupMenu(). The menu will be deleted when closed.
Interesting answer, take this scenario for example; I have 3 related items (timeout request wxframe's), when one is open I can open the menu however the other two items would be disabled.

Pardon my ignorance but I am a little lost with how to work this one out, I tried a few things since you commented but all of the "solutions" are binned as they don't work.

many thanks.
Post Reply