📄 messagebox.c
字号:
/*
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: messagebox.c 23993 2006-09-09 14:49:11Z tretiakov $
*
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/messagebox.c
* PURPOSE: Input
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Thomas Weidenmueller (w3seek@users.sourceforge.net)
* UPDATE HISTORY:
* 2003/07/28 Added some NT features
* 2003/07/27 Code ported from wine
* 09-05-2001 CSH Created
*/
/* INCLUDES ******************************************************************/
#include <user32.h>
#include <wine/debug.h>
/* DEFINES *******************************************************************/
#define MSGBOX_IDICON (1088)
#define MSGBOX_IDTEXT (100)
#define IDI_HANDA MAKEINTRESOURCEA(32513)
#define IDI_HANDW MAKEINTRESOURCEW(32513)
#define IDI_QUESTIONA MAKEINTRESOURCEA(32514)
#define IDI_QUESTIONW MAKEINTRESOURCEW(32514)
#define IDI_EXCLAMATIONA MAKEINTRESOURCEA(32515)
#define IDI_EXCLAMATIONW MAKEINTRESOURCEW(32515)
#define IDI_ASTERISKA MAKEINTRESOURCEA(32516)
#define IDI_ASTERISKW MAKEINTRESOURCEW(32516)
#define IDI_WINLOGOA MAKEINTRESOURCEA(32517)
#define IDI_WINLOGOW MAKEINTRESOURCEW(32517)
#define BTN_CX (75)
#define BTN_CY (23)
#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;
HFONT Font;
DWORD ContextHelpId;
MSGBOXCALLBACK Callback;
DWORD Style;
int DefBtn;
int nButtons;
LONG *Btns;
UINT Timeout;
} MSGBOXINFO, *PMSGBOXINFO;
/* INTERNAL FUNCTIONS ********************************************************/
static INT_PTR CALLBACK MessageBoxProc( HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
int i;
PMSGBOXINFO mbi;
HELPINFO hi;
HWND owner;
switch(message) {
case WM_INITDIALOG:
mbi = (PMSGBOXINFO)lParam;
if(!GetPropW(hwnd, L"ROS_MSGBOX"))
{
SetPropW(hwnd, L"ROS_MSGBOX", (HANDLE)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++)
{
SendDlgItemMessageW(hwnd, mbi->Btns[i], WM_SETFONT, (WPARAM)mbi->Font, 0);
}
switch(mbi->Style & MB_TYPEMASK)
{
case MB_ABORTRETRYIGNORE:
case MB_YESNO:
RemoveMenu(GetSystemMenu(hwnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
break;
}
SetFocus(GetDlgItem(hwnd, mbi->DefBtn));
if(mbi->Timeout && (mbi->Timeout != (UINT)-1))
SetTimer(hwnd, 0, mbi->Timeout, NULL);
}
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
case IDABORT:
case IDRETRY:
case IDIGNORE:
case IDYES:
case IDNO:
case IDTRYAGAIN:
case IDCONTINUE:
EndDialog(hwnd, wParam);
return 0;
case IDHELP:
/* send WM_HELP message to messagebox window */
hi.cbSize = sizeof(HELPINFO);
hi.iContextType = HELPINFO_WINDOW;
hi.iCtrlId = LOWORD(wParam);
hi.hItemHandle = (HANDLE)lParam;
hi.dwContextId = 0;
GetCursorPos(&hi.MousePos);
SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi);
return 0;
}
return 0;
case WM_HELP:
mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX");
if(!mbi)
return 0;
memcpy(&hi, (void *)lParam, sizeof(hi));
hi.dwContextId = GetWindowContextHelpId(hwnd);
if (mbi->Callback)
mbi->Callback(&hi);
else
{
owner = GetWindow(hwnd, GW_OWNER);
if(owner)
SendMessageW(GetWindow(hwnd, GW_OWNER), WM_HELP, 0, (LPARAM)&hi);
}
return 0;
case WM_CLOSE:
mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX");
if(!mbi)
return 0;
switch(mbi->Style & MB_TYPEMASK)
{
case MB_ABORTRETRYIGNORE:
case MB_YESNO:
return 1;
}
EndDialog(hwnd, IDCANCEL);
return 1;
case WM_TIMER:
if(wParam == 0)
{
EndDialog(hwnd, 32000);
}
return 0;
}
return 0;
}
static int
MessageBoxTimeoutIndirectW(
CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT Timeout)
{
DLGTEMPLATE *tpl;
DLGITEMTEMPLATE *iico, *itxt;
NONCLIENTMETRICSW nclm;
WCHAR capbuf[32];
LPVOID buf;
BYTE *dest;
LPCWSTR caption, text;
HFONT hFont;
HICON Icon;
HDC hDC;
int bufsize, ret, caplen, textlen, btnlen, i, btnleft, btntop, lmargin, nButtons = 0;
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();
if(!lpMsgBoxParams->lpszCaption || !HIWORD((LPWSTR)lpMsgBoxParams->lpszCaption))
{
LoadStringW(User32Instance, IDS_ERROR, &capbuf[0], 32);
caption = &capbuf[0];
}
else
caption = (LPWSTR)lpMsgBoxParams->lpszCaption;
if(!lpMsgBoxParams->lpszText || !HIWORD(lpMsgBoxParams->lpszText))
text = L"";
else
text = lpMsgBoxParams->lpszText;
caplen = strlenW(caption);
textlen = strlenW(text);
/* Create selected buttons */
switch(lpMsgBoxParams->dwStyle & MB_TYPEMASK)
{
case MB_OKCANCEL:
Buttons[0] = IDOK;
Buttons[1] = IDCANCEL;
nButtons = 2;
break;
case MB_CANCELTRYCONTINUE:
Buttons[0] = IDCANCEL;
Buttons[1] = IDTRYAGAIN;
Buttons[2] = IDCONTINUE;
nButtons = 3;
break;
case MB_ABORTRETRYIGNORE:
Buttons[0] = IDABORT;
Buttons[1] = IDRETRY;
Buttons[2] = IDIGNORE;
nButtons = 3;
break;
case MB_YESNO:
Buttons[0] = IDYES;
Buttons[1] = IDNO;
nButtons = 2;
break;
case MB_YESNOCANCEL:
Buttons[0] = IDYES;
Buttons[1] = IDNO;
Buttons[2] = IDCANCEL;
nButtons = 3;
break;
case MB_RETRYCANCEL:
Buttons[0] = IDRETRY;
Buttons[1] = IDCANCEL;
nButtons = 2;
break;
case MB_OK:
/* fall through */
default:
Buttons[0] = IDOK;
nButtons = 1;
break;
}
/* Create Help button */
if(lpMsgBoxParams->dwStyle & MB_HELP)
Buttons[nButtons++] = IDHELP;
switch(lpMsgBoxParams->dwStyle & MB_ICONMASK)
{
case MB_ICONEXCLAMATION:
Icon = LoadIconW(0, IDI_EXCLAMATIONW);
MessageBeep(MB_ICONEXCLAMATION);
break;
case MB_ICONQUESTION:
Icon = LoadIconW(0, IDI_QUESTIONW);
MessageBeep(MB_ICONQUESTION);
break;
case MB_ICONASTERISK:
Icon = LoadIconW(0, IDI_ASTERISKW);
MessageBeep(MB_ICONASTERISK);
break;
case MB_ICONHAND:
Icon = LoadIconW(0, IDI_HANDW);
MessageBeep(MB_ICONHAND);
break;
case MB_USERICON:
Icon = LoadIconW(lpMsgBoxParams->hInstance, lpMsgBoxParams->lpszIcon);
MessageBeep(MB_OK);
break;
default:
/* By default, Windows 95/98/NT does not associate an icon to message boxes.
* So ReactOS should do the same.
*/
Icon = (HICON)0;
MessageBeep(MB_OK);
break;
}
/* 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(User32Instance, IDS_OK, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDCANCEL:
LoadStringW(User32Instance, IDS_CANCEL, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDYES:
LoadStringW(User32Instance, IDS_YES, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDNO:
LoadStringW(User32Instance, IDS_NO, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDTRYAGAIN:
LoadStringW(User32Instance, IDS_TRYAGAIN, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDCONTINUE:
LoadStringW(User32Instance, IDS_CONTINUE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDABORT:
LoadStringW(User32Instance, IDS_ABORT, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDRETRY:
LoadStringW(User32Instance, IDS_RETRY, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDIGNORE:
LoadStringW(User32Instance, IDS_IGNORE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
case IDHELP:
LoadStringW(User32Instance, IDS_HELP, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);
break;
default:
ButtonText[i][0] = (WCHAR)0;
break;
}
/* Space for buttons */
bufsize = (bufsize + 3) & ~3;
bufsize += sizeof(DLGITEMTEMPLATE) +
3 * sizeof(WORD) +
(wcslen(ButtonText[i]) + 1) * sizeof(WCHAR);
}
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_TOPMOST;
if(lpMsgBoxParams->dwStyle & MB_RIGHT)
tpl->dwExtendedStyle |= WS_EX_RIGHT;
tpl->x = 100;
tpl->y = 100;
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 */
dest += 2 * sizeof(WORD);
memcpy(dest, caption, caplen * sizeof(WCHAR));
dest += caplen * sizeof(WCHAR);
*(WCHAR*)dest = L'\0';
dest += sizeof(WCHAR);
/* Create icon */
if(Icon)
{
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);
*(WORD*)dest = 0x0082; /* static control */
dest += sizeof(WORD);
*(WORD*)dest = 0xFFFF;
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;
itxt->style = WS_CHILD | WS_VISIBLE | SS_NOPREFIX;
if(lpMsgBoxParams->dwStyle & MB_RIGHT)
itxt->style |= SS_RIGHT;
else
itxt->style |= SS_LEFT;
itxt->dwExtendedStyle = 0;
itxt->id = MSGBOX_IDTEXT;
dest += sizeof(DLGITEMTEMPLATE);
*(WORD*)dest = 0xFFFF;
dest += sizeof(WORD);
*(WORD*)dest = 0x0082; /* static control */
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);
/* create buttons */
btnsize.cx = BTN_CX;
btnsize.cy = BTN_CY;
btnrect.left = btnrect.top = 0;
for(i = 0; i < nButtons; i++)
{
dest = (BYTE*)(((DWORD)dest + 3) & ~3);
ibtn[i] = (DLGITEMTEMPLATE *)dest;
ibtn[i]->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;
if(!defbtn && (i == ((lpMsgBoxParams->dwStyle & MB_DEFMASK) >> 8)))
{
ibtn[i]->style |= BS_DEFPUSHBUTTON;
mbi.DefBtn = Buttons[i];
defbtn = TRUE;
}
else
ibtn[i]->style |= BS_PUSHBUTTON;
ibtn[i]->dwExtendedStyle = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -