Files
MiniGUI/src/gui/dialog.c

1198 lines
33 KiB
C

///////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT NOTICE
//
// The following open source license statement does not apply to any
// entity in the Exception List published by FMSoft.
//
// For more information, please visit:
//
// https://www.fmsoft.cn/exception-list
//
//////////////////////////////////////////////////////////////////////////////
/*
* This file is part of MiniGUI, a mature cross-platform windowing
* and Graphics User Interface (GUI) support system for embedded systems
* and smart IoT devices.
*
* Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
* Copyright (C) 1998~2002, WEI Yongming
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Or,
*
* As this program is a library, any link to this program must follow
* GNU General Public License version 3 (GPLv3). If you cannot accept
* GPLv3, you need to be licensed from FMSoft.
*
* If you have got a commercial license of this program, please use it
* under the terms and conditions of the commercial license.
*
* For more information about the commercial license, please refer to
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
*/
/*
** dialog.c: The Dialog module.
**
** Create date: 1999.09.10
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "control.h"
#include "cliprect.h"
#include "gal.h"
#include "internals.h"
#include "ctrlclass.h"
void GUIAPI DestroyAllControls (HWND hDlg)
{
PMAINWIN pDlg = (PMAINWIN)hDlg;
PCONTROL pCtrl = (PCONTROL)(pDlg->hFirstChild);
PCONTROL pNext;
while (pCtrl) {
pNext = pCtrl->next;
DestroyWindow ((HWND)pCtrl);
pCtrl = pNext;
}
}
#define dlgDestroyAllControls DestroyAllControls
HWND GUIAPI CreateMainWindowIndirectParamEx (PDLGTEMPLATE pDlgTemplate,
HWND hOwner, WNDPROC WndProc, LPARAM lParam,
const char* werdr_name, WINDOW_ELEMENT_ATTR* we_attrs,
const char* window_name, const char* layer_name)
{
MAINWINCREATE CreateInfo;
HWND hMainWin;
int i;
PCTRLDATA pCtrlData;
HWND hCtrl;
HWND hFocus;
if (pDlgTemplate->controlnr > 0 && !pDlgTemplate->controls)
return HWND_INVALID;
hOwner = GetMainWindowHandle (hOwner);
CreateInfo.dwReserved = (DWORD)pDlgTemplate;
CreateInfo.dwStyle = pDlgTemplate->dwStyle & ~WS_VISIBLE;
CreateInfo.dwExStyle = pDlgTemplate->dwExStyle;
CreateInfo.spCaption = pDlgTemplate->caption;
CreateInfo.hMenu = pDlgTemplate->hMenu;
CreateInfo.hCursor = GetSystemCursor (IDC_ARROW);
CreateInfo.hIcon = pDlgTemplate->hIcon;
CreateInfo.MainWindowProc = WndProc ? WndProc : DefaultMainWinProc;
CreateInfo.lx = pDlgTemplate->x;
CreateInfo.ty = pDlgTemplate->y;
CreateInfo.rx = pDlgTemplate->x + pDlgTemplate->w;
CreateInfo.by = pDlgTemplate->y + pDlgTemplate->h;
CreateInfo.iBkColor =
GetWindowElementPixelEx (HWND_NULL, HDC_SCREEN, WE_MAINC_THREED_BODY);
CreateInfo.dwAddData = pDlgTemplate->dwAddData;
CreateInfo.hHosting = hOwner;
hMainWin = CreateMainWindowEx (&CreateInfo,
werdr_name, we_attrs, window_name, layer_name);
if (hMainWin == HWND_INVALID)
return HWND_INVALID;
for (i = 0; i < pDlgTemplate->controlnr; i++) {
pCtrlData = pDlgTemplate->controls + i;
hCtrl = CreateWindowEx2 (pCtrlData->class_name,
pCtrlData->caption,
pCtrlData->dwStyle | WS_CHILD,
pCtrlData->dwExStyle,
pCtrlData->id,
pCtrlData->x,
pCtrlData->y,
pCtrlData->w,
pCtrlData->h,
hMainWin,
pCtrlData->werdr_name,
pCtrlData->we_attrs,
pCtrlData->dwAddData);
if (hCtrl == HWND_INVALID) {
DestroyMainWindow (hMainWin);
MainWindowThreadCleanup (hMainWin);
return HWND_INVALID;
}
}
#if 0
hFocus = GetNextDlgTabItem (hMainWin, (HWND)0, FALSE);
#else
/* houhh 20100706, set the forefront control as focus. */
{
PCONTROL pCtrl;
for (pCtrl = (PCONTROL)(((PMAINWIN)hMainWin)->hFirstChild);
pCtrl && pCtrl->next; pCtrl = pCtrl->next);
hFocus = (HWND)pCtrl;
}
#endif
if (SendMessage (hMainWin, MSG_INITDIALOG, (WPARAM)hFocus, lParam)) {
if (hFocus)
SetFocus (hFocus);
}
if (!(pDlgTemplate->dwExStyle & WS_EX_DLGHIDE))
ShowWindow (hMainWin, SW_SHOWNORMAL);
return hMainWin;
}
BOOL GUIAPI DestroyMainWindowIndirect (HWND hMainWin)
{
DestroyMainWindow (hMainWin);
MainWindowThreadCleanup (hMainWin);
return TRUE;
}
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)
{
HWND hDlg;
int retCode = IDCANCEL;
MSG Msg;
if (hOwner && hOwner != HWND_INVALID && hOwner != HWND_DESKTOP)
hOwner = GetMainWindowHandle(hOwner);
/* Since 5.0.0: use internal extended style for dialgbox */
pDlgTemplate->dwExStyle |= WS_EX_DIALOGBOX;
hDlg = CreateMainWindowIndirectParamEx(pDlgTemplate,
hOwner, DlgProc, lParam,
werdr_name, we_attrs,
window_name, layer_name);
if (hDlg == HWND_INVALID)
return -1;
//MiniGUI maybe change dialog owner in CreateMainWindow, so we
//should update its owner by GetHosting.
hOwner = GetHosting (hDlg);
SetWindowAdditionalData2 (hDlg, (DWORD)(&retCode));
if (hOwner && hOwner != HWND_DESKTOP) {
if (IsWindowEnabled (hOwner)) {
EnableWindow (hOwner, FALSE);
IncludeWindowExStyle (hOwner, WS_EX_MODALDISABLED);
}
/* Throw away MSG_KEYDOWN, MSG_CHAR and MSG_KEYUP to hOwner */
while (PeekPostMessage (&Msg, hOwner,
MSG_KEYDOWN, MSG_KEYUP, PM_REMOVE));
}
while (GetMessage (&Msg, hDlg)) {
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
MainWindowCleanup (hDlg);
return retCode;
}
BOOL GUIAPI EndDialog (HWND hDlg, int endCode)
{
HWND hOwner;
BOOL isActive;
DWORD dwAddData2;
dwAddData2 = GetWindowAdditionalData2 (hDlg);
if (dwAddData2 == 0)
return FALSE;
*((int *)(dwAddData2)) = endCode;
hOwner = GetHosting (hDlg);
isActive = (GetActiveWindow() == hDlg);
DestroyMainWindow (hDlg);
if (hOwner != HWND_DESKTOP && hOwner != HWND_NULL) {
if (GetWindowExStyle (hOwner) & WS_EX_MODALDISABLED) {
EnableWindow (hOwner, TRUE);
ExcludeWindowExStyle (hOwner, WS_EX_MODALDISABLED);
if (isActive && IsWindowVisible (hOwner)) {
ShowWindow (hOwner, SW_SHOWNORMAL);
SetActiveWindow (hOwner);
}
}
}
return TRUE;
}
LRESULT GUIAPI PreDefDialogProc (HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
HWND hCurFocus;
switch (message) {
#if 0
case MSG_CREATE:
{
int i;
PCTRLDATA pCtrlData;
HWND hCtrl;
PDLGTEMPLATE pDlgTmpl
= (PDLGTEMPLATE)(((PMAINWINCREATE)lParam)->dwReserved);
for (i = 0; i < pDlgTmpl->controlnr; i++) {
pCtrlData = pDlgTmpl->controls + i;
if (pCtrlData->class_name) {
hCtrl = CreateWindowEx2 (pCtrlData->class_name,
pCtrlData->caption,
pCtrlData->dwStyle | WS_CHILD,
pCtrlData->dwExStyle,
pCtrlData->id,
pCtrlData->x,
pCtrlData->y,
pCtrlData->w,
pCtrlData->h,
hWnd,
pCtrlData->werdr_name,
pCtrlData->we_attrs,
pCtrlData->dwAddData);
}
else
break;
if (hCtrl == HWND_INVALID) {
dlgDestroyAllControls (hWnd);
return -1;
}
}
return 0;
}
#endif
case MSG_DLG_GETDEFID:
{
HWND hDef;
hDef = GetDlgDefPushButton (hWnd);
if (hDef)
return GetDlgCtrlID (hDef);
return 0;
}
case MSG_DLG_SETDEFID:
{
HWND hOldDef;
HWND hNewDef;
hNewDef = GetDlgItem (hWnd, wParam);
if (SendMessage (hNewDef, MSG_GETDLGCODE, 0, 0L) & DLGC_PUSHBUTTON) {
hOldDef = GetDlgDefPushButton (hWnd);
if (hOldDef) {
ExcludeWindowStyle (hOldDef, BS_DEFPUSHBUTTON);
InvalidateRect (hOldDef, NULL, TRUE);
}
IncludeWindowStyle (hNewDef, BS_DEFPUSHBUTTON);
InvalidateRect (hNewDef, NULL, TRUE);
return (LRESULT)hOldDef;
}
break;
}
case MSG_COMMAND:
if (wParam == IDCANCEL) {
HWND hCancel;
hCancel = GetDlgItem (hWnd, IDCANCEL);
if (hCancel && IsWindowEnabled (hCancel)
&& IsWindowVisible (hCancel))
EndDialog (hWnd, IDCANCEL);
}
break;
case MSG_CLOSE:
{
HWND hCancel;
hCancel = GetDlgItem (hWnd, IDCANCEL);
if (hCancel && IsWindowEnabled (hCancel)
&& IsWindowVisible (hCancel))
EndDialog (hWnd, IDCANCEL);
return 0;
}
case MSG_ISDIALOG:
return 1;
case MSG_KEYDOWN:
if ((hCurFocus = GetFocusChild (hWnd))
&& SendMessage (hCurFocus, MSG_GETDLGCODE, 0, 0L) &
DLGC_WANTALLKEYS)
break;
switch (wParam) {
case SCANCODE_ESCAPE:
SendMessage (hWnd, MSG_COMMAND, IDCANCEL, 0L);
return 0;
case SCANCODE_TAB:
{
HWND hNewFocus;
if (hCurFocus && SendMessage (hCurFocus, MSG_GETDLGCODE, 0, 0L) &
DLGC_WANTTAB)
break;
if (lParam & KS_SHIFT)
hNewFocus = GetNextDlgTabItem (hWnd, hCurFocus, TRUE);
else
hNewFocus = GetNextDlgTabItem (hWnd, hCurFocus, FALSE);
if (hNewFocus != hCurFocus) {
SetNullFocus (hCurFocus);
SetFocus (hNewFocus);
#if 0
SendMessage (hWnd, MSG_DLG_SETDEFID,
GetDlgCtrlID (hNewFocus), 0L);
#endif
}
return 0;
}
case SCANCODE_KEYPADENTER:
case SCANCODE_ENTER:
{
HWND hDef;
if (hCurFocus && SendMessage (hCurFocus, MSG_GETDLGCODE, 0, 0L) &
DLGC_WANTENTER)
break;
if (SendMessage (hCurFocus, MSG_GETDLGCODE, 0, 0L) &
DLGC_PUSHBUTTON)
break;
hDef = GetDlgDefPushButton (hWnd);
/* DK[07/05/10]Fix Bug4798, Check the control if has WS_DISABLED property. */
if (hDef && IsWindowEnabled(hDef)) {
SendMessage (hWnd, MSG_COMMAND, GetDlgCtrlID (hDef), 0L);
return 0;
}
}
case SCANCODE_CURSORBLOCKDOWN:
case SCANCODE_CURSORBLOCKRIGHT:
case SCANCODE_CURSORBLOCKUP:
case SCANCODE_CURSORBLOCKLEFT:
{
HWND hNewFocus;
if (hCurFocus && SendMessage (hCurFocus, MSG_GETDLGCODE, 0, 0L) &
DLGC_WANTARROWS)
break;
if (LOWORD (wParam) == SCANCODE_CURSORBLOCKDOWN
|| LOWORD (wParam) == SCANCODE_CURSORBLOCKRIGHT)
hNewFocus = GetNextDlgGroupItem (hWnd, hCurFocus, FALSE);
else
hNewFocus = GetNextDlgGroupItem (hWnd, hCurFocus, TRUE);
if (hNewFocus != hCurFocus) {
if (SendMessage (hCurFocus, MSG_GETDLGCODE, 0, 0L) &
DLGC_STATIC)
return 0;
SetFocus (hNewFocus);
#if 0
SendMessage (hWnd, MSG_DLG_SETDEFID,
GetDlgCtrlID (hNewFocus), 0L);
#endif
if (SendMessage (hNewFocus, MSG_GETDLGCODE, 0, 0L)
& DLGC_RADIOBUTTON) {
SendMessage (hNewFocus, BM_CLICK, 0, 0L);
ExcludeWindowStyle (hCurFocus, WS_TABSTOP);
IncludeWindowStyle (hNewFocus, WS_TABSTOP);
}
}
return 0;
}
}
break;
default:
break;
}
return DefaultMainWinProc (hWnd, message, wParam, lParam);
}
LINT GUIAPI GetDlgCtrlID (HWND hwndCtl)
{
PCONTROL pCtrl = (PCONTROL)hwndCtl;
if (pCtrl) {
return pCtrl->id;
}
return -1;
}
HWND GUIAPI GetDlgItem (HWND hDlg, LINT nIDDlgItem)
{
PCONTROL pCtrl;
PMAINWIN pMainWin = (PMAINWIN)hDlg;
pCtrl = (PCONTROL)(pMainWin->hFirstChild);
while (pCtrl) {
if (pCtrl->id == nIDDlgItem)
return (HWND)pCtrl;
pCtrl = pCtrl->next;
}
return 0;
}
HWND GUIAPI GetDlgDefPushButton (HWND hWnd)
{
PCONTROL pCtrl;
PMAINWIN pMainWin = (PMAINWIN)hWnd;
pCtrl = (PCONTROL)(pMainWin->hFirstChild);
while (pCtrl) {
if (SendMessage ((HWND)pCtrl,
MSG_GETDLGCODE, 0, 0L) & DLGC_DEFPUSHBUTTON)
return (HWND)pCtrl;
pCtrl = pCtrl->next;
}
return 0;
}
HWND GetNextDlgGroupItem (HWND hDlg, HWND hCtl, BOOL bPrevious)
{
PCONTROL pStartCtrl, pCtrl;
PMAINWIN pMainWin = (PMAINWIN)hDlg;
if (hCtl)
pStartCtrl = (PCONTROL)hCtl;
else {
pStartCtrl = (PCONTROL)(pMainWin->hFirstChild);
if (!pStartCtrl)
return hCtl;
if (bPrevious) {
while (pStartCtrl->next) {
pStartCtrl = pStartCtrl->next;
}
}
}
if (bPrevious) {
if (pStartCtrl->dwStyle & WS_GROUP) {
if (pStartCtrl->next) {
pCtrl = pStartCtrl->next;
while (pCtrl && pCtrl->next) {
if (pCtrl->dwStyle & WS_GROUP)
break;
pCtrl = pCtrl->next;
}
}
else
pCtrl = pStartCtrl;
}
else
pCtrl = pStartCtrl;
if (pCtrl->dwStyle & WS_GROUP || pCtrl == pStartCtrl)
pCtrl = pCtrl->prev;
while (pCtrl) {
if (pCtrl->dwStyle & WS_VISIBLE
&& !(pCtrl->dwStyle & WS_DISABLED) )
return (HWND)pCtrl;
pCtrl = pCtrl->prev;
}
}
else {
pCtrl = pStartCtrl->next;
while (pCtrl) {
if ( !(pCtrl->dwStyle & WS_GROUP) ) {
if (pCtrl->dwStyle & WS_VISIBLE
&& !(pCtrl->dwStyle & WS_DISABLED) )
return (HWND)pCtrl;
}
else
break;
pCtrl = pCtrl->next;
}
pCtrl = pStartCtrl->prev;
while (pCtrl) {
if (pCtrl->dwStyle & WS_GROUP) {
if (pCtrl->dwStyle & WS_VISIBLE
&& !(pCtrl->dwStyle & WS_DISABLED) )
return (HWND)pCtrl;
else
break;
}
pCtrl = pCtrl->prev;
}
if (pCtrl) { // pCtrl is the first control in group.
pCtrl = pCtrl->next;
while (pCtrl) {
if ( !(pCtrl->dwStyle & WS_GROUP) ) {
if (pCtrl->dwStyle & WS_VISIBLE
&& !(pCtrl->dwStyle & WS_DISABLED) )
return (HWND)pCtrl;
}
else
break;
pCtrl = pCtrl->next;
}
}
}
return hCtl;
}
HWND GUIAPI GetNextDlgTabItem (HWND hDlg, HWND hCtl, BOOL bPrevious)
{
PCONTROL pFirstCtrl, pLastCtrl, pCtrl;
PMAINWIN pMainWin = (PMAINWIN)hDlg;
pFirstCtrl = pCtrl = (PCONTROL)(pMainWin->hFirstChild);
if (!pCtrl) return hCtl;
while (pCtrl->next) {
pCtrl = pCtrl->next;
}
pLastCtrl = pCtrl;
if (hCtl) {
pCtrl = (PCONTROL)hCtl;
if (bPrevious)
pCtrl = pCtrl->prev;
else
pCtrl = pCtrl->next;
}
else if (bPrevious)
pCtrl = pLastCtrl;
else
pCtrl = pFirstCtrl;
if (bPrevious) {
while (pCtrl) {
if (pCtrl->dwStyle & WS_TABSTOP
&& pCtrl->dwStyle & WS_VISIBLE
&& !(pCtrl->dwStyle & WS_DISABLED) )
return (HWND)pCtrl;
pCtrl = pCtrl->prev;
}
pCtrl = pLastCtrl;
while (pCtrl) {
if (pCtrl->dwStyle & WS_TABSTOP
&& pCtrl->dwStyle & WS_VISIBLE
&& !(pCtrl->dwStyle & WS_DISABLED) )
return (HWND)pCtrl;
pCtrl = pCtrl->prev;
}
}
else {
while (pCtrl) {
if (pCtrl->dwStyle & WS_TABSTOP
&& pCtrl->dwStyle & WS_VISIBLE
&& !(pCtrl->dwStyle & WS_DISABLED) )
return (HWND)pCtrl;
pCtrl = pCtrl->next;
}
pCtrl = pFirstCtrl;
while (pCtrl) {
if (pCtrl->dwStyle & WS_TABSTOP
&& pCtrl->dwStyle & WS_VISIBLE
&& !(pCtrl->dwStyle & WS_DISABLED) )
return (HWND)pCtrl;
pCtrl = pCtrl->next;
}
}
return hCtl;
}
LRESULT GUIAPI SendDlgItemMessage (HWND hDlg, LINT nIDDlgItem,
UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hCtrl;
hCtrl = GetDlgItem (hDlg, nIDDlgItem);
if (hCtrl)
return SendMessage (hCtrl, message, wParam, lParam);
return -1;
}
UINT GUIAPI GetDlgItemInt (HWND hDlg, LINT nIDDlgItem, BOOL *lpTranslated,
BOOL bSigned)
{
HWND hCtrl;
char buffer [101];
unsigned long int result;
if ( !(hCtrl = GetDlgItem (hDlg, nIDDlgItem)))
goto error;
if (SendMessage (hCtrl, MSG_GETTEXT, 100, (LPARAM)buffer) == 0)
goto error;
if (bSigned)
result = strtoul (buffer, NULL, 0);
else
result = (unsigned long int)strtol (buffer, NULL, 0);
if (lpTranslated)
*lpTranslated = TRUE;
return (UINT)result;
error:
if (lpTranslated)
*lpTranslated = FALSE;
return 0;
}
BOOL GUIAPI SetDlgItemInt (HWND hDlg, LINT nIDDlgItem, UINT uValue,
BOOL bSigned)
{
HWND hCtrl;
char buffer [101];
if ( !(hCtrl = GetDlgItem (hDlg, nIDDlgItem)))
return FALSE;
if (bSigned)
snprintf (buffer, 100, "%ld", (long)uValue);
else
snprintf (buffer, 100, "%u", uValue);
buffer [100] = '\0';
return SendMessage (hCtrl, MSG_SETTEXT, 0, (LPARAM)buffer) == 0;
}
int GUIAPI GetDlgItemText (HWND hDlg, LINT nIDDlgItem, char* lpString,
int nMaxCount)
{
HWND hCtrl;
if ( !(hCtrl = GetDlgItem (hDlg, nIDDlgItem)))
return 0;
return SendMessage (hCtrl,
MSG_GETTEXT, (WPARAM)nMaxCount, (LPARAM)lpString);
}
char* GUIAPI GetDlgItemText2 (HWND hDlg, LINT id, int* lenPtr)
{
int len;
char* buff;
len = SendDlgItemMessage (hDlg, id,
MSG_GETTEXTLENGTH, 0, 0L);
if (len > 0) {
buff = malloc (len + 1);
if (buff)
SendDlgItemMessage (hDlg, id,
MSG_GETTEXT, len, (LPARAM)(buff));
}
else
buff = NULL;
if (lenPtr) *lenPtr = len;
return buff;
}
BOOL GUIAPI SetDlgItemText (HWND hDlg, LINT nIDDlgItem, const char* lpString)
{
HWND hCtrl;
if ( !(hCtrl = GetDlgItem (hDlg, nIDDlgItem)))
return FALSE;
return SendMessage (hCtrl,
MSG_SETTEXT, 0, (LPARAM)lpString) == 0;
}
#ifdef _MGCTRL_BUTTON
void GUIAPI CheckDlgButton (HWND hDlg, LINT nIDDlgItem, int nCheck)
{
HWND hCtrl;
int DlgCode;
if ( !(hCtrl = GetDlgItem (hDlg, nIDDlgItem)))
return;
DlgCode = SendMessage (hCtrl, MSG_GETDLGCODE, 0, 0L);
if (DlgCode & DLGC_BUTTON)
SendMessage (hCtrl, BM_SETCHECK, nCheck?BST_CHECKED:BST_UNCHECKED, 0L);
else if (DlgCode & DLGC_3STATE) {
SendMessage (hCtrl, BM_SETCHECK, nCheck, 0L);
}
}
void GUIAPI CheckRadioButton (HWND hDlg,
LINT idFirstButton, LINT idLastButton, LINT idCheckButton)
{
HWND hCtrl;
if ( !(hCtrl = GetDlgItem (hDlg, idCheckButton)))
return;
SendMessage (hCtrl, BM_SETCHECK, BST_CHECKED, 0L);
}
int GUIAPI IsDlgButtonChecked (HWND hDlg, LINT idButton)
{
HWND hCtrl;
if ( !(hCtrl = GetDlgItem (hDlg, idButton)))
return -1;
return SendMessage (hCtrl, BM_GETCHECK, 0, 0L);
}
#ifdef _MGCTRL_STATIC
static LRESULT MsgBoxProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case MSG_INITDIALOG:
{
HWND hFocus = GetDlgDefPushButton (hWnd);
if (hFocus)
SetFocus (hFocus);
SetWindowAdditionalData (hWnd, (DWORD)lParam);
SetWindowFont (hWnd,
(PLOGFONT)GetWindowElementAttr (hWnd, WE_FONT_MESSAGEBOX));
/* set the messagebox's body text font and color.*/
hFocus = GetDlgItem(hWnd, IDC_STATIC+100);
SetWindowFont (hFocus,
(PLOGFONT)GetWindowElementAttr (hFocus, WE_FONT_MESSAGEBOX));
SetWindowElementAttr (hFocus,WE_FGC_WINDOW,
GetWindowElementAttr (hFocus, WE_FGC_MESSAGEBOX));
return 0;
}
case MSG_COMMAND:
{
switch (wParam) {
case IDOK:
case IDCANCEL:
case IDABORT:
case IDRETRY:
case IDIGNORE:
case IDYES:
case IDNO:
if (GetDlgItem (hWnd, wParam))
EndDialog (hWnd, wParam);
break;
}
break;
}
case MSG_CHAR:
{
int id = 0;
if (HIBYTE (wParam))
break;
switch (LOBYTE (wParam)) {
case 'Y':
case 'y':
id = IDYES;
break;
case 'N':
case 'n':
id = IDNO;
break;
case 'A':
case 'a':
id = IDABORT;
break;
case 'R':
case 'r':
id = IDRETRY;
break;
case 'I':
case 'i':
id = IDIGNORE;
break;
}
if (id != 0 && GetDlgItem (hWnd, id))
EndDialog (hWnd, id);
break;
}
case MSG_CLOSE:
if (GetDlgItem (hWnd, IDCANCEL)) {
EndDialog (hWnd, IDCANCEL);
}
else if (GetDlgItem (hWnd, IDIGNORE)) {
EndDialog (hWnd, IDIGNORE);
}
else if (GetDlgItem (hWnd, IDNO)) {
EndDialog (hWnd, IDNO);
}
else if (GetDlgItem (hWnd, IDOK)) {
EndDialog (hWnd, IDOK);
}
break;
default:
break;
}
return DefaultDialogProc (hWnd, message, wParam, lParam);
}
static void get_box_xy (HWND hParentWnd, DWORD dwStyle, DLGTEMPLATE* MsgBoxData)
{
RECT rcTemp;
if (dwStyle & MB_BASEDONPARENT) {
GetWindowRect (hParentWnd, &rcTemp);
}
else {
rcTemp = g_rcScr;
}
switch (dwStyle & MB_ALIGNMASK) {
case MB_ALIGNCENTER:
MsgBoxData->x = rcTemp.left + (RECTW(rcTemp) - MsgBoxData->w)/2;
MsgBoxData->y = rcTemp.top + (RECTH(rcTemp) - MsgBoxData->h)/2;
break;
case MB_ALIGNTOPLEFT:
MsgBoxData->x = rcTemp.left;
MsgBoxData->y = rcTemp.top;
break;
case MB_ALIGNBTMLEFT:
MsgBoxData->x = rcTemp.left;
MsgBoxData->y = rcTemp.bottom - MsgBoxData->h;
break;
case MB_ALIGNTOPRIGHT:
MsgBoxData->x = rcTemp.right - MsgBoxData->w;
MsgBoxData->y = rcTemp.top;
break;
case MB_ALIGNBTMRIGHT:
MsgBoxData->x = rcTemp.right - MsgBoxData->w;
MsgBoxData->y = rcTemp.bottom - MsgBoxData->h;
break;
}
if ((MsgBoxData->x + MsgBoxData->w) > g_rcScr.right) {
MsgBoxData->x = g_rcScr.right - MsgBoxData->w;
}
if ((MsgBoxData->y + MsgBoxData->h) > g_rcScr.bottom) {
MsgBoxData->y = g_rcScr.bottom - MsgBoxData->h;
}
}
int GUIAPI MessageBox (HWND hParentWnd, const char* pszText,
const char* pszCaption, DWORD dwStyle)
{
BOOL IsTiny;
DLGTEMPLATE MsgBoxData =
{
WS_CAPTION | WS_BORDER,
WS_EX_NONE, 0, 0, 0, 0, NULL, 0, 0, 0, NULL, 0L
};
CTRLDATA CtrlData [5] =
{
{"button",
BS_PUSHBUTTON | WS_TABSTOP | WS_VISIBLE | WS_GROUP,
0, 0, 0, 0, 0, NULL, 0L},
{"button",
BS_PUSHBUTTON | WS_TABSTOP | WS_VISIBLE,
0, 0, 0, 0, 0, NULL, 0L},
{"button",
BS_PUSHBUTTON | WS_TABSTOP | WS_VISIBLE,
0, 0, 0, 0, 0, NULL, 0L}
};
int i, nButtons, buttonx, iBorder;
RECT rcText, rcButtons, rcIcon;
int width, height;
int mb_margin, mb_buttonw, mb_buttonh, mb_textw;
IsTiny = !strcasecmp (GetDefaultWindowElementRenderer()->name, "tiny");
if (IsTiny) {
int font_size = GetSysFontHeight (SYSLOGFONT_CONTROL);
mb_margin = 2;
mb_buttonw = font_size * 3;
mb_buttonh = font_size + 6;
mb_textw = 120;
}
else {
int font_size = GetSysFontHeight (SYSLOGFONT_CONTROL);
mb_margin = font_size;
mb_buttonw = font_size * 4;
mb_buttonh = (font_size < 8) ? (font_size + 6) : (font_size * 3 / 2);
mb_textw = 300;
}
/* use system font height to determine the width and height of button */
if (pszCaption)
MsgBoxData.caption = pszCaption;
else
MsgBoxData.caption = "MiniGUI";
switch (dwStyle & MB_TYPEMASK) {
case MB_OK:
MsgBoxData.controlnr = 1;
CtrlData [0].caption = GetSysText (IDS_MGST_OK);
CtrlData [0].id = IDOK;
break;
case MB_OKCANCEL:
MsgBoxData.controlnr = 2;
CtrlData [0].caption = GetSysText (IDS_MGST_OK);
CtrlData [0].id = IDOK;
CtrlData [1].caption = (dwStyle & MB_CANCELASBACK) ?
GetSysText (IDS_MGST_PREV) : GetSysText (IDS_MGST_CANCEL);
CtrlData [1].id = IDCANCEL;
break;
case MB_YESNO:
MsgBoxData.controlnr = 2;
CtrlData [0].caption = GetSysText (IDS_MGST_YES);
CtrlData [0].id = IDYES;
CtrlData [1].caption = GetSysText (IDS_MGST_NO);
CtrlData [1].id = IDNO;
break;
case MB_RETRYCANCEL:
MsgBoxData.controlnr = 2;
CtrlData [0].caption = GetSysText (IDS_MGST_RETRY);
CtrlData [0].id = IDRETRY;
CtrlData [1].caption = (dwStyle & MB_CANCELASBACK) ?
GetSysText (IDS_MGST_PREV) : GetSysText (IDS_MGST_CANCEL);
CtrlData [1].id = IDCANCEL;
break;
case MB_ABORTRETRYIGNORE:
MsgBoxData.controlnr = 3;
CtrlData [0].caption = GetSysText (IDS_MGST_ABORT);
CtrlData [0].id = IDABORT;
CtrlData [1].caption = GetSysText (IDS_MGST_RETRY);
CtrlData [1].id = IDRETRY;
CtrlData [2].caption = GetSysText (IDS_MGST_IGNORE);
CtrlData [2].id = IDIGNORE;
break;
case MB_YESNOCANCEL:
MsgBoxData.controlnr = 3;
CtrlData [0].caption = GetSysText (IDS_MGST_YES);
CtrlData [0].id = IDYES;
CtrlData [1].caption = GetSysText (IDS_MGST_NO);
CtrlData [1].id = IDNO;
CtrlData [2].caption = (dwStyle & MB_CANCELASBACK) ?
GetSysText (IDS_MGST_PREV) : GetSysText (IDS_MGST_CANCEL);
CtrlData [2].id = IDCANCEL;
break;
}
switch (dwStyle & MB_DEFMASK) {
case MB_DEFBUTTON1:
CtrlData [0].dwStyle |= BS_DEFPUSHBUTTON;
break;
case MB_DEFBUTTON2:
if (MsgBoxData.controlnr > 1)
CtrlData [1].dwStyle |= BS_DEFPUSHBUTTON;
break;
case MB_DEFBUTTON3:
if (MsgBoxData.controlnr > 2)
CtrlData [2].dwStyle |= BS_DEFPUSHBUTTON;
break;
}
nButtons = MsgBoxData.controlnr;
rcButtons.left = 0;
rcButtons.top = 0;
rcButtons.bottom = mb_buttonh;
rcButtons.right = MsgBoxData.controlnr * mb_buttonw +
(MsgBoxData.controlnr - 1) * (mb_margin << 1);
rcIcon.left = 0;
rcIcon.top = 0;
rcIcon.right = 0;
rcIcon.bottom = 0;
if (dwStyle & MB_ICONMASK) {
int id_icon = -1;
i = MsgBoxData.controlnr;
CtrlData [i].class_name= "static";
CtrlData [i].dwStyle = WS_VISIBLE | SS_ICON | WS_GROUP;
CtrlData [i].x = mb_margin;
CtrlData [i].y = mb_margin;
if (IsTiny) {
CtrlData [i].w = 16;
CtrlData [i].h = 16;
}
else {
CtrlData [i].w = 32;
CtrlData [i].h = 32;
}
CtrlData [i].id = IDC_STATIC;
CtrlData [i].caption = "";
switch (dwStyle & MB_ICONMASK) {
case MB_ICONSTOP:
id_icon = IDI_STOP;
break;
case MB_ICONINFORMATION:
id_icon = IDI_INFORMATION;
break;
case MB_ICONEXCLAMATION:
id_icon = IDI_EXCLAMATION;
break;
case MB_ICONQUESTION:
id_icon = IDI_QUESTION;
break;
}
if (IsTiny) {
if (id_icon != -1) {
CtrlData [i].dwAddData = (DWORD)GetSmallSystemIcon (id_icon);
}
rcIcon.right = 16;
rcIcon.bottom = 16;
}
else {
if (id_icon != -1) {
CtrlData [i].dwAddData = (DWORD)GetLargeSystemIcon (id_icon);
MsgBoxData.hIcon = GetSmallSystemIcon (id_icon);
}
rcIcon.right = 32;
rcIcon.bottom = 32;
}
MsgBoxData.controlnr ++;
}
rcText.left = 0;
rcText.top = 0;
rcText.right = rcButtons.right + (mb_margin << 1);
rcText.right = MAX (rcText.right, mb_textw);
rcText.bottom = GetSysCharHeight ();
SelectFont (HDC_SCREEN, __mg_def_renderer->we_fonts[WE_MESSAGEBOX]);
DrawText (HDC_SCREEN, pszText, -1, &rcText,
DT_LEFT | DT_TOP | DT_WORDBREAK | DT_EXPANDTABS | DT_CALCRECT);
if (IsTiny)
rcText.right = MAX (rcText.right, mb_textw);
i = MsgBoxData.controlnr;
CtrlData [i].class_name= "static";
CtrlData [i].dwStyle = WS_VISIBLE | SS_LEFT | WS_GROUP;
CtrlData [i].dwExStyle = 0;
CtrlData [i].x = RECTW (rcIcon) + (mb_margin << 1);
CtrlData [i].y = mb_margin;
CtrlData [i].w = RECTW (rcText);
CtrlData [i].h = RECTH (rcText);
CtrlData [i].id = IDC_STATIC+100;
CtrlData [i].caption = pszText;
CtrlData [i].dwAddData = 0;
MsgBoxData.controlnr ++;
iBorder = 1 + 2*GetWindowElementAttr (hParentWnd, WE_METRICS_WND_BORDER);
width = MAX (RECTW (rcText), RECTW (rcButtons)) + RECTW (rcIcon)
+ (mb_margin << 2)
+ (iBorder << 1);
height = MAX (RECTH (rcText), RECTH (rcIcon)) + RECTH (rcButtons)
+ mb_margin + (mb_margin << 1)
+ (iBorder << 1)
+ GetWindowElementAttr (hParentWnd, WE_METRICS_CAPTION);
buttonx = (width - RECTW (rcButtons)) >> 1;
for (i = 0; i < nButtons; i++) {
CtrlData[i].x = buttonx + i*(mb_buttonw + mb_margin);
CtrlData[i].y = MAX (RECTH (rcIcon), RECTH (rcText)) + (mb_margin<<1);
CtrlData[i].w = mb_buttonw;
CtrlData[i].h = mb_buttonh;
}
MsgBoxData.w = width;
MsgBoxData.h = height;
get_box_xy (hParentWnd, dwStyle, &MsgBoxData);
MsgBoxData.controls = CtrlData;
return DialogBoxIndirectParam (&MsgBoxData, hParentWnd, MsgBoxProc,
(LPARAM)dwStyle);
}
#endif /* _MGCTRL_STATIC */
#endif /* _MGCTRL_BUTTON */
void GUIAPI MessageBeep (DWORD dwBeep)
{
Beep ();
}