Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

dlgbegin.c

Go to the documentation of this file.
00001 /***************************************************************************\ 00002 * 00003 * DLGBEGIN.C - 00004 * 00005 * Copyright (c) 1985 - 1999, Microsoft Corporation 00006 * 00007 * Dialog Initialization Routines 00008 * 00009 * ??-???-???? mikeke Ported from Win 3.0 sources 00010 * 12-Feb-1991 mikeke Added Revalidation code 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 BOOL ValidateCallback(HANDLE h); 00017 00018 CONST WCHAR szEDITCLASS[] = TEXT("Edit"); 00019 00020 /* 00021 * Fixed, hard coded literal for Dialog hacks 00022 */ 00023 const WCHAR gwszShellFont[] = L"MS Shell Dlg"; 00024 const WCHAR gwszShellFont2[] = L"MS Shell Dlg 2"; 00025 00026 00027 #ifdef USE_MIRRORING 00028 #define MIRRORED_HWND(hwnd) (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) 00029 #endif 00030 /***************************************************************************\ 00031 * DefShortToInt 00032 * 00033 * Avoid sign extending 16 bit CW2_USEDEFAULT. We need this because the 00034 * dialog resource template uses SHORT fields to store the coordinates 00035 * but CreateWindow wants INT values. 00036 * 00037 * History: 00038 * 12/04/96 GerardoB Created 00039 \***************************************************************************/ 00040 __inline int DefShortToInt (short s) 00041 { 00042 if (s == (short)CW2_USEDEFAULT) { 00043 return (int)(DWORD)(WORD)CW2_USEDEFAULT; 00044 } else { 00045 return (int)s; 00046 } 00047 } 00048 /***************************************************************************\ 00049 * BYTE FAR *SkipSz(lpsz) 00050 * 00051 * History: 00052 \***************************************************************************/ 00053 00054 PBYTE SkipSz( 00055 UTCHAR *lpsz) 00056 { 00057 if (*lpsz == 0xFF) 00058 return (PBYTE)lpsz + 4; 00059 00060 while (*lpsz++ != 0) ; 00061 00062 return (PBYTE)lpsz; 00063 } 00064 00065 PBYTE WordSkipSz( 00066 UTCHAR *lpsz) 00067 { 00068 PBYTE pb = SkipSz(lpsz); 00069 return NextWordBoundary(pb); 00070 } 00071 00072 PBYTE DWordSkipSz( 00073 UTCHAR *lpsz) 00074 { 00075 PBYTE pb = SkipSz(lpsz); 00076 return NextDWordBoundary(pb); 00077 } 00078 00079 00080 /***************************************************************************\ 00081 * 00082 * IsFontNotGood() 00083 * 00084 * If this is a low res device, we need to check if the 00085 * font we're creating is smaller than the system font. 00086 * 00087 \***************************************************************************/ 00088 __inline BOOLEAN IsFontNotGood(LPWSTR szTempBuffer, LPCWSTR lpStrSubst, TEXTMETRIC* ptm) 00089 { 00090 // 00091 // For FarEast version, we will allow the font smaller than system font. 00092 // 00093 return _wcsicmp(szTempBuffer, lpStrSubst) || 00094 (!IS_ANY_DBCS_CHARSET(ptm->tmCharSet) && 00095 (SYSMET(CXICON) < 32 || SYSMET(CYICON) < 32) && 00096 ptm->tmHeight < gpsi->cySysFontChar); 00097 } 00098 00099 // -------------------------------------------------------------------------- 00100 // GetCharsetEnumProc() 00101 // 00102 // This gets the best asian font for a dialog box. 00103 // 00104 // 1996-Sep-11 hideyukn Port from Win95-FE 00105 // -------------------------------------------------------------------------- 00106 int CALLBACK GetCharsetEnumProc( 00107 LPLOGFONT lpLogFont, 00108 LPTEXTMETRIC lptm, 00109 DWORD nType, 00110 LPARAM lpData) 00111 { 00112 UNREFERENCED_PARAMETER(lptm); 00113 UNREFERENCED_PARAMETER(nType); 00114 00115 // 00116 // Use other than FIXED pitch sysfont when the face name isn't specified. 00117 // 00118 if ((lpLogFont->lfPitchAndFamily & 3) == FIXED_PITCH) 00119 { 00120 if (!lstrcmpi(lpLogFont->lfFaceName,L"System") || 00121 !lstrcmpi(lpLogFont->lfFaceName,L"@System")) 00122 return TRUE; // try to get another system font metric 00123 } 00124 00125 ((LPLOGFONT)lpData)->lfCharSet = lpLogFont->lfCharSet; 00126 ((LPLOGFONT)lpData)->lfPitchAndFamily = lpLogFont->lfPitchAndFamily; 00127 return FALSE; 00128 } 00129 00130 /* 00131 * Get a character set based on System's ANSI CODEPAGE 00132 */ 00133 UINT GetACPCharSet() 00134 { 00135 static UINT charset = (UINT)~0; 00136 CHARSETINFO csInfo; 00137 00138 if (charset != (UINT)~0) { 00139 return charset; 00140 } 00141 00142 // Sundown: In the TCI_SRCCODEPAGE case, the GetACP() return value is zero-extended. 00143 if (!TranslateCharsetInfo((DWORD*)UIntToPtr( GetACP() ), &csInfo, TCI_SRCCODEPAGE)) { 00144 return DEFAULT_CHARSET; 00145 } 00146 charset = csInfo.ciCharset; 00147 UserAssert(charset != (UINT)~0); 00148 return csInfo.ciCharset; 00149 } 00150 00151 #if 0 00152 BYTE GetCharsetFromResourceLang(LCID lcid) 00153 { 00154 CHARSETINFO csInfo; 00155 00156 if (!TranslateCharsetInfo((DWORD *)lcid, &csInfo, TCI_SRCLOCALE)) 00157 return DEFAULT_CHARSET; 00158 return csInfo.ciCharset; 00159 } 00160 #endif 00161 00162 /***************************************************************************\ 00163 * 00164 * CreateDlgFont() 00165 * 00166 * Create the dialog font described at the given location in a resource 00167 * 00168 \***************************************************************************/ 00169 00170 #define GET_DESKTOP_CHARSET() (GetTextCharset(hdcDlg)) 00171 00172 // 00173 // Reserved Dlg resource version number 00174 // 00175 #define DLGRSC_VER_NT5COMPAT_RESERVE 10 00176 00177 BOOL FixupDlgLogFont( 00178 HDC hdcDlg, 00179 LPLOGFONT lpLogFont, 00180 LPDLGTEMPLATE2 lpdt, 00181 BOOLEAN fUseShellFont2, 00182 BOOLEAN* pfWillTryDefaultCharset) 00183 { 00184 switch (lpdt->wDlgVer) { 00185 case 0: 00186 // DIALOG statement, which only has a facename. 00187 // The new applications are not supposed to use DIALOG statement, 00188 // they should use DIALOGEX instead. 00189 lpLogFont->lfWeight = FW_BOLD; 00190 if (!fUseShellFont2) { 00191 lpLogFont->lfCharSet = (BYTE)GET_DESKTOP_CHARSET(); 00192 *pfWillTryDefaultCharset = TRUE; 00193 } 00194 break; 00195 case 1: 00196 // 00197 // Win4 compatible DLG template 00198 // 00199 if (!fUseShellFont2) { 00200 if (IS_DBCS_ENABLED()) { 00201 if (lpLogFont->lfCharSet == ANSI_CHARSET) { 00202 // 00203 // When resource compiler generates dialog resource data 00204 // from DIALOGEX template, it can specify 'charset'. but 00205 // optional, if it is not specified, it will be filled 00206 // with 0 (ANSI charset). But, on localized version, 00207 // User might guess the default will be localized-charset 00208 // 00209 // [Dialog Resource File] 00210 // 00211 // DIALOGEX ... 00212 // ... 00213 // FONT pointsize, typeface, [weight], [italic], [charset] 00214 // 00215 // #100182 00216 // Bogus hack: 00217 // Some FE fonts started to have ANSI_CHARSET so the first attept would succeed. 00218 // We should enumerate the charset from the beginning. 00219 lpLogFont->lfCharSet = DEFAULT_CHARSET; 00220 RIPMSG0(RIP_VERBOSE, "No proper CharSet information in DIALOGEX"); 00221 } 00222 } 00223 /* 00224 * Note: Dialog resource version 2.0 or later has not been supported on 00225 * Windows 95 and 98. As of Apr/98 we decided not to deploy this new feature 00226 * in the standard tools. Still, NT 5 supports this new feature, preparing 00227 * the future transition to do the right thing. 00228 */ 00229 else if (lpLogFont->lfCharSet == ANSI_CHARSET) { 00230 // If the first attempt fail, we'll enumerate the charset for the given facename 00231 *pfWillTryDefaultCharset = TRUE; 00232 } 00233 else if (lpLogFont->lfCharSet == DEFAULT_CHARSET) { 00234 lpLogFont->lfCharSet = (BYTE)GET_DESKTOP_CHARSET(); 00235 } 00236 } 00237 break; 00238 default: 00239 if (lpdt->wDlgVer <= DLGRSC_VER_NT5COMPAT_RESERVE) { 00240 // we do nothing for the new resource compiler (>= 2.0), 00241 // since this version of dialogs are guarunteed to have 00242 // the proper character set for the dialog font. 00243 } 00244 else { 00245 RIPMSG1(RIP_WARNING, "Version %d resource is not supported.", lpdt->wDlgVer); 00246 return FALSE; 00247 } 00248 break; 00249 } 00250 00251 return TRUE; 00252 } 00253 00254 VOID FixupDlgFaceName( 00255 LPLOGFONT lpLogFont, 00256 BOOLEAN fUseShellFont, 00257 BOOLEAN fUseShellFont2, 00258 LPCWSTR lpStrSubst) 00259 { 00260 if (fUseShellFont2) { 00261 // 00262 // OK, we use "MS Shell Dlg 2" as a face name. 00263 // 00264 wcsncpycch(lpLogFont->lfFaceName, gwszShellFont2, ARRAY_SIZE(gwszShellFont2)); 00265 } 00266 else { 00267 // 00268 // Otherwise, get the face name from the dialog template. 00269 // 00270 wcsncpycch(lpLogFont->lfFaceName, lpStrSubst, sizeof(lpLogFont->lfFaceName) / sizeof(WCHAR)); 00271 } 00272 00273 // 00274 // "MS Shell Dlg" and "MS Shell Dlg2" should have native character set --- 00275 // 00276 if (fUseShellFont || fUseShellFont2) { 00277 lpLogFont->lfCharSet = (BYTE)GetACPCharSet(); 00278 } 00279 } 00280 00281 00282 HFONT CreateDlgFont(HDC hdcDlg, LPWORD FAR *lplpstr, LPDLGTEMPLATE2 lpdt, DWORD dwExpWinVer, UINT fSCDLGFlags) 00283 { 00284 LOGFONT LogFont; 00285 int fontheight, fheight; 00286 HFONT hOldFont, hFont; 00287 WCHAR szTempBuffer[LF_FACESIZE]; 00288 LPCWSTR lpStrSubst; 00289 TEXTMETRIC tm; 00290 // Font hacks 00291 BOOLEAN fDeleteFont; 00292 BOOLEAN fWillTryDefaultCharset = FALSE; 00293 BOOLEAN fUseShellFont, fUseShellFont2; 00294 00295 UNREFERENCED_PARAMETER(dwExpWinVer); 00296 UNREFERENCED_PARAMETER(fSCDLGFlags); 00297 00298 fheight = fontheight = (SHORT)(*((WORD *) *lplpstr)++); 00299 00300 if (fontheight == 0x7FFF) { 00301 // a 0x7FFF height is our special code meaning use the message box font 00302 GetObject(gpsi->hMsgFont, sizeof(LOGFONT), &LogFont); 00303 return CreateFontIndirect(&LogFont); 00304 } 00305 00306 // 00307 // The dialog template contains a font description! Use it. 00308 // 00309 00310 // Fill the LogFont with default values 00311 RtlZeroMemory(&LogFont, sizeof(LOGFONT)); 00312 00313 fontheight = -MultDiv(fontheight, gpsi->dmLogPixels, 72); 00314 LogFont.lfHeight = fontheight; 00315 00316 if (lpdt->wDlgVer) { 00317 // 00318 // If it's DIALOGEX, additional info should be read from 00319 // the template. 00320 // 00321 LogFont.lfWeight = *((WORD FAR *) *lplpstr)++; 00322 LogFont.lfItalic = *((BYTE FAR *) *lplpstr)++; 00323 LogFont.lfCharSet = *((BYTE FAR *) *lplpstr)++; 00324 } 00325 00326 // 00327 // Per shell team request, the dialog who has DS_SETFONT 00328 // *and* DS_FIXEDSYS (=> DS_SHELLFONT2) should have a font 00329 // "MS Shell Dlg 2". 00330 // 00331 lpStrSubst = *lplpstr; 00332 00333 // 00334 // Set the pointer to the next item. 00335 // 00336 *lplpstr = (WORD*)DWordSkipSz(*lplpstr); 00337 00338 fUseShellFont = _wcsicmp(lpStrSubst, gwszShellFont) == 0; 00339 00340 // 00341 // Later shell team request again, to use "Dlg 2" font only 00342 // when facename in the dialog template is "MS Shell Dlg". 00343 // 00344 fUseShellFont2 = fUseShellFont && 00345 (lpdt->style & DS_SHELLFONT) == DS_SHELLFONT && Is400Compat(dwExpWinVer) && lpdt->wDlgVer != 0; 00346 00347 if (fUseShellFont2) { 00348 TAGMSG0(DBGTAG_IMM, "CreateDlgFont: fUseShellFont2=TRUE"); 00349 } 00350 00351 // 00352 // Prepare the font character set. 00353 // 00354 if (!FixupDlgLogFont(hdcDlg, &LogFont, lpdt, fUseShellFont2, &fWillTryDefaultCharset)) { 00355 return NULL; 00356 } 00357 00358 // 00359 // Prepare the font facename. 00360 // 00361 FixupDlgFaceName(&LogFont, fUseShellFont, fUseShellFont2, lpStrSubst); 00362 00363 if (lpdt->wDlgVer < 2 && lpdt->style & DS_3DLOOK) 00364 LogFont.lfWeight = FW_NORMAL; 00365 00366 TryDefaultCharset: 00367 if (LogFont.lfCharSet == DEFAULT_CHARSET) { 00368 // 00369 // Get character set for given facename. 00370 // 00371 EnumFonts(hdcDlg, LogFont.lfFaceName, 00372 (FONTENUMPROC)GetCharsetEnumProc, (LPARAM)(&LogFont)); 00373 // 00374 // We already tried default charset. 00375 // 00376 fWillTryDefaultCharset = FALSE; 00377 } 00378 00379 // 00380 // [Windows 3.1 FarEast version did this...] 00381 // 00382 // Use FW_NORMAL as default for DIALOG template. For DIALOGEX 00383 // template, we need to respect the value in the template. 00384 // 00385 if ((!(lpdt->wDlgVer)) && // not DIALOGEX template ? 00386 (IS_ANY_DBCS_CHARSET(LogFont.lfCharSet)) && // any FarEast font ? 00387 (LogFont.lfWeight != FW_NORMAL)) { // already FW_NORMAL ? 00388 00389 // 00390 // Set weight to FW_NORMAL. 00391 // 00392 LogFont.lfWeight = FW_NORMAL; 00393 } 00394 00395 if (!(hFont = CreateFontIndirect((LPLOGFONT) &LogFont))) 00396 return(NULL); 00397 00398 fDeleteFont = FALSE; 00399 00400 if ((hOldFont = SelectFont(hdcDlg, hFont)) == NULL) { 00401 fDeleteFont = TRUE; 00402 } 00403 else { 00404 // 00405 // If this dialog has DS_SHELLFONT style, or the font is 00406 // "MS Shell Dlg", we don't judge the font integrity, 00407 // for they have been given the ACP based character set. 00408 // 00409 if (!fUseShellFont) { 00410 if (!GetTextMetrics(hdcDlg, &tm)) { 00411 RIPMSG0(RIP_WARNING, "CreateDlgFont: GetTextMetrics failed"); 00412 fDeleteFont = TRUE; 00413 } 00414 else { 00415 GetTextFaceAliasW(hdcDlg, sizeof(szTempBuffer)/sizeof(WCHAR), szTempBuffer); 00416 00417 // 00418 // If this is a low res device, we need to check if the 00419 // font we're creating is smaller than the system font. 00420 // If so, just use the system font. 00421 // 00422 if (IsFontNotGood(szTempBuffer, lpStrSubst, &tm)) { 00423 // 00424 // Couldn't find a font with the height or facename 00425 // the app wanted so use the system font instead. Note 00426 // that we need to make sure the app knows it is 00427 // getting the system font via the WM_SETFONT message 00428 // so we still need to act as if a new font is being 00429 // sent to the dialog box. 00430 // 00431 fDeleteFont = TRUE; 00432 } 00433 } 00434 } 00435 00436 UserAssert(hOldFont != NULL); 00437 SelectFont(hdcDlg, hOldFont); 00438 } 00439 00440 if (fDeleteFont) { 00441 DeleteFont(hFont); 00442 // 00443 // Font is deleted, Prepare for reTry... 00444 // 00445 hFont = NULL; 00446 } 00447 00448 // Font hack: 00449 // 00450 // 1. We fail to create font. 00451 // 2. We did *NOT* try to enumerate charset, yet. 00452 // 3. We want to try to enumerate charset 00453 // 00454 // if all of answer is 'Yes', we will try... 00455 // 00456 if (hFont == NULL && fWillTryDefaultCharset) { 00457 // 00458 // Try DEFAULT_CHARSET. 00459 // 00460 LogFont.lfCharSet = DEFAULT_CHARSET; 00461 goto TryDefaultCharset; 00462 } 00463 00464 return hFont; 00465 } 00466 00467 #undef GET_DESKTOP_CHARSET 00468 00469 #define CD_VISIBLE 0x01 00470 #define CD_GLOBALEDIT 0x02 00471 #define CD_USERFONT 0x04 00472 #define CD_SETFOREGROUND 0x08 00473 #define CD_USEDEFAULTX 0x10 00474 #define CD_USEDEFAULTCX 0x20 00475 00476 00477 /***************************************************************************\ 00478 * GetDialogMonitor 00479 * 00480 * Gets the monitor a dialog should be created on. 00481 * 00482 * Params: 00483 * hwndOwner - the owner of the dialog. May be NULL. 00484 * 00485 * History: 00486 * 10-Oct-1996 adams Created. 00487 \***************************************************************************/ 00488 00489 PMONITOR 00490 GetDialogMonitor(HWND hwndOwner, DWORD dwFlags) 00491 { 00492 PMONITOR pMonitor; 00493 PWND pwnd; 00494 HWND hwndForeground; 00495 DWORD pid; 00496 00497 UserAssert(dwFlags == MONITOR_DEFAULTTONULL || 00498 dwFlags == MONITOR_DEFAULTTOPRIMARY); 00499 00500 pMonitor = NULL; 00501 if (hwndOwner) { 00502 pwnd = ValidateHwnd(hwndOwner); 00503 if (pwnd && GETFNID(pwnd) != FNID_DESKTOP) { 00504 pMonitor = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY); 00505 } 00506 } else { 00507 /* 00508 * HACK! They passed in no owner and are creating a top level 00509 * dialog window. Does this process own the foreground window? 00510 * If so, pin to that window's monitor. That way 16-bit apps 00511 * will work mostly as expected, and old multithreaded dudes just 00512 * might too. Especially the shell, for whom many system UI pieces 00513 * pop up random dialogs inside of API calls. 00514 */ 00515 00516 hwndForeground = NtUserGetForegroundWindow(); 00517 if (hwndForeground) { 00518 GetWindowThreadProcessId(hwndForeground, &pid); 00519 if (pid == HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess)) { 00520 pwnd = ValidateHwnd(hwndForeground); 00521 if (pwnd) { 00522 pMonitor = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY); 00523 } 00524 } 00525 } 00526 } 00527 00528 if (!pMonitor && dwFlags == MONITOR_DEFAULTTOPRIMARY) { 00529 pMonitor = GetPrimaryMonitor(); 00530 } 00531 00532 return pMonitor; 00533 } 00534 00535 00536 00537 /***************************************************************************\ 00538 * InternalCreateDialog 00539 * 00540 * Creates a dialog from a template. Uses passed in menu if there is one, 00541 * destroys menu if creation failed. Server portion of 00542 * CreateDialogIndirectParam. 00543 * 00544 * WARNING: This function cannot create any windows before creating the dialog 00545 * window. Otherwise, MFC apps will break because their hook assumes 00546 * the dialog is the first window to be created. 00547 * 00548 * History: 00549 * 04-10-91 ScottLu 00550 * 04-17-91 Mikehar Win31 Merge 00551 \***************************************************************************/ 00552 00553 HWND InternalCreateDialog( 00554 HANDLE hmod, 00555 LPDLGTEMPLATE lpdt, 00556 DWORD cb, 00557 HWND hwndOwner, 00558 DLGPROC lpfnDialog, 00559 LPARAM lParam, 00560 UINT fSCDLGFlags) 00561 { 00562 HWND hwnd; 00563 HWND hwnd2; 00564 PWND pwnd; 00565 HWND hwndNewFocus; 00566 HWND hwndEditFirst = NULL; 00567 RECT rc; 00568 WORD w; 00569 UTCHAR *lpszMenu, 00570 *lpszClass, 00571 *lpszText, 00572 *lpCreateParams, 00573 *lpStr; 00574 int cxChar, 00575 cyChar; 00576 BOOL f40Compat; 00577 HFONT hNewFont = NULL; 00578 HFONT hOldFont; 00579 LPDLGITEMTEMPLATE lpdit; 00580 HMENU hMenu; 00581 BOOL fSuccess; 00582 BOOL fWowWindow; 00583 HANDLE hmodCreate; 00584 LPBYTE lpCreateParamsData; 00585 DLGTEMPLATE2 dt; 00586 DLGITEMTEMPLATE2 dit; 00587 DWORD dwExpWinVer; 00588 DWORD dsStyleOld; 00589 DWORD bFlags = 0; 00590 HDC hdcDlg; 00591 LARGE_STRING strClassName; 00592 PLARGE_STRING pstrClassName; 00593 LARGE_STRING strWindowName; 00594 PMONITOR pMonitor; 00595 00596 UNREFERENCED_PARAMETER(cb); 00597 00598 ConnectIfNecessary(); 00599 00600 UserAssert(!(fSCDLGFlags & ~(SCDLG_CLIENT|SCDLG_ANSI|SCDLG_NOREVALIDATE|SCDLG_16BIT))); // These are the only valid flags 00601 00602 /* 00603 * Is this a Win4 extended dialog? 00604 */ 00605 if (((LPDLGTEMPLATE2)lpdt)->wSignature == 0xffff) { 00606 00607 UserAssert(((LPDLGTEMPLATE2)lpdt)->wDlgVer <= DLGRSC_VER_NT5COMPAT_RESERVE); 00608 RtlCopyMemory(&dt, lpdt, sizeof dt); 00609 } else { 00610 dt.wDlgVer = 0; 00611 dt.wSignature = 0; 00612 dt.dwHelpID = 0; 00613 dt.dwExStyle = lpdt->dwExtendedStyle; 00614 dt.style = lpdt->style; 00615 dt.cDlgItems = lpdt->cdit; 00616 dt.x = lpdt->x; 00617 dt.y = lpdt->y; 00618 dt.cx = lpdt->cx; 00619 dt.cy = lpdt->cy; 00620 } 00621 00622 /* 00623 * If this is called from wow code, then the loword of hmod != 0. 00624 * In this case, allow any DS_ style bits that were passed in win3.1 00625 * to be legal in win32. Case in point: 16 bit quark xpress passes the 00626 * same bit as the win32 style DS_SETFOREGROUND. Also, VC++ sample 00627 * "scribble" does the same thing. 00628 * 00629 * For win32 apps test the DS_SETFOREGROUND bit; wow apps are not set 00630 * foreground (this is the new NT semantics) 00631 * We have to let no "valid" bits through because apps depend on them 00632 * bug 5232. 00633 */ 00634 dsStyleOld = LOWORD(dt.style); 00635 00636 /* 00637 * If the app is Win4 or greater, require correct dialog style bits. 00638 * Prevents conflicts with new bits introduced in Chicago 00639 */ 00640 dwExpWinVer = GETEXPWINVER(hmod); 00641 00642 if ( f40Compat = Is400Compat(dwExpWinVer) ) { 00643 dt.style &= (DS_VALID40 | 0xffff0000); 00644 00645 // 00646 // For old applications: 00647 // If DS_COMMONDIALOG isn't set, don't touch DS_3DLOOK style 00648 // bit. If it's there, it stays there. If not, not. That way old 00649 // apps which pass in their own templates, not commdlg's, don't get 00650 // forced 3D. 00651 // If DS_COMMONDIALOG is there, remove DS_3DLOOK. 00652 // 00653 // For new applications: 00654 // Force 3D always. 00655 // 00656 if (GETAPPVER() < VER40) { 00657 if (dt.style & DS_COMMONDIALOG) { 00658 dt.style &= ~DS_3DLOOK; 00659 dsStyleOld &= ~DS_3DLOOK; 00660 } 00661 } else { 00662 dt.style |= DS_3DLOOK; 00663 dsStyleOld |= DS_3DLOOK; 00664 } 00665 } else { 00666 #if DBG 00667 if (dt.style != (dt.style & (DS_VALID31 | DS_3DLOOK | 0xffff0000))) { 00668 RIPMSG1(RIP_WARNING, "CreateDialog: stripping invalid bits %lX", dt.style); 00669 } 00670 #endif // DBG 00671 00672 00673 /* 00674 * Don't strip off bits for old apps, they depend on this. Especially 16 bit MFC apps! 00675 * 00676 * dt.dwStyle &= (DS_VALID31 | 0xffff0000); 00677 */ 00678 } 00679 00680 if (LOWORD((ULONG_PTR)hmod) == 0) { 00681 if (dt.style & DS_SETFOREGROUND) 00682 bFlags |= CD_SETFOREGROUND; 00683 } 00684 00685 if (dsStyleOld != LOWORD(dt.style)) 00686 { 00687 00688 RIPMSG1(f40Compat ? RIP_ERROR : RIP_WARNING, 00689 "Bad dialog style bits (%x) - please remove.", 00690 LOWORD(dt.style)); 00691 // Fail new apps that pass in bogus bits! 00692 00693 if (f40Compat) { 00694 return NULL; 00695 } 00696 } 00697 00698 if ( dt.style & DS_MODALFRAME) { 00699 dt.dwExStyle |= WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE; 00700 } 00701 00702 if (( dt.style & DS_CONTEXTHELP) && f40Compat) { 00703 dt.dwExStyle |= WS_EX_CONTEXTHELP; 00704 } 00705 00706 if (dt.style & DS_CONTROL) { 00707 // Captions and system menus aren't allowed on "control" dialogs. 00708 // And strip DS_SYSMODAL. 00709 dt.style &= ~(WS_CAPTION | WS_SYSMENU | DS_SYSMODAL); 00710 } else if (dt.style & WS_DLGFRAME) { 00711 // Add on window edge same way that CreateWindowEx() will 00712 dt.dwExStyle |= WS_EX_WINDOWEDGE; 00713 } 00714 00715 if (dt.style & DS_SYSMODAL) { 00716 dt.dwExStyle |= WS_EX_TOPMOST; 00717 } 00718 00719 if (!(dt.style & WS_CHILD) || (dt.style & DS_CONTROL)) { 00720 // only a control parent if it's not a child dialog or if it's 00721 // explicitly marked as a recursive dialog 00722 dt.dwExStyle |= WS_EX_CONTROLPARENT; 00723 } 00724 00725 if (dt.x == (short)CW2_USEDEFAULT) { 00726 bFlags |= CD_USEDEFAULTX; 00727 dt.x = 0; 00728 } 00729 00730 if (dt.cx == (short)CW2_USEDEFAULT) { 00731 bFlags |= CD_USEDEFAULTCX; 00732 dt.cx = 0; 00733 } else if (dt.cx < 0) { 00734 dt.cx = 0; 00735 } 00736 00737 if (dt.cy < 0) { 00738 dt.cy = 0; 00739 } 00740 00741 00742 // If there's a menu name string, load it. 00743 lpszMenu = (LPWSTR)(((PBYTE)(lpdt)) + (dt.wDlgVer ? sizeof(DLGTEMPLATE2):sizeof(DLGTEMPLATE))); 00744 00745 /* 00746 * If the menu id is expressed as an ordinal and not a string, 00747 * skip all 4 bytes to get to the class string. 00748 */ 00749 w = *(LPWORD)lpszMenu; 00750 00751 /* 00752 * If there's a menu name string, load it. 00753 */ 00754 if (w != 0) { 00755 if ((hMenu = LoadMenu(hmod, (w == 0xFFFF) ? 00756 MAKEINTRESOURCE(*(WORD *)((PBYTE)lpszMenu + 2)) : lpszMenu)) == NULL) { 00757 RIPMSG0(RIP_WARNING, "ServerCreateDialog() failed: couldn't load menu"); 00758 goto DeleteFontAndMenuAndFail; 00759 } 00760 } else { 00761 hMenu = NULL; 00762 } 00763 00764 if (w == 0xFFFF) { 00765 lpszClass = (LPWSTR)((LPBYTE)lpszMenu + 4); 00766 } else { 00767 lpszClass = (UTCHAR *)WordSkipSz(lpszMenu); 00768 } 00769 00770 lpszText = (UTCHAR *)WordSkipSz(lpszClass); 00771 00772 lpStr = (UTCHAR *)WordSkipSz(lpszText); 00773 00774 hdcDlg = CreateCompatibleDC(NULL); 00775 if (hdcDlg == NULL) 00776 goto DeleteFontAndMenuAndFail; 00777 00778 if (dt.style & DS_SETFONT) { 00779 hNewFont = CreateDlgFont(hdcDlg, &lpStr, &dt, dwExpWinVer, fSCDLGFlags); 00780 bFlags |= CD_USERFONT; 00781 lpdit = (LPDLGITEMTEMPLATE) NextDWordBoundary(lpStr); 00782 } else if (Is400Compat(dwExpWinVer) && (dt.style & DS_FIXEDSYS)) { 00783 00784 // 00785 // B#2078 -- WISH for fixed width system font in dialog. We need 00786 // to tell the dialog that it's using a font different from the 00787 // standard system font, so set CD_USERFONT bit. 00788 // 00789 // We need the 400 compat. check for CorelDraw, since they use 00790 // this style bit for their own purposes. 00791 // 00792 hNewFont = GetStockObject(SYSTEM_FIXED_FONT); 00793 bFlags |= CD_USERFONT; 00794 lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(lpStr); 00795 } else { 00796 lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(lpStr); 00797 } 00798 00799 /* 00800 * If the application requested a particular font and for some 00801 * reason we couldn't find it, we just use the system font. BUT we 00802 * need to make sure we tell him he gets the system font. Dialogs 00803 * which never request a particular font get the system font and we 00804 * don't bother telling them this (via the WM_SETFONT message). 00805 */ 00806 00807 // Is it anything other than the default system font? If we can't get 00808 // enough memory to select in the new font specified, just use the system 00809 // font. 00810 if (hNewFont && (hOldFont = SelectFont(hdcDlg, hNewFont))) { 00811 // Get the ave character width and height to be used 00812 cxChar = GdiGetCharDimensions(hdcDlg, NULL, &cyChar); 00813 00814 SelectFont(hdcDlg, hOldFont); 00815 if (cxChar == 0) { 00816 RIPMSG0(RIP_WARNING, "InternalCreateDialog: GdiGetCharDimensions failed"); 00817 goto UseSysFontMetrics; 00818 } 00819 } 00820 else 00821 { 00822 if (hNewFont || (bFlags & CD_USERFONT)) 00823 hNewFont = ghFontSys; 00824 00825 UseSysFontMetrics: 00826 cxChar = gpsi->cxSysFontChar; 00827 cyChar = gpsi->cySysFontChar; 00828 } 00829 DeleteDC(hdcDlg); 00830 00831 if (dt.style & WS_VISIBLE) { 00832 bFlags |= CD_VISIBLE; 00833 dt.style &= ~WS_VISIBLE; 00834 } 00835 00836 if (!(dt.style & DS_LOCALEDIT)) { 00837 bFlags |= CD_GLOBALEDIT; 00838 } 00839 00840 /* Figure out dimensions of real window 00841 */ 00842 rc.left = rc.top = 0; 00843 rc.right = XPixFromXDU(dt.cx, cxChar); 00844 rc.bottom = YPixFromYDU(dt.cy, cyChar); 00845 00846 _AdjustWindowRectEx(&rc, dt.style, w, dt.dwExStyle); 00847 00848 dt.cx = (SHORT)(rc.right - rc.left); 00849 dt.cy = (SHORT)(rc.bottom - rc.top); 00850 00851 if ((dt.style & DS_CENTERMOUSE) && SYSMET(MOUSEPRESENT) && f40Compat) { 00852 pMonitor = _MonitorFromPoint(gpsi->ptCursor, MONITOR_DEFAULTTONULL); 00853 UserAssert(pMonitor); 00854 *((LPPOINT)&rc.left) = gpsi->ptCursor; 00855 rc.left -= (dt.cx / 2); 00856 rc.top -= (dt.cy / 2); 00857 } else { 00858 BOOL fNoDialogMonitor; 00859 00860 pMonitor = GetDialogMonitor(hwndOwner, MONITOR_DEFAULTTONULL); 00861 fNoDialogMonitor = pMonitor ? FALSE : TRUE; 00862 if (!pMonitor) { 00863 pMonitor = GetPrimaryMonitor(); 00864 } 00865 00866 if ((dt.style & (DS_CENTER | DS_CENTERMOUSE)) && f40Compat) { 00867 /* 00868 * Center to the work area of the owner monitor. 00869 */ 00870 rc.left = (pMonitor->rcWork.left + pMonitor->rcWork.right - dt.cx) / 2; 00871 rc.top = (pMonitor->rcWork.top + pMonitor->rcWork.bottom - dt.cy) / 2; 00872 } else { 00873 rc.left = XPixFromXDU(dt.x, cxChar); 00874 rc.top = YPixFromYDU(dt.y, cyChar); 00875 00876 if (!(dt.style & DS_ABSALIGN) && hwndOwner) { 00877 /* 00878 * Offset relative coordinates to the owner window. If it is 00879 * a child window, there is nothing to do. 00880 */ 00881 if ((HIWORD(dt.style) & MaskWF(WFTYPEMASK)) != MaskWF(WFCHILD)) { 00882 //This is will considre rc.left form the right hand side of the owner window if it a mirrored one. 00883 ClientToScreen(hwndOwner, (LPPOINT)&rc.left); 00884 00885 #ifdef USE_MIRRORING 00886 //It is not chiled then do Visual ClientToScreen 00887 //i.e. rc.left it is form the left hand side of the owner window 00888 if (MIRRORED_HWND(hwndOwner)) { 00889 rc.left -= dt.cx; 00890 } 00891 #endif 00892 00893 } 00894 } else { 00895 /* 00896 * Position the dialog in screen coordinates. If the dialog's 00897 * owner is on a different monitor than specified in the 00898 * template, move the dialog to the owner window. If the owner 00899 * doesn't exist, then use the monitor from the dialog's 00900 * template. 00901 */ 00902 00903 PMONITOR pMonitorTemplate; 00904 RECT rcTemplate; 00905 00906 rcTemplate.left = rc.left; 00907 rcTemplate.top = rc.top; 00908 rcTemplate.right = rc.left + dt.cx; 00909 rcTemplate.bottom = rc.top + dt.cy; 00910 00911 pMonitorTemplate = _MonitorFromRect(&rcTemplate, MONITOR_DEFAULTTOPRIMARY); 00912 if (fNoDialogMonitor) { 00913 pMonitor = pMonitorTemplate; 00914 } else if (pMonitorTemplate != pMonitor) { 00915 rc.left += pMonitor->rcMonitor.left - pMonitorTemplate->rcMonitor.left; 00916 rc.top += pMonitor->rcMonitor.top - pMonitorTemplate->rcMonitor.top; 00917 } 00918 } 00919 } 00920 } 00921 00922 rc.right = rc.left + dt.cx; 00923 rc.bottom = rc.top + dt.cy; 00924 00925 // If the right or bottom coordinate has overflowed, then pin it back to 00926 // a valid rectangle. Likely to happen if a minimized window is the owner of 00927 // the dialog. 00928 if (rc.left > rc.right || rc.top > rc.bottom) { 00929 OffsetRect(&rc, -dt.cx, -dt.cy); 00930 } 00931 00932 // 00933 // Need to do this for ALL dialogs, not just top-level, since we used 00934 // to in 3.1. 00935 // 00936 00937 // Clip top level dialogs within working area 00938 // Start child dialogs at least at (0, 0) 00939 RepositionRect(pMonitor, &rc, dt.style, dt.dwExStyle); 00940 00941 dt.x = (SHORT)((bFlags & CD_USEDEFAULTX) ? CW2_USEDEFAULT : rc.left); 00942 dt.y = (SHORT)(rc.top); 00943 dt.cx = (SHORT)((bFlags & CD_USEDEFAULTCX) ? CW2_USEDEFAULT : rc.right - rc.left); 00944 dt.cy = (SHORT)(rc.bottom - rc.top); 00945 00946 if (*lpszClass != 0) { 00947 if (IS_PTR(lpszClass)) { 00948 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strClassName, 00949 lpszClass, (UINT)-1); 00950 pstrClassName = &strClassName; 00951 } else { 00952 pstrClassName = (PLARGE_STRING)lpszClass; 00953 } 00954 } else { 00955 pstrClassName = (PLARGE_STRING)DIALOGCLASS; 00956 } 00957 00958 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strWindowName, 00959 lpszText, (UINT)-1); 00960 00961 UserAssert((dt.dwExStyle & WS_EX_MDICHILD) == 0); 00962 hwnd = NtUserCreateWindowEx( 00963 dt.dwExStyle | ((fSCDLGFlags & SCDLG_ANSI) ? WS_EX_ANSICREATOR : 0), 00964 pstrClassName, 00965 &strWindowName, 00966 dt.style, 00967 DefShortToInt(dt.x), 00968 dt.y, 00969 DefShortToInt(dt.cx), 00970 dt.cy, 00971 hwndOwner, 00972 hMenu, 00973 hmod, 00974 (LPVOID)NULL, 00975 dwExpWinVer); 00976 00977 if (hwnd == NULL) { 00978 RIPMSG0(RIP_WARNING, "CreateDialog() failed: couldn't create window"); 00979 DeleteFontAndMenuAndFail: 00980 if (hMenu != NULL) 00981 NtUserDestroyMenu(hMenu); 00982 /* 00983 * Only delete the font if we didn't grab it 00984 * from the dialog font cache. 00985 */ 00986 if ((hNewFont != NULL)) { 00987 DeleteObject(hNewFont); 00988 } 00989 return NULL; 00990 } 00991 00992 pwnd = ValidateHwnd(hwnd); 00993 00994 // tell WOW the hDlg of the Window just created BEFORE they get any messages 00995 // at WOW32!w32win16wndprocex 00996 if(fSCDLGFlags & SCDLG_16BIT) { 00997 TellWOWThehDlg(hwnd); 00998 } 00999 01000 /* 01001 * Before anything happens with this window, we need to mark it as a 01002 * dialog window!!!! So do that. 01003 */ 01004 if (pwnd == NULL || !ValidateDialogPwnd(pwnd)) 01005 goto DeleteFontAndMenuAndFail; 01006 01007 if (dt.dwHelpID) { 01008 NtUserSetWindowContextHelpId(hwnd, dt.dwHelpID); 01009 } 01010 01011 /* 01012 * Set up the system menu on this dialog box if it has one. 01013 */ 01014 if (TestWF(pwnd, WFSYSMENU)) { 01015 01016 /* 01017 * For a modal dialog box with a frame and caption, we want to 01018 * delete the unselectable items from the system menu. 01019 */ 01020 UserAssert(HIBYTE(WFSIZEBOX) == HIBYTE(WFMINBOX)); 01021 UserAssert(HIBYTE(WFMINBOX) == HIBYTE(WFMAXBOX)); 01022 if (!TestWF(pwnd, WFSIZEBOX | WFMINBOX | WFMAXBOX)) { 01023 01024 NtUserCallHwndLock(hwnd, SFI_XXXSETDIALOGSYSTEMMENU); 01025 } else { 01026 01027 /* 01028 * We have to give this dialog its own copy of the system menu 01029 * in case it modifies the menu. 01030 */ 01031 NtUserGetSystemMenu(hwnd, FALSE); 01032 } 01033 } 01034 01035 /* 01036 * Set fDisabled to FALSE so EndDialog will Enable if dialog is ended 01037 * before returning to DialogBox (or if modeless). 01038 */ 01039 PDLG(pwnd)->fDisabled = FALSE; 01040 01041 PDLG(pwnd)->cxChar = cxChar; 01042 PDLG(pwnd)->cyChar = cyChar; 01043 PDLG(pwnd)->lpfnDlg = lpfnDialog; 01044 PDLG(pwnd)->fEnd = FALSE; 01045 PDLG(pwnd)->result = IDOK; 01046 01047 /* 01048 * Need to remember Unicode status. 01049 */ 01050 if (fSCDLGFlags & SCDLG_ANSI) { 01051 PDLG(pwnd)->flags |= DLGF_ANSI; 01052 } 01053 01054 /* 01055 * Have to do a callback here for WOW apps. WOW needs what's in lParam 01056 * before the dialog gets any messages. 01057 */ 01058 01059 /* 01060 * If the app is a Wow app then the Lo Word of the hInstance is the 01061 * 16-bit hInstance. Set the lParam, which no-one should look at 01062 * but the app, to the 16 bit value 01063 */ 01064 if (LOWORD((ULONG_PTR)hmod) != 0) { 01065 fWowWindow = TRUE; 01066 } else { 01067 fWowWindow = FALSE; 01068 } 01069 01070 /* 01071 * If a user defined font is used, save the handle so that we can delete 01072 * it when the dialog is destroyed. 01073 */ 01074 if (bFlags & CD_USERFONT) { 01075 01076 PDLG(pwnd)->hUserFont = hNewFont; 01077 01078 if (lpfnDialog != NULL) { 01079 /* 01080 * Tell the dialog that it will be using this font... 01081 */ 01082 SendMessageWorker(pwnd, WM_SETFONT, (WPARAM)hNewFont, 0L, FALSE); 01083 } 01084 } 01085 01086 if (!dt.wDlgVer) { 01087 dit.dwHelpID = 0; 01088 } 01089 01090 /* 01091 * Loop through the dialog controls, doing a CreateWindowEx() for each of 01092 * them. 01093 */ 01094 while (dt.cDlgItems-- != 0) { 01095 DWORD dwExpWinVer2; 01096 01097 if (dt.wDlgVer) { 01098 RtlCopyMemory(&dit, lpdit, sizeof dit); 01099 } else { 01100 dit.dwHelpID = 0; 01101 dit.dwExStyle = lpdit->dwExtendedStyle; 01102 dit.style = lpdit->style; 01103 dit.x = lpdit->x; 01104 dit.y = lpdit->y; 01105 dit.cx = lpdit->cx; 01106 dit.cy = lpdit->cy; 01107 dit.dwID = lpdit->id; 01108 } 01109 01110 dit.x = XPixFromXDU(dit.x, cxChar); 01111 dit.y = YPixFromYDU(dit.y, cyChar); 01112 dit.cx = XPixFromXDU(dit.cx, cxChar); 01113 dit.cy = YPixFromYDU(dit.cy, cyChar); 01114 01115 lpszClass = (LPWSTR)(((PBYTE)(lpdit)) + (dt.wDlgVer ? sizeof(DLGITEMTEMPLATE2):sizeof(DLGITEMTEMPLATE))); 01116 01117 /* 01118 * If the first WORD is 0xFFFF the second word is the encoded class name index. 01119 * Use it to look up the class name string. 01120 */ 01121 if (*(LPWORD)lpszClass == 0xFFFF) { 01122 lpszText = lpszClass + 2; 01123 lpszClass = (LPWSTR)(gpsi->atomSysClass[*(((LPWORD)lpszClass)+1) & ~CODEBIT]); 01124 } else { 01125 lpszText = (UTCHAR *)SkipSz(lpszClass); 01126 } 01127 lpszText = (UTCHAR *)NextWordBoundary(lpszText); // UINT align lpszText 01128 01129 dit.dwExStyle |= WS_EX_NOPARENTNOTIFY; 01130 01131 // 01132 // Replace flat borders with 3D ones for DS_3DLOOK dialogs 01133 // We test the WINDOW style, not the template style now. This is so 01134 // that 4.0 apps--who get 3D stuff automatically--can turn it off on 01135 // create if they want. 01136 // 01137 01138 // 01139 // HACK! 01140 // Treat DS_3DLOOK combos like they have a WS_EX_CLIENTEDGE. Why 01141 // should we have to draw the borders of a combobox ourselves? 01142 // We can't do the same thing for WS_BORDER though becaues of 01143 // PC Fools--they use the presence of WS_BORDER to distinguish 01144 // between lists and combos. 01145 // 01146 01147 if (TestWF(pwnd, DF3DLOOK)) { 01148 if ( (dit.style & WS_BORDER) || 01149 (lpszClass == MAKEINTRESOURCE(gpsi->atomSysClass[ICLS_COMBOBOX]))) { 01150 01151 dit.style &= ~WS_BORDER; 01152 dit.dwExStyle |= WS_EX_CLIENTEDGE; 01153 } 01154 } 01155 01156 /* 01157 * Get pointer to additional data. lpszText can point to an encoded 01158 * ordinal number for some controls (e.g. static icon control) so 01159 * we check for that here. 01160 */ 01161 if (*(LPWORD)lpszText == 0xFFFF) { 01162 lpCreateParams = (LPWSTR)((PBYTE)lpszText + 4); 01163 strWindowName.Buffer = lpszText; 01164 strWindowName.Length = 4; 01165 strWindowName.MaximumLength = 4; 01166 strWindowName.bAnsi = FALSE; 01167 } else { 01168 lpCreateParams = (LPWSTR)((PBYTE)WordSkipSz(lpszText)); 01169 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strWindowName, 01170 lpszText, (UINT)-1); 01171 } 01172 01173 /* 01174 * If control is edit control and caller wants global storage 01175 * of edit text, allocate object in WOW and pass instance 01176 * handle to CreateWindowEx(). 01177 */ 01178 if (fWowWindow && (bFlags & CD_GLOBALEDIT) && 01179 ((!IS_PTR(lpszClass) && 01180 PTR_TO_ID(lpszClass) == (ATOM)(gpsi->atomSysClass[ICLS_EDIT])) || 01181 (IS_PTR(lpszClass) && 01182 (wcscmp(lpszClass, szEDITCLASS) == 0)))) { 01183 01184 /* 01185 * Allocate only one global object (first time we see editctl.) 01186 */ 01187 if (!(PDLG(pwnd)->hData)) { 01188 PDLG(pwnd)->hData = GetEditDS(); 01189 if (!(PDLG(pwnd)->hData)) 01190 goto NoCreate; 01191 } 01192 01193 hmodCreate = PDLG(pwnd)->hData; 01194 dwExpWinVer2 = GETEXPWINVER(hmodCreate); 01195 } else { 01196 hmodCreate = hmod; 01197 dwExpWinVer2 = dwExpWinVer; 01198 } 01199 01200 #if DBG 01201 if ((dit.dwExStyle & WS_EX_ANSICREATOR) != 0) { 01202 RIPMSG1(RIP_WARNING, "Bad WS_EX_ style 0x%x for a control in the dialog", 01203 dit.dwExStyle); 01204 } 01205 #endif // DBG 01206 01207 /* 01208 * Get pointer to additional data. 01209 * 01210 * For WOW, instead of pointing lpCreateParams at the CreateParams 01211 * data, set lpCreateParams to whatever DWORD is stored in the 32-bit 01212 * DLGTEMPLATE's CreateParams. WOW has already made sure that that 01213 * 32-bit value is indeed a 16:16 pointer to the CreateParams in the 01214 * 16-bit DLGTEMPLATE. 01215 */ 01216 01217 if (*lpCreateParams) { 01218 lpCreateParamsData = (LPBYTE)lpCreateParams; 01219 if (fWowWindow || fSCDLGFlags & SCDLG_16BIT) { 01220 lpCreateParamsData = 01221 (LPBYTE)ULongToPtr( *(UNALIGNED DWORD *) /* Sundown WOW: zero-extension */ 01222 (lpCreateParamsData + sizeof(WORD)) ); 01223 } 01224 } else { 01225 lpCreateParamsData = NULL; 01226 } 01227 01228 /* 01229 * If the dialog template specifies a menu ID then TestwndChild(pwnd) 01230 * must be TRUE or CreateWindowEx will think the ID is an hMenu rather 01231 * than an ID (in a dialog template you'll never have an hMenu). 01232 * However for compatibility reasons we let it go if the ID = 0. 01233 */ 01234 if (dit.dwID) { 01235 /* 01236 * This makes TestwndChild(pwnd) on this window return TRUE. 01237 */ 01238 dit.style |= WS_CHILD; 01239 dit.style &= ~WS_POPUP; 01240 } 01241 01242 if (IS_PTR(lpszClass)) { 01243 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strClassName, 01244 lpszClass, (UINT)-1); 01245 pstrClassName = &strClassName; 01246 } else { 01247 pstrClassName = (PLARGE_STRING)lpszClass; 01248 } 01249 UserAssert((dit.dwExStyle & WS_EX_MDICHILD) == 0); 01250 01251 hwnd2 = NtUserCreateWindowEx( 01252 dit.dwExStyle | ((fSCDLGFlags & SCDLG_ANSI) ? WS_EX_ANSICREATOR : 0), 01253 pstrClassName, 01254 &strWindowName, 01255 dit.style, 01256 DefShortToInt(dit.x), 01257 dit.y, 01258 DefShortToInt(dit.cx), 01259 dit.cy, 01260 hwnd, 01261 (HMENU)LongToHandle( dit.dwID ), 01262 hmodCreate, 01263 lpCreateParamsData, 01264 dwExpWinVer2); 01265 01266 if (hwnd2 == NULL) { 01267 NoCreate: 01268 /* 01269 * Couldn't create the window -- return NULL. 01270 */ 01271 if (!TestWF(pwnd, DFNOFAILCREATE)) { 01272 RIPMSG0(RIP_WARNING, "CreateDialog() failed: couldn't create control"); 01273 NtUserDestroyWindow(hwnd); 01274 return NULL; 01275 } 01276 } else { 01277 01278 if (dit.dwHelpID) { 01279 NtUserSetWindowContextHelpId(hwnd2, dit.dwHelpID); 01280 } 01281 01282 /* 01283 * If it is a not a default system font, set the font for all the 01284 * child windows of the dialogbox. 01285 */ 01286 if (hNewFont != NULL) { 01287 SendMessage(hwnd2, WM_SETFONT, (WPARAM)hNewFont, 0L); 01288 } 01289 01290 /* 01291 * Result gets ID of last (hopefully only) defpushbutton. 01292 */ 01293 if (SendMessage(hwnd2, WM_GETDLGCODE, 0, 0L) & DLGC_DEFPUSHBUTTON) { 01294 PDLG(pwnd)->result = dit.dwID; 01295 } 01296 01297 } 01298 /* 01299 * Point at next item template 01300 */ 01301 lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary( 01302 (LPBYTE)(lpCreateParams + 1) + *lpCreateParams); 01303 } 01304 01305 if (!TestWF(pwnd, DFCONTROL)) { 01306 PWND pwndT = _GetNextDlgTabItem(pwnd, NULL, FALSE); 01307 hwndEditFirst = HW(pwndT); 01308 } 01309 01310 if (lpfnDialog != NULL) { 01311 fSuccess = (BOOL)SendMessageWorker(pwnd, WM_INITDIALOG, 01312 (WPARAM)hwndEditFirst, lParam, FALSE); 01313 01314 // 01315 // Make sure the window didn't get nuked during WM_INITDIALOG 01316 // 01317 if (!RevalidateHwnd(hwnd)) { 01318 goto CreateDialogReturn; 01319 } 01320 if (fSuccess && !PDLG(pwnd)->fEnd) { 01321 01322 // 01323 // To remove the two-default-push-buttons problem, we must make 01324 // sure CheckDefPushButton() will remove default from other push 01325 // buttons. This happens only if hwndEditFirst != hwndNewFocus; 01326 // So, we make it NULL here. This breaks Designer's install 01327 // program(which can't take a DM_GETDEFID. So, we do a version 01328 // check here. 01329 // 01330 if (!TestWF(pwnd, DFCONTROL)) { 01331 PWND pwndT; 01332 if (!IsWindow(hwndEditFirst) || TestWF(pwnd, WFWIN40COMPAT)) 01333 hwndEditFirst = NULL; 01334 01335 // 01336 // They could have disabled hwndEditFirst during WM_INITDIALOG. 01337 // So, let use obtain the First Tab again. 01338 // 01339 pwndT = _GetNextDlgTabItem(pwnd, NULL, FALSE); 01340 if (hwndNewFocus = HW(pwndT)) { 01341 DlgSetFocus(hwndNewFocus); 01342 } 01343 01344 xxxCheckDefPushButton(pwnd, hwndEditFirst, hwndNewFocus); 01345 } 01346 } 01347 } 01348 01349 if (!IsWindow(hwnd)) 01350 { 01351 // Omnis7 relies on a nonzero return even though they nuked this 01352 // dialog during processing of the WM_INITDIALOG message 01353 // -- jeffbog -- 2/24/95 -- Win95B B#12368 01354 if (GETAPPVER() < VER40) { 01355 return(hwnd); 01356 } 01357 01358 return(NULL); 01359 } 01360 01361 /* 01362 * UISTATE: if keyboard indicators are on and this is a topmost dialog 01363 * set the internal bit. 01364 */ 01365 if (TEST_KbdCuesPUSIF) { 01366 /* 01367 * If property page, UISTATE bits were copied from parent when I was created 01368 * Top level dialogs act as containers and initialize their state based on 01369 * the type of the last input event, after sending UIS_INITIALIZE 01370 */ 01371 if (!TestwndChild(pwnd)) { 01372 SendMessageWorker(pwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0, FALSE); 01373 } 01374 } 01375 01376 /* 01377 * Bring this dialog into the foreground 01378 * if DS_SETFOREGROUND is set. 01379 */ 01380 if (bFlags & CD_SETFOREGROUND) { 01381 NtUserSetForegroundWindow(hwnd); 01382 if (!IsWindow(hwnd)) { 01383 hwnd = NULL; 01384 goto CreateDialogReturn; 01385 } 01386 } 01387 01388 if ((bFlags & CD_VISIBLE) && !PDLG(pwnd)->fEnd && (!TestWF(pwnd, WFVISIBLE))) { 01389 NtUserShowWindow(hwnd, SHOW_OPENWINDOW); 01390 UpdateWindow(hwnd); 01391 } 01392 01393 CreateDialogReturn: 01394 01395 /* 01396 * 17609 Gupta's SQLWin deletes the window before CreateDialog returns 01397 * but still expects non-zero return value from CreateDialog so we will 01398 * do like win 3.1 and not revalidate for 16 bit apps 01399 */ 01400 if (!(fSCDLGFlags & SCDLG_NOREVALIDATE) && !RevalidateHwnd(hwnd)) { 01401 hwnd = NULL; 01402 } 01403 01404 return hwnd; 01405 }

Generated on Sat May 15 19:39:45 2004 for test by doxygen 1.3.7