mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 23:55:41 +00:00
[USER32] Implement SoftModalMessageBox() based on the original MessageBoxTimeoutIndirectW().
Additional changes: - Adapt the message-box dialog procedure to correctly take into account the presence or absence of a CANCEL button and take appropriate actions. - Cache the strings retrieved by MB_GetString() (add FIXME notices too).
This commit is contained in:
parent
5fedabbf0a
commit
2be262bfb1
2 changed files with 295 additions and 147 deletions
|
@ -675,7 +675,7 @@
|
||||||
666 stdcall ShowStartGlass(long)
|
666 stdcall ShowStartGlass(long)
|
||||||
667 stdcall ShowWindow(long long) NtUserShowWindow
|
667 stdcall ShowWindow(long long) NtUserShowWindow
|
||||||
668 stdcall ShowWindowAsync(long long) NtUserShowWindowAsync
|
668 stdcall ShowWindowAsync(long long) NtUserShowWindowAsync
|
||||||
669 stdcall SoftModalMessageBox(long)
|
669 stdcall SoftModalMessageBox(ptr)
|
||||||
670 stdcall SubtractRect(ptr ptr ptr)
|
670 stdcall SubtractRect(ptr ptr ptr)
|
||||||
671 stdcall SwapMouseButton(long)
|
671 stdcall SwapMouseButton(long)
|
||||||
672 stdcall SwitchDesktop(long) NtUserSwitchDesktop
|
672 stdcall SwitchDesktop(long) NtUserSwitchDesktop
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
* PURPOSE: Message Boxes
|
* PURPOSE: Message Boxes
|
||||||
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||||
* Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
* Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
||||||
|
* Hermes Belusca-Maito
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
* 2003/07/28 Added some NT features
|
* 2003/07/28 Added some NT features
|
||||||
* 2003/07/27 Code ported from wine
|
* 2003/07/27 Code ported from wine
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <user32.h>
|
#include <user32.h>
|
||||||
|
#include <ntstrsafe.h>
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
||||||
|
|
||||||
|
@ -100,6 +102,43 @@ static const MSGBTNINFO MsgBtnInfo[] =
|
||||||
|
|
||||||
/* INTERNAL FUNCTIONS ********************************************************/
|
/* INTERNAL FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static UINT
|
||||||
|
LoadAllocStringW(
|
||||||
|
IN HINSTANCE hInstance OPTIONAL,
|
||||||
|
IN UINT uID,
|
||||||
|
OUT PWSTR* pString,
|
||||||
|
IN PCWSTR pDefaultString OPTIONAL)
|
||||||
|
{
|
||||||
|
UINT Length;
|
||||||
|
PCWSTR pStr;
|
||||||
|
|
||||||
|
/* Try to load the string from the resource */
|
||||||
|
Length = LoadStringW(hInstance, uID, (LPWSTR)&pStr, 0);
|
||||||
|
if (Length == 0)
|
||||||
|
{
|
||||||
|
/* If the resource string was not found, use the fallback default one */
|
||||||
|
|
||||||
|
if (!pDefaultString)
|
||||||
|
{
|
||||||
|
/* None was specified, return NULL */
|
||||||
|
*pString = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pStr = pDefaultString;
|
||||||
|
Length = wcslen(pStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a new buffer, adding a NULL-terminator */
|
||||||
|
*pString = RtlAllocateHeap(RtlGetProcessHeap(), 0, (Length + 1) * sizeof(WCHAR));
|
||||||
|
if (!*pString)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Copy the string, NULL-terminated */
|
||||||
|
RtlStringCchCopyNW(*pString, Length + 1, pStr, Length);
|
||||||
|
return Length;
|
||||||
|
}
|
||||||
|
|
||||||
static VOID MessageBoxTextToClipboard(HWND DialogWindow)
|
static VOID MessageBoxTextToClipboard(HWND DialogWindow)
|
||||||
{
|
{
|
||||||
HWND hwndText;
|
HWND hwndText;
|
||||||
|
@ -208,15 +247,14 @@ static INT_PTR CALLBACK MessageBoxProc(
|
||||||
HWND hwnd, UINT message,
|
HWND hwnd, UINT message,
|
||||||
WPARAM wParam, LPARAM lParam)
|
WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
int Alert;
|
|
||||||
PMSGBOXDATA mbd;
|
PMSGBOXDATA mbd;
|
||||||
HELPINFO hi;
|
|
||||||
HWND hwndOwner;
|
|
||||||
|
|
||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
{
|
{
|
||||||
|
int Alert;
|
||||||
|
|
||||||
mbd = (PMSGBOXDATA)lParam;
|
mbd = (PMSGBOXDATA)lParam;
|
||||||
|
|
||||||
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)mbd);
|
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)mbd);
|
||||||
|
@ -234,7 +272,7 @@ static INT_PTR CALLBACK MessageBoxProc(
|
||||||
SendDlgItemMessageW(hwnd, MSGBOX_IDICON, STM_SETICON, (WPARAM)(HICON)mbd->mbp.lpszIcon, 0);
|
SendDlgItemMessageW(hwnd, MSGBOX_IDICON, STM_SETICON, (WPARAM)(HICON)mbd->mbp.lpszIcon, 0);
|
||||||
Alert = ALERT_SYSTEM_WARNING;
|
Alert = ALERT_SYSTEM_WARNING;
|
||||||
}
|
}
|
||||||
else // Setup the rest of the alerts.
|
else /* Setup the rest of the alerts */
|
||||||
{
|
{
|
||||||
switch (mbd->mbp.dwStyle & MB_ICONMASK)
|
switch (mbd->mbp.dwStyle & MB_ICONMASK)
|
||||||
{
|
{
|
||||||
|
@ -249,32 +287,66 @@ static INT_PTR CALLBACK MessageBoxProc(
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Alert = ALERT_SYSTEM_INFORMATIONAL;
|
Alert = ALERT_SYSTEM_INFORMATIONAL;
|
||||||
/* fall through */
|
/* Fall through */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Send out the alert notifications. */
|
/* Send out the alert notifications */
|
||||||
NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd, OBJID_ALERT, Alert);
|
NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd, OBJID_ALERT, Alert);
|
||||||
|
|
||||||
switch (mbd->mbp.dwStyle & MB_TYPEMASK)
|
/* Disable the Close menu button if no Cancel button is specified */
|
||||||
|
if (mbd->uCancelId == 0)
|
||||||
{
|
{
|
||||||
case MB_ABORTRETRYIGNORE:
|
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
|
||||||
case MB_YESNO:
|
if (hSysMenu)
|
||||||
RemoveMenu(GetSystemMenu(hwnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
|
DeleteMenu(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
ASSERT(mbd->uDefButton < mbd->dwButtons);
|
|
||||||
SetFocus(GetDlgItem(hwnd, mbd->pidButton[mbd->uDefButton]));
|
/* Set the focus to the default button */
|
||||||
|
if (mbd->dwButtons > 0)
|
||||||
|
{
|
||||||
|
ASSERT(mbd->uDefButton < mbd->dwButtons);
|
||||||
|
SetFocus(GetDlgItem(hwnd, mbd->pidButton[mbd->uDefButton]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the window timer */
|
||||||
if (mbd->dwTimeout && (mbd->dwTimeout != (UINT)-1))
|
if (mbd->dwTimeout && (mbd->dwTimeout != (UINT)-1))
|
||||||
SetTimer(hwnd, 0, mbd->dwTimeout, NULL);
|
SetTimer(hwnd, 0, mbd->dwTimeout, NULL);
|
||||||
}
|
}
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
switch (LOWORD(wParam))
|
{
|
||||||
|
UINT i;
|
||||||
|
INT_PTR iCtrlId = LOWORD(wParam);
|
||||||
|
|
||||||
|
switch (iCtrlId)
|
||||||
{
|
{
|
||||||
|
/* Handle the default message-box buttons */
|
||||||
case IDOK:
|
case IDOK:
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
|
/*
|
||||||
|
* The dialog manager always sends IDCANCEL when the user
|
||||||
|
* presses ESCape. We check here whether the message box
|
||||||
|
* has a CANCEL button, or whether we should fall back to
|
||||||
|
* the OK button, by using the correct uCancelId.
|
||||||
|
*/
|
||||||
|
if (iCtrlId == IDCANCEL)
|
||||||
|
{
|
||||||
|
mbd = (PMSGBOXDATA)GetPropW(hwnd, L"ROS_MSGBOX");
|
||||||
|
if (!mbd)
|
||||||
|
return FALSE; /* Ignore */
|
||||||
|
|
||||||
|
/* Check whether we can cancel the message box */
|
||||||
|
if (mbd->uCancelId == 0)
|
||||||
|
return TRUE; // FALSE; /* No, ignore */
|
||||||
|
/* Quit with the correct return value */
|
||||||
|
iCtrlId = mbd->uCancelId;
|
||||||
|
}
|
||||||
|
if (!GetDlgItem(hwnd, iCtrlId))
|
||||||
|
return FALSE; /* Ignore */
|
||||||
|
|
||||||
|
/* Fall through */
|
||||||
case IDABORT:
|
case IDABORT:
|
||||||
case IDRETRY:
|
case IDRETRY:
|
||||||
case IDIGNORE:
|
case IDIGNORE:
|
||||||
|
@ -282,69 +354,93 @@ static INT_PTR CALLBACK MessageBoxProc(
|
||||||
case IDNO:
|
case IDNO:
|
||||||
case IDTRYAGAIN:
|
case IDTRYAGAIN:
|
||||||
case IDCONTINUE:
|
case IDCONTINUE:
|
||||||
EndDialog(hwnd, wParam);
|
EndDialog(hwnd, iCtrlId);
|
||||||
return 0;
|
return TRUE;
|
||||||
|
|
||||||
|
case IDCLOSE:
|
||||||
|
return FALSE; /* Ignore */
|
||||||
|
|
||||||
case IDHELP:
|
case IDHELP:
|
||||||
/* send WM_HELP message to messagebox window */
|
{
|
||||||
|
/* Send WM_HELP message to the message-box window */
|
||||||
|
HELPINFO hi;
|
||||||
hi.cbSize = sizeof(hi);
|
hi.cbSize = sizeof(hi);
|
||||||
hi.iContextType = HELPINFO_WINDOW;
|
hi.iContextType = HELPINFO_WINDOW;
|
||||||
hi.iCtrlId = LOWORD(wParam);
|
hi.iCtrlId = iCtrlId;
|
||||||
hi.hItemHandle = (HANDLE)lParam;
|
hi.hItemHandle = (HANDLE)lParam;
|
||||||
hi.dwContextId = 0;
|
hi.dwContextId = 0;
|
||||||
GetCursorPos(&hi.MousePos);
|
GetCursorPos(&hi.MousePos);
|
||||||
SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi);
|
SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi);
|
||||||
return 0;
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
/* Check for any other user-defined buttons */
|
||||||
|
mbd = (PMSGBOXDATA)GetPropW(hwnd, L"ROS_MSGBOX");
|
||||||
|
if (!mbd)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < mbd->dwButtons; ++i)
|
||||||
|
{
|
||||||
|
if (iCtrlId == mbd->pidButton[i])
|
||||||
|
{
|
||||||
|
EndDialog(hwnd, iCtrlId);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
case WM_COPY:
|
case WM_COPY:
|
||||||
MessageBoxTextToClipboard(hwnd);
|
MessageBoxTextToClipboard(hwnd);
|
||||||
return 0;
|
return TRUE;
|
||||||
|
|
||||||
case WM_HELP:
|
case WM_HELP:
|
||||||
{
|
{
|
||||||
|
LPHELPINFO phi = (LPHELPINFO)lParam;
|
||||||
mbd = (PMSGBOXDATA)GetPropW(hwnd, L"ROS_MSGBOX");
|
mbd = (PMSGBOXDATA)GetPropW(hwnd, L"ROS_MSGBOX");
|
||||||
if (!mbd)
|
if (!mbd)
|
||||||
return 0;
|
return FALSE;
|
||||||
memcpy(&hi, (void *)lParam, sizeof(hi));
|
phi->dwContextId = GetWindowContextHelpId(hwnd);
|
||||||
hi.dwContextId = GetWindowContextHelpId(hwnd);
|
|
||||||
|
|
||||||
if (mbd->mbp.lpfnMsgBoxCallback)
|
if (mbd->mbp.lpfnMsgBoxCallback)
|
||||||
{
|
{
|
||||||
mbd->mbp.lpfnMsgBoxCallback(&hi);
|
mbd->mbp.lpfnMsgBoxCallback(phi);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hwndOwner = GetWindow(hwnd, GW_OWNER);
|
HWND hwndOwner = GetWindow(hwnd, GW_OWNER);
|
||||||
if (hwndOwner)
|
if (hwndOwner)
|
||||||
SendMessageW(hwndOwner, WM_HELP, 0, (LPARAM)&hi);
|
SendMessageW(hwndOwner, WM_HELP, 0, lParam);
|
||||||
}
|
}
|
||||||
return 0;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
{
|
{
|
||||||
mbd = (PMSGBOXDATA)GetPropW(hwnd, L"ROS_MSGBOX");
|
mbd = (PMSGBOXDATA)GetPropW(hwnd, L"ROS_MSGBOX");
|
||||||
if (!mbd)
|
if (!mbd)
|
||||||
return 0;
|
return FALSE;
|
||||||
switch (mbd->mbp.dwStyle & MB_TYPEMASK)
|
|
||||||
{
|
/* Check whether we can cancel the message box */
|
||||||
case MB_ABORTRETRYIGNORE:
|
if (mbd->uCancelId == 0)
|
||||||
case MB_YESNO:
|
return TRUE; /* No, ignore */
|
||||||
return 1;
|
/* Quit with the correct return value */
|
||||||
}
|
EndDialog(hwnd, mbd->uCancelId);
|
||||||
EndDialog(hwnd, IDCANCEL);
|
return TRUE;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
if (wParam == 0)
|
if (wParam == 0)
|
||||||
{
|
|
||||||
EndDialog(hwnd, IDTIMEOUT);
|
EndDialog(hwnd, IDTIMEOUT);
|
||||||
}
|
return FALSE;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -352,40 +448,33 @@ MessageBoxTimeoutIndirectW(
|
||||||
CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT dwTimeout)
|
CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT dwTimeout)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
UINT i;
|
||||||
|
LPWSTR defCaption = NULL;
|
||||||
MSGBOXDATA mbd;
|
MSGBOXDATA mbd;
|
||||||
MSGBTNINFO Buttons;
|
MSGBTNINFO Buttons;
|
||||||
LPCWSTR ButtonText[MSGBOXEX_MAXBTNS];
|
LPCWSTR ButtonText[MSGBOXEX_MAXBTNS];
|
||||||
DLGTEMPLATE *tpl;
|
|
||||||
DLGITEMTEMPLATE *iico, *itxt, *ibtn;
|
|
||||||
NONCLIENTMETRICSW nclm;
|
|
||||||
LPVOID buf;
|
|
||||||
BYTE *dest;
|
|
||||||
LPCWSTR caption, text;
|
|
||||||
HFONT hFont, hOldFont;
|
|
||||||
HICON hIcon;
|
|
||||||
HWND hDCWnd;
|
|
||||||
HDC hDC;
|
|
||||||
SIZE units;
|
|
||||||
int bufsize, caplen, textlen, i, btnleft, btntop;
|
|
||||||
size_t ButtonLen;
|
|
||||||
RECT btnrect, txtrect, rc;
|
|
||||||
SIZE btnsize;
|
|
||||||
POINT iconPos; SIZE iconSize;
|
|
||||||
|
|
||||||
|
|
||||||
ZeroMemory(&mbd, sizeof(mbd));
|
ZeroMemory(&mbd, sizeof(mbd));
|
||||||
memcpy(&mbd.mbp, lpMsgBoxParams, sizeof(mbd.mbp));
|
memcpy(&mbd.mbp, lpMsgBoxParams, sizeof(mbd.mbp));
|
||||||
lpMsgBoxParams = &mbd.mbp;
|
mbd.wLanguageId = (WORD)lpMsgBoxParams->dwLanguageId;
|
||||||
|
|
||||||
mbd.wLanguageId = (WORD)lpMsgBoxParams->dwLanguageId; // FIXME!
|
|
||||||
mbd.dwTimeout = dwTimeout;
|
mbd.dwTimeout = dwTimeout;
|
||||||
|
|
||||||
|
if (!mbd.mbp.lpszCaption)
|
||||||
|
{
|
||||||
|
/* No caption, use the default one */
|
||||||
|
LoadAllocStringW(User32Instance,
|
||||||
|
IDS_ERROR,
|
||||||
|
&defCaption,
|
||||||
|
L"Error");
|
||||||
|
mbd.mbp.lpszCaption = (defCaption ? defCaption : L"Error");
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the selected buttons; unknown types will fall back to MB_OK */
|
/* Create the selected buttons; unknown types will fall back to MB_OK */
|
||||||
i = (lpMsgBoxParams->dwStyle & MB_TYPEMASK);
|
i = (lpMsgBoxParams->dwStyle & MB_TYPEMASK);
|
||||||
if (i >= ARRAYSIZE(MsgBtnInfo))
|
if (i >= ARRAYSIZE(MsgBtnInfo))
|
||||||
i = MB_OK;
|
i = MB_OK;
|
||||||
|
|
||||||
/* Get buttons IDs */
|
/* Get the buttons IDs */
|
||||||
Buttons = MsgBtnInfo[i];
|
Buttons = MsgBtnInfo[i];
|
||||||
|
|
||||||
/* Add the Help button */
|
/* Add the Help button */
|
||||||
|
@ -398,6 +487,23 @@ MessageBoxTimeoutIndirectW(
|
||||||
|
|
||||||
ASSERT(Buttons.btnCnt <= MSGBOXEX_MAXBTNS);
|
ASSERT(Buttons.btnCnt <= MSGBOXEX_MAXBTNS);
|
||||||
|
|
||||||
|
/* Retrieve the pointers to the button labels and find the Cancel button */
|
||||||
|
mbd.uCancelId = (i == MB_OK ? IDOK : 0);
|
||||||
|
for (i = 0; i < Buttons.btnCnt; ++i)
|
||||||
|
{
|
||||||
|
// FIXME: Use the strings in the correct language.
|
||||||
|
// MB_GetString gives the string in default system language.
|
||||||
|
ButtonText[i] = MB_GetString(Buttons.btnIds[i] - IDS_OK); /* or: Buttons.btnIdx[i] - IDOK */
|
||||||
|
#if 0
|
||||||
|
LoadAllocStringW(User32Instance,
|
||||||
|
Buttons.btnIds[i],
|
||||||
|
&ButtonText[i],
|
||||||
|
L"");
|
||||||
|
#endif
|
||||||
|
if (Buttons.btnIdx[i] == IDCANCEL)
|
||||||
|
mbd.uCancelId = IDCANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
mbd.pidButton = Buttons.btnIdx;
|
mbd.pidButton = Buttons.btnIdx;
|
||||||
mbd.ppszButtonText = ButtonText;
|
mbd.ppszButtonText = ButtonText;
|
||||||
mbd.dwButtons = Buttons.btnCnt;
|
mbd.dwButtons = Buttons.btnCnt;
|
||||||
|
@ -406,49 +512,96 @@ MessageBoxTimeoutIndirectW(
|
||||||
/* Make the first button the default button if none other is */
|
/* Make the first button the default button if none other is */
|
||||||
if (mbd.uDefButton >= mbd.dwButtons)
|
if (mbd.uDefButton >= mbd.dwButtons)
|
||||||
mbd.uDefButton = 0;
|
mbd.uDefButton = 0;
|
||||||
// mbd.uCancelId;
|
|
||||||
|
|
||||||
|
/* Call the helper function */
|
||||||
|
ret = SoftModalMessageBox(&mbd);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (i = 0; i < mbd.dwButtons; i++)
|
||||||
|
{
|
||||||
|
if (ButtonText[i] && *ButtonText[i])
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, ButtonText[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (defCaption)
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, defCaption);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
WINAPI
|
||||||
|
SoftModalMessageBox(IN LPMSGBOXDATA lpMsgBoxData)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
MSGBOXDATA mbd;
|
||||||
|
LPMSGBOXPARAMSW lpMsgBoxParams = &mbd.mbp;
|
||||||
|
DLGTEMPLATE *tpl;
|
||||||
|
DLGITEMTEMPLATE *iico, *itxt, *ibtn;
|
||||||
|
NONCLIENTMETRICSW nclm;
|
||||||
|
LPVOID buf;
|
||||||
|
BYTE *dest;
|
||||||
|
LPWSTR caption, text;
|
||||||
|
HFONT hFont, hOldFont;
|
||||||
|
HICON hIcon;
|
||||||
|
HWND hDCWnd;
|
||||||
|
HDC hDC;
|
||||||
|
SIZE units;
|
||||||
|
int bufsize, caplen, textlen, i, btnleft, btntop;
|
||||||
|
size_t ButtonLen;
|
||||||
|
RECT btnrect, txtrect, rc;
|
||||||
|
SIZE btnsize;
|
||||||
|
POINT iconPos; SIZE iconSize;
|
||||||
|
|
||||||
|
/* Capture the MsgBoxData */
|
||||||
|
memcpy(&mbd, lpMsgBoxData, sizeof(mbd));
|
||||||
|
|
||||||
/* Load the caption */
|
/* Load the caption */
|
||||||
if (!lpMsgBoxParams->lpszCaption)
|
caption = NULL;
|
||||||
{
|
if (lpMsgBoxParams->lpszCaption && IS_INTRESOURCE(lpMsgBoxParams->lpszCaption))
|
||||||
/* No caption, use the default one */
|
|
||||||
caplen = LoadStringW(User32Instance, IDS_ERROR, (LPWSTR)&caption, 0);
|
|
||||||
}
|
|
||||||
else if (IS_INTRESOURCE(lpMsgBoxParams->lpszCaption))
|
|
||||||
{
|
{
|
||||||
/* User-defined resource string */
|
/* User-defined resource string */
|
||||||
caplen = LoadStringW(lpMsgBoxParams->hInstance,
|
caplen = LoadAllocStringW(lpMsgBoxParams->hInstance,
|
||||||
PtrToUlong(lpMsgBoxParams->lpszCaption),
|
PtrToUlong(lpMsgBoxParams->lpszCaption),
|
||||||
(LPWSTR)&caption, 0);
|
&caption,
|
||||||
|
NULL);
|
||||||
|
lpMsgBoxParams->lpszCaption = caption;
|
||||||
}
|
}
|
||||||
else
|
else if (lpMsgBoxParams->lpszCaption)
|
||||||
{
|
{
|
||||||
/* UNICODE string pointer */
|
/* UNICODE string pointer */
|
||||||
caption = lpMsgBoxParams->lpszCaption;
|
caplen = wcslen(lpMsgBoxParams->lpszCaption);
|
||||||
caplen = wcslen(caption);
|
}
|
||||||
|
if (!lpMsgBoxParams->lpszCaption)
|
||||||
|
{
|
||||||
|
/* No caption, use blank */
|
||||||
|
lpMsgBoxParams->lpszCaption = L"";
|
||||||
|
caplen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the text */
|
/* Load the text */
|
||||||
|
text = NULL;
|
||||||
|
if (lpMsgBoxParams->lpszText && IS_INTRESOURCE(lpMsgBoxParams->lpszText))
|
||||||
|
{
|
||||||
|
/* User-defined resource string */
|
||||||
|
textlen = LoadAllocStringW(lpMsgBoxParams->hInstance,
|
||||||
|
PtrToUlong(lpMsgBoxParams->lpszText),
|
||||||
|
&text,
|
||||||
|
NULL);
|
||||||
|
lpMsgBoxParams->lpszText = text;
|
||||||
|
}
|
||||||
|
else if (lpMsgBoxParams->lpszText)
|
||||||
|
{
|
||||||
|
/* UNICODE string pointer */
|
||||||
|
textlen = wcslen(lpMsgBoxParams->lpszText);
|
||||||
|
}
|
||||||
if (!lpMsgBoxParams->lpszText)
|
if (!lpMsgBoxParams->lpszText)
|
||||||
{
|
{
|
||||||
/* No text, use blank */
|
/* No text, use blank */
|
||||||
text = L"";
|
lpMsgBoxParams->lpszText = L"";
|
||||||
textlen = 0;
|
textlen = 0;
|
||||||
}
|
}
|
||||||
else if (IS_INTRESOURCE(lpMsgBoxParams->lpszText))
|
|
||||||
{
|
|
||||||
/* User-defined resource string */
|
|
||||||
textlen = LoadStringW(lpMsgBoxParams->hInstance,
|
|
||||||
PtrToUlong(lpMsgBoxParams->lpszText),
|
|
||||||
(LPWSTR)&text, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* UNICODE string pointer */
|
|
||||||
text = lpMsgBoxParams->lpszText;
|
|
||||||
textlen = wcslen(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the icon */
|
/* Load the icon */
|
||||||
switch (lpMsgBoxParams->dwStyle & MB_ICONMASK)
|
switch (lpMsgBoxParams->dwStyle & MB_ICONMASK)
|
||||||
|
@ -483,7 +636,7 @@ MessageBoxTimeoutIndirectW(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Reuse the internal pointer! */
|
/* Reuse the internal pointer! */
|
||||||
((MSGBOXPARAMSW*)lpMsgBoxParams)->lpszIcon = (LPCWSTR)hIcon;
|
lpMsgBoxParams->lpszIcon = (LPCWSTR)hIcon;
|
||||||
|
|
||||||
/* Basic space */
|
/* Basic space */
|
||||||
bufsize = sizeof(DLGTEMPLATE) +
|
bufsize = sizeof(DLGTEMPLATE) +
|
||||||
|
@ -509,31 +662,17 @@ MessageBoxTimeoutIndirectW(
|
||||||
/* Space for the buttons */
|
/* Space for the buttons */
|
||||||
for (i = 0; i < mbd.dwButtons; i++)
|
for (i = 0; i < mbd.dwButtons; i++)
|
||||||
{
|
{
|
||||||
/* Get the default text of the buttons */
|
if (!mbd.ppszButtonText[i] || !*mbd.ppszButtonText[i])
|
||||||
if (Buttons.btnIds[i])
|
|
||||||
{
|
|
||||||
LPCWSTR pStr;
|
|
||||||
ButtonLen = LoadStringW(User32Instance,
|
|
||||||
Buttons.btnIds[i],
|
|
||||||
(LPWSTR)&pStr, 0);
|
|
||||||
mbd.ppszButtonText[i] = RtlAllocateHeap(GetProcessHeap(), 0, (ButtonLen + 1) * sizeof(WCHAR));
|
|
||||||
if (mbd.ppszButtonText[i])
|
|
||||||
{
|
|
||||||
memcpy((LPWSTR)mbd.ppszButtonText[i], pStr, ButtonLen * sizeof(WCHAR));
|
|
||||||
((LPWSTR)mbd.ppszButtonText[i])[ButtonLen] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mbd.ppszButtonText[i] = L"";
|
|
||||||
ButtonLen = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* No text, use blank */
|
/* No text, use blank */
|
||||||
mbd.ppszButtonText[i] = L"";
|
mbd.ppszButtonText[i] = L"";
|
||||||
ButtonLen = 0;
|
ButtonLen = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* UNICODE string pointer */
|
||||||
|
ButtonLen = wcslen(mbd.ppszButtonText[i]);
|
||||||
|
}
|
||||||
|
|
||||||
bufsize = ALIGN_UP(bufsize, DWORD);
|
bufsize = ALIGN_UP(bufsize, DWORD);
|
||||||
bufsize += sizeof(DLGITEMTEMPLATE) +
|
bufsize += sizeof(DLGITEMTEMPLATE) +
|
||||||
|
@ -542,7 +681,7 @@ MessageBoxTimeoutIndirectW(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the dialog template */
|
/* Allocate the dialog template */
|
||||||
buf = RtlAllocateHeap(GetProcessHeap(), 0, bufsize);
|
buf = RtlAllocateHeap(RtlGetProcessHeap(), 0, bufsize);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
goto Quit;
|
goto Quit;
|
||||||
|
|
||||||
|
@ -554,7 +693,7 @@ MessageBoxTimeoutIndirectW(
|
||||||
hFont = CreateFontIndirectW(&nclm.lfMessageFont);
|
hFont = CreateFontIndirectW(&nclm.lfMessageFont);
|
||||||
if (!hFont)
|
if (!hFont)
|
||||||
{
|
{
|
||||||
ERR("Cannot retrieve nclm.lfMessageFont!\n");
|
ERR("Cannot retrieve nclm.lfMessageFont! (error %lu)\n", GetLastError());
|
||||||
goto Quit;
|
goto Quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,7 +707,7 @@ MessageBoxTimeoutIndirectW(
|
||||||
}
|
}
|
||||||
if (!hDC)
|
if (!hDC)
|
||||||
{
|
{
|
||||||
ERR("GetDCEx() failed, bail out!\n");
|
ERR("GetDCEx() failed, bail out! (error %lu)\n", GetLastError());
|
||||||
goto Quit;
|
goto Quit;
|
||||||
}
|
}
|
||||||
hOldFont = SelectObject(hDC, hFont);
|
hOldFont = SelectObject(hDC, hFont);
|
||||||
|
@ -577,7 +716,7 @@ MessageBoxTimeoutIndirectW(
|
||||||
if (!units.cx)
|
if (!units.cx)
|
||||||
{
|
{
|
||||||
DWORD defUnits;
|
DWORD defUnits;
|
||||||
ERR("GdiGetCharDimensions() failed, falling back to default values!\n");
|
ERR("GdiGetCharDimensions() failed, falling back to default values (error %lu)\n", GetLastError());
|
||||||
defUnits = GetDialogBaseUnits();
|
defUnits = GetDialogBaseUnits();
|
||||||
units.cx = LOWORD(defUnits);
|
units.cx = LOWORD(defUnits);
|
||||||
units.cy = HIWORD(defUnits);
|
units.cy = HIWORD(defUnits);
|
||||||
|
@ -590,7 +729,7 @@ MessageBoxTimeoutIndirectW(
|
||||||
txtrect.top = txtrect.left = txtrect.bottom = 0;
|
txtrect.top = txtrect.left = txtrect.bottom = 0;
|
||||||
if (textlen != 0)
|
if (textlen != 0)
|
||||||
{
|
{
|
||||||
DrawTextW(hDC, text, textlen, &txtrect,
|
DrawTextW(hDC, lpMsgBoxParams->lpszText, textlen, &txtrect,
|
||||||
DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_EXPANDTABS | DT_EXTERNALLEADING | DT_EDITCONTROL | DT_CALCRECT);
|
DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_EXPANDTABS | DT_EXTERNALLEADING | DT_EDITCONTROL | DT_CALCRECT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -682,7 +821,6 @@ MessageBoxTimeoutIndirectW(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the dialog template */
|
/* Initialize the dialog template */
|
||||||
tpl = (DLGTEMPLATE *)buf;
|
tpl = (DLGTEMPLATE *)buf;
|
||||||
|
|
||||||
|
@ -701,7 +839,7 @@ MessageBoxTimeoutIndirectW(
|
||||||
|
|
||||||
*(DWORD*)dest = 0; /* no menu and use default window class */
|
*(DWORD*)dest = 0; /* no menu and use default window class */
|
||||||
dest += 2 * sizeof(WORD);
|
dest += 2 * sizeof(WORD);
|
||||||
memcpy(dest, caption, caplen * sizeof(WCHAR));
|
memcpy(dest, lpMsgBoxParams->lpszCaption, caplen * sizeof(WCHAR));
|
||||||
dest += caplen * sizeof(WCHAR);
|
dest += caplen * sizeof(WCHAR);
|
||||||
*(WCHAR*)dest = L'\0';
|
*(WCHAR*)dest = L'\0';
|
||||||
dest += sizeof(WCHAR);
|
dest += sizeof(WCHAR);
|
||||||
|
@ -755,7 +893,7 @@ MessageBoxTimeoutIndirectW(
|
||||||
dest += sizeof(WORD);
|
dest += sizeof(WORD);
|
||||||
*(WORD*)dest = 0x0082; /* static control */
|
*(WORD*)dest = 0x0082; /* static control */
|
||||||
dest += sizeof(WORD);
|
dest += sizeof(WORD);
|
||||||
memcpy(dest, text, textlen * sizeof(WCHAR));
|
memcpy(dest, lpMsgBoxParams->lpszText, textlen * sizeof(WCHAR));
|
||||||
dest += textlen * sizeof(WCHAR);
|
dest += textlen * sizeof(WCHAR);
|
||||||
*(WCHAR*)dest = 0;
|
*(WCHAR*)dest = 0;
|
||||||
dest += sizeof(WCHAR);
|
dest += sizeof(WCHAR);
|
||||||
|
@ -808,10 +946,11 @@ MessageBoxTimeoutIndirectW(
|
||||||
btnleft += btnsize.cx + MSGBOXEX_BUTTONSPACING;
|
btnleft += btnsize.cx + MSGBOXEX_BUTTONSPACING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the size and position of the messagebox window */
|
/* Calculate the size and position of the message-box window */
|
||||||
btnleft = max(btnleft - MSGBOXEX_BUTTONSPACING, rc.left + txtrect.right);
|
btnleft = max(btnleft - MSGBOXEX_BUTTONSPACING, rc.left + txtrect.right);
|
||||||
btnleft += MSGBOXEX_MARGIN;
|
btnleft += MSGBOXEX_MARGIN;
|
||||||
btntop += btnsize.cy + MSGBOXEX_MARGIN;
|
if (mbd.dwButtons > 0)
|
||||||
|
btntop += btnsize.cy + MSGBOXEX_MARGIN;
|
||||||
|
|
||||||
/* Set the size and position of the static message */
|
/* Set the size and position of the static message */
|
||||||
itxt->x = RESCALE_X(rc.left, units);
|
itxt->x = RESCALE_X(rc.left, units);
|
||||||
|
@ -823,19 +962,20 @@ MessageBoxTimeoutIndirectW(
|
||||||
tpl->cx = RESCALE_X(btnleft, units);
|
tpl->cx = RESCALE_X(btnleft, units);
|
||||||
tpl->cy = RESCALE_Y(btntop, units);
|
tpl->cy = RESCALE_Y(btntop, units);
|
||||||
|
|
||||||
/* Finally show the messagebox */
|
/* Finally show the message-box */
|
||||||
ret = DialogBoxIndirectParamW(lpMsgBoxParams->hInstance, tpl,
|
ret = DialogBoxIndirectParamW(lpMsgBoxParams->hInstance, tpl,
|
||||||
lpMsgBoxParams->hwndOwner,
|
lpMsgBoxParams->hwndOwner,
|
||||||
MessageBoxProc, (LPARAM)&mbd);
|
MessageBoxProc, (LPARAM)&mbd);
|
||||||
|
|
||||||
Quit:
|
Quit:
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, buf);
|
if (buf)
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, buf);
|
||||||
|
|
||||||
for (i = 0; i < mbd.dwButtons; i++)
|
if (text)
|
||||||
{
|
RtlFreeHeap(RtlGetProcessHeap(), 0, text);
|
||||||
if (mbd.ppszButtonText[i] && *(mbd.ppszButtonText[i]))
|
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR)mbd.ppszButtonText[i]);
|
if (caption)
|
||||||
}
|
RtlFreeHeap(RtlGetProcessHeap(), 0, caption);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1098,24 +1238,13 @@ MessageBoxTimeoutW(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
DWORD
|
|
||||||
WINAPI
|
|
||||||
SoftModalMessageBox(DWORD Unknown0)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
MessageBeep(IN UINT uType)
|
MessageBeep(
|
||||||
|
IN UINT uType)
|
||||||
{
|
{
|
||||||
return NtUserxMessageBeep(uType);
|
return NtUserxMessageBeep(uType);
|
||||||
}
|
}
|
||||||
|
@ -1130,9 +1259,30 @@ MessageBeep(IN UINT uType)
|
||||||
*/
|
*/
|
||||||
LPCWSTR
|
LPCWSTR
|
||||||
WINAPI
|
WINAPI
|
||||||
MB_GetString(IN UINT wBtn)
|
MB_GetString(
|
||||||
|
IN UINT wBtn)
|
||||||
{
|
{
|
||||||
LPCWSTR btnStr = NULL;
|
static BOOL bCached = FALSE;
|
||||||
|
static MBSTRING MBStrings[MAX_MB_STRINGS]; // FIXME: Use gpsi->MBStrings when this is loaded by Win32k!
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME - TODO: The gpsi->MBStrings[] array should be loaded by win32k!
|
||||||
|
//
|
||||||
|
ASSERT(IDCONTINUE <= MAX_MB_STRINGS);
|
||||||
|
if (!bCached)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < MAX_MB_STRINGS; ++i)
|
||||||
|
{
|
||||||
|
/*gpsi->*/MBStrings[i].uID = IDOK + i;
|
||||||
|
/*gpsi->*/MBStrings[i].uStr = IDS_OK + i; // See user32/include/resource.h
|
||||||
|
LoadStringW(User32Instance,
|
||||||
|
/*gpsi->*/MBStrings[i].uStr,
|
||||||
|
/*gpsi->*/MBStrings[i].szName,
|
||||||
|
ARRAYSIZE(/*gpsi->*/MBStrings[i].szName));
|
||||||
|
}
|
||||||
|
bCached = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The allowable IDs are between "IDOK - 1" (0) and "IDCONTINUE - 1" (10) inclusive.
|
* The allowable IDs are between "IDOK - 1" (0) and "IDCONTINUE - 1" (10) inclusive.
|
||||||
|
@ -1141,9 +1291,7 @@ MB_GetString(IN UINT wBtn)
|
||||||
if (wBtn > IDCONTINUE - 1)
|
if (wBtn > IDCONTINUE - 1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wBtn += 800; // See user32/include/resource.h
|
return /*gpsi->*/MBStrings[wBtn].szName;
|
||||||
LoadStringW(User32Instance, wBtn, (LPWSTR)&btnStr, 0);
|
|
||||||
return btnStr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue