reactos操作系统实现(177)

MessageBoxTimeoutIndirectW的实现代码如下:

#001  static int

#002  MessageBoxTimeoutIndirectW(

#003    CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT Timeout)

#004  {

#005      DLGTEMPLATE *tpl;

#006      DLGITEMTEMPLATE *iico, *itxt;

#007      NONCLIENTMETRICSW nclm;

#008      WCHAR capbuf[32];

#009      LPVOID buf;

#010      BYTE *dest;

#011      LPCWSTR caption, text;

#012      HFONT hFont;

#013      HICON Icon;

#014      HDC hDC;

#015      int bufsize, ret, caplen, textlen, btnlen, i, btnleft, btntop, lmargin, nButtons = 0;

#016      LONG Buttons[MSGBOXEX_MAXBTNS];

#017      WCHAR ButtonText[MSGBOXEX_MAXBTNS][MSGBOXEX_MAXBTNSTR];

#018      DLGITEMTEMPLATE *ibtn[MSGBOXEX_MAXBTNS];

#019      RECT btnrect, txtrect, rc;

#020      SIZE btnsize;

#021      MSGBOXINFO mbi;

#022      BOOL defbtn = FALSE;

 

获取对话框架基本显示单元的大小。

#023      DWORD units = GetDialogBaseUnits();

#024 

 

判断是否设置有显示标题字符串,如果没有设置,就从用户应用程序里获取错误显示字符串作为标题。

#025      if(!lpMsgBoxParams->lpszCaption || !HIWORD((LPWSTR)lpMsgBoxParams->lpszCaption))

#026      {

#027        LoadStringW(User32Instance, IDS_ERROR, &capbuf[0], 32);

#028        caption = &capbuf[0];

#029      }

#030      else

#031        caption = (LPWSTR)lpMsgBoxParams->lpszCaption;

#032 

 

判断是否需要显示的字符串。

#033      if(!lpMsgBoxParams->lpszText || !HIWORD(lpMsgBoxParams->lpszText))

#034        text = L"";

#035      else

#036        text = lpMsgBoxParams->lpszText;

#037 

 

获取标题和显示字符串的大小。

#038      caplen = strlenW(caption);

#039      textlen = strlenW(text);

#040 

 

根据用户的设置来选择显示什么类型的按钮。

#041      /* Create selected buttons */

#042      switch(lpMsgBoxParams->dwStyle & MB_TYPEMASK)

#043      {

#044          case MB_OKCANCEL:

#045              Buttons[0] = IDOK;

#046              Buttons[1] = IDCANCEL;

#047              nButtons = 2;

#048              break;

#049          case MB_CANCELTRYCONTINUE:

#050              Buttons[0] = IDCANCEL;

#051              Buttons[1] = IDTRYAGAIN;

#052              Buttons[2] = IDCONTINUE;

#053              nButtons = 3;

#054              break;

#055          case MB_ABORTRETRYIGNORE:

#056              Buttons[0] = IDABORT;

#057              Buttons[1] = IDRETRY;

#058              Buttons[2] = IDIGNORE;

#059              nButtons = 3;

#060              break;

#061          case MB_YESNO:

#062              Buttons[0] = IDYES;

#063              Buttons[1] = IDNO;

#064              nButtons = 2;

#065              break;

#066          case MB_YESNOCANCEL:

#067              Buttons[0] = IDYES;

#068              Buttons[1] = IDNO;

#069              Buttons[2] = IDCANCEL;

#070              nButtons = 3;

#071              break;

#072          case MB_RETRYCANCEL:

#073              Buttons[0] = IDRETRY;

#074              Buttons[1] = IDCANCEL;

#075              nButtons = 2;

#076              break;

#077          case MB_OK:

#078              /* fall through */

#079          default:

#080              Buttons[0] = IDOK;

#081              nButtons = 1;

#082              break;

#083      }

 

判断是否显示帮助按钮。

#084      /* Create Help button */

#085      if(lpMsgBoxParams->dwStyle & MB_HELP)

#086        Buttons[nButtons++] = IDHELP;

#087 

 

根据用户设置选择什么类型的图标显示,并调用函数MessageBeep提示不同的提示声音。

#088      switch(lpMsgBoxParams->dwStyle & MB_ICONMASK)

#089      {

#090        case MB_ICONEXCLAMATION:

#091          Icon = LoadIconW(0, IDI_EXCLAMATIONW);

#092          MessageBeep(MB_ICONEXCLAMATION);

#093          break;

#094        case MB_ICONQUESTION:

#095          Icon = LoadIconW(0, IDI_QUESTIONW);

#096          MessageBeep(MB_ICONQUESTION);

#097          break;

#098        case MB_ICONASTERISK:

#099          Icon = LoadIconW(0, IDI_ASTERISKW);

#100          MessageBeep(MB_ICONASTERISK);

#101          break;

#102        case MB_ICONHAND:

#103          Icon = LoadIconW(0, IDI_HANDW);

#104          MessageBeep(MB_ICONHAND);

#105          break;

#106        case MB_USERICON:

#107          Icon = LoadIconW(lpMsgBoxParams->hInstance, lpMsgBoxParams->lpszIcon);

#108          MessageBeep(MB_OK);

#109          break;

#110        default:

#111          /* By default, Windows 95/98/NT does not associate an icon to message boxes.

#112           * So ReactOS should do the same.

#113           */

#114          Icon = (HICON)0;

#115          MessageBeep(MB_OK);

#116          break;

#117      }

#118

 

分配基本空间的大小。 

#119      /* Basic space */

#120      bufsize = sizeof(DLGTEMPLATE) +

#121                2 * sizeof(WORD) +                         /* menu and class */

#122                (caplen + 1) * sizeof(WCHAR);              /* title */

#123 

 

图标占用空间的大小。

#124      /* Space for icon */

#125      if (NULL != Icon)

#126      {

#127        bufsize = (bufsize + 3) & ~3;

#128        bufsize += sizeof(DLGITEMTEMPLATE) +

#129                   4 * sizeof(WORD) +

#130                   sizeof(WCHAR);

#131      }

#132 

 

显示字符串占用空间。

#133      /* Space for text */

#134      bufsize = (bufsize + 3) & ~3;

#135      bufsize += sizeof(DLGITEMTEMPLATE) +

#136                 3 * sizeof(WORD) +

#137                 (textlen + 1) * sizeof(WCHAR);

#138 

#139 

 

加载所有按钮的字符串。

#140      for(i = 0; i < nButtons; i++)

#141      {

#142        switch(Buttons[i])

#143        {

#144          case IDOK:

#145            LoadStringW(User32Instance, IDS_OK, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#146            break;

#147          case IDCANCEL:

#148            LoadStringW(User32Instance, IDS_CANCEL, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#149            break;

#150          case IDYES:

#151            LoadStringW(User32Instance, IDS_YES, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#152            break;

#153          case IDNO:

#154            LoadStringW(User32Instance, IDS_NO, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#155            break;

#156          case IDTRYAGAIN:

#157            LoadStringW(User32Instance, IDS_TRYAGAIN, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#158            break;

#159          case IDCONTINUE:

#160            LoadStringW(User32Instance, IDS_CONTINUE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#161            break;

#162          case IDABORT:

#163            LoadStringW(User32Instance, IDS_ABORT, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#164            break;

#165          case IDRETRY:

#166            LoadStringW(User32Instance, IDS_RETRY, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#167            break;

#168          case IDIGNORE:

#169            LoadStringW(User32Instance, IDS_IGNORE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#170            break;

#171          case IDHELP:

#172            LoadStringW(User32Instance, IDS_HELP, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1);

#173            break;

#174          default:

#175            ButtonText[i][0] = (WCHAR)0;

#176            break;

#177        }

#178 

 

按钮的空间大小。

#179        /* Space for buttons */

#180        bufsize = (bufsize + 3) & ~3;

#181        bufsize += sizeof(DLGITEMTEMPLATE) +

#182                   3 * sizeof(WORD) +

#183                   (wcslen(ButtonText[i]) + 1) * sizeof(WCHAR);

#184      }

#185 

 

从进程堆空间里分配内存。

#186      buf = RtlAllocateHeap(GetProcessHeap(), 0, bufsize);

#187      if(!buf)

#188      {

#189        return 0;

#190      }

#191      iico = itxt = NULL;

#192 

 

创建一个兼容DC

#193      hDC = CreateCompatibleDC(0);

#194 

 

下面获取消息窗口显示的字体。

#195      nclm.cbSize = sizeof(nclm);

