Page 1 of 1

wxTreeCtrl context menu

Posted: Sat Mar 16, 2019 7:15 am
by sigipa
Hello All,

I'm having some trouble getting a context menu event to fire with the wxTreeCtrl. I'm actually using a wxGenericDirCtrl and getting the tree from it. I've included the relevant code below. I'm new to wxWidgets, so perhaps I'm doing something stupid. Any advice would be much appreciated.

Code: Select all

   
   
      fileTree = new wxGenericDirCtrl(this, ID_FileTree, wxDirDialogDefaultFolderStr,
      wxDefaultPosition,
      wxSize(200, 150),
      wxDIRCTRL_3D_INTERNAL | wxSUNKEN_BORDER,
      wxEmptyString, 
      0,
      "test");

    Connect(ID_FileTree, wxEVT_DIRCTRL_SELECTIONCHANGED, wxCommandEventHandler(MainFrame::OnFolderSelect));
    Connect(ID_FileTree, wxEVT_DIRCTRL_FILEACTIVATED, wxCommandEventHandler(MainFrame::OnFileSelect));
    wxTreeCtrl  *tree = fileTree->GetTreeCtrl();
    tree->Connect(ID_Tree, wxEVT_TREE_ITEM_RIGHT_CLICK, wxTreeEventHandler(MainFrame::OnTreeItemMenu));
    tree->Connect(ID_Tree, wxEVT_TREE_ITEM_MENU, wxTreeEventHandler(MainFrame::OnTreeItemMenu));
    tree->Connect(ID_Tree, wxEVT_CONTEXT_MENU, wxTreeEventHandler(MainFrame::OnTreeItemMenu));
    ...
    
    
  void MainFrame::OnTreeItemMenu(wxTreeEvent& evt)
  {
    wxTreeCtrl *tree = fileTree->GetTreeCtrl();


    messages->AppendText("OnTreeItemMenu\n");

    // This event handler creates a new menu and displays
    // it as a popup menu with the wxWindow::PopupMenu function

    wxMenu menu;
    menu.Append(ID_TreePermissions, "Show node text");

    // We need to pass some data (the text of the node) to
    // the menu event handler. We create a class that holds
    // the needed data and use the Connect function to
    // associate our event handler with the menu.
    UserData* userData = new UserData();
    userData->data = tree->GetItemText(evt.GetItem());
    menu.Connect(ID_TreePermissions, wxEVT_MENU,
      (wxObjectEventFunction)&MainFrame::OnMenuItem,
      userData, this);

    // Display the menu as a popup menu
    PopupMenu(&menu);

    evt.Skip();
  }
     
    
Thanks,
-S

Re: wxTreeCtrl context menu

Posted: Sat Mar 16, 2019 8:44 am
by sigipa
Hello All,

I figured this out. The tree used by the wxGenericDirCtrl did not have an id set. setting the tree id solved the issue.

Thanks,
-S

Re: wxTreeCtrl context menu

Posted: Sat Mar 16, 2019 9:28 am
by sigipa
Hello All,

Okay. There was one more little wrinkle. When I set the tree id, it broke the wxGenericDirCtrl event handling. Apparently, the wxGenericDirCtrl sets an id for the tree itself. The correct thing to do was to just call GetId() on the tree and use that to connect the handler. I've included the code snippet below, to help anyone else that may run into this.



Code: Select all

 wxTreeCtrl  *tree = fileTree->GetTreeCtrl();
  Connect(tree->GetId(), wxEVT_TREE_ITEM_RIGHT_CLICK, wxTreeEventHandler(MainFrame::OnTreeItemMenu));
  Connect(tree->GetId() wxEVT_TREE_ITEM_MENU, wxTreeEventHandler(MainFrame::OnTreeItemMenu));
  Connect(tree->GetId(), wxEVT_CONTEXT_MENU, wxTreeEventHandler(MainFrame::OnTreeItemMenu));
Thanks,
-S

Re: wxTreeCtrl context menu

Posted: Sat Mar 16, 2019 2:58 pm
by ONEEYEMAN
Hi,
2 things:

1. In the new code it is strongly recommended to use Bind() instead of Connect(). Connect() should be used only for backward compatibility.
2. You don't need to assign Id to anything if you are not using event table.

Code: Select all

m_treeCtrl->Bind( wxEVT_TREE_ITEM_RIGHT_CLICK, &MainFrame::OnTreeItemMenu, this );
if this code is inside MainFrame class method.

As you can see it is much less typing and Bind() is more error prone as it can give you an error during compilation time.

Thank you.