March 8, 2017
by Tamás Móréh
modified at November 27, 2017

How to use Context Menus on DG dialogs

Sometimes we need context menus on our add-on’s panels. Since the DG::PanelObserver class has the PanelContextMenuRequested event handler, it is pretty easy.

In the localised grc you have a strings resource:

'STR#' RESID "Context Menu strings" {
    /* [  1] */     "Say hello!"
    /* [  2] */     "Close"
}

In your panel class (Dialog or Palette) declaration you have the following fields:

class MyDialog : public DG::ModalDialog,
    public DG::PanelObserver
{
protected:
    enum MenuStrings {
        HelloId     = 1,
        CloseId     = 2
    };

    DG::Menu          menu;
    DG::Command       helloCommand;
    DG::Command       closeCommand;
    DG::CommandTable  commandTable;

    virtual void      PanelContextMenuRequested (const DG::PanelContextMenuEvent& ev, bool* needHelp, bool* processed) override;
public:
    MyDialog ();
    virtual ~MyDialog ();
};

The implementation:

MyDialog::MyDialog () :
    DG::ModalDialog (ACAPI_GetOwnResModule(), RESID, ACAPI_GetOwnResModule()),
    /* other initializers */
    menu            ("-"),
    helloCommand    (HelloId, MDID_DEV, MDID_ADDON),
    closeCommand    (CloseId, MDID_DEV, MDID_ADDON)
{
    Attach (*this);

    menu.AddMenuItem (DG::MenuSimpleItem (helloCommand));
    menu.AddMenuItem (DG::MenuSeparatorItem ());
    menu.AddMenuItem (DG::MenuSimpleItem (closeCommand));

    GS::UniString buffer;
    RSGetIndString (&buffer, RESID, HelloId, ACAPI_GetOwnResModule ());
    commandTable.Add (helloCommand, new DG::CommandDescriptor (helloCommand, buffer));
    RSGetIndString (&buffer, RESID, CloseId, ACAPI_GetOwnResModule ());
    commandTable.Add (closeCommand, new DG::CommandDescriptor (closeCommand, buffer));
}

MyDialog::~MyDialog ()
{
    for (auto it = commandTable.EnumerateValues (); it != nullptr; ++it) {
        delete *it;
    }
}

void MyDialog::PanelContextMenuRequested (const DG::PanelContextMenuEvent& ev, bool* needHelp, bool* processed)
{
    *needHelp = false;
    DG::ContextMenu contextMenu ("-", &menu);
    contextMenu.SetEnabledCommands (commandTable);
    DG::CommandEvent* commandEvent = contextMenu.Display (ev.GetPosition ());

    if (commandEvent != nullptr) {
        ULong cmd = commandEvent->GetCommand ().GetCommandId ();
        switch (cmd) {
        case HelloId:
            ACAPI_WriteReport ("Hello from Context Menu", true);
            break;
        case CloseId:
            PostCloseRequest (Cancel);
            break;
        default:
            break;
        }
        *processed = true;
        delete commandEvent;
    }
}