#196      SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0);

#197      hFont = CreateFontIndirectW (&nclm.lfMessageFont);

#198 

 

下面开始根据对话框的资源结构在内存里构造窗口显示模板。

#199      tpl = (DLGTEMPLATE *)buf;

#200  

#201      tpl->style = WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU | DS_CENTER | DS_MODALFRAME | DS_NOIDLEMSG;

#202      tpl->dwExtendedStyle = WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;

#203      if(lpMsgBoxParams->dwStyle & MB_TOPMOST)

#204        tpl->dwExtendedStyle |= WS_EX_TOPMOST;

#205      if(lpMsgBoxParams->dwStyle & MB_RIGHT)

#206        tpl->dwExtendedStyle |= WS_EX_RIGHT;

#207      tpl->x = 100;

#208      tpl->y = 100;

#209      tpl->cdit = nButtons + ((Icon != (HICON)0) ? 1 : 0) + 1;

#210 

#211      dest = (BYTE *)(tpl + 1);

#212 

#213      *(WORD*)dest = 0; /* no menu */

#214      *(((WORD*)dest) + 1) = 0; /* use default window class */

#215      dest += 2 * sizeof(WORD);

#216      memcpy(dest, caption, caplen * sizeof(WCHAR));

#217      dest += caplen * sizeof(WCHAR);

#218      *(WCHAR*)dest = L'/0';

#219      dest += sizeof(WCHAR);

#220 

 

创建图标。

#221      /* Create icon */

#222      if(Icon)

#223      {

#224        dest = (BYTE*)(((ULONG_PTR)dest + 3) & ~3);

#225        iico = (DLGITEMTEMPLATE *)dest;

#226        iico->style = WS_CHILD | WS_VISIBLE | SS_ICON;

#227        iico->dwExtendedStyle = 0;

#228        iico->id = MSGBOX_IDICON;

#229 

#230        dest += sizeof(DLGITEMTEMPLATE);

#231        *(WORD*)dest = 0xFFFF;

#232        dest += sizeof(WORD);

#233        *(WORD*)dest = 0x0082; /* static control */

#234        dest += sizeof(WORD);

#235        *(WORD*)dest = 0xFFFF;

#236        dest += sizeof(WORD);

#237        *(WCHAR*)dest = 0;

#238        dest += sizeof(WCHAR);

#239        *(WORD*)dest = 0;

#240        dest += sizeof(WORD);

#241      }

#242 

 

创建静态框显示字符串。

#243      /* create static for text */

#244      dest = (BYTE*)(((DWORD)dest + 3) & ~3);

#245      itxt = (DLGITEMTEMPLATE *)dest;

#246      itxt->style = WS_CHILD | WS_VISIBLE | SS_NOPREFIX;

#247      if(lpMsgBoxParams->dwStyle & MB_RIGHT)

#248        itxt->style |= SS_RIGHT;

#249      else

#250        itxt->style |= SS_LEFT;

#251      itxt->dwExtendedStyle = 0;

#252      itxt->id = MSGBOX_IDTEXT;

#253      dest += sizeof(DLGITEMTEMPLATE);

#254      *(WORD*)dest = 0xFFFF;

#255      dest += sizeof(WORD);

#256      *(WORD*)dest = 0x0082; /* static control */

#257      dest += sizeof(WORD);

#258      memcpy(dest, text, textlen * sizeof(WCHAR));

#259      dest += textlen * sizeof(WCHAR);

#260      *(WCHAR*)dest = 0;

#261      dest += sizeof(WCHAR);

#262      *(WORD*)dest = 0;

#263      dest += sizeof(WORD);

#264 

 

创建要显示的按钮。

#265      /* create buttons */

#266      btnsize.cx = BTN_CX;

#267      btnsize.cy = BTN_CY;

#268      btnrect.left = btnrect.top = 0;

#269      for(i = 0; i < nButtons; i++)

#270      {

#271        dest = (BYTE*)(((DWORD)dest + 3) & ~3);

#272        ibtn[i] = (DLGITEMTEMPLATE *)dest;

#273        ibtn[i]->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;

#274        if(!defbtn && (i == ((lpMsgBoxParams->dwStyle & MB_DEFMASK) >> 8)))

#275        {

#276          ibtn[i]->style |= BS_DEFPUSHBUTTON;

