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,MSGBOXEX_MAXBTNSTR - 1); #149 break; #150 case IDYES: #151 LoadStringW(User32Instance,IDS_YES,MSGBOXEX_MAXBTNSTR - 1); #152 break; #153 case IDNO: #154 LoadStringW(User32Instance,IDS_NO,MSGBOXEX_MAXBTNSTR - 1); #155 break; #156 case IDTRYAGAIN: #157 LoadStringW(User32Instance,IDS_TRYAGAIN,MSGBOXEX_MAXBTNSTR - 1); #158 break; #159 case IDCONTINUE: #160 LoadStringW(User32Instance,IDS_CONTINUE,MSGBOXEX_MAXBTNSTR - 1); #161 break; #162 case IDABORT: #163 LoadStringW(User32Instance,IDS_ABORT,MSGBOXEX_MAXBTNSTR - 1); #164 break; #165 case IDRETRY: #166 LoadStringW(User32Instance,IDS_RETRY,MSGBOXEX_MAXBTNSTR - 1); #167 break; #168 case IDIGNORE: #169 LoadStringW(User32Instance,IDS_IGNORE,MSGBOXEX_MAXBTNSTR - 1); #170 break; #171 case IDHELP: #172 LoadStringW(User32Instance,IDS_HELP,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(),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,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,&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,&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(),buf); #429 return ret; #430} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |