57 KiB
Look-and-feel and UI effects
- Look and Feel Renderer and attributes of window elements
- Double Buffering Main Window
- Customization of Desktop
Look and Feel Renderer and attributes of window elements
MiniGUI 3.0 has totally different window and control's look and feel
implementation mechanism than previous version. The old version must configure
options and select UI style before compile the program, and it can only select
one of three styles, fashion, classic and flat. MiniGUI 3.0 has look and feel
renderer to draw the look-and-feel of window and control. MiniGUI 3.0 provides
four renderers for application, user can select any one when needs a renderer.
The advantage of renderer technology is, we can change look and feel of
application by modifying MiniGUI configuration file, but also by APIs
.
Application can even customize its own renderer. It is very convenience for
customized UI. The implementation of renderer has two parts as follow:
- Attributes of window elements, include the information of window elements, such as color, size, font and so on.
- Rendering method of window elements, it defines how to draw window elements.
MiniGUI renderer creates categories for attributes of each part of window and
control, defines drawing interface, so as to get a complete look and feel
renderer mechanism. MiniGUI 3.0 has four renderers, classic, flat, fashion and
skin. Classic
is default renderer, that means, application draws window and
control's look and feel by using classic renderer when MiniGUI is initializing.
Fashion renderer is supported by mGPlus component.
Application can select a specified renderer for certain window and define attribute of window element's look and feel. Application can also define its own renderer to draw the UI.
Attributes of Window Elements
MiniGUI defines the following window elements:
Table 1 Window elements and their names in configuration file and codes
Name in config file | Code Name | Meaning |
---|---|---|
caption | WE_METRICS_CAPTION |
Window caption size |
WE_FONT_CAPTION | Window caption font | |
fgc_active_caption |
WE_FGC_ACTIVE_CAPTION | Foreground color of active window caption |
bgca_active_caption |
WE_BGCA_ACTIVE_CAPTION | Gradient start color of active window caption background color |
bgcb_active_caption |
WE_BGCB_ACTIVE_CAPTION | Gradient end color of active window caption background color |
fgc_inactive_caption |
WE_FGC_INACTIVE_CAPTION | Foreground color of inactive window caption |
bgca_inactive_caption |
WE_BGCA_INACTIVE_CAPTION | Gradient start color of inactive window caption background color |
bgcb_inactive_caption |
WE_BGCB_INACTIVE_CAPTION | Gradient end color of inactive window caption background color |
menu | WE_METRICS_MENU | Height of menu item and menu bar |
WE_FONT_MENU | Menu font | |
fgc_menu |
WE_FGC_MENU | Foreground color of menu |
bgc_menu |
WE_BGC_MENU | Background color of menu |
border | WE_METRICS_WND_BORDER | Width of window border |
fgc_active_border |
WE_FGC_ACTIVE_WND_BORDER | Border color of active window |
fgc_inactive_border |
WE_FGC_INACTIVE_WND_BORDER | Border color of inactive window |
scrollbar | WE_METRICS_SCROLLBAR | Scrollbar size |
fgc_msgbox |
WE_FGC_MESSAGEBOX | Foreground color of message box |
WE_FONT_MESSAGEBOX | Font of message box | |
fgc_tip |
WE_FGC_TOOLTIP | Foreground color of tooltip |
bgc_tip |
WE_BGC_TOOLTIP | Background color of tooltip |
WE_FONT_TOOLTIP | Tooltip font | |
fgc_window |
WE_FGC_WINDOW | Foreground color of window |
bgc_window |
WE_BGC_WINDOW | Background color of window |
fgc_3dbox |
WE_FGC_THREED_BODY | Color of symbols on 3D body, such as check mark and arrow |
mainc_3dbox |
WE_MAINC_THREED_BODY | Color of 3D body (border and face) |
fgc_selected_item |
WE_FGC_SELECTED_ITEM | Foreground color of selected menu item (list item) |
bgc_selected_item |
WE_BGC_SELECTED_ITEM | Background color of selected menu item (list item) |
bgc_selected_lostfocus |
WE_BGC_SELECTED_LOSTFOCUS | Background color when selected menu item (list item) lost focus |
fgc_disabled_item |
WE_FGC_DISABLED_ITEM | Foreground color of disabled menu item (list item) |
bgc_disabled_item |
WE_BGC_DISABLED_ITEM | Background color of disabled menu item (list item) |
fgc_hilight_item |
WE_FGC_HIGHLIGHT_ITEM | Foreground color of highlighted menu item (list item) |
bgc_hilight_item |
WE_BGC_HIGHLIGHT_ITEM | Background color of highlighted menu item (list item) |
fgc_significant_item |
WE_FGC_SIGNIFICANT_ITEM | Foreground color of significant menu item (list item) |
bgc_significant_item |
WE_BGC_SIGNIFICANT_ITEM | Background color of significant menu item (list item) |
bgc_desktop |
WE_BGC_DESKTOP | Background color of desktop |
Above table introduces all window elements. The name in configuration means
this element's name in MiniGUI.cfg
(MiniGUI configuration file). User can
modify the value of attributes of window element in the configuration file to
change window's look and feel. Code name is to specify the window element when
modifying the attribute of window element by using function interface.
Attributes of skin renderer's window skin
To replace SKIN
APIs
in MGExt
library with renderer, MiniGUI 3.0 uses
skin
renderer. Skin renderer has not only window attributes of other renderers, but
also attributes of window skin. The descriptions of attributes of window skin
are as follow:
Table 2 Attributes of window skin and their names in configuration file and codes
Name in config file | Code Name | Meaning |
---|---|---|
skin_bkgnd |
WE_LFSKIN_WND_BKGND | Skin image of desktop background |
skin_caption |
WE_LFSKIN_CAPTION | Skin image of window caption |
skin_caption_btn |
WE_LFSKIN_CAPTION_BTN | Skin image of window caption button |
skin_scrollbar_hshaft |
WE_LFSKIN_SCROLLBAR_HSHAFT | Skin image of horizontal scrollbar shaft |
skin_scrollbar_vshaft |
WE_LFSKIN_SCROLLBAR_VSHAFT | Skin image of vertical scrollbar shaft |
skin_scrollbar_hthumb |
WE_LFSKIN_SCROLLBAR_HTHUMB | Skin image of horizontal scrollbar thumb |
skin_scrollbar_vthumb |
WE_LFSKIN_SCROLLBAR_VTHUMB | Skin image of vertical scrollbar thumb |
skin_scrollbar_arrows |
WE_LFSKIN_SCROLLBAR_ARROWS | Skin image of scrollbar arrow |
skin_tborder |
WE_LFSKIN_BORDER_TOP | Skin image of top border |
skin_bborder |
WE_LFSKIN_BORDER_BOTTOM | Skin image of bottom border |
skin_lborder |
WE_LFSKIN_BORDER_LEFT | Skin image of left border |
skin_rborder |
WE_LFSKIN_BORDER_RIGHT | Skin image of right border |
skin_arrows |
WE_LFSKIN_ARROWS | Skin image of arrow |
skin_arrows_shell |
WE_LFSKIN_ARROWS_SHELL | Skin image of arrow's shell |
skin_pushbtn |
WE_LFSKIN_PUSHBUTTON | Skin image of push button |
skin_radiobtn |
WE_LFSKIN_RADIOBUTTON | Skin image of radio button |
skin_checkbtn |
WE_LFSKIN_CHECKBUTTON | Skin image of check button |
skin_tree |
WE_LFSKIN_TREE | Skin image of tree control |
skin_header |
WE_LFSKIN_HEADER | Skin image of header |
skin_tab |
WE_LFSKIN_TAB | Skin image of tab on property sheet |
skin_tbslider_h |
WE_LFSKIN_TBSLIDER_H | Skin image of horizontal sliderbar |
skin_tbslider_v |
WE_LFSKIN_TBSLIDER_V | Skin image of vertical sliderbar |
skin_trackbar_horz |
WE_LFSKIN_TRACKBAR_HORZ | Skin image of horizontal trackbar |
skin_trackbar_vert |
WE_LFSKIN_TRACKBAR_VERT | Skin image of vertical trackbar |
skin_progressbar_htrack |
WE_LFSKIN_PROGRESS_HTRACKBAR | Skin image of horizontal progress bar |
skin_progressbar_vtrack |
WE_LFSKIN_PROGRESS_VTRACKBAR | Skin image of vertical progress bar |
skin_progressbar_hchunk |
WE_LFSKIN_PROGRESS_HCHUNK | Skin image of horizontal progress chunk |
skin_progressbar_vchunk |
WE_LFSKIN_PROGRESS_VCHUNK | Skin image of vertical progress chunk |
Operating function of window attribute
We can change window attribute before execute program and control look and feel
of window by changing MiniGUI configuration file. We can also customize look
and feel of window in the program by using APIs
. To help with operating of
window attribute, MiniGUI defines the following API to implement operating of
window attribute.
MG_EXPORT DWORD GUIAPI GetWindowElementAttr (HWND hwnd, int we_attr_id);
MG_EXPORT DWORD GUIAPI SetWindowElementAttr (HWND hwnd, int we_attr_id,
DWORD we_attr);
MG_EXPORT gal_pixel GUIAPI GetWindowElementPixelEx (HWND hwnd,
HDC hdc, int we_attr_id);
MG_EXPORT BOOL GUIAPI SetWindowElementRenderer (HWND hWnd,
const char* werdr_name, const WINDOW_ELEMENT_ATTR* we_attrs);
we_attr_id
in above all functions is attribute ID of window element. This
ID
must be one of code names in Table 1 and 2.
GetWindowElementAttr
is to get certain element's attribute ID of specified
window. hwnd is window handle and we_attr_id
is attribute ID of window
element.
The following codes are for getting color of 3D body's border and face.
DWORD main_c;
main_c = GetWindowElementAttr (hwnd, WE_MAINC_THREED_BODY);
SetWindowElementAttr
is to set certain element's attribute ID of specified
window. hwnd is window handle, we_attr_id
is attribute ID of window element
and
we_attr
is attribute value.
In the following codes, it gets min height of menu first, then compares the height with height of window. Window's min height will be set to menu's if height of menu is greater than window's.
int menu_height_min;
/** expect menu size of renderer*/
int menu_height_expect;
font_size = ((PLOGFONT)GetWindowElementAttr (hwnd, WE_FONT_MENU))->size;
menu_height_min = font_size + (LFRDR_MENUITEMOFFY_MIN << 1);
menu_height_expect = GetWindowElementAttr (hwnd, WE_METRICS_MENU);
/** reset menu height */
if (menu_height_expect < menu_height_min) {
SetWindowElementAttr (hwnd, WE_METRICS_MENU, menu_height_min);
}
GetWindowElementPixelEx
is to get color value of window element. hwnd is
window
handle, hdc is DC
handle and we_attr_id
is attribute ID of window
element.
The following codes can get gradient start color of window caption background.
gal_pixel active_color;
active_color = GetWindowElementPixelEx(hWnd, hdc, WE_BGCA_ACTIVE_CAPTION);
SetWindowElementRenderer
is to set current renderer of window and change
attributes of window. hWnd
is window handle, werdr_name
is renderer's name
which will be set, we_attrs
is structure array of modified attribute of
window.
The ID of last element in array is -1, it means, this is the end.
WINDOW_ELEMENT_ATTR
structure is as follow:
typedef struct _WINDOW_ELEMENT_ATTR {
/** The attribute identifier. */
int we_attr_id;
/** The attribute value. */
DWORD we_attr;
} WINDOW_ELEMENT_ATTR;
The first member in structure is attribute id of window element which needs to be changed, the second one is needed attribute value.
The following codes set flat as current window renderer and modify some attributes of window.
WINDOW_ELEMENT_ATTR my_we_attrs [] = {
{FGC_WINDOW, 0x00FFFFFF},
{MWM_BORDER, 2},
{SYSLOGFONT_CAPTION, (DWORD)my_caption_font},
{-1, 0}
SetWindowElementRenderer (hWnd, "flat", my_we_atts);
};
Renderer Management
Renderer consists of two parts: attribute of window element and matches render
method. We have introduced attribute of window and relevant function
interfaces, and then we introduce render method and how to use renderer. The
structure which is used by renderer is WINDOW_ELEMENT_RENDERER
, it consists
of
renderer name, pointer of render method interface and relevant attribute of
window.
typedef struct _WINDOW_ELEMENT_RENDERER {
const char name[LEN_RENDERER_NAME+1];
int (*init) (PWERENDERER renderer);
int (*deinit) (PWERENDERER renderer);
DWORD (*calc_3dbox_color) (DWORD color, int flag);
void (*draw_3dbox) (HDC hdc, const RECT* pRect, DWORD color, DWORD flag);
void (*draw_radio) (HDC hdc, const RECT* pRect, DWORD color, int status);
void (*draw_checkbox) (HDC hdc, const RECT* pRect, DWORD color,
int status);
void (*draw_checkmark) (HDC hdc, const RECT* pRect, DWORD color,
int status);
void (*draw_arrow) (HWND hWnd, HDC hdc, const RECT* pRect, DWORD color, int status);
void (*draw_fold) (HWND hWnd, HDC hdc, const RECT* pRect, DWORD color,
int status, int next);
void (*draw_focus_frame) (HDC hdc, const RECT *pRect, DWORD color);
void (*draw_normal_item) (HWND hWnd, HDC hdc, const RECT* pRect,
DWORD color);
void (*draw_hilite_item) (HWND hWnd, HDC hdc, const RECT* pRect,
DWORD color);
void (*draw_disabled_item) (HWND hWnd, HDC hdc, const RECT* pRect,
DWORD color);
void (*draw_significant_item) (HWND hWnd, HDC hdc, const RECT* pRect,
DWORD color);
void (*draw_push_button) (HWND hWnd, HDC hdc, const RECT* pRect,
DWORD color1, DWORD color2, int status);
void (*draw_radio_button) (HWND hWnd, HDC hdc, const RECT* pRect, int status);
void (*draw_check_button) (HWND hWnd, HDC hdc, const RECT* pRect, int status);
void (*draw_border) (HWND hWnd, HDC hdc, BOOL is_active);
void (*draw_caption) (HWND hWnd, HDC hdc, BOOL is_active);
void (*draw_caption_button) (HWND hwnd, HDC hdc, int ht_code, int state);
void (*draw_scrollbar) (HWND hWnd, HDC hdc, int sb_pos);
void (*calc_trackbar_rect) (HWND hWnd, LFRDR_TRACKBARINFO *info,
DWORD dwStyle, const RECT* rcClient, RECT* rcRuler,
RECT* rcBar, RECT* rcBorder);
void (*draw_trackbar) (HWND hWnd, HDC hdc, LFRDR_TRACKBARINFO *info);
int (*calc_we_area) (HWND hWnd, int which, RECT* we_area);
int (*calc_we_metrics) (HWND hWnd,
LFRDR_WINSTYLEINFO* style_info, int which);
int (*hit_test) (HWND hWnd, int x, int y);
int (*on_click_hotspot) (HWND hWnd, int which);
void (*draw_custom_hotspot) (HWND hWnd, HDC hdc, int ht_code, int state);
void (*calc_thumb_area) (HWND hWnd, BOOL vertical,
LFSCROLLBARINFO* sb_info);
void (*disabled_text_out) (HWND hWnd, HDC hdc, const char* spText,
PRECT rc, DWORD dt_fmt);
void (*draw_tab) (HWND hWnd, HDC hdc, RECT *rect, char *title,
DWORD color, int flag, HICON icon);
void (*draw_progress) (HWND hWnd, HDC hdc,
int nMax, int nMin, int nPos, BOOL fVertical);
void (*draw_header) (HWND hWnd, HDC hdc, const RECT* pRect, DWORD color);
DWORD (*on_get_rdr_attr) (int we_attr_id);
DWORD (*on_set_rdr_attr) (int we_attr_id, DWORD we_attr, BOOL change);
void (*erase_background) (HWND hWnd, HDC hdc, const RECT *rect);
void (*draw_normal_menu_item) (HWND hWnd, HDC hdc, const RECT* pRect,
DWORD color);
void (*draw_hilite_menu_item) (HWND hWnd, HDC hdc, const RECT* pRect,
DWORD color);
void (*draw_disabled_menu_item) (HWND hWnd, HDC hdc, const RECT* pRect,
DWORD color);
int we_metrics [WE_METRICS_NUMBER];
DWORD we_colors [WE_COLORS_NUMBER][3];
PLOGFONT we_fonts [WE_FONTS_NUMBER];
HICON we_icon [2][SYSICO_ITEM_NUMBER];
unsigned int refcount;
const void* private_info;
} WINDOW_ELEMENT_RENDERER;
The following table explains each member in the structure.
Table 3 Explanation of renderer structure member
Member Name | Meaning |
---|---|
name | Renderer name, length is LEN_RENDERER_NAME . Macro LEN_RENDERER_NAME is defined as 15 |
init | Renderer initialization function pointer. It initializes basic renderer information which are window attribute information and private information, such as size, font and color of window element |
deinit | Renderer destroy function pointer. It frees resources that were allocated by renderer |
calc_3dbox_color |
Calculating function pointer of 3D box's color. It gets color value according to calculating flat and color of 3D box's border and face |
draw_3dbox |
Drawing function pointer of 3D box |
draw_radio |
Drawing function pointer of radio box |
draw_checkbox |
Drawing function pointer of check box without check mark |
draw_checkmark |
Drawing function pointer of check box with check mark |
draw_arrow |
Drawing function pointer of arrow |
draw_fold |
Drawing function pointer of fold/unfold |
draw_focus_frame |
Drawing function pointer of focus frame |
draw_normal_item |
Drawing function pointer of list item in normal state |
draw_hilite_item |
Drawing function pointer of list item in highlighted state |
draw_disabled_item |
Drawing function pointer of disabled list item |
draw_significant_item |
Drawing function pointer of significant list item |
draw_push_button |
Drawing function pointer of push button |
draw_radio_button |
Drawing function pointer of radio button |
draw_check_button |
Drawing function pointer of check button |
draw_border |
Drawing function pointer of window border |
draw_caption |
Drawing function pointer of window caption |
draw_caption_button |
Drawing function pointer of window caption button. The buttons include minimize/maximize/close button |
draw_scrollbar |
Drawing function pointer of scrollbar |
calc_trackbar_rect |
Drawing function pointer of rectangle of track bar |
draw_trackbar |
Drawing function pointer of track bar |
calc_we_area |
Calculating function pointer of window element area. The areas include border, caption, caption buttons, toolbar, menu, client area and horizontal/vertical scrollbar |
calc_we_metrics |
Calculating function pointer of window element size. The elements are as same as elements in calc_we_area |
hit_test |
Function pointer of window element clicked by mouse |
on_click_hotspot |
Corresponding function pointer when mouse clicks hot spot |
draw_custom_hotspot |
Drawing function pointer of hot spot |
calc_thumb_area |
Calculating function pointer of thumb of horizontal/vertical scrollbar |
disabled_text_out |
Output function pointer of disabled area text |
draw_tab |
Drawing function pointer of tab on property sheet |
draw_progress |
Drawing function pointer of progress bar |
draw_header |
Drawing function pointer of header on listbox or grid view control |
on_get_rdr_attr |
Get function pointer of renderer's private information |
on_set_rdr_attr |
Set function pointer of renderer's private information |
erase_background |
Drawing function pointer of erasing window background |
draw_normal_menu_item |
Drawing function pointer of menu item in normal state |
draw_hilite_menu_item |
Drawing function pointer of menu item in highlighted state |
draw_disabled_menu_item |
Drawing function pointer of disabled menu item |
we_metrics |
Attribute of window size |
we_colors |
Attribute of window color |
we_fonts |
Attribute of window font |
we_icon |
Attribute of window icon handle |
refcount | Attribute of window reference counter |
private_info |
Pointer of renderer's private information |
MiniGUI provides the following API to manage renderer:
GetWindowRendererFromName
: Get renderer from name. Function prototype is as follows:
MG_EXPORT const WINDOW_ELEMENT_RENDERER* GUIAPI GetWindowRendererFromName (const char* name);
AddWindowElementRenderer
: Add renderer to MiniGUI. Function prototype is as follows:
MG_EXPORT BOOL GUIAPI AddWindowElementRenderer (const char* name, const WINDOW_ELEMENT_RENDERER* we_rdr);
RemoveWindowElementRenderer
: Remove renderer from MiniGUI. Function prototype is as follow:
MG_EXPORT BOOL GUIAPI RemoveWindowElementRenderer (const char* name);
GetDefaultWindowElementRenderer
: Get default renderer. Function prototype is as follow:
MG_EXPORT const WINDOW_ELEMENT_RENDERER* GUIAPI GetDefaultWindowElementRenderer (void);
SetDefaultWindowElementRenderer
: Set default renderer. Function prototype is as follow:
MG_EXPORT const char* GUIAPI SetDefaultWindowElementRenderer (const char* name);
SetWindowElementRenderer
: Specify renderer. Function prototype is as follow:
MG_EXPORT BOOL GUIAPI SetWindowElementRenderer (HWND hWnd, const char* werdr_name, const WINDOW_ELEMENT_ATTR* we_attrs);
Creating main window
It needs more arguments to create main window after draw a window by using
renderer, for API compatible, MiniGUI created a new function,
CreateMainWindowEx
, and packaged the old creating function. Function
prototype
is as follow.
MG_EXPORT HWND GUIAPI CreateMainWindowEx (PMAINWINCREATE pCreateInfo,
const char* werdr_name, const WINDOW_ELEMENT_ATTR* we_attrs,
const char* window_name, const char* layer_name);
static inline HWND GUIAPI CreateMainWindow (PMAINWINCREATE pCreateInfo)
{
return CreateMainWindowEx (pCreateInfo, NULL, NULL, NULL, NULL);
}
pCreateInfo
Main window structure, we have introduced it in chapter 3, Window and Message.window_name
andlayer_name
are reserved arguments for later version.werdr_name
The name of window element's renderer which will be used. Will use default renderer if it isNULL
.we_attrs
Attribute table of window element's look and feel. Will use default attribute table if it isNULL
.
Creating control
Similar with main window creating, there is also a new function,
CreateWindowEx2
, to create control. MiniGUI also packaged old creating
function, CreateWindowEx
.
MG_EXPORT 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)
These functions have be introduced in chapter 5, Foundation of Control Programming.
Creating dialog box
- Modal dialog box creating
MG_EXPORT int GUIAPI DialogBoxIndirectParamEx (PDLGTEMPLATE pDlgTemplate,
HWND hOwner, WNDPROC DlgProc, LPARAM lParam,
const char* werdr_name, WINDOW_ELEMENT_ATTR* we_attrs,
const char* window_name, const char* layer_name);
static inline int GUIAPI DialogBoxIndirectParam (PDLGTEMPLATE pDlgTemplate,
HWND hOwner, WNDPROC DlgProc, LPARAM lParam)
{
return DialogBoxIndirectParamEx (pDlgTemplate, hOwner, DlgProc, lParam,
NULL, NULL, NULL, NULL);
}
- Modeless dialog box creating
MG_EXPORT HWND GUIAPI CreateMainWindowIndirectParamEx (PDLGTEMPLATE pDlgTemplate,
HWND hOwner, WNDPROC DlgProc, LPARAM lParam,
const char* werdr_name, WINDOW_ELEMENT_ATTR* we_attrs,
const char* window_name, const char* layer_name);
static inline HWND GUIAPI CreateMainWindowIndirectParam (PDLGTEMPLATE pDlgTemplate,
HWND hOwner, WNDPROC DlgProc, LPARAM lParam)
{
return CreateMainWindowIndirectParamEx (pDlgTemplate, hOwner, DlgProc, lParam,
NULL, NULL, NULL, NULL);
}
Above functions end in Ex are new added functions. They have been introduced in chapter 4, Foundation of Dialog Box Programming.
Double Buffering Main Window
Double buffering main window mechanism is a window rendering method which is
provide by MiniGUI. In this mechanism, when drawing main window, the window is
drawn in matched memory DC
first, and then we can calculate the data in DC
by
using various algorithms to get various special display effects, such as
push-pull, scrolling and page turning. Another function of the mechanism is
improving the efficient of window drawing and solving blinking issue when doing
window drawing.
Extension Style of Double Buffering Main Window
We can create main window or dialog box with memory DC
which matches window
DC
by using the extension style of double buffering main window. The definition is
as follow:
#define WS_EX_AUTOSECONDARYDC 0x00001000L
The following code is an example for creating main window with double buffer.
HWND hMainWnd;
MAINWINCREATE CreateInfo;
CreateInfo.dwStyle = WS_NONE;
CreateInfo.dwExStyle = WS_EX_AUTOSECONDARYDC;
CreateInfo.spCaption = "Watch";
CreateInfo.hMenu = 0;
CreateInfo.hCursor = GetSystemCursor(0);
CreateInfo.hIcon = 0;
CreateInfo.MainWindowProc = WatchWinProc;
CreateInfo.lx = 0;
CreateInfo.ty = 0;
CreateInfo.rx = 240;
CreateInfo.by = 320;
CreateInfo.iBkColor = PIXEL_lightwhite;
CreateInfo.dwAddData = 0;
CreateInfo.hHosting = hosting;
hMainWnd = CreateMainWindow (&CreateInfo);
Functions of double buffering window mechanism
- Double buffers
DC
creating function,CreateSecondaryDC
, creates compatible memoryDC
and returns according to passed window's size.
MG_EXPORT HDC GUIAPI CreateSecondaryDC (HWND hwnd);
SetSecondaryDC
sets already made memoryDC
as one of double buffers of target main window. It also copies callback function from double buffer's screenDC
.
typedef int (* ON_UPDATE_SecondaryDC)(HWND hwnd, HDC secondary_dc, HDC real_dc, cont RECT* update_rc, DWORD area_flags);
MG_EXPORT HDC GUIAPI SetSecondaryDC (HWND hwnd, HDC secondary_dc, ON_UPDATE_SECONDARYDC on_update_secondarydc);
It is necessary to note the following when invoking SetSecondaryDC
:
- If main window has
WS_EX_AUTOSecondaryDC
style, it will disable this style and invokeDeleteSecondaryDC
to delete exist double buffers and returnHDC_SCREEN
. - If main window doesn't have
WS_EX_AUTOSecondaryDC
style, it will return the handle of exist double buffers. The exist double buffers is managed by application. - If
HDC_SCREEN
is passed, it will cancel double buffering mechanism of window. - If passed
ON_UPDATE_SecondaryDC
isNULL
, MiniGUI will not draw the contents of screenDC
to screen automatically, user needs to copy the contents of double buffers to screenDC
by usingBitBlt
function. Otherwise the application takes responsibility of copying double buffers to screenDC
to get UI effects.
In the following code, main window is drawn on double buffer after set double buffer of main window.
HDC hdc;
hdc = GetSecondaryDC (hWnd);
SetSecondaryDC(hWnd, hdc, DoubleBufferProc);
UpdateAll (hWnd, TRUE);
SetSecondaryDC(hWnd, hdc, NULL);
GetSecondaryDC
can get the handle of double buffer.
MG_EXPORT HDC GUIAPI GetSecondaryDC (HWND hwnd);
GetSecondaryClientDC
is to get theDC
of double buffering window's client. If the window doesn't support double buffer, it returns theDC
of window's client, equal toGetClientDC
.
MG_EXPORT HDC GUIAPI GetSecondaryClientDC (HWND hwnd);
ReleaseSecondaryDC
releases theDC
of double buffer. It will do nothing, it theDC
is main window double buffer'sDC
.
MG_EXPORT void GUIAPI ReleaseSecondaryDC (HWND hwnd, HDC hdc);
DeleteSecondaryDC
deletes theDC
created byCreateSecondaryDC
.
static inline void GUIAPI DeleteSecondaryDC (HWND hwnd);
GetSecondarySubDC
is only for double buffer, it creates sub-DC based on theDC
of private window, so the sub-DC can be the clientDC
of main window or be regarded to control'sDC
. Both main window (or its control) withWS_EX_SecondaryDC
style is drawing non-client and the return value ofBeginPaint
should useGetSecondarySubDC
to get sub-DC of double bufferDC
, to ensure that all drawings in main window is on double bufferDC
.
HDC GUIAPI GetSecondarySubDC (HDC secondary_dc, HWND hwnd_main, HWND hwnd_child, BOOL client);
ReleaseSecondarySubDC
releases sub-DC of privateDC
.
void GUIAPI ReleaseSecondarySubDC (HDC secondary_subdc, HWND hwnd_child);
Sample program of double buffering mechanism
- Create main window with double buffer, and then add the codes of UI effects before message loop.
MSG Msg;
HWND hMainWnd;
MAINWINCREATE CreateInfo;
CreateInfo.dwStyle = WS_NONE;
CreateInfo.dwExStyle = WS_EX_AUTOSECONDARYDC;
CreateInfo.spCaption = "Watch";
CreateInfo.hMenu = 0;
CreateInfo.hCursor = GetSystemCursor(0);
CreateInfo.hIcon = 0;
CreateInfo.MainWindowProc = WatchWinProc;
CreateInfo.lx = 0;
CreateInfo.ty = 0;
CreateInfo.rx = 240;
CreateInfo.by = 320;
CreateInfo.iBkColor = PIXEL_lightwhite;
CreateInfo.dwAddData = 0;
CreateInfo.hHosting = hosting;
hMainWnd = CreateMainWindow (&CreateInfo);
if (hMainWnd == HWND_INVALID)
return -1;
switch (ue_type) {
MSG Msg;
HWND hMainWnd;
MAINWINCREATE CreateInfo;
CreateInfo.dwStyle = WS_NONE;
CreateInfo.dwExStyle = WS_EX_AUTOSECONDARYDC;
CreateInfo.spCaption = "Watch";
CreateInfo.hMenu = 0;
CreateInfo.hCursor = GetSystemCursor(0);
CreateInfo.hIcon = 0;
CreateInfo.MainWindowProc = WatchWinProc;
CreateInfo.lx = 0;
CreateInfo.ty = 0;
CreateInfo.rx = 240;
CreateInfo.by = 320;
CreateInfo.iBkColor = PIXEL_lightwhite;
CreateInfo.dwAddData = 0;
CreateInfo.hHosting = hosting;
hMainWnd = CreateMainWindow (&CreateInfo);
if (hMainWnd == HWND_INVALID)
return -1;
//Add the codes of UI effects.
switch (ue_type) {
case 1:
ue_1_start (hMainWnd); //fade-in fade-out
break;
case 2:
ue_2_start (hMainWnd); //push-pull
break;
case 3:
ue_3_start (hMainWnd); //Scrolling
break;
default:
ShowWindow (hMainWnd, SW_SHOWNORMAL);
break;
}
while (GetMessage (&Msg, hMainWnd)) {
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
MainWindowThreadCleanup (hMainWnd);
return 0;
- The codes of three UI effects
/fade-in fade-out
static void ue_1_start (HWND hwnd)
{
MSG msg;
HDC sec_dc;
sec_dc = GetSecondaryDC (hwnd);
SetSecondaryDC (hwnd, sec_dc, ON_UPDSECDC_DONOTHING);
ShowWindow (hwnd, SW_SHOWNORMAL);
/* wait for MSG_IDLE */
while (GetMessage (&msg, hwnd)) {
if (msg.message == MSG_IDLE)
break;
DispatchMessage (&msg);
}
SetMemDCAlpha (sec_dc, MEMDC_FLAG_SRCALPHA, 64);
BitBlt (sec_dc, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
usleep (100000);
SetMemDCAlpha (sec_dc, MEMDC_FLAG_SRCALPHA, 128);
BitBlt (sec_dc, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
usleep (100000);
SetMemDCAlpha (sec_dc, 0, 0);
BitBlt (sec_dc, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
/* restore to default behavior */
SetSecondaryDC (hwnd, sec_dc, ON_UPDSECDC_DEFAULT);
}
//Push-pull
static void ue_2_start (HWND hwnd)
{
MSG msg;
HWND hosting;
HDC sec_dc_active, sec_dc_hosting;
/* disable output of the hosting and the active main windows */
hosting = GetHosting (hwnd);
sec_dc_hosting = GetSecondaryDC (hosting);
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DONOTHING);
sec_dc_active = GetSecondaryDC (hwnd);
SetSecondaryDC (hwnd, sec_dc_active, ON_UPDSECDC_DONOTHING);
/* get the content of the active main window */
ShowWindow (hwnd, SW_SHOWNORMAL);
/* wait for MSG_IDLE */
while (GetMessage (&msg, hwnd)) {
if (msg.message == MSG_IDLE)
break;
DispatchMessage (&msg);
}
/* push and poll */
BitBlt (sec_dc_hosting, 0, 0, 240, 320, HDC_SCREEN, -60, 0, 0);
BitBlt (sec_dc_active, 0, 0, 60, 320, HDC_SCREEN, 240-60, 0, 0);
usleep (100000);
BitBlt (sec_dc_hosting, 0, 0, 240, 320, HDC_SCREEN, -120, 0, 0);
BitBlt (sec_dc_active, 0, 0, 120, 320, HDC_SCREEN, 240-120, 0, 0);
usleep (100000);
BitBlt (sec_dc_active, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
/* restore to default behavior */
SetSecondaryDC (hwnd, sec_dc_active, ON_UPDSECDC_DEFAULT);
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DEFAULT);
}
//Scrolling
static void ue_3_start (HWND hwnd)
{
MSG msg;
HWND hosting;
HDC sec_dc_active, sec_dc_hosting;
/* disable output of the hosting and the active main windows */
hosting = GetHosting (hwnd);
sec_dc_hosting = GetSecondaryDC (hosting);
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DONOTHING);
sec_dc_active = GetSecondaryDC (hwnd);
SetSecondaryDC (hwnd, sec_dc_active, ON_UPDSECDC_DONOTHING);
/* get the content of the active main window */
ShowWindow (hwnd, SW_SHOWNORMAL);
/* wait for MSG_IDLE */
while (GetMessage (&msg, hwnd)) {
if (msg.message == MSG_IDLE)
break;
DispatchMessage (&msg);
}
BitBlt (sec_dc_hosting, 30, 0, 120-30, 320, HDC_SCREEN, 0, 0, 0);
BitBlt (sec_dc_hosting, 120, 0, 120-30, 320, HDC_SCREEN, 120+30, 0, 0);
BitBlt (sec_dc_active, 120-30, 0, 30+30, 320, HDC_SCREEN, 120-30, 0, 0);
usleep (100000);
BitBlt (sec_dc_hosting, 60, 0, 120-60, 320, HDC_SCREEN, 0, 0, 0);
BitBlt (sec_dc_hosting, 120, 0, 120-60, 320, HDC_SCREEN, 120+60, 0, 0);
BitBlt (sec_dc_active, 120-60, 0, 60+60, 320, HDC_SCREEN, 120-60, 0, 0);
usleep (100000);
BitBlt (sec_dc_active, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
/* restore to default behavior */
SetSecondaryDC (hwnd, sec_dc_active, ON_UPDSECDC_DEFAULT);
}
- Invoke UI effects codes in window close message
......
case MSG_CLOSE:
......
switch (_ue_type) {
case 1:
ue_1_term (hWnd);
break;
case 2:
ue_2_term (hWnd);
break;
case 3:
ue_3_term (hWnd);
break;
}
DestroyMainWindow (hWnd);
return 0;
......
- The codes of three UI effects when window is closing
//fade-in fade-out
static void ue_1_term (HWND hwnd)
{
HWND hosting;
HDC sec_dc_active, sec_dc_hosting;
hosting = GetHosting (hwnd);
sec_dc_active = GetSecondaryDC (hwnd);
SetSecondaryDC (hwnd, sec_dc_active, ON_UPDSECDC_DONOTHING);
sec_dc_hosting = GetSecondaryDC (hosting);
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DONOTHING);
SetMemDCAlpha (sec_dc_hosting, MEMDC_FLAG_SRCALPHA, 64);
BitBlt (sec_dc_hosting, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
usleep (100000);
SetMemDCAlpha (sec_dc_hosting, MEMDC_FLAG_SRCALPHA, 128);
BitBlt (sec_dc_hosting, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
usleep (100000);
SetMemDCAlpha (sec_dc_hosting, 0, 0);
BitBlt (sec_dc_hosting, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
/* restore to default behavior */
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DEFAULT);
}
//Push-pull
static void ue_2_term (HWND hwnd)
{
HWND hosting;
HDC sec_dc_active, sec_dc_hosting;
sec_dc_active = GetSecondaryDC (hwnd);
SetSecondaryDC (hwnd, sec_dc_active, ON_UPDSECDC_DONOTHING);
hosting = GetHosting (hwnd);
sec_dc_hosting = GetSecondaryDC (hosting);
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DONOTHING);
/* push and poll */
BitBlt (sec_dc_hosting, 240-60, 0, 60, 320, HDC_SCREEN, 0, 0, 0);
BitBlt (sec_dc_active, 0, 0, 240-60, 320, HDC_SCREEN, 60, 0, 0);
usleep (100000);
BitBlt (sec_dc_hosting, 240-120, 0, 120, 320, HDC_SCREEN, 0, 0, 0);
BitBlt (sec_dc_active, 0, 0, 120, 320, HDC_SCREEN, 120, 0, 0);
usleep (100000);
BitBlt (sec_dc_hosting, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
/* restore to default behavior */
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DEFAULT);
}
//Scrolling
static void ue_3_term (HWND hwnd)
{
HWND hosting;
HDC sec_dc_active, sec_dc_hosting;
sec_dc_active = GetSecondaryDC (hwnd);
SetSecondaryDC (hwnd, sec_dc_active, ON_UPDSECDC_DONOTHING);
hosting = GetHosting (hwnd);
sec_dc_hosting = GetSecondaryDC (hosting);
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DONOTHING);
BitBlt (sec_dc_hosting, 60, 0, 120-60, 320, HDC_SCREEN, 0, 0, 0);
BitBlt (sec_dc_hosting, 120, 0, 120-60, 320, HDC_SCREEN, 120+60, 0, 0);
BitBlt (sec_dc_active, 120-60, 0, 60+60, 320, HDC_SCREEN, 120-60, 0, 0);
usleep (100000);
BitBlt (sec_dc_hosting, 30, 0, 120-30, 320, HDC_SCREEN, 0, 0, 0);
BitBlt (sec_dc_hosting, 120, 0, 120-30, 320, HDC_SCREEN, 120+30, 0, 0);
BitBlt (sec_dc_active, 120-30, 0, 30+30, 320, HDC_SCREEN, 120-30, 0, 0);
usleep (100000);
BitBlt (sec_dc_hosting, 0, 0, 240, 320, HDC_SCREEN, 0, 0, 0);
/* restore to default behavior */
SetSecondaryDC (hosting, sec_dc_hosting, ON_UPDSECDC_DEFAULT);
}
- Three UI effects
Figure 1 UI effect of double buffering main window
Customization of Desktop
MiniGUI provides a set of desktop window customization interfaces as callback functions. Through these interfaces, application can control desktop window to response each message, it is similar to the desktop of Windows.
Structure of Desktop Customization
typedef struct _DESKTOPOPS {
/** called when starting a new session, and return a context */
void* (*init) (void);
/** called when terminating a seesion */
void (*deinit) (void* context);
/** called when the desktop should be repainted */
void (*paint_desktop) (void* context,
HDC dc_desktop, const RECT* inv_rc);
/** the keyboard event handler for the desktop */
void (*keyboard_handler) (void* context,
int message, WPARAM wParam, LPARAM lParam);
/** the mouse event handler for the desktop */
void (*mouse_handler) (void* context,
int message, WPARAM wParam, LPARAM lParam);
/** the desktop menu customizer */
void (*customize_desktop_menu) (void* context,
HMENU hmenu, int start_pos);
/** the desktop menu command handler */
void (*desktop_menucmd_handler) (void* context, int id);
} DESKTOPOPS;
Members in the structure:
- init: The function of initializing set of operations, it returns context.
- deinit: The function of destroying set of operations.
- paint_desktop: Repaint function for desktop
- keyboard_handler: Keyboard's handler, it can handle the following keyboard messages:
- MSG_DT_KEYDOWN
- MSG_DT_KEYUP
- MSG_DT_KEYLONGPRESS:
- MSG_DT_KEYALWAYSPRESS:
- MSG_DT_CHAR:
- MSG_DT_SYSKEYDOWN:
- MSG_DT_SYSCHAR:
- MSG_DT_SYSKEYUP
- mouse_handler: Mouse's handler, it can handle the following mouse messages:
- MSG_DT_LBUTTONDOWN
- MSG_DT_LBUTTONUP
- MSG_DT_LBUTTONDBLCLK
- MSG_DT_MOUSEMOVE
- MSG_DT_RBUTTONDOWN
- MSG_DT_RBUTTONDBLCLK
- MSG_DT_RBUTTONUP
- customize_desktop_menu: Constructor of customized popup menu.
- desktop_menucmd_handler: Response function of popup menu.
Functions of Desktop Customization
- Customize the function which set the interface.
/* Set a new desktop operation set, and return the old one */
DESKTOPS* SetCustomDesktopOperationSet (DESKTOPOPS* dsk_ops);
This function is to set assigned desktop customization structure. Desktop window will invoke set function interface to handle the message later.
- Update function of desktop window:
void DesktopUpdateAllWindow (void);
This function updates all windows on desktop. It is convenience to repaint all windows.
Sample program
This sample program is in mginit, a directory of mg-samples. Due to limited space, only key codes are listed here. Callback functions of desktop customization interfaces are defined in desktop.c:
DESKTOPOPS mg_dsk_ops =
{
this_init,
this_deinit,
this_paint_desktop,
this_keyboard_handler,
this_mouse_handler,
this_customize_desktop_menu,
this_desktop_menucmd_handler,
};
Callback functions of desktop customization interfaces are as follow:
static void free_dsp_app (void)
{
int i;
DSPITEM* item;
item = icon_info.app_items;
for (i = 0; i < icon_info.nr_apps; i++, item++) {
if (item->bmp.bmBits) {
UnloadBitmap (&item->bmp);
item->bmp.bmBits = NULL;
}
}
free (icon_info.app_items);
icon_info.app_items = NULL;
}
static BOOL get_dsp_app (void)
{
int i;
DSPITEM* item;
char section [10];
int distance_x = START_X;
int distance_y = START_Y;
SIZE size;
if (GetIntValueFromEtcFile (APP_INFO_FILE, "desktop", "app_nr", &icon_info.nr_apps) = ETC_OK)
return FALSE;
if (icon_info.nr_apps <= 0)
return FALSE;
if (GetValueFromEtcFile (APP_INFO_FILE, "desktop", "bg_pic", icon_info.bg_path, PATH_MAX) = ETC_OK)
return FALSE;
if ((icon_info.app_items = (DSPITEM*)calloc (icon_info.nr_apps, sizeof (DSPITEM))) == NULL) {
return FALSE;
}
item = icon_info.app_items;
for (i = 0; i < icon_info.nr_apps; i++, item++) {
sprintf (section, "dsp-app%d", i);
if (GetValueFromEtcFile (APP_INFO_FILE, section, "path", item->path, PATH_MAX) = ETC_OK)
goto error;
if (GetValueFromEtcFile (APP_INFO_FILE, section, "name", item->name, NAME_MAX) = ETC_OK)
goto error;
if (GetValueFromEtcFile (APP_INFO_FILE, section, "layer", item->layer, LEN_LAYER_NAME) = ETC_OK)
goto error;
if (GetValueFromEtcFile (APP_INFO_FILE, section, "pictrue", item->bmp_path, PATH_MAX + NAME_MAX) = ETC_OK)
goto error;
if (LoadBitmap (HDC_SCREEN, &item->bmp, item->bmp_path) = ERR_BMP_OK) {
fprintf (stderr, "desktop load resource:%s error. \n", item->bmp_path);
goto error;
}
item->cdpath = TRUE;
item->hot_spot_rc.left = distance_x;
item->hot_spot_rc.right = item->hot_spot_rc.left + DEF_WIDTH;
item->hot_spot_rc.top = distance_y;
item->hot_spot_rc.bottom = item->hot_spot_rc.top + DEF_HEIGHT;
GetTextExtent(HDC_SCREEN, item->name, -1, &size);
item->text_rc.top = item->hot_spot_rc.bottom;
item->text_rc.left = (item->hot_spot_rc.right + item->hot_spot_rc.left - size.cx)/2;
item->text_rc.bottom = item->text_rc.top + size.cy;
item->text_rc.right = item->text_rc.left + size.cx;
distance_y += SPACE + RECTH(item->hot_spot_rc);
if(distance_y + DEF_HEIGHT >= g_rcDesktop.bottom)
{
distance_y = START_Y;
distance_x += SPACE + DEF_WIDTH;
}
}
return TRUE;
error:
free_dsp_app ();
return FALSE;
}
static HMENU create_icon_menu (void)
{
HMENU hmnu;
MENUITEMINFO mii;
memset (&mii, 0, sizeof(MENUITEMINFO));
mii.type = MFT_STRING;
mii.id = 0;
mii.typedata = (DWORD)MGDT_ST_ICONMENU;
hmnu = CreatePopupMenu (&mii);
memset (&mii, 0, sizeof(MENUITEMINFO));
mii.type = MFT_STRING ;
mii.state = 0;
mii.id = ID_OP;
mii.typedata = (DWORD)MGDT_ST_OPEN;
InsertMenuItem(hmnu, 2, TRUE, &mii);
memset (&mii, 0, sizeof(MENUITEMINFO));
mii.type = MFT_STRING ;
mii.state = 0;
mii.id = ID_AB;
mii.typedata = (DWORD)MGDT_ST_ABOUT;
InsertMenuItem(hmnu, 3, TRUE, &mii);
return hmnu;
}
//Read relative resources of desktop and create picture menu when initializing.
static void* this_init(void)
{
Context *con = malloc(sizeof(Context));
get_dsp_app ();
icon_info.focus = 0xFFFF;
if(0 = strcmp(icon_info.bg_path, ""))
{
con->bg = (PBITMAP)malloc(sizeof(BITMAP));
LoadBitmapFromFile(HDC_SCREEN, con->bg, icon_info.bg_path);
}
else
con->bg = NULL;
con->icon_menu = create_icon_menu();
return (void *)con;
}
//Release memory space
static void this_deinit(void* context)
{
if(((Context *)context)->bg)
UnloadBitmap (((Context *)context)->bg);
free_dsp_app ();
if (context = NULL) free(context);
return;
}
//Paint desktop
static void this_paint_desktop(void* context, HDC dc_desktop, const RECT* inv_rc)
{
PBITMAP bg_bmp = NULL;
int i = 0;
DSPITEM* item;
if(((Context *)context)->bg)
bg_bmp = ((Context *)context)->bg;
SelectClipRect (dc_desktop, inv_rc);
if (bg_bmp) {
FillBoxWithBitmap (dc_desktop, 0, 0,
g_rcDesktop.right, g_rcDesktop.bottom, bg_bmp);
}else {
SetBrushColor (dc_desktop, PIXEL_blue);
FillBox(dc_desktop, g_rcDesktop.left, g_rcDesktop.top,
RECTW(g_rcDesktop), RECTH(g_rcDesktop));
}
item = icon_info.app_items;
for(i = 0; i < icon_info.nr_apps; i++, item++)
{
if(i == icon_info.focus)
{
SetBrushColor (dc_desktop, PIXEL_darkblue);
FillBox(dc_desktop, item->hot_spot_rc.left,
item->hot_spot_rc.top,
RECTW(item->hot_spot_rc),
RECTH(item->hot_spot_rc));
}
FillBoxWithBitmap (dc_desktop,
item->hot_spot_rc.left,
item->hot_spot_rc.top,
RECTW(item->hot_spot_rc),
RECTH(item->hot_spot_rc),
&item->bmp);
SetBkMode(dc_desktop, BM_TRANSPARENT);
TextOut(dc_desktop,
item->text_rc.left, item->text_rc.top, item->name);
}
}
//Keyboard message of dekstop
static void this_keyboard_handler(void* context, int message,
WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case MSG_DT_KEYDOWN:
break;
case MSG_DT_KEYUP:
break;
}
}
static void this_customize_desktop_menu (void* context, HMENU hmnu, int start_pos)
{
((Context *)context)->hmenu = hmnu;
MENUITEMINFO mii;
memset (&mii, 0, sizeof(MENUITEMINFO));
mii.type = MFT_STRING;
mii.id = ID_UP;
mii.typedata = (DWORD)MGDT_ST_REFRESH;
mii.hsubmenu = 0;
InsertMenuItem (hmnu, start_pos , TRUE, &mii);
#if 0
mii.type = MFT_STRING;
mii.id = ID_CB;
mii.typedata = (DWORD)"Change BkPicture";
mii.hsubmenu = 0;
InsertMenuItem (hmnu, start_pos + 1, TRUE, &mii);
#endif
mii.type = MFT_STRING;
mii.id = ID_AB;
mii.typedata = (DWORD)MGDT_ST_ABOUTM;
mii.hsubmenu = 0;
InsertMenuItem (hmnu, start_pos + 1, TRUE, &mii);
}
pid_t exec_app_name (const char* file_name, const char* app_name, const char * argv)
{
pid_t pid = 0;
if ((pid = vfork ()) > 0) {
fprintf (stderr, "new child, pid: %d.\n", pid);
}
else if (pid == 0) {
if (execl (file_name, app_name, argv, NULL) < 0)
fprintf(stderr, "execl error\n");
perror ("execl");
_exit (1);
}
else {
perror ("vfork");
}
return pid;
}
//Mouse message of dekstop
static void this_mouse_handler(void* context, int message, WPARAM wParam, LPARAM lParam)
{
int x, y;
int i = 0;
DSPITEM* item;
static int old_x = 0, old_y = 0;
x = LOSWORD (lParam);
y = HISWORD (lParam);
switch(message)
{
case MSG_DT_LBUTTONDOWN:
{
item = icon_info.app_items;
for(i = 0; i < icon_info.nr_apps; i++, item++)
{
if (PtInRect(&item->hot_spot_rc, x, y))
{
icon_info.focus = i;
old_x = x;
old_y = y;
SendMessage(HWND_DESKTOP, MSG_ERASEDESKTOP,
0, (LPARAM)&item->hot_spot_rc);
break;
}
}
break;
}
case MSG_DT_LBUTTONUP:
{
icon_info.focus = 0xFFFF;
SendMessage(HWND_DESKTOP, MSG_ERASEDESKTOP, 0, 0);
break;
}
case MSG_DT_LBUTTONDBLCLK:
{
char buff [PATH_MAX + NAME_MAX + 1];
item = icon_info.app_items;
for(i = 0; i < icon_info.nr_apps; i++, item++)
{
if (PtInRect(&item->hot_spot_rc, x, y))
{
if(item->cdpath)
{
chdir(item->path);
}
strcpy (buff, item->path);
strcat (buff, item->name);
exec_app_name(buff, item->name, "-layer");
break;
}
}
break;
}
case MSG_DT_MOUSEMOVE:
{
RECT rc;
if (icon_info.focus == 0xFFFF) break;
item = icon_info.app_items;
for(i = 0; i < icon_info.nr_apps; i++, item++)
{
if (i == icon_info.focus )
{
GetBoundRect(&rc, &item->text_rc, &item->hot_spot_rc);
item->hot_spot_rc.left += x - old_x;
item->hot_spot_rc.right += x - old_x;
item->hot_spot_rc.top += y - old_y;
item->hot_spot_rc.bottom += y - old_y;
item->text_rc.left += x - old_x;
item->text_rc.right += x - old_x;
item->text_rc.top += y - old_y;
item->text_rc.bottom += y - old_y;
old_x = x;
old_y = y;
GetBoundRect(&rc, &rc, &item->hot_spot_rc);
GetBoundRect(&rc, &rc, &item->text_rc);
SendMessage(HWND_DESKTOP, MSG_ERASEDESKTOP, 0, (LPARAM)&rc);
}
}
break;
}
case MSG_DT_RBUTTONUP:
{
BOOL flag = FALSE;
item = icon_info.app_items;
for(i = 0; i < icon_info.nr_apps; i++, item++)
{
if (PtInRect(&item->hot_spot_rc, x, y))
{
icon_info.focus = i;
SendMessage(HWND_DESKTOP, MSG_ERASEDESKTOP,
0, (LPARAM)&item->hot_spot_rc);
TrackPopupMenu (((Context *)context)->icon_menu,
TPM_DEFAULT, x, y, HWND_DESKTOP);
flag = TRUE;
break;
}
}
if(!flag)
TrackPopupMenu (((Context *)context)->hmenu, TPM_DEFAULT, x, y, HWND_DESKTOP);
break;
}
}
}
//
static void this_desktop_menucmd_handler (void* context, int id)
{
if(!context)
return;
if(id == ID_UP)
{
DesktopUpdateAllWindow();
}
#if 0
else if(id == ID_CB)
{
NEWFILEDLGDATA file_data;
int choise = 0;
// file_data.IsSave = FALSE;
strcpy(file_data.filepath,".");
choise = ShowOpenDialog(HWND_DESKTOP, 50, 50, 300, 200, &file_data);
if(choise == IDOK)
{
if(access(file_data.filefullname, F_OK) < 0)
{
printf("file not exist!\n");
}
else
{
printf("ok!\n");
}
}
}
#endif
else if(id == ID_AB)
{
#ifdef _MGMISC_ABOUTDLG
#ifdef _MGRM_THREADS
OpenAboutDialog ();
#else
OpenAboutDialog (HWND_DESKTOP);
#endif
#endif
}
else if(id == ID_OP)
{
int i = 0;
DSPITEM* item;
char buff [PATH_MAX + NAME_MAX + 1];
item = icon_info.app_items;
for(i = 0; i < icon_info.nr_apps; i++, item++)
{
if (i == icon_info.focus)
{
if(item->cdpath)
{
chdir(item->path);
}
strcpy (buff, item->path);
strcat (buff, item->name);
exec_app_name(buff, item->name, "-layer");
icon_info.focus = 0xFFFF;
break;
}
}
}
else if(id == ID_RN)
{
icon_info.focus = 0xFFFF;
}
return;
}
There is a configuration file, mginit.rc. We can get relative resources of desktop by loading this file. The contents of mginit.rc are as follow:
[taskbar]
nr=3
autostart=0
logo=res/feynman.png
[app0]
path=../minesweeper/
name=minesweeper
layer=
tip=Game&of&Minesweaper
icon=res/kmines.gif
[app1]
path=../housekeeper/
name=housekeeper
layer=
tip=Sokoban
icon=res/ksokoban.gif
[app2]
path=../same/
name=same
layer=
tip=Game&of&Same
icon=res/ksame.gif
[desktop]
app_nr=8
bg_pic=res/bk.jpg
[dsp-app0]
path=../minesweeper/
name=minesweeper
layer=
pictrue=res/minesweep.png
[dsp-app1]
path=../housekeeper/
name=housekeeper
layer=
pictrue=res/housekeeper.png
[dsp-app2]
path=../same/
name=same
layer=
pictrue=res/same.png
[dsp-app3]
path=../graphics/
name=graphics
layer=
pictrue=res/graphics.png
[dsp-app4]
path=../font_text/
name=font_text
layer=
pictrue=res/font.png
[dsp-app5]
path=../ctrl_dlg/
name=ctrl_dlg
layer=
pictrue=res/dialog.png
[dsp-app6]
path=../graphics/
name=graphicsex
layer=
pictrue=res/graphicsex.png
[dsp-app7]
path=../dbuff/
name=dbuff
layer=
pictrue=res/thaifont.png
Initialized desktop customization structure in main function is set to MiniGUI. The following code is in mginit.c (please refer to chapter 17):
int MiniGUIMain (int args, const char* arg[])
{
struct sigaction siga;
MSG msg;
OnNewDelClient = on_new_del_client;
OnChangeLayer = on_change_layer;
if (!ServerStartup (0, 0, 0)) {
fprintf (stderr,
"Can not start the server of MiniGUI-Processes: mginit.\n");
return 1;
}
SetCustomDesktopOperationSet(&mg_dsk_ops);
if ((hTaskBar = create_task_bar ()) == HWND_INVALID) {
fprintf (stderr, "Can not create task bar.\n");
return 2;
}
siga.sa_handler = child_wait;
siga.sa_flags = 0;
memset (&siga.sa_mask, 0, sizeof(sigset_t));
sigaction (SIGCHLD, &siga, NULL);
while (GetMessage (&msg, hTaskBar)) {
DispatchMessage (&msg);
}
return 0;
}
The screenshot of the application.
Figure 2 Customization of Desktop
<< Icon, Cursor, and Caret | Table of Contents | Other Programming Topic >>