Assigning keyboard shortcuts to controls.

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.
User avatar
doublemax
Moderator
Moderator
Posts: 16022
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Assigning keyboard shortcuts to controls.

Post by doublemax » Wed May 12, 2021 7:48 pm

Yes, the events only inform you about what happened, i.e. if a checkbox was toggled, you get the event telling you about it. But it doesn't work in the other direction, just sending the event won't change the state of the checkbox.
Use the source, Luke!

apoorv569
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 207
Joined: Tue Oct 20, 2020 3:35 pm

Re: Assigning keyboard shortcuts to controls.

Post by apoorv569 » Thu May 13, 2021 4:44 am

doublemax wrote:
Wed May 12, 2021 6:13 pm
No. You can't just cast a wxKeyEvent to a wxCommandEvent.

E.g. to emulate a button click event:

Code: Select all

wxCommandEvent evt(wxEVT_BUTTON);

// this two are not always needed, depends on your event binding and 
// whether the event handlers use these values
evt.SetId( /* control id */ );
evt.SetEventObject( /* control pointer */ );

m_Frame->AddPendingEvent(evt);
I made the App class friend in MainFrame, in MainFrame.hpp file I have this,

Code: Select all

        friend class App;
Then in the App class I made these changes, it seems to work, wxButton, wxToggleButton and wxCheckBox all seem to work. The spacebar does not work when focus is on wxDataViewListCtrl, however if autoplay (wxCheckBox) is on, then spacebar works, maybe for a different reason.

Code: Select all

int App::FilterEvent(wxEvent& event)
{
    if(event.GetEventType() == wxEVT_KEY_DOWN /* || event.GetEventType() == wxEVT_KEY_UP */)
    {
        wxWindow* focusedWindow = wxWindow::FindFocus();
        if(focusedWindow != NULL)
        {
            const wxString& className = focusedWindow->GetClassInfo()->GetClassName();

            wxLogDebug("Focused window: %s", className);

            // if SearchCtrl has focus, let all keys through
            if(className == wxT("wxSearchCtrl"))
            {
                wxLogDebug("SearchCtrl focused skipping key filtering");
                return wxEventFilter::Event_Skip;
            }
            else if(className == wxT("wxTreeCtrl"))
            {
                wxLogDebug("TreeCtrl focused skipping key filtering");
                return wxEventFilter::Event_Skip;
            }
        }

        wxKeyEvent* keyEvent = wxDynamicCast(&event, wxKeyEvent);

        wxCommandEvent playEvent(wxEVT_BUTTON);
        wxCommandEvent muteEvent(wxEVT_TOGGLEBUTTON);
        wxCommandEvent loopEvent(wxEVT_TOGGLEBUTTON);
        wxCommandEvent stopEvent(wxEVT_BUTTON);
        wxCommandEvent autoplayEvent(wxEVT_CHECKBOX);
        wxCommandEvent settingsEvent(wxEVT_BUTTON);

        // Setting ID and EventObject to their handlers
        playEvent.SetId(BC_Play);
        playEvent.SetEventObject(m_Frame->m_PlayButton);

        muteEvent.SetId(BC_Mute);
        muteEvent.SetEventObject(m_Frame->m_MuteButton);

        loopEvent.SetId(BC_Loop);
        loopEvent.SetEventObject(m_Frame->m_LoopButton);

        stopEvent.SetId(BC_Stop);
        stopEvent.SetEventObject(m_Frame->m_StopButton);

        autoplayEvent.SetId(BC_Autoplay);
        autoplayEvent.SetEventObject(m_Frame->m_AutoPlayCheck);

        playEvent.SetId(BC_Settings);
        playEvent.SetEventObject(m_Frame->m_SettingsButton);

        // Check for key presses
        if(keyEvent != NULL)
        {
            switch (keyEvent->GetKeyCode())
            {
                case WXK_SPACE:
                    wxLogDebug("Space pressed");
                    return wxEventFilter::Event_Processed;
                    break;
                case 'A':
                    if (m_Frame->m_AutoPlayCheck->GetValue())
                        m_Frame->m_AutoPlayCheck->SetValue(false);
                    else
                        m_Frame->m_AutoPlayCheck->SetValue(true);
                    m_Frame->OnCheckAutoplay(autoplayEvent);
                    wxLogDebug("A pressed");
                    return wxEventFilter::Event_Processed;
                    break;
                case 'S':
                    m_Frame->OnClickStop(stopEvent);
                    wxLogDebug("S pressed");
                    return wxEventFilter::Event_Processed;
                    break;
                case 'P':
                    m_Frame->OnClickPlay(playEvent);
                    wxLogDebug("P pressed");
                    return wxEventFilter::Event_Processed;
                    break;
                case 'O':
                    m_Frame->OnClickSettings(settingsEvent);
                    wxLogDebug("O pressed");
                    return wxEventFilter::Event_Processed;
                    break;
                case 'L':
                    if (m_Frame->m_LoopButton->GetValue())
                        m_Frame->m_LoopButton->SetValue(false);
                    else
                        m_Frame->m_LoopButton->SetValue(true);
                    m_Frame->OnClickLoop(loopEvent);
                    wxLogDebug("L pressed");
                    return wxEventFilter::Event_Processed;
                    break;
                case 'M':
                    if (m_Frame->m_MuteButton->GetValue())
                        m_Frame->m_MuteButton->SetValue(false);
                    else
                        m_Frame->m_MuteButton->SetValue(true);
                    m_Frame->OnClickMute(muteEvent);
                    wxLogDebug("M pressed");
                    return wxEventFilter::Event_Processed;
                    break;
            }
        }
    }

    return -1;
}
I would really like to assign the "P" key to "Spacebar" as most applications dealing with sound/music files, like a music player DAW or something uses spacebar to play/pause, but it won't work here (unless the autoplay is checked on, though I haven't binded spacebar to anything, which is weird). But anyways, is this correct, can it cause me problems later, or should I not do it?

