Foundation of Control Programming
There are predefined controls in a relatively complex GUI system, and they are the main elements for the human-machine interaction. This chapter will illustrate what is the control and control class, and briefly introduce the predefined control classes in MiniGUI.
Control and Control Class
The concept of controls (or widgets) is well known. The control can be interpreted as the child window in the main window. The behaviors of these child windows, as well as that of the main window, both can accept the exterior input such as the keyboard and the mouse, and can output in their own regions - but all the actions are restricted within the main window. MiniGUI also supports child windows, and can create nested child windows in the child window. We refer to all the child windows in MiniGUI as controls.
In Window or X Window, the system will predefine some control classes. When you use a certain control class to create controls, all the controls belonging to this control class will have the same behaviors and appearances. With this technique, the consistent human-machine interaction interface can be ensured, and the program can construct the graphics user interface as building toy bricks. MiniGUI uses the concept of control and control class, and can conveniently overload the existed control to make it have some special effects. For example, when an edit box which only allows digit to input in, you can realize it by overloading the existed EDIT
control class, instead of developing a new control class.
If you have the experience of developing a Windows application, you should remember that before creating a new window, you must assure that the corresponding window class of this new window has existed in the system. In Windows operating system, each window created by the program corresponds to a certain window class. This concept is similar to the relationship between the class and the object in the object-oriented programming. Referring to the terms of object oriented, each window in Windows is an instance of a certain window class. Similar concepts are present in the X Window programming; for example, each widget created is actually an instance of a certain widget class.
Thus, if a program needs to create a window, it should first be sure to select the correct window class, because each window class determines the appearances and behaviors of the corresponding window instances. Herein the presentation means the appearance of the window, such as the width of the window border, whether or not the caption bar exists, etc. The behavior means the response of the window to the user input. Each GUI system will predefine some window classes. Examples of the common window classes include the button, list box, scroll bar, edit box, etc. If the window to be created by the program is very special, you can first register your own window class, and then create an instance of this window class. Thus the code reusability is improved substantially.
In MiniGUI, the main window is generally considered as a special window. Since the reusability of the main window code is usually very low, it will cause additional unnecessary memory space if we register a window class for each main window in a usual way. So we do not provide window class support in the main window, but all the child windows, i.e. controls, in the main window support the concept of the window class (control class). MiniGUI provides the predefined control classes commonly used, including button (including radio button, check box), static control, list box, progress bar, track bar, edit box, etc. A program can customize its own control class, register the control class and then create the corresponding control instances. Table 1 lists the predefined control classes and the corresponding class names in MiniGUI.
Table 1 Control class and corresponding class name predefined in MiniGUI
Control Class
Class Name
C Macro for Control Name
Note
Multi-Line Edit Box
"mledit"
CTRL_MLEDIT
(same with TRL_TEXTEDIT
)
Creating Control Instance by Using Predefined Control Class
In MiniGUI, by calling the CreateWindow
function (the CreateWindow
is in fact a macro of the CreateWindowEx
function) can create an instance of a certain control class. The control class can be either the predefined MiniGUI control classes in Table 1, or a user-defined control class. Following are the prototypes of several functions related to CreateWindow
function (minigui/window.h):
HWND GUIAPI CreateWindowEx2 (const char* spClassName,
const char* spCaption, DWORD dwStyle, DWORD dwExStyle,
int id, int x, int y, int w, int h, HWND hParentWnd,
const char* werdr_name, const WINDOW_ELEMENT_ATTR* we_attrs,
DWORD dwAddData);
static inline HWND GUIAPI CreateWindowEx (const char* spClassName,
const char* spCaption, DWORD dwStyle, DWORD dwExStyle,
int id, int x, int y, int w, int h, HWND hParentWnd,
DWORD dwAddData)
{
return CreateWindowEx2 (spClassName, spCaption, dwStyle, dwExStyle,
id, x, y, w, h, hParentWnd, NULL, NULL, dwAddData);
}
#define CreateWindow(class_name, caption, style, id, x, y, w, h, parent, add_data) \
CreateWindowEx(class_name, caption, style, 0, id, x, y, w, h, parent, add_data)
BOOL GUIAPI DestroyWindow (HWND hWnd);
The CreateWindow
function creates a child window, i.e. a control. It specifies the control class (class_name), the control caption (caption), the control style (style), the control identifier (id), and the initial position and size of the control (x, y, w, h). This function also specifies the parent window (parent) of the child window. The parameter add_data
is used to pass a special data to the control, and the data structures pointed to by this pointer are different for different control classes.
The affection of the CreateWindowEx
function is same as CreateWindow
function; however, the CreateWindowEx
can be used to specify the extended style (dwExStyle) of the control.
CreateWindowEx2
function is a new added function in MiniGUI 3.0. It is based on CreateWindowEx
and has two new arguments: werdr_name
and we_attrs,
they specify the name and the property of renderer for control.
The DestroyWindow
function is used to destroy the control or the child window created by above two functions.
The program in List 1 creates several types of controls by using the predefined control classes: static control, button and single-line edit box. Among them hStaticWnd1
is the static control created in the main window hWnd
; hButton1
, hButton2
, hEdit1
, and hStaticWnd2
are several controls created in hStaicWnd1
, and existing as the child controls of hStaticWnd1
; While hEdit2
is the child control of hStaicWnd2
, and is the grandchild control of hStaticWnd1
.
List 1 Creating controls using the predefined control classes
#define IDC_STATIC1 100
#define IDC_STATIC2 150
#define IDC_BUTTON1 110
#define IDC_BUTTON2 120
#define IDC_EDIT1 130
#define IDC_EDIT2 140
/* Create a static control */
hStaticWnd1 = CreateWindow (CTRL_STATIC,
"This is a static control",
WS_CHILD | SS_NOTIFY | SS_SIMPLE | WS_VISIBLE | WS_BORDER,
IDC_STATIC1,
10, 10, 180, 300, hWnd, 0);
/* Create two button controls in hStaticWnd1 */
hButton1 = CreateWindow (CTRL_BUTTON,
"Button1",
WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE,
IDC_BUTTON1,
20, 20, 80, 20, hStaticWnd1, 0);
hButton2 = CreateWindow (CTRL_BUTTON,
"Button2",
WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE,
IDC_BUTTON2,
20, 50, 80, 20, hStaticWnd1, 0);
/* Create one edit control in hStaticWnd1 */
hEdit1 = CreateWindow (CTRL_EDIT,
"Edit Box 1",
WS_CHILD | WS_VISIBLE | WS_BORDER,
IDC_EDIT1,
20, 80, 100, 24, hStaticWnd1, 0);
/* Create a static control in hStaticWnd1 */
hStaticWnd2 = CreateWindow (CTRL_STATIC,
"This is child static control",
WS_CHILD | SS_NOTIFY | SS_SIMPLE | WS_VISIBLE | WS_BORDER,
IDC_STATIC1,
20, 110, 100, 50, hStaticWnd1, 0);
/* Create an edit box hEdit2 in hStaticWnd2,
* thus hEdit2 is the grandchild window of hStaticWnd1 */
hEdit2 = CreateWindow (CTRL_EDIT,
"Edit Box 2",
WS_CHILD | WS_VISIBLE | WS_BORDER,
IDC_EDIT2,
0, 20, 100, 24, hStaticWnd2, 0);
Topics Involved in Control Programming
In control programming, besides creating and destroying of the control, following subjects are usually involved:
The control has its own window style definition. You need to specify the needed style when creating the control. Different styles will result in different appearance and behavior.
Getting or setting the status and contents and so on of the control. In general, sending some general or special messages to the control can complete this. In addition, the general functions for windows are usually suitable for the controls, such as
ShowWindow
,MoveWindow
,EnableWindow
,SetWindowFont
, etc.Informing the parent window by notification messages when a certain event happens in the control. Notification messages are generally sent by
MSG_COMMAND
messages.WParam
parameter of this message consists of the window identifier and the notification code, andlParam
includes the handle of the control sending the notification messages. For example, when users change the contents of an edit box, the edit box will sendEN_CHANGE
notification message to the parent window. If the window procedure of the parent window needs to know this change, the notification message should be handled in the window procedure of the parent window as follows:
switch (message) {
case MSG_COMMAND:
{
int id = LOWORD(wParam);
int nc = HIWORD(wParam);
if (id == ID_MYEDIT && nc == EN_CHANGE) {
/* The user has changed the content of ID_MYEDIT edit box
* of the child window, and further handling is being done now. */
}
}
break;
}
MiniGUI V1.2.6 introduces
SetNotificationCallback
function for the notification message handling of control. This function can set a callback function of the notification message for a control. When the control has a notification message, it will call the callback function, instead of sending the notification message to the parent window. New applications should use this function as far as possible to handle notification messages of a control to get a good program structure. All the sample programs for this guide use this interface to handle notification messages of a control.
The function in List 2 creates a simple dialog box by using the predefined control classes. When the user inputs data in unit of millimeter (mm) into the edit box, the system will display the corresponding data in unit of inch in the static control below the edit box, and return the data input by the user to the function calling the dialog box when the user select “OK” button.
List 2 Realizing a simple input dialog box using the predefined controls
#include <stdio.h>
#include <stdlib.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
/* Define dialog box template */
static DLGTEMPLATE DlgBoxInputLen =
{
WS_BORDER | WS_CAPTION,
WS_EX_NONE,
120, 150, 400, 160,
"请输入长度",
0, 0,
4, NULL,
0
};
#define IDC_SIZE_MM 100
#define IDC_SIZE_INCH 110
/*
* The dialog includes four controls in total, which are used to
* display prompt information, input value, display the
* transformed length value, and show a “OK” button to close the program
*/
static CTRLDATA CtrlInputLen [] =
{
{
CTRL_STATIC,
WS_VISIBLE | SS_SIMPLE,
10, 10, 380, 18,
IDC_STATIC,
"请输入长度(单位:毫米)",
0
},
{
CTRL_EDIT,
WS_VISIBLE | WS_TABSTOP | WS_BORDER,
10, 40, 380, 24,
IDC_SIZE_MM,
NULL,
0
},
{
CTRL_STATIC,
WS_VISIBLE | SS_SIMPLE,
10, 70, 380, 18,
IDC_SIZE_INCH,
"相当于 0.00 英寸",
0
},
{
CTRL_BUTTON,
WS_TABSTOP | WS_VISIBLE | BS_DEFPUSHBUTTON,
170, 100, 60, 25,
IDOK,
"确定",
0
}
};
/* This is the notification callback funciton of the input box. */
static void my_notif_proc (HWND hwnd, int id, int nc, DWORD add_data)
{
/* When the value in the input box is changed,
* get the value, transform it into inch,and display it in the inch box
*/
if (id == IDC_SIZE_MM && nc == EN_CHANGE) {
char buff [60];
double len;
GetWindowText (hwnd, buff, 32);
len = atof (buff);
len = len / 25.4;
sprintf (buff, "相当于 %.5f 英寸", len);
SetDlgItemText (GetParent (hwnd), IDC_SIZE_INCH, buff);
}
}
/* The dialog box callback function */
static int InputLenDialogBoxProc (HWND hDlg, int message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case MSG_INITDIALOG:
/*
* Save the pointer passed by the last parameter of DialogBoxIndirectParam
* in the form of window additonal data for future use.
*/
SetWindowAdditionalData (hDlg, lParam);
/* Set the notification callback function for the edit box.
*/
SetNotificationCallback (GetDlgItem (hDlg, IDC_SIZE_MM), my_notif_proc);
return 1;
case MSG_COMMAND:
switch (wParam) {
case IDOK:
{
char buff [40];
/* Get data from the input box, and save it in the pointer passed in.
*/
double* length = (double*) GetWindowAdditionalData (hDlg);
GetWindowText (GetDlgItem (hDlg, IDC_SIZE_MM), buff, 32);
*length = atof (buff);
}
case IDCANCEL:
EndDialog (hDlg, wParam);
break;
}
break;
}
return DefaultDialogProc (hDlg, message, wParam, lParam);
}
static void InputLenDialogBox (HWND hWnd, double* length)
{
DlgBoxInputLen.controls = CtrlInputLen;
DialogBoxIndirectParam (&DlgBoxInputLen, hWnd, InputLenDialogBoxProc, (LPARAM)length);
}
int MiniGUIMain (int argc, const char* argv[])
{
double length;
#ifdef _MGRM_PROCESSES
JoinLayer(NAME_DEF_LAYER , "input" , 0 , 0);
#endif
InputLenDialogBox (HWND_DESKTOP, &length);
/* Print the value input by the user in the dialog box to the terminal
*/
printf ("The length is %.5f mm.\n", length);
return 0;
}
#ifndef _MGRM_PROCESSES
#include <minigui/dti.c>
#endif
The running effect of the program in List 2 is shown in Figure 1. Please refer to the input.c file of the sample program package for this guide to get the complete source code of the program.
Figure 1 A simple input dialog box
In the Part IV
, we will introduce the predefined controls of MiniGUI. We will describe all the predefined controls in three aspects: the purpose and usage of the control, the styles, messages, and notification codes. We will also give the sample code of the controls.
Operations Specific to Control
MiniGUI provides some operation functions specific to control, as show in Table 2.
Table 2 Operation functions specific to control
Function
Purpose
Comment
GetNotificationCallback
Gets the notification callback procedure of a control
Appear in MiniGUI version 1.2.6
SetNotificationCallback
Sets the notification callback procedure of a control
^
NotifyParentEx
Sends a notification message to the parent
<< Foundation of Dialog Box Programming | Table of Contents | Advanced Programming of Control >>
Last updated