ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

messagebox.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.