#277          mbi.DefBtn = Buttons[i];

#278          defbtn = TRUE;

#279        }

#280        else

#281          ibtn[i]->style |= BS_PUSHBUTTON;

#282        ibtn[i]->dwExtendedStyle = 0;

#283        ibtn[i]->id = Buttons[i];

#284        dest += sizeof(DLGITEMTEMPLATE);

#285        *(WORD*)dest = 0xFFFF;

#286        dest += sizeof(WORD);

#287        *(WORD*)dest = 0x0080; /* button control */

#288        dest += sizeof(WORD);

#289        btnlen = strlenW(ButtonText[i]);

#290        memcpy(dest, ButtonText[i], btnlen * sizeof(WCHAR));

#291        dest += btnlen * sizeof(WCHAR);

#292        *(WORD*)dest = 0;

#293        dest += sizeof(WORD);

#294        *(WORD*)dest = 0;

#295        dest += sizeof(WORD);

#296        SelectObject(hDC, hFont);

 

显示按钮的字符串。

#297        DrawTextW(hDC, ButtonText[i], btnlen, &btnrect, DT_LEFT | DT_SINGLELINE | DT_CALCRECT);

#298        btnsize.cx = max(btnsize.cx, btnrect.right);

#299        btnsize.cy = max(btnsize.cy, btnrect.bottom);

#300      }

#301 

 

如果有按钮,就设置第一个为缺省选中按钮。

#302      /* make first button the default button if no other is */

#303      if(!defbtn)

#304      {

#305        ibtn[0]->style &= ~BS_PUSHBUTTON;

#306        ibtn[0]->style |= BS_DEFPUSHBUTTON;

#307        mbi.DefBtn = Buttons[0];

#308      }

#309 

 

计算位置和窗口显示的大小。

#310      /* calculate position and size of controls */

#311      txtrect.right = GetSystemMetrics(SM_CXSCREEN) / 5 * 4;

#312      if(Icon)

#313        txtrect.right -= GetSystemMetrics(SM_CXICON) + MSGBOXEX_SPACING;

#314      txtrect.top = txtrect.left = txtrect.bottom = 0;

#315      SelectObject(hDC, hFont);

#316      if (textlen != 0)

#317      {

#318        DrawTextW(hDC, text, textlen, &txtrect, DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);

#319      }

#320      else

#321      {

#322        txtrect.right = txtrect.left + 1;

#323        txtrect.bottom = txtrect.top + 1;

#324      }

#325      txtrect.right++;

#326 

 

计算图标显示的位置和大小。

#327      /* calculate position and size of the icon */

#328      rc.left = rc.bottom = rc.right = 0;

#329      btntop = 0;

#330 

#331      if(iico)

#332      {

#333        rc.right = GetSystemMetrics(SM_CXICON);

#334        rc.bottom = GetSystemMetrics(SM_CYICON);

#335        #ifdef MSGBOX_ICONVCENTER

#336        rc.top = MSGBOXEX_MARGIN + (max(txtrect.bottom, rc.bottom) / 2) - (GetSystemMetrics(SM_CYICON) / 2);

#337        rc.top = max(MSGBOXEX_SPACING, rc.top);

#338        #else

#339        rc.top = MSGBOXEX_MARGIN;

#340        #endif

#341        btnleft = (nButtons * (btnsize.cx + MSGBOXEX_BUTTONSPACING)) - MSGBOXEX_BUTTONSPACING;

#342        if(btnleft > txtrect.right + rc.right + MSGBOXEX_SPACING)

#343        {

#344          #ifdef MSGBOX_TEXTHCENTER

#345          lmargin = MSGBOXEX_MARGIN + ((btnleft - txtrect.right - rc.right - MSGBOXEX_SPACING) / 2);

#346          #else

#347          lmargin = MSGBOXEX_MARGIN;

#348          #endif

#349          btnleft = MSGBOXEX_MARGIN;

#350        }

#351        else

#352        {

#353          lmargin = MSGBOXEX_MARGIN;

#354          btnleft = MSGBOXEX_MARGIN + ((txtrect.right + rc.right + MSGBOXEX_SPACING) / 2) - (btnleft / 2);

#355        }

#356        rc.left = lmargin;

#357        iico->x = (rc.left * 4) / LOWORD(units);

