Page 1 of 1

Keyboard Shortcuts without a Menu Complete with wxWidgets example (applicable to other languages/toolkit Rate Topic: ***** 1 Votes

#1 gabehabe  Icon User is offline

  • GabehabeSwamp
  • member icon

Reputation: 919
  • View blog
  • Posts: 10,726
  • Joined: 06-February 08

Posted 11 September 2009 - 02:26 PM

Been a while since I wrote one of these. :)

Okay, so... creating keyboard shortcuts in a wxWidgets application, without adding billions of menu items. It's actually a very simple process, which can be applied to most, if not all, languages and UI developments. All we really need to do is design keyboard events for our main application, the main thing being checking for modifier keys. (Such as Ctrl, Alt, etc)

This tutorial is gonna be fairly short since it's quite a simple concept. But it's nice to know, and seems to be quite a common topic in all languages and UI toolkits.

But in this tutorial, my example is going to be wxWidgets based. If you're not familiar with wxWidgets, you might want to read the short series of tutorials I wrote to get acquainted with the toolkit:
Part I - setting up wxWidgets
Part II - familiarising yourself with wxWidgets
Part III - create a notepad application in wxWidgets (events tutorial)

So to start off, I'm gonna throw a load of code under your nose. It's only the basic layout for a simple application:
// basic setup code, I'll fly past this. If you're not familiar, check out this tutorial:
// [url="http://www.dreamincode.net/forums/showtopic66948.htm"]http://www.dreamincode.net/forums/showtopic66948.htm[/url]

#include <wx/wx.h>

class app : public wxApp {
    public:
        virtual bool OnInit();
    private:
        wxTextCtrl* txt;
        wxCheckBox* chk;

        void key_shortcut(wxKeyEvent&);
        DECLARE_EVENT_TABLE()
};

// if you're not familiar with events, check out this tutorial:
// [url="http://www.dreamincode.net/forums/showtopic67058.htm"]http://www.dreamincode.net/forums/showtopic67058.htm[/url]

BEGIN_EVENT_TABLE(app, wxApp)
    EVT_KEY_DOWN(app::key_shortcut)
END_EVENT_TABLE()

IMPLEMENT_APP(app)

bool app::OnInit() {
    wxFrame* win = new wxFrame(NULL, wxID_ANY, wxT("Keyboard Shortcuts, No Menu!"), wxDefaultPosition, wxSize(250, 125));
    win->Show(true);

    this->txt = new wxTextCtrl(win, wxID_ANY, wxT("Press Ctrl+G to append text to me"), wxPoint(0,0), wxSize(250, 50), wxTE_MULTILINE);
    this->chk = new wxCheckBox(win, wxID_ANY, wxT("Press Ctrl+Left to toggle me."), wxPoint(0, 55), wxDefaultSize);

    return true;
}

There shouldn't really be anything new here, if you've followed all the tutorials I mentioned above. We simply create our App class which inherits from wxApp, give it a couple of inputs, and initialise it. We also IMPLEMENT_APP it, which basically tells wxWidgets that it's our "main" in the program.

The text control will have "Press Ctrl+G to append text to me" when initialised, and the checkbox will have a label which reads "Press Ctrl+Left to toggle me."

Right, onto the event. The bulk of this tutorial is gonna be how to use the wxKeyEvent to check for modifier keys, etc. I've only used two objects to keep the code short and sweet. You could of course do this with as many as you wish. It's fast, effective, and easy to implement.

First off, we're going to open up our function:
void app::key_shortcut(wxKeyEvent& e) {
Simple enough.
The next part could be laid out in a number of ways, since we could use multiple ifs, or a nested switch. Since I'm only using Ctrl shortcuts, I'll use an if statement to check if the control key is being held. (This is known as a modifier key)
if(e.GetModifiers() == wxMOD_CONTROL) {
As you can see, we're checking if the control key is being held down. For information on other modifiers, click here.

The next thing we need is a switch, to check for the key being pressed along with the control key. To do this, we need to call GetKeyCode() of our wxKeyEvent.
		switch(e.GetKeyCode()) {
			case 'G': // can return the upper ASCII value of a key
				// do whatever you like for a Ctrl+G event here!
				this->txt->AppendText(wxT(" gabehabe ftw!"));
				break;
			case WXK_LEFT: // we also have special keycodes for non-ascii values.
				// get a full list of special keycodes here:
				// http://docs.wxwidgets.org/stable/wx_keycodes.html
				this->chk->SetValue(!this->chk->GetValue());
				break;
			default: // do nothing
				break;
		}
And finally, all we need to do is close off our if statement and function:
	} // end if
} // end function

And that's all there is to creating keyboard shortcuts without a menu! :)

Like I said, it's a rather simple concept, but certainly something worth knowing.

As always, here's the complete code in a block, complete with lots of comments:
// basic setup code, I'll fly past this. If you're not familiar, check out this tutorial:
// http://www.dreamincode.net/forums/showtopic66948.htm

#include <wx/wx.h>

class app : public wxApp {
	public:
		virtual bool OnInit();
	private:
		wxTextCtrl* txt;
		wxCheckBox* chk;

		void key_shortcut(wxKeyEvent&);
		DECLARE_EVENT_TABLE()
};

// if you're not familiar with events, check out this tutorial:
// http://www.dreamincode.net/forums/showtopic67058.htm

BEGIN_EVENT_TABLE(app, wxApp)
	EVT_KEY_DOWN(app::key_shortcut)
END_EVENT_TABLE()

IMPLEMENT_APP(app)

bool app::OnInit() {
	wxFrame* win = new wxFrame(NULL, wxID_ANY, wxT("Keyboard Shortcuts, No Menu!"), wxDefaultPosition, wxSize(250, 125));
	win->Show(true);

	this->txt = new wxTextCtrl(win, wxID_ANY, wxT("Press Ctrl+G to append text to me"), wxPoint(0,0), wxSize(250, 50), wxTE_MULTILINE);
	this->chk = new wxCheckBox(win, wxID_ANY, wxT("Press Ctrl+Left to toggle me."), wxPoint(0, 55), wxDefaultSize);

	return true;
}

// this is the method I'll be focusing on. The key_shortcut event which we create
// to do fancy stuff without adding billions of menu items

void app::key_shortcut(wxKeyEvent& e) {
	// of course, it doesn't have to be the control key. You can use others:
	// http://docs.wxwidgets.org/stable/wx_wxkeyevent.html
	if(e.GetModifiers() == wxMOD_CONTROL) {
		switch(e.GetKeyCode()) {
			case 'G': // can return the upper ASCII value of a key
				// do whatever you like for a Ctrl+G event here!
				this->txt->AppendText(wxT(" gabehabe ftw!"));
				break;
			case WXK_LEFT: // we also have special keycodes for non-ascii values.
				// get a full list of special keycodes here:
				// http://docs.wxwidgets.org/stable/wx_keycodes.html
				this->chk->SetValue(!this->chk->GetValue());
				break;
			default: // do nothing
				break;
		}
	}
}


The result is this rather crude looking user interface:
Attached Image

Is This A Good Question/Topic? 1
  • +

Page 1 of 1