1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
|
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="highlight.min.css">
<script src="highlight.min.js"></script><script>
hljs.configure({languages: ['cpp']});
hljs.highlightAll();
</script><title>Chapter 23. Keyboard and Mouse Events</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
<link rel="home" href="index.html" title="Programming with gtkmm 4">
<link rel="up" href="index.html" title="Programming with gtkmm 4">
<link rel="prev" href="sec-filechooser-filedialog.html" title="FileChooser and FileDialog">
<link rel="next" href="sec-keyboardevents-propagation.html" title="Event Propagation">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr><th colspan="3" align="center">Chapter 23. Keyboard and Mouse Events</th></tr>
<tr>
<td width="20%" align="left">
<a accesskey="p" href="sec-filechooser-filedialog.html"><img src="icons/prev.png" alt="Prev"></a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="sec-keyboardevents-propagation.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
</table>
<hr>
</div>
<div class="chapter">
<div class="titlepage"><div><div><h1 class="title">
<a name="chapter-keyboardevents"></a>Chapter 23. Keyboard and Mouse Events</h1></div></div></div>
<div class="toc">
<p><b>Table of Contents</b></p>
<ul class="toc">
<li><span class="section"><a href="chapter-keyboardevents.html#sec-keyboardevents-overview">Overview</a></span></li>
<li><span class="section"><a href="sec-keyboardevents-propagation.html">Event Propagation</a></span></li>
<li><span class="section"><a href="sec-keyboardevents-mouse.html">Mouse Events</a></span></li>
</ul>
</div>
<p>
Event signals differ in some ways from other signals. These differences are described
in the <a class="link" href="sec-eventsignals.html" title="Event signals">Event signals</a> section in
the appendix. Here we will use keyboard events and mouse events to show how
events can be used in a program.
</p>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="sec-keyboardevents-overview"></a>Overview</h2></div></div></div>
<p>
Whenever you press or release a key, an event is emitted. You can add an
event controller and connect a signal handler to handle such events.
</p>
<p>
The event signal handler will receive arguments that depend on the type of event.
For key press events the arguments are (<span class="type">guint</span> <code class="varname">keyval</code>,
<span class="type">guint</span> <code class="varname">keycode</code>, <span class="type">Gdk::ModifierType</span> <code class="varname">state</code>).
As described in the <a class="link" href="sec-eventsignals.html" title="Event signals">appendix</a>,
the key press event signal handler returns a <span class="type">bool</span> value, to indicate that
the signal is fully handled (<code class="literal">true</code>) or allow event propagation
(<code class="literal">false</code>).
</p>
<p>
To determine which key was pressed or released, you read the value of
the <code class="varname">keyval</code> argument and compare it with a constant in the
<a class="ulink" href="https://gitlab.gnome.org/GNOME/gtk/tree/main/gdk/gdkkeysyms.h" target="_top">
<code class="filename"><gdk/gdkkeysyms.h></code></a> header file. The states of
modifier keys (shift, ctrl, etc.) are available as bit-flags in
<code class="varname">state</code>.
</p>
<p>
Here's a simple example:
</p>
<pre class="programlisting"><code class="code">
bool MyClass::on_key_pressed(guint keyval, guint, Gdk::ModifierType state)
{
if (keyval == GDK_KEY_1 &&
(state & (Gdk::ModifierType::SHIFT_MASK | Gdk::ModifierType::CONTROL_MASK |
Gdk::ModifierType::ALT_MASK)) == Gdk::ModifierType::ALT_MASK)
{
handle_alt_press();
return true;
}
return false;
}
// in MyClass constructor
auto controller = Gtk::EventControllerKey::create();
controller->signal_key_pressed().connect(
sigc::mem_fun(*this, &MyClass::on_key_pressed), false);
add_controller(controller);
</code></pre>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="keyboardevents-simple-example"></a>Example</h3></div></div></div>
<p>
In this example there are three keyboard shortcuts:
<span class="keycap"><strong>Alt</strong></span>+<span class="keycap"><strong>1</strong></span> selects the first radio button,
<span class="keycap"><strong>Alt</strong></span>+<span class="keycap"><strong>2</strong></span> selects the second one, and the
<span class="keycap"><strong>Esc</strong></span> key hides (closes) the window.
</p>
<div class="figure">
<a name="figure-keyboardevents-simple"></a><p class="title"><b>Figure 23.1. Keyboard Events - Simple</b></p>
<div class="figure-contents">
<div class="screenshot">
<div class="mediaobject"><img src="figures/events_simple.png" alt="Keyboard Events - Simple"></div>
</div>
</div>
</div>
<br class="figure-break">
<p><a class="ulink" href="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/events/keyboard_simple/" target="_top">Source Code</a></p>
<p>File: <code class="filename">examplewindow.h</code> (For use with gtkmm 4)</p>
<pre class="programlisting"><code class="code">#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
virtual ~ExampleWindow();
private:
// Signal handler:
bool on_window_key_pressed(guint keyval, guint keycode, Gdk::ModifierType state);
Gtk::Box m_container;
Gtk::CheckButton m_first;
Gtk::CheckButton m_second;
};
#endif //GTKMM_EXAMPLEWINDOW_H
</code></pre>
<p>File: <code class="filename">examplewindow.cc</code> (For use with gtkmm 4)</p>
<pre class="programlisting"><code class="code">#include "examplewindow.h"
ExampleWindow::ExampleWindow()
{
set_title("Keyboard Events");
m_container.set_margin(10);
set_child(m_container);
// Radio buttons:
m_first.set_label("First");
m_second.set_label("Second");
m_second.set_group(m_first);
m_first.set_active();
// Main Container:
m_container.set_orientation(Gtk::Orientation::HORIZONTAL);
m_container.append(m_first);
m_container.append(m_second);
// Events.
auto controller = Gtk::EventControllerKey::create();
controller->signal_key_pressed().connect(
sigc::mem_fun(*this, &ExampleWindow::on_window_key_pressed), false);
add_controller(controller);
}
bool ExampleWindow::on_window_key_pressed(guint keyval, guint, Gdk::ModifierType state)
{
//Gdk::ModifierType::ALT_MASK -> the 'Alt' key(mask)
//GDK_KEY_1 -> the '1' key
//GDK_KEY_2 -> the '2' key
//select the first radio button, when we press alt + 1
if((keyval == GDK_KEY_1) &&
(state & (Gdk::ModifierType::SHIFT_MASK | Gdk::ModifierType::CONTROL_MASK | Gdk::ModifierType::ALT_MASK)) == Gdk::ModifierType::ALT_MASK)
{
m_first.set_active();
//returning true, cancels the propagation of the event
return true;
}
else if((keyval == GDK_KEY_2) &&
(state & (Gdk::ModifierType::SHIFT_MASK | Gdk::ModifierType::CONTROL_MASK | Gdk::ModifierType::ALT_MASK)) == Gdk::ModifierType::ALT_MASK)
{
//and the second radio button, when we press alt + 2
m_second.set_active();
return true;
}
else if(keyval == GDK_KEY_Escape)
{
//close the window, when the 'esc' key is pressed
set_visible(false);
return true;
}
//the event has not been handled
return false;
}
ExampleWindow::~ExampleWindow()
{
}
</code></pre>
<p>File: <code class="filename">main.cc</code> (For use with gtkmm 4)</p>
<pre class="programlisting"><code class="code">#include "examplewindow.h"
#include <gtkmm/application.h>
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create("org.gtkmm.example");
//Shows the window and returns when it is closed.
return app->make_window_and_run<ExampleWindow>(argc, argv);
}
</code></pre>
</div>
</div>
</div>
<div class="navfooter">
<hr>
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left">
<a accesskey="p" href="sec-filechooser-filedialog.html"><img src="icons/prev.png" alt="Prev"></a> </td>
<td width="20%" align="center"> </td>
<td width="40%" align="right"> <a accesskey="n" href="sec-keyboardevents-propagation.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
<tr>
<td width="40%" align="left" valign="top">FileChooser and FileDialog </td>
<td width="20%" align="center"><a accesskey="h" href="index.html"><img src="icons/home.png" alt="Home"></a></td>
<td width="40%" align="right" valign="top"> Event Propagation</td>
</tr>
</table>
</div>
</body>
</html>
|