#358        iico->y = (rc.top * 8) / HIWORD(units);

#359        iico->cx = (rc.right * 4) / LOWORD(units);

#360        iico->cy = (rc.bottom * 8) / HIWORD(units);

#361        btntop = rc.top + rc.bottom + MSGBOXEX_SPACING;

#362        rc.left += rc.right + MSGBOXEX_SPACING;

#363      }

#364      else

#365      {

#366        btnleft = (nButtons * (btnsize.cx + MSGBOXEX_BUTTONSPACING)) - MSGBOXEX_BUTTONSPACING;

#367        if(btnleft > txtrect.right)

#368        {

#369          #ifdef MSGBOX_TEXTHCENTER

#370          lmargin = MSGBOXEX_MARGIN + ((btnleft - txtrect.right) / 2);

#371          #else

#372          lmargin = MSGBOXEX_MARGIN;

#373          #endif

#374          btnleft = MSGBOXEX_MARGIN;

#375        }

#376        else

#377        {

#378          lmargin = MSGBOXEX_MARGIN;

#379          btnleft = MSGBOXEX_MARGIN + (txtrect.right / 2) - (btnleft / 2);

#380        }

#381        rc.left = lmargin;

#382      }

 

计算按钮显示位置。

#383      /* calculate position of the text */

#384      rc.top = MSGBOXEX_MARGIN + (rc.bottom / 2) - (txtrect.bottom / 2);

#385      rc.top = max(rc.top, MSGBOXEX_MARGIN);

#386      /* calculate position of the buttons */

#387      btntop = max(rc.top + txtrect.bottom + MSGBOXEX_SPACING, btntop);

#388      for(i = 0; i < nButtons; i++)

#389      {

#390        ibtn[i]->x = (btnleft * 4) / LOWORD(units);

#391        ibtn[i]->y = (btntop * 8) / HIWORD(units);

#392        ibtn[i]->cx = (btnsize.cx * 4) / LOWORD(units);

#393        ibtn[i]->cy = (btnsize.cy * 8) / HIWORD(units);

#394        btnleft += btnsize.cx + MSGBOXEX_BUTTONSPACING;

#395      }

 

计算消息窗口的大小和位置。

#396      /* calculate size and position of the messagebox window */

#397      btnleft = max(btnleft - MSGBOXEX_BUTTONSPACING, rc.left + txtrect.right);

#398      btnleft += MSGBOXEX_MARGIN;

#399      btntop +=  btnsize.cy + MSGBOXEX_MARGIN;

#400      /* set size and position of the message static */

#401      itxt->x = (rc.left * 4) / LOWORD(units);

#402      itxt->y = (rc.top * 8) / HIWORD(units);

#403      itxt->cx = (((btnleft - rc.left - MSGBOXEX_MARGIN) * 4) / LOWORD(units));

#404      itxt->cy = ((txtrect.bottom * 8) / HIWORD(units));

#405      /* set size of the window */

#406      tpl->cx = (btnleft * 4) / LOWORD(units);

#407      tpl->cy = (btntop * 8) / HIWORD(units);

#408 

 

填写下面的结构,并调用函数DialogBoxIndirectParamW来显示对话框窗口,MessageBoxProc作为对话框的消息处理函数。

#409      /* finally show the messagebox */

#410      mbi.Icon = Icon;

#411      mbi.Font = hFont;

#412      mbi.ContextHelpId = lpMsgBoxParams->dwContextHelpId;

#413      mbi.Callback = lpMsgBoxParams->lpfnMsgBoxCallback;

#414      mbi.Style = lpMsgBoxParams->dwStyle;

#415      mbi.nButtons = nButtons;

#416      mbi.Btns = &Buttons[0];

#417      mbi.Timeout = Timeout;

#418 

#419      if(hDC)

#420        DeleteDC(hDC);

#421 

#422      ret =  DialogBoxIndirectParamW(lpMsgBoxParams->hInstance, tpl, lpMsgBoxParams->hwndOwner,

#423                                     MessageBoxProc, (LPARAM)&mbi);

#424 

#425      if(hFont)

#426        DeleteObject(hFont);

#427 

#428      RtlFreeHeap(GetProcessHeap(), 0, buf);

#429      return ret;

#430  }

posted @ 2010-01-09 21:00  ajuanabc  阅读(164)  评论(0编辑  收藏  举报