Event handling |
||||||||||||||||||||
| PGUI: Event handling | ||||||||||||||||||||
|
Contents: |
Modern grapical environments use event model for communicating between interactive objects and the input/output system. The event model was developed to support direct manipulation interfaces. Direct manipulation is when the user is presented with concrete objects on the display and then manipulates those objects with interactive devices. Event model makes it possible to support a large number of simultaneously available commands and actions. For example, think about the possible actions available in a file manager application (Windows explorer). Windowing systemA windowing system makes it possible for several interactive applications to run simultaneously. In a windowing system a user interface of an application is built of
The software view of a windowing system is a hierarchy of (usually) rectangular windows and child windows. An application usually has one or more top level windows (root windows). A root window is managed by the windowing system or a separate process called the window manager. Window eventsUser actions with the input devices are translated into software events (messages) and distributed to the appropriate window. Events (or messages) are identified by an event type. Input eventsMouse events:
Every mouse event carries the mouse coordinates and the state of the modifier buttons. Mouse click occurs when the mouse button is pressed down and released sufficiently close to the same spot. Depending on the situation, the spot might be one pixel or a single ui component. Usually, a window receives mouse messages that happens inside it. A window can capture the mouse in order to receive all mouse events. Keyboard events:
Window receives keyboard events if it has the input focus. Window gets input focus for example when it is clicked with the mouse. The window gets notified with event messages about receiving and losing input focus. Windowing eventsWindow management events:
RedrawingWhen the contents of the window need to be redrawn, an update event is sent to the window. The window handles the event by drawing the contents of the window or a portion of the contents. Redrawing (or updating) is commonly a low-level event. It is "sent" to a window when there are no other messages to process. The main event loopThe main event loop get the events from the event queue, translates, and dispatches then to the corresponding windows. The generic form fo the main event loop is Initialization
while (not time to quit) {
Get next event E
if (not FilteredEvent(E)) {
Translate event E
Dispatch event E
}
}
In object oriented systems (Java, MFC, .NET) the main event loop is hidden behind the class implementation. In Win32 API -programming the event loop is similar to the above example. Event handlingDispatching eventsDispatching commonly uses bottom-first algorithm in using the mouse position for identifying the window. It starts from the bottom of the window hierarchy and proceeds upwards to find the window that wants to process the event. Keyboard event are sent to the window that has the input focus. Input focus can be changed by clicking on a window or just moving the mouse on top of a window. Mouse events usually go to topmost (visually, hierarchically at the bottom) window including the mouse coordinates. A window can capture the mouse in order to receive other mouse events. Window procedure in Win APIWin32 uses a callback function called the window procedure to handle the messages sent to the window. The window procedure is linked to the window with the help of a window class. // in Winmain
wndclass.lpfnWndProc = WndProc;
RegisterClass(&wndclass);
...
// the window procedure
LRESULT CALLBACK WndProc (HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam) {
switch (message) {
...
case WM_LBUTTONDOWN:
// handle the event
return 0;
...
}
}
The window has a reference to the window class and the window class has a reference to the window procedure. Using these two references Win32 OS can call the window procedure. Message maps in MFCIn MFC window class, a message map is used to link member functions
to messages. Message map is a simple associative array where keys are message
types ( Because the correct implementation of message maps requires relatively complex
code MFC provides a large set of macros for creating message maps. To process
left-mouse-button-down messages ( class CMainWindow : public CWnd
{
...
protected:
afx_msg void OnLButtonDown (UINT nFlags, CPoint point);
DECLARE_MESSAGE_MAP ()
};
// implementation
BEGIN_MESSAGE_MAP (CMainWindow, CWnd)
...
ON_WM_LBUTTONDOWN ()
...
END_MESSAGE_MAP ()
void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point)
{
// handle the event
}
The macros // In the class declaration
DECLARE_MESSAGE_MAP ()
// In the class implementation
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
ON_WM_PAINT ()
END_MESSAGE_MAP ()
are precompiled to // In the class declaration
private:
static const AFX_MSGMAP_ENTRY _messageEntries[];
protected:
static const AFX_MSGMAP messageMap;
virtual const AFX_MSGMAP* GetMessageMap() const;
// In the class implementation
const AFX_MSGMAP* CMainWindow::GetMessageMap() const
{
return &CMainWindow::messageMap;
}
const AFX_MSGMAP CMainWindow::messageMap = {
&CFrameWnd::messageMap,
&CMainWindow::_messageEntries[0]
};
const AFX_MSGMAP_ENTRY CMainWindow::_messageEntries[] = {
{ WM_PAINT, 0, 0, 0, AfxSig_vv,
(AFX_PMSG)(AFX_PMSGW)(void (CWnd::*)(void))OnPaint },
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }
};
Notice the reference to the superclass message map. If the message type can not be found from this message map the search continues from the superclass. Event listeners in JavaIn Java, a user interface component include a list of event handlers for different event groups. Event handlers are interfaces called "listeners". To listen to a set of events, a class needs to implements one of more of these interfaces. The user interface components include functions for adding all supported event listener types. The general form of these functions is public void addEventListener(EventListener l); where Event is replaced with the real listener type. For example, to listen to mouse-button-pressed-down -events, we write public class MyComponent
extends JComponent
implements MouseListener
{
public Mycomponent() {
...
addMouseListener(this);
...
}
public void mousePressed(MouseEvent e) {
// handle the event
}
// the other mouse listener functions
...
}
Package java.awt.event includes the most common event listener interfaces:
Adapter is a class including an empty implementation of every method in the listener interface. Thus you do not have to write the empty methods in your own code, if you are using separate event processing classes. Additional event listener interfaces can be found in package javax.swing.event. Delegates and event handlers in .NET
.NET uses delegate classes to process events. A delegate is a special kind of
class that holds a reference to a method with a pre-defined signature. Namespace
public delegate void MouseEventHandler( object sender, MouseEventArgs e ); By convention, the first parameter for event handlers delegate is the source of the event, and the second parameter is an object including event arguments. There is also a generic event delegate for events with no arguments: public delegate void EventHandler( object sender, EventArgs e );
The class Event handlers can be connected to a class with a special language construct called event. For mouse button down events the corresponding handler in the class Form is public event MouseEventHandler MouseDown; The event handler can be connected (wired) to the form with MouseDown += new MouseEventHandler(MyMouseDown); where MyMouseDown is your own local event handler method: private void MyMouseDown(object sender, MouseEventArgs e) {
// x-coordinate
int x = e.X;
// y-coordinate
int y = e.Y;
// which button
if (e.Button == MouseButtons.Left) {
...
}
}
ExamplesDrawLines-example in several versions. Moving things in several versions. |
See also: |
||||||||||||||||||
| Jarkko Leponiemi, Wednesday, 15-Oct-2003 07:41:05 EEST | ||||||||||||||||||||