Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmessagebox.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS kernel 00003 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 /* 00020 * 00021 * PROJECT: ReactOS user32.dll 00022 * FILE: lib/user32/windows/messagebox.c 00023 * PURPOSE: Input 00024 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 00025 * Thomas Weidenmueller (w3seek@users.sourceforge.net) 00026 * UPDATE HISTORY: 00027 * 2003/07/28 Added some NT features 00028 * 2003/07/27 Code ported from wine 00029 * 09-05-2001 CSH Created 00030 */ 00031 00032 /* INCLUDES ******************************************************************/ 00033 00034 #include <user32.h> 00035 00036 #include <wine/debug.h> 00037 00038 WINE_DEFAULT_DEBUG_CHANNEL(user32); 00039 00040 /* DEFINES *******************************************************************/ 00041 00042 #define MSGBOX_IDICON (1088) 00043 #define MSGBOX_IDTEXT (100) 00044 00045 #define IDI_HANDA MAKEINTRESOURCEA(32513) 00046 #define IDI_HANDW MAKEINTRESOURCEW(32513) 00047 #define IDI_QUESTIONA MAKEINTRESOURCEA(32514) 00048 #define IDI_QUESTIONW MAKEINTRESOURCEW(32514) 00049 #define IDI_EXCLAMATIONA MAKEINTRESOURCEA(32515) 00050 #define IDI_EXCLAMATIONW MAKEINTRESOURCEW(32515) 00051 #define IDI_ASTERISKA MAKEINTRESOURCEA(32516) 00052 #define IDI_ASTERISKW MAKEINTRESOURCEW(32516) 00053 #define IDI_WINLOGOA MAKEINTRESOURCEA(32517) 00054 #define IDI_WINLOGOW MAKEINTRESOURCEW(32517) 00055 00056 #define BTN_CX (75) 00057 #define BTN_CY (23) 00058 00059 #define MSGBOXEX_SPACING (16) 00060 #define MSGBOXEX_BUTTONSPACING (6) 00061 #define MSGBOXEX_MARGIN (12) 00062 #define MSGBOXEX_MAXBTNSTR (32) 00063 #define MSGBOXEX_MAXBTNS (4) 00064 00065 typedef struct _MSGBOXINFO { 00066 MSGBOXPARAMSW; // Wine passes this too. 00067 // ReactOS 00068 HICON Icon; 00069 HFONT Font; 00070 int DefBtn; 00071 int nButtons; 00072 LONG *Btns; 00073 UINT Timeout; 00074 } MSGBOXINFO, *PMSGBOXINFO; 00075 00076 /* INTERNAL FUNCTIONS ********************************************************/ 00077 00078 static VOID MessageBoxTextToClipboard(HWND DialogWindow) 00079 { 00080 HWND hwndText; 00081 PMSGBOXINFO mbi; 00082 int cchTotal, cchTitle, cchText, cchButton, i, n, cchBuffer; 00083 LPWSTR pszBuffer, pszBufferPos, pMessageBoxText, pszTitle, pszText, pszButton; 00084 WCHAR szButton[MSGBOXEX_MAXBTNSTR]; 00085 HGLOBAL hGlobal; 00086 00087 static const WCHAR szLine[30] = 00088 {'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-', 00089 '-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0}; 00090 00091 mbi = (PMSGBOXINFO)GetPropW(DialogWindow, L"ROS_MSGBOX"); 00092 hwndText = GetDlgItem(DialogWindow, MSGBOX_IDTEXT); 00093 cchTitle = GetWindowTextLengthW(DialogWindow) + 1; 00094 cchText = GetWindowTextLengthW(hwndText) + 1; 00095 00096 if(!mbi) 00097 return; 00098 00099 pMessageBoxText = (LPWSTR)RtlAllocateHeap(GetProcessHeap(), 0, (cchTitle + cchText) * sizeof(WCHAR)); 00100 00101 if(pMessageBoxText == NULL) 00102 { 00103 RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText); 00104 return; 00105 } 00106 00107 pszTitle = pMessageBoxText; 00108 pszText = pMessageBoxText + cchTitle; 00109 00110 00111 00112 if(GetWindowTextW(DialogWindow, pszTitle, cchTitle) == 0 || 00113 GetWindowTextW(hwndText, pszText, cchText) == 0) 00114 { 00115 RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText); 00116 return; 00117 } 00118 00119 /* 00120 * Calculate the total buffer size. 00121 */ 00122 cchTotal = 6 + cchTitle + cchText + (lstrlenW(szLine) * 4) + (mbi->nButtons * MSGBOXEX_MAXBTNSTR + 3); 00123 00124 hGlobal = GlobalAlloc(GHND, cchTotal * sizeof(WCHAR)); 00125 00126 pszBuffer = (LPWSTR)GlobalLock(hGlobal); 00127 00128 if(pszBuffer == NULL) 00129 { 00130 RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText); 00131 GlobalFree(hGlobal); 00132 return; 00133 } 00134 00135 /* 00136 * First format title and text. 00137 * ------------------ 00138 * Title 00139 * ------------------ 00140 * Text 00141 * ------------------ 00142 */ 00143 cchBuffer = wsprintfW(pszBuffer, L"%s%s\r\n%s%s\r\n%s", szLine, pszTitle, szLine, pszText, szLine); 00144 pszBufferPos = pszBuffer + cchBuffer; 00145 00146 for(i = 0; i < mbi->nButtons; i++) 00147 { 00148 GetDlgItemTextW(DialogWindow, mbi->Btns[i], szButton, MSGBOXEX_MAXBTNSTR); 00149 00150 cchButton = strlenW(szButton); 00151 pszButton = szButton; 00152 00153 /* Skip '&' character. */ 00154 if(szButton[0] == '&') 00155 { 00156 pszButton = pszButton + 1; 00157 cchButton = cchButton - 1; 00158 } 00159 00160 for(n = 0; n < cchButton; n++) 00161 *(pszBufferPos++) = pszButton[n]; 00162 00163 /* Add spaces. */ 00164 *(pszBufferPos++) = L' '; 00165 *(pszBufferPos++) = L' '; 00166 *(pszBufferPos++) = L' '; 00167 } 00168 00169 wsprintfW(pszBufferPos, L"\r\n%s", szLine); 00170 00171 GlobalUnlock(hGlobal); 00172 00173 if(OpenClipboard(DialogWindow)) 00174 { 00175 EmptyClipboard(); 00176 SetClipboardData(CF_UNICODETEXT, hGlobal); 00177 CloseClipboard(); 00178 } 00179 else 00180 { 00181 GlobalFree(hGlobal); 00182 } 00183 RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText); 00184 } 00185 00186 static INT_PTR CALLBACK MessageBoxProc( HWND hwnd, UINT message, 00187 WPARAM wParam, LPARAM lParam ) 00188 { 00189 int i, Alert; 00190 PMSGBOXINFO mbi; 00191 HELPINFO hi; 00192 HWND owner; 00193 00194 switch(message) { 00195 case WM_INITDIALOG: 00196 mbi = (PMSGBOXINFO)lParam; 00197 00198 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)mbi); 00199 NtUserxSetMessageBox(hwnd); 00200 00201 if(!GetPropW(hwnd, L"ROS_MSGBOX")) 00202 { 00203 SetPropW(hwnd, L"ROS_MSGBOX", (HANDLE)lParam); 00204 00205 if (mbi->dwContextHelpId) 00206 SetWindowContextHelpId(hwnd, mbi->dwContextHelpId); 00207 00208 if (mbi->Icon) 00209 { 00210 SendDlgItemMessageW(hwnd, MSGBOX_IDICON, STM_SETICON, (WPARAM)mbi->Icon, 0); 00211 Alert = ALERT_SYSTEM_WARNING; 00212 } 00213 else // Setup the rest of the alerts. 00214 { 00215 switch(mbi->dwStyle & MB_ICONMASK) 00216 { 00217 case MB_ICONWARNING: 00218 Alert = ALERT_SYSTEM_WARNING; 00219 break; 00220 case MB_ICONERROR: 00221 Alert = ALERT_SYSTEM_ERROR; 00222 break; 00223 case MB_ICONQUESTION: 00224 Alert = ALERT_SYSTEM_QUERY; 00225 break; 00226 default: 00227 Alert = ALERT_SYSTEM_INFORMATIONAL; 00228 /* fall through */ 00229 } 00230 } 00231 /* Send out the alert notifications. */ 00232 NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd, OBJID_ALERT, Alert); 00233 00234 /* set control fonts */ 00235 SendDlgItemMessageW(hwnd, MSGBOX_IDTEXT, WM_SETFONT, (WPARAM)mbi->Font, 0); 00236 for(i = 0; i < mbi->nButtons; i++) 00237 { 00238 SendDlgItemMessageW(hwnd, mbi->Btns[i], WM_SETFONT, (WPARAM)mbi->Font, 0); 00239 } 00240 switch(mbi->dwStyle & MB_TYPEMASK) 00241 { 00242 case MB_ABORTRETRYIGNORE: 00243 case MB_YESNO: 00244 RemoveMenu(GetSystemMenu(hwnd, FALSE), SC_CLOSE, MF_BYCOMMAND); 00245 break; 00246 } 00247 SetFocus(GetDlgItem(hwnd, mbi->DefBtn)); 00248 if(mbi->Timeout && (mbi->Timeout != (UINT)-1)) 00249 SetTimer(hwnd, 0, mbi->Timeout, NULL); 00250 } 00251 return 0; 00252 00253 case WM_COMMAND: 00254 switch (LOWORD(wParam)) 00255 { 00256 case IDOK: 00257 case IDCANCEL: 00258 case IDABORT: 00259 case IDRETRY: 00260 case IDIGNORE: 00261 case IDYES: 00262 case IDNO: 00263 case IDTRYAGAIN: 00264 case IDCONTINUE: 00265 EndDialog(hwnd, wParam); 00266 return 0; 00267 case IDHELP: 00268 /* send WM_HELP message to messagebox window */ 00269 hi.cbSize = sizeof(HELPINFO); 00270 hi.iContextType = HELPINFO_WINDOW; 00271 hi.iCtrlId = LOWORD(wParam); 00272 hi.hItemHandle = (HANDLE)lParam; 00273 hi.dwContextId = 0; 00274 GetCursorPos(&hi.MousePos); 00275 SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi); 00276 return 0; 00277 } 00278 return 0; 00279 00280 case WM_COPY: 00281 MessageBoxTextToClipboard(hwnd); 00282 return 0; 00283 00284 case WM_HELP: 00285 mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX"); 00286 if(!mbi) 00287 return 0; 00288 memcpy(&hi, (void *)lParam, sizeof(hi)); 00289 hi.dwContextId = GetWindowContextHelpId(hwnd); 00290 00291 if (mbi->lpfnMsgBoxCallback) 00292 mbi->lpfnMsgBoxCallback(&hi); 00293 else 00294 { 00295 owner = GetWindow(hwnd, GW_OWNER); 00296 if(owner) 00297 SendMessageW(GetWindow(hwnd, GW_OWNER), WM_HELP, 0, (LPARAM)&hi); 00298 } 00299 return 0; 00300 00301 case WM_CLOSE: 00302 mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX"); 00303 if(!mbi) 00304 return 0; 00305 switch(mbi->dwStyle & MB_TYPEMASK) 00306 { 00307 case MB_ABORTRETRYIGNORE: 00308 case MB_YESNO: 00309 return 1; 00310 } 00311 EndDialog(hwnd, IDCANCEL); 00312 return 1; 00313 00314 case WM_TIMER: 00315 if(wParam == 0) 00316 { 00317 EndDialog(hwnd, 32000); 00318 } 00319 return 0; 00320 } 00321 return 0; 00322 } 00323 00324 static int 00325 MessageBoxTimeoutIndirectW( 00326 CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT Timeout) 00327 { 00328 DLGTEMPLATE *tpl; 00329 DLGITEMTEMPLATE *iico, *itxt; 00330 NONCLIENTMETRICSW nclm; 00331 WCHAR capbuf[32]; 00332 LPVOID buf; 00333 BYTE *dest; 00334 LPCWSTR caption, text; 00335 HFONT hFont; 00336 HICON Icon; 00337 HDC hDC; 00338 int bufsize, ret, caplen, textlen, btnlen, i, btnleft, btntop, lmargin, nButtons = 0; 00339 LONG Buttons[MSGBOXEX_MAXBTNS]; 00340 WCHAR ButtonText[MSGBOXEX_MAXBTNS][MSGBOXEX_MAXBTNSTR]; 00341 DLGITEMTEMPLATE *ibtn[MSGBOXEX_MAXBTNS]; 00342 RECT btnrect, txtrect, rc; 00343 SIZE btnsize; 00344 MSGBOXINFO mbi; 00345 BOOL defbtn = FALSE; 00346 DWORD units = GetDialogBaseUnits(); 00347 00348 if(!lpMsgBoxParams->lpszCaption || !HIWORD((LPWSTR)lpMsgBoxParams->lpszCaption)) 00349 { 00350 LoadStringW(User32Instance, IDS_ERROR, &capbuf[0], 32); 00351 caption = &capbuf[0]; 00352 } 00353 else 00354 caption = (LPWSTR)lpMsgBoxParams->lpszCaption; 00355 00356 if(!lpMsgBoxParams->lpszText || !HIWORD(lpMsgBoxParams->lpszText)) 00357 text = L""; 00358 else 00359 text = lpMsgBoxParams->lpszText; 00360 00361 caplen = strlenW(caption); 00362 textlen = strlenW(text); 00363 00364 /* Create selected buttons */ 00365 switch(lpMsgBoxParams->dwStyle & MB_TYPEMASK) 00366 { 00367 case MB_OKCANCEL: 00368 Buttons[0] = IDOK; 00369 Buttons[1] = IDCANCEL; 00370 nButtons = 2; 00371 break; 00372 case MB_CANCELTRYCONTINUE: 00373 Buttons[0] = IDCANCEL; 00374 Buttons[1] = IDTRYAGAIN; 00375 Buttons[2] = IDCONTINUE; 00376 nButtons = 3; 00377 break; 00378 case MB_ABORTRETRYIGNORE: 00379 Buttons[0] = IDABORT; 00380 Buttons[1] = IDRETRY; 00381 Buttons[2] = IDIGNORE; 00382 nButtons = 3; 00383 break; 00384 case MB_YESNO: 00385 Buttons[0] = IDYES; 00386 Buttons[1] = IDNO; 00387 nButtons = 2; 00388 break; 00389 case MB_YESNOCANCEL: 00390 Buttons[0] = IDYES; 00391 Buttons[1] = IDNO; 00392 Buttons[2] = IDCANCEL; 00393 nButtons = 3; 00394 break; 00395 case MB_RETRYCANCEL: 00396 Buttons[0] = IDRETRY; 00397 Buttons[1] = IDCANCEL; 00398 nButtons = 2; 00399 break; 00400 case MB_OK: 00401 /* fall through */ 00402 default: 00403 Buttons[0] = IDOK; 00404 nButtons = 1; 00405 break; 00406 } 00407 /* Create Help button */ 00408 if(lpMsgBoxParams->dwStyle & MB_HELP) 00409 Buttons[nButtons++] = IDHELP; 00410 00411 switch(lpMsgBoxParams->dwStyle & MB_ICONMASK) 00412 { 00413 case MB_ICONEXCLAMATION: 00414 Icon = LoadIconW(0, IDI_EXCLAMATIONW); 00415 MessageBeep(MB_ICONEXCLAMATION); 00416 break; 00417 case MB_ICONQUESTION: 00418 Icon = LoadIconW(0, IDI_QUESTIONW); 00419 MessageBeep(MB_ICONQUESTION); 00420 break; 00421 case MB_ICONASTERISK: 00422 Icon = LoadIconW(0, IDI_ASTERISKW); 00423 MessageBeep(MB_ICONASTERISK); 00424 break; 00425 case MB_ICONHAND: 00426 Icon = LoadIconW(0, IDI_HANDW); 00427 MessageBeep(MB_ICONHAND); 00428 break; 00429 case MB_USERICON: 00430 Icon = LoadIconW(lpMsgBoxParams->hInstance, lpMsgBoxParams->lpszIcon); 00431 MessageBeep(MB_OK); 00432 break; 00433 default: 00434 /* By default, Windows 95/98/NT does not associate an icon to message boxes. 00435 * So ReactOS should do the same. 00436 */ 00437 Icon = (HICON)0; 00438 MessageBeep(MB_OK); 00439 break; 00440 } 00441 00442 /* Basic space */ 00443 bufsize = sizeof(DLGTEMPLATE) + 00444 2 * sizeof(WORD) + /* menu and class */ 00445 (caplen + 1) * sizeof(WCHAR); /* title */ 00446 00447 /* Space for icon */ 00448 if (NULL != Icon) 00449 { 00450 bufsize = (bufsize + 3) & ~3; 00451 bufsize += sizeof(DLGITEMTEMPLATE) + 00452 4 * sizeof(WORD) + 00453 sizeof(WCHAR); 00454 } 00455 00456 /* Space for text */ 00457 bufsize = (bufsize + 3) & ~3; 00458 bufsize += sizeof(DLGITEMTEMPLATE) + 00459 3 * sizeof(WORD) + 00460 (textlen + 1) * sizeof(WCHAR); 00461 00462 00463 for(i = 0; i < nButtons; i++) 00464 { 00465 switch(Buttons[i]) 00466 { 00467 case IDOK: 00468 LoadStringW(User32Instance, IDS_OK, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00469 break; 00470 case IDCANCEL: 00471 LoadStringW(User32Instance, IDS_CANCEL, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00472 break; 00473 case IDYES: 00474 LoadStringW(User32Instance, IDS_YES, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00475 break; 00476 case IDNO: 00477 LoadStringW(User32Instance, IDS_NO, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00478 break; 00479 case IDTRYAGAIN: 00480 LoadStringW(User32Instance, IDS_TRYAGAIN, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00481 break; 00482 case IDCONTINUE: 00483 LoadStringW(User32Instance, IDS_CONTINUE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00484 break; 00485 case IDABORT: 00486 LoadStringW(User32Instance, IDS_ABORT, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00487 break; 00488 case IDRETRY: 00489 LoadStringW(User32Instance, IDS_RETRY, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00490 break; 00491 case IDIGNORE: 00492 LoadStringW(User32Instance, IDS_IGNORE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00493 break; 00494 case IDHELP: 00495 LoadStringW(User32Instance, IDS_HELP, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); 00496 break; 00497 default: 00498 ButtonText[i][0] = (WCHAR)0; 00499 break; 00500 } 00501 00502 /* Space for buttons */ 00503 bufsize = (bufsize + 3) & ~3; 00504 bufsize += sizeof(DLGITEMTEMPLATE) + 00505 3 * sizeof(WORD) + 00506 (wcslen(ButtonText[i]) + 1) * sizeof(WCHAR); 00507 } 00508 00509 buf = RtlAllocateHeap(GetProcessHeap(), 0, bufsize); 00510 if(!buf) 00511 { 00512 return 0; 00513 } 00514 iico = itxt = NULL; 00515 00516 hDC = CreateCompatibleDC(0); 00517 00518 nclm.cbSize = sizeof(nclm); 00519 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0); 00520 hFont = CreateFontIndirectW (&nclm.lfMessageFont); 00521 00522 tpl = (DLGTEMPLATE *)buf; 00523 00524 tpl->style = WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU | DS_CENTER | DS_MODALFRAME | DS_NOIDLEMSG; 00525 tpl->dwExtendedStyle = WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT; 00526 if(lpMsgBoxParams->dwStyle & MB_TOPMOST) 00527 tpl->dwExtendedStyle |= WS_EX_TOPMOST; 00528 if(lpMsgBoxParams->dwStyle & MB_RIGHT) 00529 tpl->dwExtendedStyle |= WS_EX_RIGHT; 00530 tpl->x = 100; 00531 tpl->y = 100; 00532 tpl->cdit = nButtons + ((Icon != (HICON)0) ? 1 : 0) + 1; 00533 00534 dest = (BYTE *)(tpl + 1); 00535 00536 *(WORD*)dest = 0; /* no menu */ 00537 *(((WORD*)dest) + 1) = 0; /* use default window class */ 00538 dest += 2 * sizeof(WORD); 00539 memcpy(dest, caption, caplen * sizeof(WCHAR)); 00540 dest += caplen * sizeof(WCHAR); 00541 *(WCHAR*)dest = L'\0'; 00542 dest += sizeof(WCHAR); 00543 00544 /* Create icon */ 00545 if(Icon) 00546 { 00547 dest = (BYTE*)(((ULONG_PTR)dest + 3) & ~3); 00548 iico = (DLGITEMTEMPLATE *)dest; 00549 iico->style = WS_CHILD | WS_VISIBLE | SS_ICON; 00550 iico->dwExtendedStyle = 0; 00551 iico->id = MSGBOX_IDICON; 00552 00553 dest += sizeof(DLGITEMTEMPLATE); 00554 *(WORD*)dest = 0xFFFF; 00555 dest += sizeof(WORD); 00556 *(WORD*)dest = 0x0082; /* static control */ 00557 dest += sizeof(WORD); 00558 *(WORD*)dest = 0xFFFF; 00559 dest += sizeof(WORD); 00560 *(WCHAR*)dest = 0; 00561 dest += sizeof(WCHAR); 00562 *(WORD*)dest = 0; 00563 dest += sizeof(WORD); 00564 } 00565 00566 /* create static for text */ 00567 dest = (BYTE*)(((UINT_PTR)dest + 3) & ~3); 00568 itxt = (DLGITEMTEMPLATE *)dest; 00569 itxt->style = WS_CHILD | WS_VISIBLE | SS_NOPREFIX; 00570 if(lpMsgBoxParams->dwStyle & MB_RIGHT) 00571 itxt->style |= SS_RIGHT; 00572 else 00573 itxt->style |= SS_LEFT; 00574 itxt->dwExtendedStyle = 0; 00575 itxt->id = MSGBOX_IDTEXT; 00576 dest += sizeof(DLGITEMTEMPLATE); 00577 *(WORD*)dest = 0xFFFF; 00578 dest += sizeof(WORD); 00579 *(WORD*)dest = 0x0082; /* static control */ 00580 dest += sizeof(WORD); 00581 memcpy(dest, text, textlen * sizeof(WCHAR)); 00582 dest += textlen * sizeof(WCHAR); 00583 *(WCHAR*)dest = 0; 00584 dest += sizeof(WCHAR); 00585 *(WORD*)dest = 0; 00586 dest += sizeof(WORD); 00587 00588 /* create buttons */ 00589 btnsize.cx = BTN_CX; 00590 btnsize.cy = BTN_CY; 00591 btnrect.left = btnrect.top = 0; 00592 for(i = 0; i < nButtons; i++) 00593 { 00594 dest = (BYTE*)(((UINT_PTR)dest + 3) & ~3); 00595 ibtn[i] = (DLGITEMTEMPLATE *)dest; 00596 ibtn[i]->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP; 00597 if(!defbtn && (i == ((lpMsgBoxParams->dwStyle & MB_DEFMASK) >> 8))) 00598 { 00599 ibtn[i]->style |= BS_DEFPUSHBUTTON; 00600 mbi.DefBtn = Buttons[i]; 00601 defbtn = TRUE; 00602 } 00603 else 00604 ibtn[i]->style |= BS_PUSHBUTTON; 00605 ibtn[i]->dwExtendedStyle = 0; 00606 ibtn[i]->id = Buttons[i]; 00607 dest += sizeof(DLGITEMTEMPLATE); 00608 *(WORD*)dest = 0xFFFF; 00609 dest += sizeof(WORD); 00610 *(WORD*)dest = 0x0080; /* button control */ 00611 dest += sizeof(WORD); 00612 btnlen = strlenW(ButtonText[i]); 00613 memcpy(dest, ButtonText[i], btnlen * sizeof(WCHAR)); 00614 dest += btnlen * sizeof(WCHAR); 00615 *(WORD*)dest = 0; 00616 dest += sizeof(WORD); 00617 *(WORD*)dest = 0; 00618 dest += sizeof(WORD); 00619 SelectObject(hDC, hFont); 00620 DrawTextW(hDC, ButtonText[i], btnlen, &btnrect, DT_LEFT | DT_SINGLELINE | DT_CALCRECT); 00621 btnsize.cx = max(btnsize.cx, btnrect.right); 00622 btnsize.cy = max(btnsize.cy, btnrect.bottom); 00623 } 00624 00625 /* make first button the default button if no other is */ 00626 if(!defbtn) 00627 { 00628 ibtn[0]->style &= ~BS_PUSHBUTTON; 00629 ibtn[0]->style |= BS_DEFPUSHBUTTON; 00630 mbi.DefBtn = Buttons[0]; 00631 } 00632 00633 /* calculate position and size of controls */ 00634 txtrect.right = GetSystemMetrics(SM_CXSCREEN) / 5 * 4; 00635 if(Icon) 00636 txtrect.right -= GetSystemMetrics(SM_CXICON) + MSGBOXEX_SPACING; 00637 txtrect.top = txtrect.left = txtrect.bottom = 0; 00638 SelectObject(hDC, hFont); 00639 if (textlen != 0) 00640 { 00641 DrawTextW(hDC, text, textlen, &txtrect, DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT); 00642 } 00643 else 00644 { 00645 txtrect.right = txtrect.left + 1; 00646 txtrect.bottom = txtrect.top + 1; 00647 } 00648 txtrect.right++; 00649 00650 /* calculate position and size of the icon */ 00651 rc.left = rc.bottom = rc.right = 0; 00652 btntop = 0; 00653 00654 if(iico) 00655 { 00656 rc.right = GetSystemMetrics(SM_CXICON); 00657 rc.bottom = GetSystemMetrics(SM_CYICON); 00658 #ifdef MSGBOX_ICONVCENTER 00659 rc.top = MSGBOXEX_MARGIN + (max(txtrect.bottom, rc.bottom) / 2) - (GetSystemMetrics(SM_CYICON) / 2); 00660 rc.top = max(MSGBOXEX_SPACING, rc.top); 00661 #else 00662 rc.top = MSGBOXEX_MARGIN; 00663 #endif 00664 btnleft = (nButtons * (btnsize.cx + MSGBOXEX_BUTTONSPACING)) - MSGBOXEX_BUTTONSPACING; 00665 if(btnleft > txtrect.right + rc.right + MSGBOXEX_SPACING) 00666 { 00667 #ifdef MSGBOX_TEXTHCENTER 00668 lmargin = MSGBOXEX_MARGIN + ((btnleft - txtrect.right - rc.right - MSGBOXEX_SPACING) / 2); 00669 #else 00670 lmargin = MSGBOXEX_MARGIN; 00671 #endif 00672 btnleft = MSGBOXEX_MARGIN; 00673 } 00674 else 00675 { 00676 lmargin = MSGBOXEX_MARGIN; 00677 btnleft = MSGBOXEX_MARGIN + ((txtrect.right + rc.right + MSGBOXEX_SPACING) / 2) - (btnleft / 2); 00678 } 00679 rc.left = lmargin; 00680 iico->x = (rc.left * 4) / LOWORD(units); 00681 iico->y = (rc.top * 8) / HIWORD(units); 00682 iico->cx = (rc.right * 4) / LOWORD(units); 00683 iico->cy = (rc.bottom * 8) / HIWORD(units); 00684 btntop = rc.top + rc.bottom + MSGBOXEX_SPACING; 00685 rc.left += rc.right + MSGBOXEX_SPACING; 00686 } 00687 else 00688 { 00689 btnleft = (nButtons * (btnsize.cx + MSGBOXEX_BUTTONSPACING)) - MSGBOXEX_BUTTONSPACING; 00690 if(btnleft > txtrect.right) 00691 { 00692 #ifdef MSGBOX_TEXTHCENTER 00693 lmargin = MSGBOXEX_MARGIN + ((btnleft - txtrect.right) / 2); 00694 #else 00695 lmargin = MSGBOXEX_MARGIN; 00696 #endif 00697 btnleft = MSGBOXEX_MARGIN; 00698 } 00699 else 00700 { 00701 lmargin = MSGBOXEX_MARGIN; 00702 btnleft = MSGBOXEX_MARGIN + (txtrect.right / 2) - (btnleft / 2); 00703 } 00704 rc.left = lmargin; 00705 } 00706 /* calculate position of the text */ 00707 rc.top = MSGBOXEX_MARGIN + (rc.bottom / 2) - (txtrect.bottom / 2); 00708 rc.top = max(rc.top, MSGBOXEX_MARGIN); 00709 /* calculate position of the buttons */ 00710 btntop = max(rc.top + txtrect.bottom + MSGBOXEX_SPACING, btntop); 00711 for(i = 0; i < nButtons; i++) 00712 { 00713 ibtn[i]->x = (btnleft * 4) / LOWORD(units); 00714 ibtn[i]->y = (btntop * 8) / HIWORD(units); 00715 ibtn[i]->cx = (btnsize.cx * 4) / LOWORD(units); 00716 ibtn[i]->cy = (btnsize.cy * 8) / HIWORD(units); 00717 btnleft += btnsize.cx + MSGBOXEX_BUTTONSPACING; 00718 } 00719 /* calculate size and position of the messagebox window */ 00720 btnleft = max(btnleft - MSGBOXEX_BUTTONSPACING, rc.left + txtrect.right); 00721 btnleft += MSGBOXEX_MARGIN; 00722 btntop += btnsize.cy + MSGBOXEX_MARGIN; 00723 /* set size and position of the message static */ 00724 itxt->x = (rc.left * 4) / LOWORD(units); 00725 itxt->y = (rc.top * 8) / HIWORD(units); 00726 itxt->cx = (((btnleft - rc.left - MSGBOXEX_MARGIN) * 4) / LOWORD(units)); 00727 itxt->cy = ((txtrect.bottom * 8) / HIWORD(units)); 00728 /* set size of the window */ 00729 tpl->cx = (btnleft * 4) / LOWORD(units); 00730 tpl->cy = (btntop * 8) / HIWORD(units); 00731 00732 /* finally show the messagebox */ 00733 mbi.Icon = Icon; 00734 mbi.Font = hFont; 00735 mbi.dwContextHelpId = lpMsgBoxParams->dwContextHelpId; 00736 mbi.lpfnMsgBoxCallback = lpMsgBoxParams->lpfnMsgBoxCallback; 00737 mbi.dwStyle = lpMsgBoxParams->dwStyle; 00738 mbi.nButtons = nButtons; 00739 mbi.Btns = &Buttons[0]; 00740 mbi.Timeout = Timeout; 00741 00742 /* Pass on to Justin Case so he can peek the message? */ 00743 mbi.cbSize = lpMsgBoxParams->cbSize; 00744 mbi.hwndOwner = lpMsgBoxParams->hwndOwner; 00745 mbi.hInstance = lpMsgBoxParams->hInstance; 00746 mbi.lpszText = lpMsgBoxParams->lpszText; 00747 mbi.lpszCaption = lpMsgBoxParams->lpszCaption; 00748 mbi.lpszIcon = lpMsgBoxParams->lpszIcon; 00749 mbi.dwLanguageId = lpMsgBoxParams->dwLanguageId; 00750 00751 if(hDC) 00752 DeleteDC(hDC); 00753 00754 ret = DialogBoxIndirectParamW(lpMsgBoxParams->hInstance, tpl, lpMsgBoxParams->hwndOwner, 00755 MessageBoxProc, (LPARAM)&mbi); 00756 00757 if(hFont) 00758 DeleteObject(hFont); 00759 00760 RtlFreeHeap(GetProcessHeap(), 0, buf); 00761 return ret; 00762 } 00763 00764 /* FUNCTIONS *****************************************************************/ 00765 00766 00767 /* 00768 * @implemented 00769 */ 00770 int 00771 WINAPI 00772 MessageBoxA( 00773 HWND hWnd, 00774 LPCSTR lpText, 00775 LPCSTR lpCaption, 00776 UINT uType) 00777 { 00778 return MessageBoxExA(hWnd, lpText, lpCaption, uType, LANG_NEUTRAL); 00779 } 00780 00781 00782 /* 00783 * @implemented 00784 */ 00785 int 00786 WINAPI 00787 MessageBoxExA( 00788 HWND hWnd, 00789 LPCSTR lpText, 00790 LPCSTR lpCaption, 00791 UINT uType, 00792 WORD wLanguageId) 00793 { 00794 MSGBOXPARAMSA msgbox; 00795 00796 msgbox.cbSize = sizeof(msgbox); 00797 msgbox.hwndOwner = hWnd; 00798 msgbox.hInstance = 0; 00799 msgbox.lpszText = lpText; 00800 msgbox.lpszCaption = lpCaption; 00801 msgbox.dwStyle = uType; 00802 msgbox.lpszIcon = NULL; 00803 msgbox.dwContextHelpId = 0; 00804 msgbox.lpfnMsgBoxCallback = NULL; 00805 msgbox.dwLanguageId = wLanguageId; 00806 00807 return MessageBoxIndirectA(&msgbox); 00808 } 00809 00810 00811 /* 00812 * @implemented 00813 */ 00814 int 00815 WINAPI 00816 MessageBoxExW( 00817 HWND hWnd, 00818 LPCWSTR lpText, 00819 LPCWSTR lpCaption, 00820 UINT uType, 00821 WORD wLanguageId) 00822 { 00823 MSGBOXPARAMSW msgbox; 00824 00825 msgbox.cbSize = sizeof(msgbox); 00826 msgbox.hwndOwner = hWnd; 00827 msgbox.hInstance = 0; 00828 msgbox.lpszText = lpText; 00829 msgbox.lpszCaption = lpCaption; 00830 msgbox.dwStyle = uType; 00831 msgbox.lpszIcon = NULL; 00832 msgbox.dwContextHelpId = 0; 00833 msgbox.lpfnMsgBoxCallback = NULL; 00834 msgbox.dwLanguageId = wLanguageId; 00835 00836 return MessageBoxTimeoutIndirectW(&msgbox, (UINT)-1); 00837 } 00838 00839 00840 /* 00841 * @implemented 00842 */ 00843 int 00844 WINAPI 00845 MessageBoxIndirectA( 00846 CONST MSGBOXPARAMSA *lpMsgBoxParams) 00847 { 00848 MSGBOXPARAMSW msgboxW; 00849 UNICODE_STRING textW, captionW, iconW; 00850 int ret; 00851 00852 if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszText)) 00853 { 00854 RtlCreateUnicodeStringFromAsciiz(&textW, (PCSZ)lpMsgBoxParams->lpszText); 00855 /* 00856 * UNICODE_STRING objects are always allocated with an extra byte so you 00857 * can null-term if you want 00858 */ 00859 textW.Buffer[textW.Length / sizeof(WCHAR)] = L'\0'; 00860 } 00861 else 00862 textW.Buffer = (LPWSTR)lpMsgBoxParams->lpszText; 00863 00864 if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszCaption)) 00865 { 00866 RtlCreateUnicodeStringFromAsciiz(&captionW, (PCSZ)lpMsgBoxParams->lpszCaption); 00867 /* 00868 * UNICODE_STRING objects are always allocated with an extra byte so you 00869 * can null-term if you want 00870 */ 00871 captionW.Buffer[captionW.Length / sizeof(WCHAR)] = L'\0'; 00872 } 00873 else 00874 captionW.Buffer = (LPWSTR)lpMsgBoxParams->lpszCaption; 00875 00876 if(lpMsgBoxParams->dwStyle & MB_USERICON) 00877 { 00878 if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszIcon)) 00879 { 00880 RtlCreateUnicodeStringFromAsciiz(&iconW, (PCSZ)lpMsgBoxParams->lpszIcon); 00881 /* 00882 * UNICODE_STRING objects are always allocated with an extra byte so you 00883 * can null-term if you want 00884 */ 00885 iconW.Buffer[iconW.Length / sizeof(WCHAR)] = L'\0'; 00886 } 00887 else 00888 iconW.Buffer = (LPWSTR)lpMsgBoxParams->lpszIcon; 00889 } 00890 else 00891 iconW.Buffer = NULL; 00892 00893 msgboxW.cbSize = sizeof(msgboxW); 00894 msgboxW.hwndOwner = lpMsgBoxParams->hwndOwner; 00895 msgboxW.hInstance = lpMsgBoxParams->hInstance; 00896 msgboxW.lpszText = textW.Buffer; 00897 msgboxW.lpszCaption = captionW.Buffer; 00898 msgboxW.dwStyle = lpMsgBoxParams->dwStyle; 00899 msgboxW.lpszIcon = iconW.Buffer; 00900 msgboxW.dwContextHelpId = lpMsgBoxParams->dwContextHelpId; 00901 msgboxW.lpfnMsgBoxCallback = lpMsgBoxParams->lpfnMsgBoxCallback; 00902 msgboxW.dwLanguageId = lpMsgBoxParams->dwLanguageId; 00903 00904 ret = MessageBoxTimeoutIndirectW(&msgboxW, (UINT)-1); 00905 00906 if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszText)) 00907 RtlFreeUnicodeString(&textW); 00908 00909 if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszCaption)) 00910 RtlFreeUnicodeString(&captionW); 00911 00912 if ((lpMsgBoxParams->dwStyle & MB_USERICON) && HIWORD((UINT_PTR)iconW.Buffer)) 00913 RtlFreeUnicodeString(&iconW); 00914 00915 return ret; 00916 } 00917 00918 00919 /* 00920 * @implemented 00921 */ 00922 int 00923 WINAPI 00924 MessageBoxIndirectW( 00925 CONST MSGBOXPARAMSW *lpMsgBoxParams) 00926 { 00927 return MessageBoxTimeoutIndirectW(lpMsgBoxParams, (UINT)-1); 00928 } 00929 00930 00931 /* 00932 * @implemented 00933 */ 00934 int 00935 WINAPI 00936 MessageBoxW( 00937 HWND hWnd, 00938 LPCWSTR lpText, 00939 LPCWSTR lpCaption, 00940 UINT uType) 00941 { 00942 return MessageBoxExW(hWnd, lpText, lpCaption, uType, LANG_NEUTRAL); 00943 } 00944 00945 /* 00946 * @implemented 00947 */ 00948 int 00949 WINAPI 00950 MessageBoxTimeoutA( 00951 HWND hWnd, 00952 LPCSTR lpText, 00953 LPCSTR lpCaption, 00954 UINT uType, 00955 WORD wLanguageId, 00956 DWORD dwTime) 00957 { 00958 MSGBOXPARAMSW msgboxW; 00959 UNICODE_STRING textW, captionW; 00960 int ret; 00961 00962 if (HIWORD((UINT_PTR)lpText)) 00963 RtlCreateUnicodeStringFromAsciiz(&textW, (PCSZ)lpText); 00964 else 00965 textW.Buffer = (LPWSTR)lpText; 00966 00967 if (HIWORD((UINT_PTR)lpCaption)) 00968 RtlCreateUnicodeStringFromAsciiz(&captionW, (PCSZ)lpCaption); 00969 else 00970 captionW.Buffer = (LPWSTR)lpCaption; 00971 00972 msgboxW.cbSize = sizeof(msgboxW); 00973 msgboxW.hwndOwner = hWnd; 00974 msgboxW.hInstance = 0; 00975 msgboxW.lpszText = textW.Buffer; 00976 msgboxW.lpszCaption = captionW.Buffer; 00977 msgboxW.dwStyle = uType; 00978 msgboxW.lpszIcon = NULL; 00979 msgboxW.dwContextHelpId = 0; 00980 msgboxW.lpfnMsgBoxCallback = NULL; 00981 msgboxW.dwLanguageId = wLanguageId; 00982 00983 ret = MessageBoxTimeoutIndirectW(&msgboxW, (UINT)dwTime); 00984 00985 if (HIWORD(textW.Buffer)) 00986 RtlFreeUnicodeString(&textW); 00987 00988 if (HIWORD(captionW.Buffer)) 00989 RtlFreeUnicodeString(&captionW); 00990 00991 return ret; 00992 } 00993 00994 /* 00995 * @implemented 00996 */ 00997 int 00998 WINAPI 00999 MessageBoxTimeoutW( 01000 HWND hWnd, 01001 LPCWSTR lpText, 01002 LPCWSTR lpCaption, 01003 UINT uType, 01004 WORD wLanguageId, 01005 DWORD dwTime) 01006 { 01007 MSGBOXPARAMSW msgbox; 01008 01009 msgbox.cbSize = sizeof(msgbox); 01010 msgbox.hwndOwner = hWnd; 01011 msgbox.hInstance = 0; 01012 msgbox.lpszText = lpText; 01013 msgbox.lpszCaption = lpCaption; 01014 msgbox.dwStyle = uType; 01015 msgbox.lpszIcon = NULL; 01016 msgbox.dwContextHelpId = 0; 01017 msgbox.lpfnMsgBoxCallback = NULL; 01018 msgbox.dwLanguageId = wLanguageId; 01019 01020 return MessageBoxTimeoutIndirectW(&msgbox, (UINT)dwTime); 01021 } 01022 01023 01024 /* 01025 * @unimplemented 01026 */ 01027 DWORD 01028 WINAPI 01029 SoftModalMessageBox(DWORD Unknown0) 01030 { 01031 UNIMPLEMENTED; 01032 return 0; 01033 } 01034 01035 01036 /* 01037 * @implemented 01038 */ 01039 BOOL 01040 WINAPI 01041 MessageBeep(UINT uType) 01042 { 01043 return NtUserxMessageBeep(uType); 01044 } 01045 01046 01047 /* 01048 * @implemented 01049 */ 01050 LPWSTR WINAPI MB_GetString(DWORD string) 01051 { 01052 UNIMPLEMENTED; 01053 return NULL; 01054 } 01055 01056 /* EOF */ Generated on Fri May 25 2012 04:37:10 for ReactOS by
1.7.6.1
|