3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/messagebox.c
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
27 * 2003/07/28 Added some NT features
28 * 2003/07/27 Code ported from wine
29 * 09-05-2001 CSH Created
32 /* INCLUDES ******************************************************************/
36 #include <wine/debug.h>
38 WINE_DEFAULT_DEBUG_CHANNEL(user32
);
40 /* DEFINES *******************************************************************/
42 #define MSGBOX_IDICON (1088)
43 #define MSGBOX_IDTEXT (100)
45 #define IDI_HANDA MAKEINTRESOURCEA(32513)
46 #define IDI_HANDW MAKEINTRESOURCEW(32513)
47 #define IDI_QUESTIONA MAKEINTRESOURCEA(32514)
48 #define IDI_QUESTIONW MAKEINTRESOURCEW(32514)
49 #define IDI_EXCLAMATIONA MAKEINTRESOURCEA(32515)
50 #define IDI_EXCLAMATIONW MAKEINTRESOURCEW(32515)
51 #define IDI_ASTERISKA MAKEINTRESOURCEA(32516)
52 #define IDI_ASTERISKW MAKEINTRESOURCEW(32516)
53 #define IDI_WINLOGOA MAKEINTRESOURCEA(32517)
54 #define IDI_WINLOGOW MAKEINTRESOURCEW(32517)
59 #define MSGBOXEX_SPACING (16)
60 #define MSGBOXEX_BUTTONSPACING (6)
61 #define MSGBOXEX_MARGIN (12)
62 #define MSGBOXEX_MAXBTNSTR (32)
63 #define MSGBOXEX_MAXBTNS (4)
65 typedef struct _MSGBOXINFO
{
66 MSGBOXPARAMSW
; // Wine passes this too.
74 } MSGBOXINFO
, *PMSGBOXINFO
;
76 /* INTERNAL FUNCTIONS ********************************************************/
78 static VOID
MessageBoxTextToClipboard(HWND DialogWindow
)
82 int cchTotal
, cchTitle
, cchText
, cchButton
, i
, n
, cchBuffer
;
83 LPWSTR pszBuffer
, pszBufferPos
, pMessageBoxText
, pszTitle
, pszText
, pszButton
;
84 WCHAR szButton
[MSGBOXEX_MAXBTNSTR
];
87 static const WCHAR szLine
[30] =
88 {'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-',
89 '-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0};
91 mbi
= (PMSGBOXINFO
)GetPropW(DialogWindow
, L
"ROS_MSGBOX");
92 hwndText
= GetDlgItem(DialogWindow
, MSGBOX_IDTEXT
);
93 cchTitle
= GetWindowTextLengthW(DialogWindow
) + 1;
94 cchText
= GetWindowTextLengthW(hwndText
) + 1;
99 pMessageBoxText
= (LPWSTR
)RtlAllocateHeap(GetProcessHeap(), 0, (cchTitle
+ cchText
) * sizeof(WCHAR
));
101 if(pMessageBoxText
== NULL
)
103 RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText
);
107 pszTitle
= pMessageBoxText
;
108 pszText
= pMessageBoxText
+ cchTitle
;
112 if(GetWindowTextW(DialogWindow
, pszTitle
, cchTitle
) == 0 ||
113 GetWindowTextW(hwndText
, pszText
, cchText
) == 0)
115 RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText
);
120 * Calculate the total buffer size.
122 cchTotal
= 6 + cchTitle
+ cchText
+ (lstrlenW(szLine
) * 4) + (mbi
->nButtons
* MSGBOXEX_MAXBTNSTR
+ 3);
124 hGlobal
= GlobalAlloc(GHND
, cchTotal
* sizeof(WCHAR
));
126 pszBuffer
= (LPWSTR
)GlobalLock(hGlobal
);
128 if(pszBuffer
== NULL
)
130 RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText
);
136 * First format title and text.
143 cchBuffer
= wsprintfW(pszBuffer
, L
"%s%s\r\n%s%s\r\n%s", szLine
, pszTitle
, szLine
, pszText
, szLine
);
144 pszBufferPos
= pszBuffer
+ cchBuffer
;
146 for(i
= 0; i
< mbi
->nButtons
; i
++)
148 GetDlgItemTextW(DialogWindow
, mbi
->Btns
[i
], szButton
, MSGBOXEX_MAXBTNSTR
);
150 cchButton
= strlenW(szButton
);
151 pszButton
= szButton
;
153 /* Skip '&' character. */
154 if(szButton
[0] == '&')
156 pszButton
= pszButton
+ 1;
157 cchButton
= cchButton
- 1;
160 for(n
= 0; n
< cchButton
; n
++)
161 *(pszBufferPos
++) = pszButton
[n
];
164 *(pszBufferPos
++) = L
' ';
165 *(pszBufferPos
++) = L
' ';
166 *(pszBufferPos
++) = L
' ';
169 wsprintfW(pszBufferPos
, L
"\r\n%s", szLine
);
171 GlobalUnlock(hGlobal
);
173 if(OpenClipboard(DialogWindow
))
176 SetClipboardData(CF_UNICODETEXT
, hGlobal
);
183 RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText
);
186 static INT_PTR CALLBACK
MessageBoxProc( HWND hwnd
, UINT message
,
187 WPARAM wParam
, LPARAM lParam
)
196 mbi
= (PMSGBOXINFO
)lParam
;
198 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LONG_PTR
)mbi
);
199 NtUserxSetMessageBox(hwnd
);
201 if(!GetPropW(hwnd
, L
"ROS_MSGBOX"))
203 SetPropW(hwnd
, L
"ROS_MSGBOX", (HANDLE
)lParam
);
205 if (mbi
->dwContextHelpId
)
206 SetWindowContextHelpId(hwnd
, mbi
->dwContextHelpId
);
210 SendDlgItemMessageW(hwnd
, MSGBOX_IDICON
, STM_SETICON
, (WPARAM
)mbi
->Icon
, 0);
211 Alert
= ALERT_SYSTEM_WARNING
;
213 else // Setup the rest of the alerts.
215 switch(mbi
->dwStyle
& MB_ICONMASK
)
218 Alert
= ALERT_SYSTEM_WARNING
;
221 Alert
= ALERT_SYSTEM_ERROR
;
223 case MB_ICONQUESTION
:
224 Alert
= ALERT_SYSTEM_QUERY
;
227 Alert
= ALERT_SYSTEM_INFORMATIONAL
;
231 /* Send out the alert notifications. */
232 NotifyWinEvent(EVENT_SYSTEM_ALERT
, hwnd
, OBJID_ALERT
, Alert
);
234 /* set control fonts */
235 SendDlgItemMessageW(hwnd
, MSGBOX_IDTEXT
, WM_SETFONT
, (WPARAM
)mbi
->Font
, 0);
236 for(i
= 0; i
< mbi
->nButtons
; i
++)
238 SendDlgItemMessageW(hwnd
, mbi
->Btns
[i
], WM_SETFONT
, (WPARAM
)mbi
->Font
, 0);
240 switch(mbi
->dwStyle
& MB_TYPEMASK
)
242 case MB_ABORTRETRYIGNORE
:
244 RemoveMenu(GetSystemMenu(hwnd
, FALSE
), SC_CLOSE
, MF_BYCOMMAND
);
247 SetFocus(GetDlgItem(hwnd
, mbi
->DefBtn
));
248 if(mbi
->Timeout
&& (mbi
->Timeout
!= (UINT
)-1))
249 SetTimer(hwnd
, 0, mbi
->Timeout
, NULL
);
254 switch (LOWORD(wParam
))
265 EndDialog(hwnd
, wParam
);
268 /* send WM_HELP message to messagebox window */
269 hi
.cbSize
= sizeof(HELPINFO
);
270 hi
.iContextType
= HELPINFO_WINDOW
;
271 hi
.iCtrlId
= LOWORD(wParam
);
272 hi
.hItemHandle
= (HANDLE
)lParam
;
274 GetCursorPos(&hi
.MousePos
);
275 SendMessageW(hwnd
, WM_HELP
, 0, (LPARAM
)&hi
);
281 MessageBoxTextToClipboard(hwnd
);
285 mbi
= (PMSGBOXINFO
)GetPropW(hwnd
, L
"ROS_MSGBOX");
288 memcpy(&hi
, (void *)lParam
, sizeof(hi
));
289 hi
.dwContextId
= GetWindowContextHelpId(hwnd
);
291 if (mbi
->lpfnMsgBoxCallback
)
292 mbi
->lpfnMsgBoxCallback(&hi
);
295 owner
= GetWindow(hwnd
, GW_OWNER
);
297 SendMessageW(GetWindow(hwnd
, GW_OWNER
), WM_HELP
, 0, (LPARAM
)&hi
);
302 mbi
= (PMSGBOXINFO
)GetPropW(hwnd
, L
"ROS_MSGBOX");
305 switch(mbi
->dwStyle
& MB_TYPEMASK
)
307 case MB_ABORTRETRYIGNORE
:
311 EndDialog(hwnd
, IDCANCEL
);
317 EndDialog(hwnd
, 32000);
325 MessageBoxTimeoutIndirectW(
326 CONST MSGBOXPARAMSW
*lpMsgBoxParams
, UINT Timeout
)
329 DLGITEMTEMPLATE
*iico
, *itxt
;
330 NONCLIENTMETRICSW nclm
;
334 LPCWSTR caption
, text
;
338 int bufsize
, ret
, caplen
, textlen
, btnlen
, i
, btnleft
, btntop
, lmargin
, nButtons
= 0;
339 LONG Buttons
[MSGBOXEX_MAXBTNS
];
340 WCHAR ButtonText
[MSGBOXEX_MAXBTNS
][MSGBOXEX_MAXBTNSTR
];
341 DLGITEMTEMPLATE
*ibtn
[MSGBOXEX_MAXBTNS
];
342 RECT btnrect
, txtrect
, rc
;
346 DWORD units
= GetDialogBaseUnits();
348 if(!lpMsgBoxParams
->lpszCaption
|| !HIWORD((LPWSTR
)lpMsgBoxParams
->lpszCaption
))
350 LoadStringW(User32Instance
, IDS_ERROR
, &capbuf
[0], 32);
351 caption
= &capbuf
[0];
354 caption
= (LPWSTR
)lpMsgBoxParams
->lpszCaption
;
356 if(!lpMsgBoxParams
->lpszText
|| !HIWORD(lpMsgBoxParams
->lpszText
))
359 text
= lpMsgBoxParams
->lpszText
;
361 caplen
= strlenW(caption
);
362 textlen
= strlenW(text
);
364 /* Create selected buttons */
365 switch(lpMsgBoxParams
->dwStyle
& MB_TYPEMASK
)
369 Buttons
[1] = IDCANCEL
;
372 case MB_CANCELTRYCONTINUE
:
373 Buttons
[0] = IDCANCEL
;
374 Buttons
[1] = IDTRYAGAIN
;
375 Buttons
[2] = IDCONTINUE
;
378 case MB_ABORTRETRYIGNORE
:
379 Buttons
[0] = IDABORT
;
380 Buttons
[1] = IDRETRY
;
381 Buttons
[2] = IDIGNORE
;
392 Buttons
[2] = IDCANCEL
;
396 Buttons
[0] = IDRETRY
;
397 Buttons
[1] = IDCANCEL
;
407 /* Create Help button */
408 if(lpMsgBoxParams
->dwStyle
& MB_HELP
)
409 Buttons
[nButtons
++] = IDHELP
;
411 switch(lpMsgBoxParams
->dwStyle
& MB_ICONMASK
)
413 case MB_ICONEXCLAMATION
:
414 Icon
= LoadIconW(0, IDI_EXCLAMATIONW
);
415 MessageBeep(MB_ICONEXCLAMATION
);
417 case MB_ICONQUESTION
:
418 Icon
= LoadIconW(0, IDI_QUESTIONW
);
419 MessageBeep(MB_ICONQUESTION
);
421 case MB_ICONASTERISK
:
422 Icon
= LoadIconW(0, IDI_ASTERISKW
);
423 MessageBeep(MB_ICONASTERISK
);
426 Icon
= LoadIconW(0, IDI_HANDW
);
427 MessageBeep(MB_ICONHAND
);
430 Icon
= LoadIconW(lpMsgBoxParams
->hInstance
, lpMsgBoxParams
->lpszIcon
);
434 /* By default, Windows 95/98/NT does not associate an icon to message boxes.
435 * So ReactOS should do the same.
443 bufsize
= sizeof(DLGTEMPLATE
) +
444 2 * sizeof(WORD
) + /* menu and class */
445 (caplen
+ 1) * sizeof(WCHAR
); /* title */
450 bufsize
= (bufsize
+ 3) & ~3;
451 bufsize
+= sizeof(DLGITEMTEMPLATE
) +
457 bufsize
= (bufsize
+ 3) & ~3;
458 bufsize
+= sizeof(DLGITEMTEMPLATE
) +
460 (textlen
+ 1) * sizeof(WCHAR
);
463 for(i
= 0; i
< nButtons
; i
++)
468 LoadStringW(User32Instance
, IDS_OK
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
471 LoadStringW(User32Instance
, IDS_CANCEL
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
474 LoadStringW(User32Instance
, IDS_YES
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
477 LoadStringW(User32Instance
, IDS_NO
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
480 LoadStringW(User32Instance
, IDS_TRYAGAIN
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
483 LoadStringW(User32Instance
, IDS_CONTINUE
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
486 LoadStringW(User32Instance
, IDS_ABORT
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
489 LoadStringW(User32Instance
, IDS_RETRY
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
492 LoadStringW(User32Instance
, IDS_IGNORE
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
495 LoadStringW(User32Instance
, IDS_HELP
, ButtonText
[i
], MSGBOXEX_MAXBTNSTR
- 1);
498 ButtonText
[i
][0] = (WCHAR
)0;
502 /* Space for buttons */
503 bufsize
= (bufsize
+ 3) & ~3;
504 bufsize
+= sizeof(DLGITEMTEMPLATE
) +
506 (wcslen(ButtonText
[i
]) + 1) * sizeof(WCHAR
);
509 buf
= RtlAllocateHeap(GetProcessHeap(), 0, bufsize
);
516 hDC
= CreateCompatibleDC(0);
518 nclm
.cbSize
= sizeof(nclm
);
519 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, sizeof(nclm
), &nclm
, 0);
520 hFont
= CreateFontIndirectW (&nclm
.lfMessageFont
);
522 tpl
= (DLGTEMPLATE
*)buf
;
524 tpl
->style
= WS_CAPTION
| WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_SYSMENU
| DS_CENTER
| DS_MODALFRAME
| DS_NOIDLEMSG
;
525 tpl
->dwExtendedStyle
= WS_EX_DLGMODALFRAME
| WS_EX_WINDOWEDGE
| WS_EX_CONTROLPARENT
;
526 if(lpMsgBoxParams
->dwStyle
& MB_TOPMOST
)
527 tpl
->dwExtendedStyle
|= WS_EX_TOPMOST
;
528 if(lpMsgBoxParams
->dwStyle
& MB_RIGHT
)
529 tpl
->dwExtendedStyle
|= WS_EX_RIGHT
;
532 tpl
->cdit
= nButtons
+ ((Icon
!= (HICON
)0) ? 1 : 0) + 1;
534 dest
= (BYTE
*)(tpl
+ 1);
536 *(WORD
*)dest
= 0; /* no menu */
537 *(((WORD
*)dest
) + 1) = 0; /* use default window class */
538 dest
+= 2 * sizeof(WORD
);
539 memcpy(dest
, caption
, caplen
* sizeof(WCHAR
));
540 dest
+= caplen
* sizeof(WCHAR
);
541 *(WCHAR
*)dest
= L
'\0';
542 dest
+= sizeof(WCHAR
);
547 dest
= (BYTE
*)(((ULONG_PTR
)dest
+ 3) & ~3);
548 iico
= (DLGITEMTEMPLATE
*)dest
;
549 iico
->style
= WS_CHILD
| WS_VISIBLE
| SS_ICON
;
550 iico
->dwExtendedStyle
= 0;
551 iico
->id
= MSGBOX_IDICON
;
553 dest
+= sizeof(DLGITEMTEMPLATE
);
554 *(WORD
*)dest
= 0xFFFF;
555 dest
+= sizeof(WORD
);
556 *(WORD
*)dest
= 0x0082; /* static control */
557 dest
+= sizeof(WORD
);
558 *(WORD
*)dest
= 0xFFFF;
559 dest
+= sizeof(WORD
);
561 dest
+= sizeof(WCHAR
);
563 dest
+= sizeof(WORD
);
566 /* create static for text */
567 dest
= (BYTE
*)(((UINT_PTR
)dest
+ 3) & ~3);
568 itxt
= (DLGITEMTEMPLATE
*)dest
;
569 itxt
->style
= WS_CHILD
| WS_VISIBLE
| SS_NOPREFIX
;
570 if(lpMsgBoxParams
->dwStyle
& MB_RIGHT
)
571 itxt
->style
|= SS_RIGHT
;
573 itxt
->style
|= SS_LEFT
;
574 itxt
->dwExtendedStyle
= 0;
575 itxt
->id
= MSGBOX_IDTEXT
;
576 dest
+= sizeof(DLGITEMTEMPLATE
);
577 *(WORD
*)dest
= 0xFFFF;
578 dest
+= sizeof(WORD
);
579 *(WORD
*)dest
= 0x0082; /* static control */
580 dest
+= sizeof(WORD
);
581 memcpy(dest
, text
, textlen
* sizeof(WCHAR
));
582 dest
+= textlen
* sizeof(WCHAR
);
584 dest
+= sizeof(WCHAR
);
586 dest
+= sizeof(WORD
);
591 btnrect
.left
= btnrect
.top
= 0;
592 for(i
= 0; i
< nButtons
; i
++)
594 dest
= (BYTE
*)(((UINT_PTR
)dest
+ 3) & ~3);
595 ibtn
[i
] = (DLGITEMTEMPLATE
*)dest
;
596 ibtn
[i
]->style
= WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
;
597 if(!defbtn
&& (i
== ((lpMsgBoxParams
->dwStyle
& MB_DEFMASK
) >> 8)))
599 ibtn
[i
]->style
|= BS_DEFPUSHBUTTON
;
600 mbi
.DefBtn
= Buttons
[i
];
604 ibtn
[i
]->style
|= BS_PUSHBUTTON
;
605 ibtn
[i
]->dwExtendedStyle
= 0;
606 ibtn
[i
]->id
= Buttons
[i
];
607 dest
+= sizeof(DLGITEMTEMPLATE
);
608 *(WORD
*)dest
= 0xFFFF;
609 dest
+= sizeof(WORD
);
610 *(WORD
*)dest
= 0x0080; /* button control */
611 dest
+= sizeof(WORD
);
612 btnlen
= strlenW(ButtonText
[i
]);
613 memcpy(dest
, ButtonText
[i
], btnlen
* sizeof(WCHAR
));
614 dest
+= btnlen
* sizeof(WCHAR
);
616 dest
+= sizeof(WORD
);
618 dest
+= sizeof(WORD
);
619 SelectObject(hDC
, hFont
);
620 DrawTextW(hDC
, ButtonText
[i
], btnlen
, &btnrect
, DT_LEFT
| DT_SINGLELINE
| DT_CALCRECT
);
621 btnsize
.cx
= max(btnsize
.cx
, btnrect
.right
);
622 btnsize
.cy
= max(btnsize
.cy
, btnrect
.bottom
);
625 /* make first button the default button if no other is */
628 ibtn
[0]->style
&= ~BS_PUSHBUTTON
;
629 ibtn
[0]->style
|= BS_DEFPUSHBUTTON
;
630 mbi
.DefBtn
= Buttons
[0];
633 /* calculate position and size of controls */
634 txtrect
.right
= GetSystemMetrics(SM_CXSCREEN
) / 5 * 4;
636 txtrect
.right
-= GetSystemMetrics(SM_CXICON
) + MSGBOXEX_SPACING
;
637 txtrect
.top
= txtrect
.left
= txtrect
.bottom
= 0;
638 SelectObject(hDC
, hFont
);
641 DrawTextW(hDC
, text
, textlen
, &txtrect
, DT_LEFT
| DT_NOPREFIX
| DT_WORDBREAK
| DT_CALCRECT
);
645 txtrect
.right
= txtrect
.left
+ 1;
646 txtrect
.bottom
= txtrect
.top
+ 1;
650 /* calculate position and size of the icon */
651 rc
.left
= rc
.bottom
= rc
.right
= 0;
656 rc
.right
= GetSystemMetrics(SM_CXICON
);
657 rc
.bottom
= GetSystemMetrics(SM_CYICON
);
658 #ifdef MSGBOX_ICONVCENTER
659 rc
.top
= MSGBOXEX_MARGIN
+ (max(txtrect
.bottom
, rc
.bottom
) / 2) - (GetSystemMetrics(SM_CYICON
) / 2);
660 rc
.top
= max(MSGBOXEX_SPACING
, rc
.top
);
662 rc
.top
= MSGBOXEX_MARGIN
;
664 btnleft
= (nButtons
* (btnsize
.cx
+ MSGBOXEX_BUTTONSPACING
)) - MSGBOXEX_BUTTONSPACING
;
665 if(btnleft
> txtrect
.right
+ rc
.right
+ MSGBOXEX_SPACING
)
667 #ifdef MSGBOX_TEXTHCENTER
668 lmargin
= MSGBOXEX_MARGIN
+ ((btnleft
- txtrect
.right
- rc
.right
- MSGBOXEX_SPACING
) / 2);
670 lmargin
= MSGBOXEX_MARGIN
;
672 btnleft
= MSGBOXEX_MARGIN
;
676 lmargin
= MSGBOXEX_MARGIN
;
677 btnleft
= MSGBOXEX_MARGIN
+ ((txtrect
.right
+ rc
.right
+ MSGBOXEX_SPACING
) / 2) - (btnleft
/ 2);
680 iico
->x
= (rc
.left
* 4) / LOWORD(units
);
681 iico
->y
= (rc
.top
* 8) / HIWORD(units
);
682 iico
->cx
= (rc
.right
* 4) / LOWORD(units
);
683 iico
->cy
= (rc
.bottom
* 8) / HIWORD(units
);
684 btntop
= rc
.top
+ rc
.bottom
+ MSGBOXEX_SPACING
;
685 rc
.left
+= rc
.right
+ MSGBOXEX_SPACING
;
689 btnleft
= (nButtons
* (btnsize
.cx
+ MSGBOXEX_BUTTONSPACING
)) - MSGBOXEX_BUTTONSPACING
;
690 if(btnleft
> txtrect
.right
)
692 #ifdef MSGBOX_TEXTHCENTER
693 lmargin
= MSGBOXEX_MARGIN
+ ((btnleft
- txtrect
.right
) / 2);
695 lmargin
= MSGBOXEX_MARGIN
;
697 btnleft
= MSGBOXEX_MARGIN
;
701 lmargin
= MSGBOXEX_MARGIN
;
702 btnleft
= MSGBOXEX_MARGIN
+ (txtrect
.right
/ 2) - (btnleft
/ 2);
706 /* calculate position of the text */
707 rc
.top
= MSGBOXEX_MARGIN
+ (rc
.bottom
/ 2) - (txtrect
.bottom
/ 2);
708 rc
.top
= max(rc
.top
, MSGBOXEX_MARGIN
);
709 /* calculate position of the buttons */
710 btntop
= max(rc
.top
+ txtrect
.bottom
+ MSGBOXEX_SPACING
, btntop
);
711 for(i
= 0; i
< nButtons
; i
++)
713 ibtn
[i
]->x
= (btnleft
* 4) / LOWORD(units
);
714 ibtn
[i
]->y
= (btntop
* 8) / HIWORD(units
);
715 ibtn
[i
]->cx
= (btnsize
.cx
* 4) / LOWORD(units
);
716 ibtn
[i
]->cy
= (btnsize
.cy
* 8) / HIWORD(units
);
717 btnleft
+= btnsize
.cx
+ MSGBOXEX_BUTTONSPACING
;
719 /* calculate size and position of the messagebox window */
720 btnleft
= max(btnleft
- MSGBOXEX_BUTTONSPACING
, rc
.left
+ txtrect
.right
);
721 btnleft
+= MSGBOXEX_MARGIN
;
722 btntop
+= btnsize
.cy
+ MSGBOXEX_MARGIN
;
723 /* set size and position of the message static */
724 itxt
->x
= (rc
.left
* 4) / LOWORD(units
);
725 itxt
->y
= (rc
.top
* 8) / HIWORD(units
);
726 itxt
->cx
= (((btnleft
- rc
.left
- MSGBOXEX_MARGIN
) * 4) / LOWORD(units
));
727 itxt
->cy
= ((txtrect
.bottom
* 8) / HIWORD(units
));
728 /* set size of the window */
729 tpl
->cx
= (btnleft
* 4) / LOWORD(units
);
730 tpl
->cy
= (btntop
* 8) / HIWORD(units
);
732 /* finally show the messagebox */
735 mbi
.dwContextHelpId
= lpMsgBoxParams
->dwContextHelpId
;
736 mbi
.lpfnMsgBoxCallback
= lpMsgBoxParams
->lpfnMsgBoxCallback
;
737 mbi
.dwStyle
= lpMsgBoxParams
->dwStyle
;
738 mbi
.nButtons
= nButtons
;
739 mbi
.Btns
= &Buttons
[0];
740 mbi
.Timeout
= Timeout
;
742 /* Pass on to Justin Case so he can peek the message? */
743 mbi
.cbSize
= lpMsgBoxParams
->cbSize
;
744 mbi
.hwndOwner
= lpMsgBoxParams
->hwndOwner
;
745 mbi
.hInstance
= lpMsgBoxParams
->hInstance
;
746 mbi
.lpszText
= lpMsgBoxParams
->lpszText
;
747 mbi
.lpszCaption
= lpMsgBoxParams
->lpszCaption
;
748 mbi
.lpszIcon
= lpMsgBoxParams
->lpszIcon
;
749 mbi
.dwLanguageId
= lpMsgBoxParams
->dwLanguageId
;
754 ret
= DialogBoxIndirectParamW(lpMsgBoxParams
->hInstance
, tpl
, lpMsgBoxParams
->hwndOwner
,
755 MessageBoxProc
, (LPARAM
)&mbi
);
760 RtlFreeHeap(GetProcessHeap(), 0, buf
);
764 /* FUNCTIONS *****************************************************************/
778 return MessageBoxExA(hWnd
, lpText
, lpCaption
, uType
, LANG_NEUTRAL
);
794 MSGBOXPARAMSA msgbox
;
796 msgbox
.cbSize
= sizeof(msgbox
);
797 msgbox
.hwndOwner
= hWnd
;
798 msgbox
.hInstance
= 0;
799 msgbox
.lpszText
= lpText
;
800 msgbox
.lpszCaption
= lpCaption
;
801 msgbox
.dwStyle
= uType
;
802 msgbox
.lpszIcon
= NULL
;
803 msgbox
.dwContextHelpId
= 0;
804 msgbox
.lpfnMsgBoxCallback
= NULL
;
805 msgbox
.dwLanguageId
= wLanguageId
;
807 return MessageBoxIndirectA(&msgbox
);
823 MSGBOXPARAMSW msgbox
;
825 msgbox
.cbSize
= sizeof(msgbox
);
826 msgbox
.hwndOwner
= hWnd
;
827 msgbox
.hInstance
= 0;
828 msgbox
.lpszText
= lpText
;
829 msgbox
.lpszCaption
= lpCaption
;
830 msgbox
.dwStyle
= uType
;
831 msgbox
.lpszIcon
= NULL
;
832 msgbox
.dwContextHelpId
= 0;
833 msgbox
.lpfnMsgBoxCallback
= NULL
;
834 msgbox
.dwLanguageId
= wLanguageId
;
836 return MessageBoxTimeoutIndirectW(&msgbox
, (UINT
)-1);
846 CONST MSGBOXPARAMSA
*lpMsgBoxParams
)
848 MSGBOXPARAMSW msgboxW
;
849 UNICODE_STRING textW
, captionW
, iconW
;
852 if (HIWORD((UINT_PTR
)lpMsgBoxParams
->lpszText
))
854 RtlCreateUnicodeStringFromAsciiz(&textW
, (PCSZ
)lpMsgBoxParams
->lpszText
);
856 * UNICODE_STRING objects are always allocated with an extra byte so you
857 * can null-term if you want
859 textW
.Buffer
[textW
.Length
/ sizeof(WCHAR
)] = L
'\0';
862 textW
.Buffer
= (LPWSTR
)lpMsgBoxParams
->lpszText
;
864 if (HIWORD((UINT_PTR
)lpMsgBoxParams
->lpszCaption
))
866 RtlCreateUnicodeStringFromAsciiz(&captionW
, (PCSZ
)lpMsgBoxParams
->lpszCaption
);
868 * UNICODE_STRING objects are always allocated with an extra byte so you
869 * can null-term if you want
871 captionW
.Buffer
[captionW
.Length
/ sizeof(WCHAR
)] = L
'\0';
874 captionW
.Buffer
= (LPWSTR
)lpMsgBoxParams
->lpszCaption
;
876 if(lpMsgBoxParams
->dwStyle
& MB_USERICON
)
878 if (HIWORD((UINT_PTR
)lpMsgBoxParams
->lpszIcon
))
880 RtlCreateUnicodeStringFromAsciiz(&iconW
, (PCSZ
)lpMsgBoxParams
->lpszIcon
);
882 * UNICODE_STRING objects are always allocated with an extra byte so you
883 * can null-term if you want
885 iconW
.Buffer
[iconW
.Length
/ sizeof(WCHAR
)] = L
'\0';
888 iconW
.Buffer
= (LPWSTR
)lpMsgBoxParams
->lpszIcon
;
893 msgboxW
.cbSize
= sizeof(msgboxW
);
894 msgboxW
.hwndOwner
= lpMsgBoxParams
->hwndOwner
;
895 msgboxW
.hInstance
= lpMsgBoxParams
->hInstance
;
896 msgboxW
.lpszText
= textW
.Buffer
;
897 msgboxW
.lpszCaption
= captionW
.Buffer
;
898 msgboxW
.dwStyle
= lpMsgBoxParams
->dwStyle
;
899 msgboxW
.lpszIcon
= iconW
.Buffer
;
900 msgboxW
.dwContextHelpId
= lpMsgBoxParams
->dwContextHelpId
;
901 msgboxW
.lpfnMsgBoxCallback
= lpMsgBoxParams
->lpfnMsgBoxCallback
;
902 msgboxW
.dwLanguageId
= lpMsgBoxParams
->dwLanguageId
;
904 ret
= MessageBoxTimeoutIndirectW(&msgboxW
, (UINT
)-1);
906 if (HIWORD((UINT_PTR
)lpMsgBoxParams
->lpszText
))
907 RtlFreeUnicodeString(&textW
);
909 if (HIWORD((UINT_PTR
)lpMsgBoxParams
->lpszCaption
))
910 RtlFreeUnicodeString(&captionW
);
912 if ((lpMsgBoxParams
->dwStyle
& MB_USERICON
) && HIWORD((UINT_PTR
)iconW
.Buffer
))
913 RtlFreeUnicodeString(&iconW
);
925 CONST MSGBOXPARAMSW
*lpMsgBoxParams
)
927 return MessageBoxTimeoutIndirectW(lpMsgBoxParams
, (UINT
)-1);
942 return MessageBoxExW(hWnd
, lpText
, lpCaption
, uType
, LANG_NEUTRAL
);
958 MSGBOXPARAMSW msgboxW
;
959 UNICODE_STRING textW
, captionW
;
962 if (HIWORD((UINT_PTR
)lpText
))
963 RtlCreateUnicodeStringFromAsciiz(&textW
, (PCSZ
)lpText
);
965 textW
.Buffer
= (LPWSTR
)lpText
;
967 if (HIWORD((UINT_PTR
)lpCaption
))
968 RtlCreateUnicodeStringFromAsciiz(&captionW
, (PCSZ
)lpCaption
);
970 captionW
.Buffer
= (LPWSTR
)lpCaption
;
972 msgboxW
.cbSize
= sizeof(msgboxW
);
973 msgboxW
.hwndOwner
= hWnd
;
974 msgboxW
.hInstance
= 0;
975 msgboxW
.lpszText
= textW
.Buffer
;
976 msgboxW
.lpszCaption
= captionW
.Buffer
;
977 msgboxW
.dwStyle
= uType
;
978 msgboxW
.lpszIcon
= NULL
;
979 msgboxW
.dwContextHelpId
= 0;
980 msgboxW
.lpfnMsgBoxCallback
= NULL
;
981 msgboxW
.dwLanguageId
= wLanguageId
;
983 ret
= MessageBoxTimeoutIndirectW(&msgboxW
, (UINT
)dwTime
);
985 if (HIWORD(textW
.Buffer
))
986 RtlFreeUnicodeString(&textW
);
988 if (HIWORD(captionW
.Buffer
))
989 RtlFreeUnicodeString(&captionW
);
1007 MSGBOXPARAMSW msgbox
;
1009 msgbox
.cbSize
= sizeof(msgbox
);
1010 msgbox
.hwndOwner
= hWnd
;
1011 msgbox
.hInstance
= 0;
1012 msgbox
.lpszText
= lpText
;
1013 msgbox
.lpszCaption
= lpCaption
;
1014 msgbox
.dwStyle
= uType
;
1015 msgbox
.lpszIcon
= NULL
;
1016 msgbox
.dwContextHelpId
= 0;
1017 msgbox
.lpfnMsgBoxCallback
= NULL
;
1018 msgbox
.dwLanguageId
= wLanguageId
;
1020 return MessageBoxTimeoutIndirectW(&msgbox
, (UINT
)dwTime
);
1029 SoftModalMessageBox(DWORD Unknown0
)
1041 MessageBeep(UINT uType
)
1043 return NtUserxMessageBeep(uType
);
1050 LPWSTR WINAPI
MB_GetString(DWORD string
)