* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: messagebox.c,v 1.19 2003/10/12 00:39:50 weiden Exp $
+/* $Id$
*
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/messagebox.c
/* INCLUDES ******************************************************************/
-#include <windows.h>
-#include <messages.h>
#include <user32.h>
-#include <string.h>
-#include <ntos/rtl.h>
-#include <stdio.h>
-#include <stdlib.h>
+#define NDEBUG
#include <debug.h>
-#include "resource.h"
-
-typedef UINT *LPUINT;
-#include <mmsystem.h>
/* DEFINES *******************************************************************/
#define MSGBOXEX_SPACING (16)
#define MSGBOXEX_BUTTONSPACING (6)
#define MSGBOXEX_MARGIN (12)
+#define MSGBOXEX_MAXBTNSTR (32)
+#define MSGBOXEX_MAXBTNS (4)
typedef struct _MSGBOXINFO {
HICON Icon;
/* INTERNAL FUNCTIONS ********************************************************/
-static inline unsigned int strlenW( const WCHAR *str )
-{
- const WCHAR *s = str;
- while (*s) s++;
- return s - str;
-}
-
static INT_PTR CALLBACK MessageBoxProc( HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
PMSGBOXINFO mbi;
HELPINFO hi;
HWND owner;
-
+
switch(message) {
case WM_INITDIALOG:
mbi = (PMSGBOXINFO)lParam;
if(mbi->Icon)
SendDlgItemMessageW(hwnd, MSGBOX_IDICON, STM_SETICON, (WPARAM)mbi->Icon, 0);
SetWindowContextHelpId(hwnd, mbi->ContextHelpId);
-
+
/* set control fonts */
SendDlgItemMessageW(hwnd, MSGBOX_IDTEXT, WM_SETFONT, (WPARAM)mbi->Font, 0);
for(i = 0; i < mbi->nButtons; i++)
SetTimer(hwnd, 0, mbi->Timeout, NULL);
}
return 0;
-
+
case WM_COMMAND:
switch (LOWORD(wParam))
{
return 0;
}
return 0;
-
+
case WM_HELP:
mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX");
if(!mbi)
SendMessageW(GetWindow(hwnd, GW_OWNER), WM_HELP, 0, (LPARAM)&hi);
}
return 0;
-
+
case WM_CLOSE:
mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX");
if(!mbi)
}
EndDialog(hwnd, IDCANCEL);
return 1;
-
+
case WM_TIMER:
if(wParam == 0)
{
static int
MessageBoxTimeoutIndirectW(
- CONST LPMSGBOXPARAMS lpMsgBoxParams, UINT Timeout)
+ CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT Timeout)
{
DLGTEMPLATE *tpl;
DLGITEMTEMPLATE *iico, *itxt;
NONCLIENTMETRICSW nclm;
- WCHAR capbuf[32], btnbuf[32];
- HMODULE hUser32;
+ WCHAR capbuf[32];
LPVOID buf;
BYTE *dest;
- LPWSTR caption, text;
+ LPCWSTR caption, text;
HFONT hFont;
HICON Icon;
HDC hDC;
int bufsize, ret, caplen, textlen, btnlen, i, btnleft, btntop, lmargin, nButtons = 0;
- LONG Buttons[4];
- LPWSTR ButtonText[4];
- DLGITEMTEMPLATE *ibtn[4];
+ LONG Buttons[MSGBOXEX_MAXBTNS];
+ WCHAR ButtonText[MSGBOXEX_MAXBTNS][MSGBOXEX_MAXBTNSTR];
+ DLGITEMTEMPLATE *ibtn[MSGBOXEX_MAXBTNS];
RECT btnrect, txtrect, rc;
SIZE btnsize;
MSGBOXINFO mbi;
BOOL defbtn = FALSE;
DWORD units = GetDialogBaseUnits();
-
- hUser32 = GetModuleHandleW(L"USER32");
-
+
if(!lpMsgBoxParams->lpszCaption || !HIWORD((LPWSTR)lpMsgBoxParams->lpszCaption))
{
- LoadStringW(hUser32, IDS_ERROR, &capbuf[0], 32);
+ LoadStringW(User32Instance, IDS_ERROR, &capbuf[0], 32);
caption = &capbuf[0];
}
else
caption = (LPWSTR)lpMsgBoxParams->lpszCaption;
-
- if(!lpMsgBoxParams->lpszText || !HIWORD((LPWSTR)lpMsgBoxParams->lpszText))
+
+ if(!lpMsgBoxParams->lpszText || !HIWORD(lpMsgBoxParams->lpszText))
text = L"";
else
- text = (LPWSTR)lpMsgBoxParams->lpszText;
-
+ text = lpMsgBoxParams->lpszText;
+
caplen = strlenW(caption);
textlen = strlenW(text);
-
+
/* Create selected buttons */
switch(lpMsgBoxParams->dwStyle & MB_TYPEMASK)
{
/* Create Help button */
if(lpMsgBoxParams->dwStyle & MB_HELP)
Buttons[nButtons++] = IDHELP;
-
+
switch(lpMsgBoxParams->dwStyle & MB_ICONMASK)
{
case MB_ICONEXCLAMATION:
MessageBeep(MB_ICONHAND);
break;
case MB_USERICON:
- Icon = LoadIconW(lpMsgBoxParams->hInstance, (LPCWSTR)lpMsgBoxParams->lpszIcon);
+ Icon = LoadIconW(lpMsgBoxParams->hInstance, lpMsgBoxParams->lpszIcon);
MessageBeep(MB_OK);
break;
default:
MessageBeep(MB_OK);
break;
}
-
- bufsize = 0;
-
+
+ /* Basic space */
+ bufsize = sizeof(DLGTEMPLATE) +
+ 2 * sizeof(WORD) + /* menu and class */
+ (caplen + 1) * sizeof(WCHAR); /* title */
+
+ /* Space for icon */
+ if (NULL != Icon)
+ {
+ bufsize = (bufsize + 3) & ~3;
+ bufsize += sizeof(DLGITEMTEMPLATE) +
+ 4 * sizeof(WORD) +
+ sizeof(WCHAR);
+ }
+
+ /* Space for text */
+ bufsize = (bufsize + 3) & ~3;
+ bufsize += sizeof(DLGITEMTEMPLATE) +
+ 3 * sizeof(WORD) +
+ (textlen + 1) * sizeof(WCHAR);
+
+
for(i = 0; i < nButtons; i++)
{
switch(Buttons[i])
{
case IDOK:
- LoadStringW(hUser32, IDS_OK, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_OK, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDCANCEL:
- LoadStringW(hUser32, IDS_CANCEL, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_CANCEL, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDYES:
- LoadStringW(hUser32, IDS_YES, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_YES, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDNO:
- LoadStringW(hUser32, IDS_NO, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_NO, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDTRYAGAIN:
- LoadStringW(hUser32, IDS_TRYAGAIN, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_TRYAGAIN, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDCONTINUE:
- LoadStringW(hUser32, IDS_CONTINUE, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_CONTINUE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDABORT:
- LoadStringW(hUser32, IDS_ABORT, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_ABORT, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDRETRY:
- LoadStringW(hUser32, IDS_RETRY, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_RETRY, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDIGNORE:
- LoadStringW(hUser32, IDS_IGNORE, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_IGNORE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDHELP:
- LoadStringW(hUser32, IDS_HELP, &btnbuf[0], 32);
- ButtonText[i] = &btnbuf[0];
+ LoadStringW(User32Instance, IDS_HELP, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
default:
- ButtonText[i] = NULL;
+ ButtonText[i][0] = (WCHAR)0;
break;
}
- if(ButtonText[i])
- bufsize += ((strlenW(ButtonText[i]) + 1) * sizeof(WCHAR));
- }
-
- if(Icon)
- {
- bufsize += sizeof(DLGITEMTEMPLATE) + (3 * sizeof(WORD)); /* icon */
+
+ /* Space for buttons */
+ bufsize = (bufsize + 3) & ~3;
+ bufsize += sizeof(DLGITEMTEMPLATE) +
+ 3 * sizeof(WORD) +
+ (wcslen(ButtonText[i]) + 1) * sizeof(WCHAR);
}
-
- bufsize += sizeof(DLGTEMPLATE) +
- (2 * sizeof(WORD)) + /* menu and class */
- ((caplen + 1) * sizeof(WCHAR)) + /* title */
- ((nButtons + 1) * sizeof(DLGITEMTEMPLATE)) + /* text and controls */
- ((textlen + 1) * sizeof(WCHAR)); /* text */
-
-
- buf = RtlAllocateHeap(RtlGetProcessHeap(), 0, bufsize);
+
+ buf = RtlAllocateHeap(GetProcessHeap(), 0, bufsize);
if(!buf)
{
return 0;
}
iico = itxt = NULL;
-
+
hDC = CreateCompatibleDC(0);
-
+
nclm.cbSize = sizeof(nclm);
SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0);
hFont = CreateFontIndirectW (&nclm.lfMessageFont);
-
+
tpl = (DLGTEMPLATE *)buf;
-
+
tpl->style = WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU | DS_CENTER | DS_MODALFRAME | DS_NOIDLEMSG;
tpl->dwExtendedStyle = WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
if(lpMsgBoxParams->dwStyle & MB_TOPMOST)
tpl->dwExtendedStyle |= WS_EX_RIGHT;
tpl->x = 100;
tpl->y = 100;
- tpl->cdit = nButtons + (Icon != (HICON)0) + 1;
-
+ tpl->cdit = nButtons + ((Icon != (HICON)0) ? 1 : 0) + 1;
+
dest = (BYTE *)(tpl + 1);
-
+
*(WORD*)dest = 0; /* no menu */
- *(WORD*)(dest + 1) = 0; /* use default window class */
+ *(((WORD*)dest) + 1) = 0; /* use default window class */
dest += 2 * sizeof(WORD);
memcpy(dest, caption, caplen * sizeof(WCHAR));
dest += caplen * sizeof(WCHAR);
- *(WORD*)dest = 0;
- dest += sizeof(WORD);
-
+ *(WCHAR*)dest = L'\0';
+ dest += sizeof(WCHAR);
+
/* Create icon */
if(Icon)
{
- dest = (BYTE*)(((DWORD)dest + 3) & ~3);
+ dest = (BYTE*)(((ULONG_PTR)dest + 3) & ~3);
iico = (DLGITEMTEMPLATE *)dest;
iico->style = WS_CHILD | WS_VISIBLE | SS_ICON;
iico->dwExtendedStyle = 0;
iico->id = MSGBOX_IDICON;
-
+
dest += sizeof(DLGITEMTEMPLATE);
*(WORD*)dest = 0xFFFF;
dest += sizeof(WORD);
dest += sizeof(WORD);
*(WORD*)dest = 0xFFFF;
dest += sizeof(WORD);
- *(WORD*)dest = 0;
- dest += sizeof(WORD);
+ *(WCHAR*)dest = 0;
+ dest += sizeof(WCHAR);
*(WORD*)dest = 0;
dest += sizeof(WORD);
}
-
+
/* create static for text */
dest = (BYTE*)(((DWORD)dest + 3) & ~3);
itxt = (DLGITEMTEMPLATE *)dest;
dest += sizeof(WORD);
memcpy(dest, text, textlen * sizeof(WCHAR));
dest += textlen * sizeof(WCHAR);
+ *(WCHAR*)dest = 0;
+ dest += sizeof(WCHAR);
*(WORD*)dest = 0;
dest += sizeof(WORD);
- *(WORD*)dest = 0;
- dest += sizeof(WORD);
-
+
/* create buttons */
btnsize.cx = BTN_CX;
btnsize.cy = BTN_CY;
btnsize.cx = max(btnsize.cx, btnrect.right);
btnsize.cy = max(btnsize.cy, btnrect.bottom);
}
-
+
/* make first button the default button if no other is */
if(!defbtn)
{
ibtn[0]->style |= BS_DEFPUSHBUTTON;
mbi.DefBtn = Buttons[0];
}
-
+
/* calculate position and size of controls */
txtrect.right = GetSystemMetrics(SM_CXSCREEN) / 5 * 4;
if(Icon)
SelectObject(hDC, hFont);
DrawTextW(hDC, text, textlen, &txtrect, DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
txtrect.right++;
-
+
/* calculate position and size of the icon */
rc.left = rc.bottom = rc.right = 0;
btntop = 0;
-
+
if(iico)
{
rc.right = GetSystemMetrics(SM_CXICON);
btnleft += btnsize.cx + MSGBOXEX_BUTTONSPACING;
}
/* calculate size and position of the messagebox window */
- btnleft = max(btnleft - MSGBOXEX_BUTTONSPACING, rc.left + txtrect.right);
+ btnleft = max(btnleft - MSGBOXEX_BUTTONSPACING, rc.left + txtrect.right);
btnleft += MSGBOXEX_MARGIN;
btntop += btnsize.cy + MSGBOXEX_MARGIN;
/* set size and position of the message static */
/* set size of the window */
tpl->cx = (btnleft * 4) / LOWORD(units);
tpl->cy = (btntop * 8) / HIWORD(units);
-
+
/* finally show the messagebox */
mbi.Icon = Icon;
mbi.Font = hFont;
mbi.nButtons = nButtons;
mbi.Btns = &Buttons[0];
mbi.Timeout = Timeout;
-
+
if(hDC)
DeleteDC(hDC);
-
+
ret = DialogBoxIndirectParamW(lpMsgBoxParams->hInstance, tpl, lpMsgBoxParams->hwndOwner,
MessageBoxProc, (LPARAM)&mbi);
if(hFont)
DeleteObject(hFont);
-
- RtlFreeHeap(RtlGetProcessHeap(), 0, buf);
+
+ RtlFreeHeap(GetProcessHeap(), 0, buf);
return ret;
}
UINT uType,
WORD wLanguageId)
{
- MSGBOXPARAMS msgbox;
+ MSGBOXPARAMSA msgbox;
msgbox.cbSize = sizeof(msgbox);
msgbox.hwndOwner = hWnd;
UINT uType,
WORD wLanguageId)
{
- MSGBOXPARAMS msgbox;
+ MSGBOXPARAMSW msgbox;
msgbox.cbSize = sizeof(msgbox);
msgbox.hwndOwner = hWnd;
msgbox.hInstance = 0;
- msgbox.lpszText = (LPCSTR)lpText;
- msgbox.lpszCaption =(LPCSTR) lpCaption;
+ msgbox.lpszText = lpText;
+ msgbox.lpszCaption = lpCaption;
msgbox.dwStyle = uType;
msgbox.lpszIcon = NULL;
msgbox.dwContextHelpId = 0;
int
STDCALL
MessageBoxIndirectA(
- CONST LPMSGBOXPARAMS lpMsgBoxParams)
+ CONST MSGBOXPARAMSA *lpMsgBoxParams)
{
- MSGBOXPARAMS msgboxW;
+ MSGBOXPARAMSW msgboxW;
UNICODE_STRING textW, captionW, iconW;
int ret;
if (HIWORD((UINT)lpMsgBoxParams->lpszText))
+ {
RtlCreateUnicodeStringFromAsciiz(&textW, (PCSZ)lpMsgBoxParams->lpszText);
+ /*
+ * UNICODE_STRING objects are always allocated with an extra byte so you
+ * can null-term if you want
+ */
+ textW.Buffer[textW.Length / sizeof(WCHAR)] = L'\0';
+ }
else
textW.Buffer = (LPWSTR)lpMsgBoxParams->lpszText;
if (HIWORD((UINT)lpMsgBoxParams->lpszCaption))
+ {
RtlCreateUnicodeStringFromAsciiz(&captionW, (PCSZ)lpMsgBoxParams->lpszCaption);
+ /*
+ * UNICODE_STRING objects are always allocated with an extra byte so you
+ * can null-term if you want
+ */
+ captionW.Buffer[captionW.Length / sizeof(WCHAR)] = L'\0';
+ }
else
captionW.Buffer = (LPWSTR)lpMsgBoxParams->lpszCaption;
- if (HIWORD((UINT)lpMsgBoxParams->lpszIcon))
- RtlCreateUnicodeStringFromAsciiz(&iconW, (PCSZ)lpMsgBoxParams->lpszIcon);
+ if(lpMsgBoxParams->dwStyle & MB_USERICON)
+ {
+ if (HIWORD((UINT)lpMsgBoxParams->lpszIcon))
+ {
+ RtlCreateUnicodeStringFromAsciiz(&iconW, (PCSZ)lpMsgBoxParams->lpszIcon);
+ /*
+ * UNICODE_STRING objects are always allocated with an extra byte so you
+ * can null-term if you want
+ */
+ iconW.Buffer[iconW.Length / sizeof(WCHAR)] = L'\0';
+ }
+ else
+ iconW.Buffer = (LPWSTR)lpMsgBoxParams->lpszIcon;
+ }
else
- iconW.Buffer = (LPWSTR)lpMsgBoxParams->lpszIcon;
+ iconW.Buffer = NULL;
msgboxW.cbSize = sizeof(msgboxW);
msgboxW.hwndOwner = lpMsgBoxParams->hwndOwner;
msgboxW.hInstance = lpMsgBoxParams->hInstance;
- msgboxW.lpszText = (LPCSTR)textW.Buffer;
- msgboxW.lpszCaption = (LPCSTR)captionW.Buffer;
+ msgboxW.lpszText = textW.Buffer;
+ msgboxW.lpszCaption = captionW.Buffer;
msgboxW.dwStyle = lpMsgBoxParams->dwStyle;
- msgboxW.lpszIcon = (LPCSTR)iconW.Buffer;
+ msgboxW.lpszIcon = iconW.Buffer;
msgboxW.dwContextHelpId = lpMsgBoxParams->dwContextHelpId;
msgboxW.lpfnMsgBoxCallback = lpMsgBoxParams->lpfnMsgBoxCallback;
msgboxW.dwLanguageId = lpMsgBoxParams->dwLanguageId;
ret = MessageBoxTimeoutIndirectW(&msgboxW, (UINT)-1);
- if (HIWORD(textW.Buffer))
+ if (HIWORD((UINT)lpMsgBoxParams->lpszText))
RtlFreeUnicodeString(&textW);
- if (HIWORD(captionW.Buffer))
+ if (HIWORD((UINT)lpMsgBoxParams->lpszCaption))
RtlFreeUnicodeString(&captionW);
- if (HIWORD(iconW.Buffer))
+ if ((lpMsgBoxParams->dwStyle & MB_USERICON) && HIWORD((UINT)iconW.Buffer))
RtlFreeUnicodeString(&iconW);
return ret;
int
STDCALL
MessageBoxIndirectW(
- CONST LPMSGBOXPARAMS lpMsgBoxParams)
+ CONST MSGBOXPARAMSW *lpMsgBoxParams)
{
return MessageBoxTimeoutIndirectW(lpMsgBoxParams, (UINT)-1);
}
WORD wLanguageId,
DWORD dwTime)
{
- MSGBOXPARAMS msgboxW;
+ MSGBOXPARAMSW msgboxW;
UNICODE_STRING textW, captionW;
int ret;
msgboxW.cbSize = sizeof(msgboxW);
msgboxW.hwndOwner = hWnd;
msgboxW.hInstance = 0;
- msgboxW.lpszText = (LPCSTR)textW.Buffer;
- msgboxW.lpszCaption = (LPCSTR)captionW.Buffer;
+ msgboxW.lpszText = textW.Buffer;
+ msgboxW.lpszCaption = captionW.Buffer;
msgboxW.dwStyle = uType;
msgboxW.lpszIcon = NULL;
msgboxW.dwContextHelpId = 0;
WORD wLanguageId,
DWORD dwTime)
{
- MSGBOXPARAMS msgbox;
+ MSGBOXPARAMSW msgbox;
msgbox.cbSize = sizeof(msgbox);
msgbox.hwndOwner = hWnd;
msgbox.hInstance = 0;
- msgbox.lpszText = (LPCSTR)lpText;
- msgbox.lpszCaption =(LPCSTR) lpCaption;
+ msgbox.lpszText = lpText;
+ msgbox.lpszCaption = lpCaption;
msgbox.dwStyle = uType;
msgbox.lpszIcon = NULL;
msgbox.dwContextHelpId = 0;
/*
* @implemented
*/
-WINBOOL
+BOOL
STDCALL
MessageBeep(UINT uType)
{
if(waveOutGetNumDevs() == 0)
return Beep(500, 100); // Beep through speaker
/* fall through */
- case MB_OK:
+ case MB_OK:
EventName = L"SystemDefault";
break;
case MB_ICONASTERISK: