Files
minigui-docs/programming-guide/MiniGUIProgGuidePart1Chapter08.md
2019-12-24 14:36:26 +08:00

835 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Input Messages
- [Keyboard](#keyboard)
+ [Keyboard Input](#keyboard-input)
+ [Key Stroke Message](#key-stroke-message)
+ [Character Message](#character-message)
+ [Key Status](#key-status)
+ [Input Focus](#input-focus)
+ [Sample Program](#sample-program)
- [Mouse](#mouse)
+ [Mouse Input](#mouse-input)
+ [Mouse Message](#mouse-message)
+ [Capture of Mouse](#capture-of-mouse)
+ [Tracking Mouse Cursor](#tracking-mouse-cursor)
- [Event Hook](#event-hook)
The application receives the users input from keyboard and mouse (or other
pointing device, such as touch-screen). Application of MiniGUI receives
keyboard and mouse input by handling messages sent to window. We will describe
generation of keyboard and mouse message, and how application receives and
handles messages of keyboard and mouse in this chapter.
## Keyboard
### Keyboard Input
Figure 1 illustrates the process of handling keyboard input in MiniGUI.
![Keyboard input in MiniGUI](figures/9.1_T.jpeg)
__Figure 1__ Keyboard input in MiniGUI
MiniGUI receives original input event or data from keyboard through keyboard
device driver, and transforms it into MiniGUI abstract keyboard event and data.
Related handling procedures of bottom layer event transform these keyboard
events into key press/release messages of top layer and put them in the message
queue. Application gets these messages through message loop, and dispatches
them to window procedure for handling. MiniGUI can support 255 keys, and each
key corresponds to a unique “scan code”, scan code less than 129 is used to
define keys on `PC` keyboard. The following is the definition of some scan
codes
in `minigui/common.h`:
```cpp
#define MGUI_NR_KEYS 255
#define NR_KEYS 128
#define SCANCODE_USER (NR_KEYS + 1)
#define SCANCODE_ESCAPE 1
#define SCANCODE_1 2
#define SCANCODE_2 3
#define SCANCODE_3 4
#define SCANCODE_4 5
#define SCANCODE_5 6
#define SCANCODE_6 7
#define SCANCODE_7 8
#define SCANCODE_8 9
#define SCANCODE_9 10
#define SCANCODE_0 11
#define SCANCODE_MINUS 12
#define SCANCODE_EQUAL 13
#define SCANCODE_BACKSPACE 14
#define SCANCODE_TAB 15
...
```
### Key Stroke Message
When a key is pressed down, application will receive a message `MSG_KEYDOWN` or
`MGS_SYSKEYDOWN`; and releasing a key will generate a message `MSG_KEYUP` or
`MGS_SYSKEYUP`.
Pressing key and releasing key messages are usually appear in pairs; while the
user presses a key and does not release it, auto repeating characteristic of
the keyboard will be started up after a period of time, and the system will
generate a series of messages `MSG_KEYDOWN` or `MGS_SYSKEYDOWN`; and a message
`MSG_KEYUP` or `MSG_SYSKEYUP` will not be generated till the user releases this
key.
In MiniGUI, when the user presses one key as `ALT` being pressed down, system
keystroke messages `MSG_SYSKEYDOWN` and `MSG_SYSKEYUP` will be generated.
Non-system keystroke generates non-system keystroke messages `MSG_KEYDOWN` and
`MSG_KEYUP`. System keystroke messages are used to control the activation of
menu
in MiniGUI, and non-system keystroke messages are mainly used in application.
If a system keystroke message is handled by application, this message should be
transferred to the function `DefaultMainWinProc` for handling furthermore.
Otherwise, system operation will be disabled.
Keystroke messages `wParam` parameter presents the scan code of the key, and
`lParam` parameter includes the status flags of special keys such as `SHIFT`,
`ALT`,
`CTRL`, etc.
### Character Message
Usually, a typical window procedure does not handle directly the key stroke
messages of character keys, but handles character message `MSG_CHAR` of the
character key, and `wParam` parameter of message `MSG_CHAR` presents the encode
value of this character.
`MSG_CHAR` is usually generated by `TranslateMessage` function, which checks
the
scan code and the status of the corresponding key when receiving messages
`MSG_KEYDOWN` and `MSG_SYSKEYDOWN`. If it can be transformed to a character,
`MSG_CHAR` or `MSG_SYSCHAR` message of the corresponding character will be
generated, and will be sent to the target window of the keystroke message. The
application generally calls `TranslateMessage` function before
`DispatchMessage` in
a message loop is as follows:
```cpp
while (GetMessage(&Msg, hMainWnd)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
```
Because `TranslateMessage` function handles messages `MSG_KEYDOWN` and
`MSG_SYSKEYDOWN` before dispatching message, generates character message, and
transfers it directly to window procedure, window procedure will receive the
character message of character key first and then receive keystroke message.
Usually, parameter `wParam` of character message includes the `ISO8859-1`
encode of
the character, and the content of parameter `lParam` is the same as the
parameter
of keystroke message generating the character message.
The basic rule for handling key stroke message and character message is: You
can handle message `MSG_CHAR` if you want to get keyboard character input into
window; and you can handle message `MSG_KEYDOWN` when you want to get cursor
keys, function keys, Del, Ins, Shift, Ctrl and Alt key strokes.
### Key Status
Meanwhile handling keyboard messages, application need determine the current
status of special shift keys (Shift, Ctrl and Alt) or switch keys (CapsLock,
`NumLock`, and `ScrollLock`). Parameter `lParam` includes the status flags of
special
keys, and application can determine the status of a certain key by using `AND`
operation of specific macro with this parameter. For example, if (lParam &
`KS_LEFTCTRL`) is `TRUE`, left `CTRL` key is pressed down. Key status macros
defined
by MiniGUI include:
```
KS_CAPSLOCK CapsLock key is locked
KS_NUMLOCK NumLock key is locked
KS_SCROLLLOCK ScrollLock key is locked
KS_LEFTCTRL Left Ctrl key is pressed down
KS_RIGHTCTRL Right Ctrl key is pressed down
KS_CTRL One of Ctrl keys is pressed
KS_LEFTSHIFT Left Shift key is pressed down
KS_RIGHTSHIFT Right Shift key is pressed down
KS_SHIFT One of Shift keys is pressed down
KS_IMEPOST The message is posted by IME window
KS_LEFTBUTTON Left mouse button is preesed down
KS_RIGHTBUTTON Right mouse button is preesed down
KS_MIDDLBUTTON Middle mouse button is preesed down
KS_CAPTURED Mouse is captured by the target window
```
Except `KS_CAPTURED` can only be used for mouse message, other macros can be
used
both for handling keystroke messages and mouse messages.
Application can get key status value through `GetShiftKeyStatus` function:
```cpp
DWORD GUIAPI GetShiftKeyStatus (void);\
```
The return value of this function includes the status of all above keys.
Application can determine a certain key status by using `AND` operation of
specific macro with the return value. For example, using `GetShiftKeyStatus(`)
&
`KS_CTRL` to determine whether the left or right Ctrl key is pressed, if it is
the value of expression above is `TRUE`.
Application can also get the status of a certain key on the keyboard through
`GetKeyStatus` function:
```cpp
BOOL GUIAPI GetKeyStatus (UINT uKey);
```
Parameter `uKey` presents the scan code of the key to be required. If this key
is
pressed down, `GetKeyStatus` returns `TRUE`, otherwise returns `FALSE`.
### Input Focus
System sends keyboard messages to the message queue of the window currently
having input focus. Window with input focus can receive keyboard input, such
windows are usually active main window, child window of active main window or
grandchild window of active main window, etc. Child window usually indicates to
have input focus by displaying a blinking caret. Please refer to Chapter 10
“Icon, Cursor, and Caret” for information about caret.
Input focus is a property of window, and system can make keyboard shared to all
the windows displayed on the screen through changing the input focus among
these windows. The user can move input focus from one window to another. If
input focus is moved from one window to another, system sends message
`MSG_KILLFOCUS` to the window losing focus, and sends message `MSG_SETFOCUS` to
the
window gaining focus.
Application can get the handle of the child window having input focus of a
certain window by calling `GetFocusChild` function:
```cpp
#define GetFocus GetFocusChild
HWND GUIAPI GetFocusChild (HWND hWnd);
```
Parent window can put input focus to any one of its child windows by calling
`SetFocusChild` function:
```cpp
#define SetFocus SetFocusChild
HWND GUIAPI SetFocusChild (HWND hWnd);
```
### Sample Program
The code in List 1 illustrates simple concept of keyboard input. The complete
code of this program is included in simplekey.c of sample program package
`mg-samples` for this guide.
List 1 simplekey.c
```cpp
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
static int SimplekeyWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case MSG_KEYDOWN:
/* Print the scan code of the key pressed */
printf ("MGS_KEYDOWN: key %d\n", LOWORD(wParam));
break;
case MSG_KEYUP:
/* Print the scan code of the key released */
printf ("MGS_KEYUP: key %d\n", LOWORD(wParam));
break;
case MSG_CHAR:
/* Print the encode of the translated character */
printf ("MGS_CHAR: char %d\n", wParam);
break;
case MSG_CLOSE:
DestroyAllControls (hWnd);
DestroyMainWindow (hWnd);
PostQuitMessage (hWnd);
return 0;
}
return DefaultMainWinProc(hWnd, message, wParam, lParam);
}
/* the below code for creating main window are omitted */
```
Window procedure of above program prints the parameter `wParam` of each message
`MSG_KEYDOWN`, `MSG_KEYUP`, and `MGS_CHAR` it received. The value of this
parameter may be scan code of the pressed/released key (MSG_KEYDOWN and
`MSG_KEYUP`), and may also be encode value of the character (MSG_CHAR).
## Mouse
### Mouse Input
The handling for mouse is similar to that for keyboard in MiniGUI, as shown in
Figure 2.
![alt](figures/9.2_T.jpeg)
Figure 2 Mouse input in MiniGUI
MiniGUI receives original input event or data through mouse device driver, and
transforms it into MiniGUI abstract mouse event and data. Related bottom event
handling procedures transform these mouse events into mouse messages of top
layer and put them into the message queue. Application gets these messages
through message loop, and dispatches them to window procedure for handling.
When the user moves the mouse, system moves an icon called mouse cursor. Mouse
cursor includes a pixel point called hotspot, which is used by system to track
and identify the mouse position. If a mouse event occurs, the window under the
hotspot usually receives related mouse messages. Window, which can receive
mouse messages, are not always active window or window-having keyboard input
focus. Please refer to Chapter 10 “Icon, Cursor, and Caret” for information
about mouse cursor.
### Mouse Message
As long as the user moves mouse, presses down or releases mouse button, a mouse
event will be generated. MiniGUI transforms mouse input events of bottom layer
into mouse messages and posts them into the message queen of corresponding
window. When mouse cursor is within a window, or a mouse event occurs when the
window captures the mouse, the window will receive mouse message, regardless
whether this window is active or has input focus.
Mouse messages can be divided into tow group: client area messages and
non-client area messages. Application usually treats only client area mouse
messages and ignores non-client area mouse messages.
If mouse cursor is in client area of the window when mouse event occurs, the
window will receive a client area mouse message. If the user moves mouse in
client area, system posts a message `MSG_MOUSEMOVE` to the window. When cursor
is in client area, the following message is sent if the user presses down or
releases a mouse button:
```cpp
MSG_LBUTTONDOWN left mouse button is pressed down
MSG_LBUTTONUP left mouse button is released
MSG_RBUTTONDOWN right mouse button is pressed down
MSG_RBUTTONUP right mouse button is released
MSG_LBUTTONDBLCLK left mouse button is double clicked
MSG_RBUTTONDBLCLK right mouse button is double clicked
```
Parameter `lParam` of mouse messages in client area indicates the position of
hotspot, the low word is the x-coordinate of the point and the high word is the
y-coordinate. These two positions are both given in client area coordinate,
i.e., coordinates relative to upper-left (0, 0) of client area of the window.
It should be noted that the position coordinates of above messages are given in
screen coordinate when a window captures the mouse.
Parameter `lParam` is the key status value discussed in previous section, which
indicates the status of other buttons of mouse and shift keys of `CTRL` and
`SHIFT` etc., when mouse event occurs. You must check these flags when you need
to handle mouse messages according to other buttons or status of `CTRL` and
`SHIFT` keys. For example, if (lParam & `KS_SHIFT`) is `TRUE`, then a mouse
event takes place when `SHIFT` key is pressed down.
If mouse event occurs in the non-client area of the window, such as caption
bar, menu and window scrollbar, the window will receive a mouse message of
non-client area, which includes:
```
MSG_NCLBUTTONDOWN left mouse button is pressed down
MSG_NCLBUTTONUP left mouse button is released
MSG_NCRBUTTONDOWN right mouse button is pressed down
MSG_NCRBUTTONUP right mouse button is released
MSG_NCLBUTTONDBLCLK left mouse button is double clicked
MSG_NCRBUTTONDBLCLK right mouse button is double clicked
```
Usually, application need not handle non-client area mouse messages, but leaves
them to system for default handling; thereby some system function can be
implemented.
Parameter `lParam` of non-client area mouse message includes x-coordinate at
low word and y-coordinate at high word, which are both window coordinate.
Parameter `wParam` of non-client area mouse message indicates the position of
non-client area when moving or clicking mouse button, which is one of the
identifiers beginning with `HT` defined in `minigui/window.h`:
```cpp
#define HT_UNKNOWN 0x00
#define HT_OUT 0x01
#define HT_MENUBAR 0x02
#define HT_TRANSPARENT 0x03
#define HT_BORDER_TOP 0x04
#define HT_BORDER_BOTTOM 0x05
#define HT_BORDER_LEFT 0x06
#define HT_BORDER_RIGHT 0x07
#define HT_CORNER_TL 0x08
#define HT_CORNER_TR 0x09
#define HT_CORNER_BL 0x0A
#define HT_CORNER_BR 0x0B
#define HT_CLIENT 0x0C
#define HT_NEEDCAPTURE 0x10
#define HT_BORDER 0x11
#define HT_NCLIENT 0x12
#define HT_CAPTION 0x13
#define HT_ICON 0x14
#define HT_CLOSEBUTTON 0x15
#define HT_MAXBUTTON 0x16
#define HT_MINBUTTON 0x17
#define HT_HSCROLL 0x18
#define HT_VSCROLL 0x19
```
Above identifiers are called hit-testing code, and the hotspot position
identified includes caption bar, menu bar, and client area etc.
If a mouse event occurs, system will send a `MSG_HITTEST` (`MSG_NCHITTEST`)
message
to the window having cursor hotspot or the window capturing the mouse, and
MiniGUI determines whether send the mouse message to the client area or
non-client area.
`WParam` parameter of `MSG_HITTEST` message is the x-coordinate of the cursor
hotspot, and `lParam` parameter is the y-coordinate of the cursor hotspot. The
default mouse message procedure in MiniGUI handles `MSG_HITTEST` message,
checks
the pair of coordinate and returns a hit-testing code of the cursor hotspot. If
the cursor hotspot is in the client area of the window, the hit-testing code of
`HT_CLIENT` is returned, and MiniGUI switched the screen coordinate into client
area coordinate, and then post client area mouse messages to corresponding
window process. If the cursor hotspot is in the non-client area of the window,
other hit-testing codes are returned, and MiniGUI post non-client area mouse
messages to window procedure, and place the hit-testing code into `wParam`
parameter, and place the cursor coordinate into `lParam` paramter.
### Capture of Mouse
The window procedure usually received mouse messages only when the mouse cursor
is in the client area or non-client area, i.e., the system only sends mouse
messages to a window under the cursor hotspot. While in some cases the
application may need to receive mouse messages, even if the cursor hotspot is
outside its window area. In this case, we can use `SetCapture` function to make
a
certain window capture the mouse, so that this window will receive all mouse
messages before the application calls `ReleaseCapture` to recover normal mouse
handling mode:
The following are the function definitions about capture of mouse:
```cpp
HWND GUIAPI SetCapture(HWND hWnd);
void GUIAPI ReleaseCapture(void);
HWND GUIAPI GetCapture(void);
```
At a certain time, only one window can capture the mouse, and the application
can use `GetCapture` function to determine which window has captured the mouse
at
present.
Generally speaking, the mouse is only captured when the mouse button is pressed
down in the client area, and releases the mouse capture when the mouse button
is released.
The code in List 2 creates a simple button-like control, and its response to
the mouse action is like a button and can demonstrate the necessity of the
mouse capture, although it can do nothing and does not look like a button very
much. The complete code is available in program capture.c in the example
program package `mg-samples` for this guide.
__List 2__ capture.c
```cpp
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#define IDC_MYBUTTON 100
/* the callback function of the simple button control class */
static int MybuttonWindowProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
/*
* used to save the button status.
* Noet: you should not use a static variable to save
* the information of a control instance.
*/
static int status = 0;
switch (message) {
case MSG_LBUTTONDOWN:
/* set the pressed status */
status = 1;
/* capture the mouse */
SetCapture (hWnd);
/* invalidate the control, causing to repaint the button */
InvalidateRect (hWnd, NULL, TRUE);
break;
case MSG_LBUTTONUP:
if (GetCapture() = hWnd)
break;
/* set the released status */
status = 0;
/* release the mouse */
ReleaseCapture ();
/* invalidate the control, causing to repaint the button */
InvalidateRect (hWnd, NULL, TRUE);
break;
case MSG_PAINT:
hdc = BeginPaint (hWnd);
/* perform different repainting according to the pressed or released status */
if (status) {
SetBkMode(hdc, BM_TRANSPARENT);
TextOut(hdc, 0, 0, "pressed");
}
EndPaint(hWnd, hdc);
return 0;
case MSG_DESTROY:
return 0;
}
return DefaultControlProc (hWnd, message, wParam, lParam);
}
/* this function registers simple button control class */
BOOL RegisterMybutton (void)
{
WNDCLASS WndClass;
WndClass.spClassName = "mybutton";
WndClass.dwStyle = 0;
WndClass.dwExStyle = 0;
WndClass.hCursor = GetSystemCursor(0);
WndClass.iBkColor = PIXEL_lightgray;
WndClass.WinProc = MybuttonWindowProc;
return RegisterWindowClass (&WndClass);
}
/* main windoww proc */
static int CaptureWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case MSG_CREATE:
/* register the simple button control class */
RegisterMybutton();
/* creates an instance of the simple button cotrol class */
CreateWindow ("mybutton", "", WS_VISIBLE | WS_CHILD, IDC_MYBUTTON,
30, 50, 60, 20, hWnd, 0);
break;
case MSG_CLOSE:
/* destroys the control and the main window */
DestroyAllControls (hWnd);
DestroyMainWindow (hWnd);
PostQuitMessage (hWnd);
return 0;
}
return DefaultMainWinProc(hWnd, message, wParam, lParam);
}
/* the code below for creating the main window are omitted */
```
### Tracking Mouse Cursor
Tracking the position of the mouse cursor is one of the tasks the GUI
application usually needs to do. For example, the position of the mouse cursor
needs to be tracked when the painting program performs painting operation, so
that the user can paint in the client area of the window by dragging the mouse.
`MSG_LBUTTONDOWN`, `MSG_LBUTTONUP`, and `MSG_MOUSEMOVE` messages need to be
handled
for tracking the mouse cursor. Generally, the window procedure begins to track
the mouse cursor when `MSG_LBUTTONDOWN` message occurs, determines the current
position of the cursor through handling `MSG_MOUSEMOVE` message, and ends
tracking the mouse cursor when `MSG_LBUTTONUP` occurs.
The code in List 3 is a simple painting program, which allows you to paint
arbitrarily in the client area of the window, and clear the screen when the
user clicks the right button. The complete code of this program is available in
program painter.c in the example program package `mg-samples` for this guide.
__List 3__ painter.c
```cpp
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
static int PainterWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
/* Use static variables to save the running status
* and the position where the mouse is pressed
*/
static BOOL bdraw = FALSE;
static int pre_x, pre_y;
switch (message) {
case MSG_LBUTTONDOWN:
/* enter painting status; capture the mouse and write the position
* where the mouse is pressed
*/
bdraw = TRUE;
SetCapture(hWnd);
pre_x = LOWORD (lParam);
pre_y = HIWORD (lParam);
break;
case MSG_MOUSEMOVE:
{
int x = LOWORD (lParam);
int y = HIWORD (lParam);
if (bdraw) {
/* if it is in painting status, the moused is indicated to be captured,
* and therefore the mouse coordinates need to be converted from
* screen coordinate to client coordinate
*/
ScreenToClient(hWnd, &x, &y);
/* get the graphics device context of the client area and begin to paint */
hdc = GetClientDC(hWnd);
SetPenColor(hdc, PIXEL_red);
/* paint a straight line from the previous position
* to the current mouse position
*/
MoveTo(hdc, pre_x, pre_y);
LineTo(hdc, x, y);
ReleaseDC(hdc);
/* update the previous position with the current mouse position */
pre_x = x;
pre_y = y;
}
break;
}
case MSG_LBUTTONUP:
/* quit painting status and release the mouse */
bdraw = FALSE;
ReleaseCapture();
break;
case MSG_RBUTTONDOWN:
/* click the right buttion of the mouse to clear the window */
InvalidateRect(hWnd, NULL, TRUE);
break;
case MSG_CLOSE:
DestroyAllControls (hWnd);
DestroyMainWindow (hWnd);
PostQuitMessage (hWnd);
return 0;
}
return DefaultMainWinProc (hWnd, message, wParam, lParam);
}
/* the code below for creating main window are omitted */
```
![A simple painting program](figures/9.3.jpeg)
__Figure 3__ A simple painting program
The painting flag is set to be `TRUE` when painter handles `MSG_LBUTTONDOWN`
message, so that the program can paint when receiving `MSG_MOUSEMOVE` message.
In
order to prevent the mouse from being released in other window and prevent the
window procedure from receiving `MSG_LBUTTONUP` message, painter calls
`SetCapture`
function to capture the mouse when `MSG_LBUTTONDOWN` message occurs.
The program performs painting in `MSG_MOUSEMOVE` message, ends painting when
receiving `MSG_LBUTTONUP`, and calls `ReleaseCapture` to release the mouse
capture.
The program calls `InvalidateRect` function to clear the content in the client
region when receiving `MSG_RBUTTONDOWN`.
## Event Hook
In common cases, keyboard events and mouse events are transferred from the
bottom layer device to the application window procedure in a normal approach
for handling. MiniGUI provides a kind of mechanism so that we can capture these
events before they are transformed to corresponding message queue and
transferred to specific windows. Then there are two choices available: Let the
event transferred in the normal approach; or cancel the normal event handling
process. This is the hook mechanism. The hook is a callback function in nature,
and if the application registers a hook, the system will call this callback
function in the midway of transferring messages, and then determine whether to
continue to transfer the message according to the return value of the callback
function.
The prototype of the hook callback function defined for MiniGUI-Threads and
MiniGUI-Standalone is as follows:
```cpp
typedef int (* MSGHOOK)(void* context, HWND dst_wnd, int msg, WPARAM wparam, LPARAM lparam);
```
Wherein context is a context data passed in when registering the hook, which
may be a pointer; `dst_wnd` is the target main window of this message; msg is
the
message identifier; wparam and lparam are the two parameters of the message.
The returned value of the hook function determines whether the system continues
to transfer the event: continues to transfer the event when returning
`HOOK_GOON`; and stops transferring the event when returning `HOOK_STOP`.
The application may call the following two functions to register the hook
function of the keyboard and the mouse events for MiniGUI-Threads and
MiniGUI-Standalone, respectively:
```cpp
MSGHOOK GUIAPI RegisterKeyMsgHook (void* context, MSGHOOK hook);
MSGHOOK GUIAPI RegisterMouseMsgHook (void* context, MSGHOOK hook);
```
You need only pass the context information and the pointer of the hook callback
function when calling these two functions. If you want to unregister the hook
function previously registered, you need only transfer `NULL` in, as described
below:
```cpp
int my_hook (void* context, HWND dst_wnd, int msg, WPARAM wParam, LPARAM lparam)
{
if (...)
return HOOK_GOON;
else
return HOOK_STOP;
}
MSGHOOK old_hook = RegisterKeyMsgHook (my_context, my_hook);
...
/* Restore old hook */
RegisterKeyMsgHook (0, old_hook);
```
Event hook mechanism is very import to some applications, for example, you can
use keyboard hook when the application needs to capture some global keys.
When you handle the event hook under MiniGUI-Threads, the following fact must
be noted:
__NOTE__ The hook callback function is called by the desktop thread, i.e., the
hook callback function is executed in the desktop thread, therefore, you can
not send messages to other threads through `SendMessage` in the hook callback
function, which may cause the occurrence of a possible deadlock.
Besides the hook mechanism for MiniGUI-Threads and MiniGUI-Standalone described
above, MiniGUI provides a different hook mechanism for MiniGUI-Processes.
For a client of MiniGUI-Processes, you can use the following functions to
register a hook window:
```cpp
HWND GUIAPI RegisterKeyHookWindow (HWND hwnd, DWORD flag);
HWND GUIAPI RegisterMouseHookWindow (HWND hwnd, DWORD flag);
```
Wherein hwnd is the handle to a window of a client, flag indicates whether stop
or continue handling the hooked messages: `HOOK_GOON` to continue and
`HOOK_STOP`
to stop.
After registering a key/mouse hook window, the server of MiniGUI-Processes will
post the key/mouse messages to the window of the client first. It will
determine whether stop handling the messages or continue the normal handling by
the flag of the hook.
MiniGUI provides another hook mechanism for the server of MiniGUI-Processes.
The event can be received in the sever process, captured before it is
transferred to its desktop window or a certain client for further handling. On
the event-transferring path, the position of this hook is earlier than that of
the hook mentioned above.
The prototype of the hook callback function prepared for the sever process of
MiniGUI-Processes is:
```cpp
typedef int (* SRVEVTHOOK) (PMSG pMsg);
```
Here, `pMsg` is the pointer to the message structure to be transferred. The
server can modify arbitrarily the value in the message structure, which this
pointer points to. The sever process will continue the normal handling of the
event when the callback function returns `HOOK_GOON`, and cancels the handling
when `HOOK_STOP` is returned.
`mginit` program can register hook function in the system through the following
function:
```cpp
SRVEVTHOOK GUIAPI SetServerEventHook (SRVEVTHOOK SrvEvtHook);
```
This function returns the old hook function.
By using the hook function, we can monitor the idle of the system, and start up
the screen saver when the system idle time is up to the specified value.
----
[&lt;&lt; Scrollbar](MiniGUIProgGuidePart1Chapter07.md) |
[Table of Contents](README.md) |
[Icon, Cursor, and Caret &gt;&gt;](MiniGUIProgGuidePart1Chapter09.md)
[Release Notes for MiniGUI 3.2]: /supplementary-docs/Release-Notes-for-MiniGUI-3.2.md
[Release Notes for MiniGUI 4.0]: /supplementary-docs/Release-Notes-for-MiniGUI-4.0.md
[Showing Text in Complex or Mixed Scripts]: /supplementary-docs/Showing-Text-in-Complex-or-Mixed-Scripts.md
[Supporting and Using Extra Input Messages]: /supplementary-docs/Supporting-and-Using-Extra-Input-Messages.md
[Using CommLCD NEWGAL Engine and Comm IAL Engine]: /supplementary-docs/Using-CommLCD-NEWGAL-Engine-and-Comm-IAL-Engine.md
[Using Enhanced Font Interfaces]: /supplementary-docs/Using-Enhanced-Font-Interfaces.md
[Using Images and Fonts on System without File System]: /supplementary-docs/Using-Images-and-Fonts-on-System-without-File-System.md
[Using SyncUpdateDC to Reduce Screen Flicker]: /supplementary-docs/Using-SyncUpdateDC-to-Reduce-Screen-Flicker.md
[Writing DRM Engine Driver for Your GPU]: /supplementary-docs/Writing-DRM-Engine-Driver-for-Your-GPU.md
[Writing MiniGUI Apps for 64-bit Platforms]: /supplementary-docs/Writing-MiniGUI-Apps-for-64-bit-Platforms.md
[Quick Start]: /user-manual/MiniGUIUserManualQuickStart.md
[Building MiniGUI]: /user-manual/MiniGUIUserManualBuildingMiniGUI.md
[Compile-time Configuration]: /user-manual/MiniGUIUserManualCompiletimeConfiguration.md
[Runtime Configuration]: /user-manual/MiniGUIUserManualRuntimeConfiguration.md
[Tools]: /user-manual/MiniGUIUserManualTools.md
[Feature List]: /user-manual/MiniGUIUserManualFeatureList.md
[MiniGUI Overview]: /MiniGUI-Overview.md
[MiniGUI User Manual]: /user-manual/README.md
[MiniGUI Programming Guide]: /programming-guide/README.md
[MiniGUI Porting Guide]: /porting-guide/README.md
[MiniGUI Supplementary Documents]: /supplementary-docs/README.md
[MiniGUI API Reference Manuals]: /api-reference/README.md
[MiniGUI Official Website]: http://www.minigui.com
[Beijing FMSoft Technologies Co., Ltd.]: https://www.fmsoft.cn
[FMSoft Technologies]: https://www.fmsoft.cn
[HarfBuzz]: https://www.freedesktop.org/wiki/Software/HarfBuzz/