21 KiB
Foundation of Control Programming
- Control and Control Class
- Creating Control Instance by Using Predefined Control Class
- Topics Involved in Control Programming
- Operations Specific to Control
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 |
---|---|---|---|
Static Text | "static" | CTRL_STATIC | refer to Chapter 19 |
Button | "button" | CTRL_BUTTON | refer to Chapter 20 |
List Box | "listbox" | CTRL_LISTBOX | refer to Chapter 21 |
Single-Line Edit Box | "sledit" | CTRL_SLEDIT | refer to Chapter 22 |
Multi-Line Edit Box | "mledit" | CTRL_MLEDIT | (same with TRL_TEXTEDIT ) |
Text Edit Box | “textedit” | CTRL_TEXTEDIT | refer to Chapter 22 |
Combo Box | “combobox” | CTRL_COMBOBOX | refer to Chapter 23 |
Menu Button | "menubutton" | CTRL_MENUBUTTON | refer to Chapter 24 |
Progress Bar | "progressbar" | CTRL_PRORESSBAR | refer to Chapter 25 |
Trackbar | "trackbar" | CTRL_TRACKBAR | refer to Chapter 26 |
New Toolbar | "newtoolbar" | CTRL_NEWTOOLBAR | refer to Chapter 27 |
Property Sheet | "propsheet" | CTRL_PROPSHEET | refer to Chapter 28 |
Scrollable Window | "scrollwnd" | CTRL_SCROLLWND | refer to Chapter 29 |
Scrollable View | "scrollview" | CTRL_SCROLLVIEW | refer to Chapter 30 |
Tree View | "treeview" | CTRL_TREEVIEW | refer to Chapter 31 |
List View | "listview" | CTRL_LISTVIEW | refer to Chapter 32 |
Month Calendar | "monthcalendar" | CTRL_MONTHCALENDAR | refer to Chapter 33 |
SpinBox |
"spinbox" | CTRL_SPINBOX | refer to Chapter 34 |
Cool Bar | "coolbar" | CTRL_COOLBAR | refer to Chapter 35 |
Animation | "animation" | CTRL_ANIMATION | refer to Chapter 36 |
Grid View | “gridview” | CTRL_GRIDVIEW | refer to Chapter 37 |
Icon View | “iconview” | CTRL_ICONVIEW | refer to Chapter 38 |
Scrollbar | "scrollbar" | CTRL_SCROLLBAR | refer to Chapter 39 |
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 >>