User avatar
doublemax
Moderator
Moderator
Posts: 16022
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Assigning keyboard shortcuts to controls.

Post by doublemax » Thu May 13, 2021 6:27 am

Code: Select all

        wxCommandEvent playEvent(wxEVT_BUTTON);
        wxCommandEvent muteEvent(wxEVT_TOGGLEBUTTON);
        wxCommandEvent loopEvent(wxEVT_TOGGLEBUTTON);
        wxCommandEvent stopEvent(wxEVT_BUTTON);
        wxCommandEvent autoplayEvent(wxEVT_CHECKBOX);
        wxCommandEvent settingsEvent(wxEVT_BUTTON);
I wouldn't create all wxCommandEvents at the same time, i'd move them into their respective switch case, but in principle this looks ok.
Use the source, Luke!

apoorv569
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 207
Joined: Tue Oct 20, 2020 3:35 pm

Re: Assigning keyboard shortcuts to controls.

Post by apoorv569 » Thu May 13, 2021 7:13 am

doublemax wrote:
Thu May 13, 2021 6:27 am

Code: Select all

        wxCommandEvent playEvent(wxEVT_BUTTON);
        wxCommandEvent muteEvent(wxEVT_TOGGLEBUTTON);
        wxCommandEvent loopEvent(wxEVT_TOGGLEBUTTON);
        wxCommandEvent stopEvent(wxEVT_BUTTON);
        wxCommandEvent autoplayEvent(wxEVT_CHECKBOX);
        wxCommandEvent settingsEvent(wxEVT_BUTTON);
I wouldn't create all wxCommandEvents at the same time, i'd move them into their respective switch case, but in principle this looks ok.
So it is safe to assume this will work okay, and will not cause any problems?

User avatar
doublemax
Moderator
Moderator
Posts: 16022
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Assigning keyboard shortcuts to controls.

Post by doublemax » Thu May 13, 2021 7:38 am

I can't make any promises, this is still very hackish after all, but i think it should work.
Use the source, Luke!

Post Reply