Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1397 lines
45 KiB

  1. /***************************************************************************\
  2. *
  3. * DLGBEGIN.C -
  4. *
  5. * Copyright (c) 1985 - 1999, Microsoft Corporation
  6. *
  7. * Dialog Initialization Routines
  8. *
  9. * ??-???-???? mikeke Ported from Win 3.0 sources
  10. * 12-Feb-1991 mikeke Added Revalidation code
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. BOOL ValidateCallback(HANDLE h);
  15. CONST WCHAR szEDITCLASS[] = TEXT("Edit");
  16. /*
  17. * Fixed, hard coded literal for Dialog hacks
  18. */
  19. const WCHAR gwszShellFont[] = L"MS Shell Dlg";
  20. const WCHAR gwszShellFont2[] = L"MS Shell Dlg 2";
  21. /***************************************************************************\
  22. * DefShortToInt
  23. *
  24. * Avoid sign extending 16 bit CW2_USEDEFAULT. We need this because the
  25. * dialog resource template uses SHORT fields to store the coordinates
  26. * but CreateWindow wants INT values.
  27. *
  28. * History:
  29. * 12/04/96 GerardoB Created
  30. \***************************************************************************/
  31. __inline int DefShortToInt (short s)
  32. {
  33. if (s == (short)CW2_USEDEFAULT) {
  34. return (int)(DWORD)(WORD)CW2_USEDEFAULT;
  35. } else {
  36. return (int)s;
  37. }
  38. }
  39. /***************************************************************************\
  40. * BYTE FAR *SkipSz(lpsz)
  41. *
  42. * History:
  43. \***************************************************************************/
  44. PBYTE SkipSz(
  45. UTCHAR *lpsz)
  46. {
  47. if (*lpsz == 0xFF)
  48. return (PBYTE)lpsz + 4;
  49. while (*lpsz++ != 0) ;
  50. return (PBYTE)lpsz;
  51. }
  52. PBYTE WordSkipSz(
  53. UTCHAR *lpsz)
  54. {
  55. PBYTE pb = SkipSz(lpsz);
  56. return NextWordBoundary(pb);
  57. }
  58. PBYTE DWordSkipSz(
  59. UTCHAR *lpsz)
  60. {
  61. PBYTE pb = SkipSz(lpsz);
  62. return NextDWordBoundary(pb);
  63. }
  64. /***************************************************************************\
  65. *
  66. * IsFontNotGood()
  67. *
  68. * If this is a low res device, we need to check if the
  69. * font we're creating is smaller than the system font.
  70. *
  71. \***************************************************************************/
  72. __inline BOOLEAN IsFontNotGood(LPWSTR szTempBuffer, LPCWSTR lpStrSubst, TEXTMETRIC* ptm)
  73. {
  74. //
  75. // For FarEast version, we will allow the font smaller than system font.
  76. //
  77. return _wcsicmp(szTempBuffer, lpStrSubst) ||
  78. (!IS_ANY_DBCS_CHARSET(ptm->tmCharSet) &&
  79. (SYSMET(CXICON) < 32 || SYSMET(CYICON) < 32) &&
  80. ptm->tmHeight < gpsi->cySysFontChar);
  81. }
  82. // --------------------------------------------------------------------------
  83. // GetCharsetEnumProc()
  84. //
  85. // This gets the best asian font for a dialog box.
  86. //
  87. // 1996-Sep-11 hideyukn Port from Win95-FE
  88. // --------------------------------------------------------------------------
  89. int CALLBACK GetCharsetEnumProc(
  90. LPLOGFONT lpLogFont,
  91. LPTEXTMETRIC lptm,
  92. DWORD nType,
  93. LPARAM lpData)
  94. {
  95. UNREFERENCED_PARAMETER(lptm);
  96. UNREFERENCED_PARAMETER(nType);
  97. //
  98. // Use other than FIXED pitch sysfont when the face name isn't specified.
  99. //
  100. if ((lpLogFont->lfPitchAndFamily & 3) == FIXED_PITCH)
  101. {
  102. if (!lstrcmpi(lpLogFont->lfFaceName,L"System") ||
  103. !lstrcmpi(lpLogFont->lfFaceName,L"@System"))
  104. return TRUE; // try to get another system font metric
  105. }
  106. ((LPLOGFONT)lpData)->lfCharSet = lpLogFont->lfCharSet;
  107. ((LPLOGFONT)lpData)->lfPitchAndFamily = lpLogFont->lfPitchAndFamily;
  108. return FALSE;
  109. }
  110. /*
  111. * Get a character set based on System's ANSI CODEPAGE
  112. */
  113. UINT GetACPCharSet()
  114. {
  115. static UINT charset = (UINT)~0;
  116. CHARSETINFO csInfo;
  117. if (charset != (UINT)~0) {
  118. return charset;
  119. }
  120. // Sundown: In the TCI_SRCCODEPAGE case, the GetACP() return value is zero-extended.
  121. if (!TranslateCharsetInfo((DWORD*)UIntToPtr( GetACP() ), &csInfo, TCI_SRCCODEPAGE)) {
  122. return DEFAULT_CHARSET;
  123. }
  124. charset = csInfo.ciCharset;
  125. UserAssert(charset != (UINT)~0);
  126. return csInfo.ciCharset;
  127. }
  128. #if 0
  129. BYTE GetCharsetFromResourceLang(LCID lcid)
  130. {
  131. CHARSETINFO csInfo;
  132. if (!TranslateCharsetInfo((DWORD *)lcid, &csInfo, TCI_SRCLOCALE))
  133. return DEFAULT_CHARSET;
  134. return csInfo.ciCharset;
  135. }
  136. #endif
  137. /***************************************************************************\
  138. *
  139. * CreateDlgFont()
  140. *
  141. * Create the dialog font described at the given location in a resource
  142. *
  143. \***************************************************************************/
  144. #define GET_DESKTOP_CHARSET() (GetTextCharset(hdcDlg))
  145. //
  146. // Reserved Dlg resource version number
  147. //
  148. #define DLGRSC_VER_NT5COMPAT_RESERVE 10
  149. BOOL FixupDlgLogFont(
  150. HDC hdcDlg,
  151. LPLOGFONT lpLogFont,
  152. LPDLGTEMPLATE2 lpdt,
  153. BOOLEAN fUseShellFont2,
  154. BOOLEAN* pfWillTryDefaultCharset)
  155. {
  156. switch (lpdt->wDlgVer) {
  157. case 0:
  158. // DIALOG statement, which only has a facename.
  159. // The new applications are not supposed to use DIALOG statement,
  160. // they should use DIALOGEX instead.
  161. lpLogFont->lfWeight = FW_BOLD;
  162. if (!fUseShellFont2) {
  163. lpLogFont->lfCharSet = (BYTE)GET_DESKTOP_CHARSET();
  164. *pfWillTryDefaultCharset = TRUE;
  165. }
  166. break;
  167. case 1:
  168. //
  169. // Win4 compatible DLG template
  170. //
  171. if (!fUseShellFont2) {
  172. if (IS_DBCS_ENABLED()) {
  173. if (lpLogFont->lfCharSet == ANSI_CHARSET) {
  174. //
  175. // When resource compiler generates dialog resource data
  176. // from DIALOGEX template, it can specify 'charset'. but
  177. // optional, if it is not specified, it will be filled
  178. // with 0 (ANSI charset). But, on localized version,
  179. // User might guess the default will be localized-charset
  180. //
  181. // [Dialog Resource File]
  182. //
  183. // DIALOGEX ...
  184. // ...
  185. // FONT pointsize, typeface, [weight], [italic], [charset]
  186. //
  187. // #100182
  188. // Bogus hack:
  189. // Some FE fonts started to have ANSI_CHARSET so the first attept would succeed.
  190. // We should enumerate the charset from the beginning.
  191. lpLogFont->lfCharSet = DEFAULT_CHARSET;
  192. RIPMSG0(RIP_VERBOSE, "No proper CharSet information in DIALOGEX");
  193. }
  194. }
  195. /*
  196. * Note: Dialog resource version 2.0 or later has not been supported on
  197. * Windows 95 and 98. As of Apr/98 we decided not to deploy this new feature
  198. * in the standard tools. Still, NT 5 supports this new feature, preparing
  199. * the future transition to do the right thing.
  200. */
  201. else if (lpLogFont->lfCharSet == ANSI_CHARSET) {
  202. // If the first attempt fail, we'll enumerate the charset for the given facename
  203. *pfWillTryDefaultCharset = TRUE;
  204. }
  205. else if (lpLogFont->lfCharSet == DEFAULT_CHARSET) {
  206. lpLogFont->lfCharSet = (BYTE)GET_DESKTOP_CHARSET();
  207. }
  208. }
  209. break;
  210. default:
  211. if (lpdt->wDlgVer <= DLGRSC_VER_NT5COMPAT_RESERVE) {
  212. // we do nothing for the new resource compiler (>= 2.0),
  213. // since this version of dialogs are guarunteed to have
  214. // the proper character set for the dialog font.
  215. }
  216. else {
  217. RIPMSG1(RIP_WARNING, "Version %d resource is not supported.", lpdt->wDlgVer);
  218. return FALSE;
  219. }
  220. break;
  221. }
  222. return TRUE;
  223. }
  224. VOID FixupDlgFaceName(
  225. LPLOGFONT lpLogFont,
  226. BOOLEAN fUseShellFont,
  227. BOOLEAN fUseShellFont2,
  228. LPCWSTR lpStrSubst)
  229. {
  230. if (fUseShellFont2) {
  231. //
  232. // OK, we use "MS Shell Dlg 2" as a face name.
  233. //
  234. wcsncpycch(lpLogFont->lfFaceName, gwszShellFont2, ARRAY_SIZE(gwszShellFont2));
  235. }
  236. else {
  237. //
  238. // Otherwise, get the face name from the dialog template.
  239. //
  240. wcsncpycch(lpLogFont->lfFaceName, lpStrSubst, sizeof(lpLogFont->lfFaceName) / sizeof(WCHAR));
  241. }
  242. //
  243. // "MS Shell Dlg" and "MS Shell Dlg2" should have native character set ---
  244. //
  245. if (fUseShellFont || fUseShellFont2) {
  246. lpLogFont->lfCharSet = (BYTE)GetACPCharSet();
  247. }
  248. }
  249. HFONT CreateDlgFont(HDC hdcDlg, LPWORD FAR *lplpstr, LPDLGTEMPLATE2 lpdt, DWORD dwExpWinVer, UINT fSCDLGFlags)
  250. {
  251. LOGFONT LogFont;
  252. int fontheight, fheight;
  253. HFONT hOldFont, hFont;
  254. WCHAR szTempBuffer[LF_FACESIZE];
  255. LPCWSTR lpStrSubst;
  256. TEXTMETRIC tm;
  257. // Font hacks
  258. BOOLEAN fDeleteFont;
  259. BOOLEAN fWillTryDefaultCharset = FALSE;
  260. BOOLEAN fUseShellFont, fUseShellFont2;
  261. UNREFERENCED_PARAMETER(dwExpWinVer);
  262. UNREFERENCED_PARAMETER(fSCDLGFlags);
  263. fheight = fontheight = (SHORT)(*((WORD *) *lplpstr)++);
  264. if (fontheight == 0x7FFF) {
  265. // a 0x7FFF height is our special code meaning use the message box font
  266. GetObject(KHFONT_TO_HFONT(gpsi->hMsgFont), sizeof(LOGFONT), &LogFont);
  267. return CreateFontIndirect(&LogFont);
  268. }
  269. //
  270. // The dialog template contains a font description! Use it.
  271. //
  272. // Fill the LogFont with default values
  273. RtlZeroMemory(&LogFont, sizeof(LOGFONT));
  274. fontheight = -MultDiv(fontheight, gpsi->dmLogPixels, 72);
  275. LogFont.lfHeight = fontheight;
  276. if (lpdt->wDlgVer) {
  277. //
  278. // If it's DIALOGEX, additional info should be read from
  279. // the template.
  280. //
  281. LogFont.lfWeight = *((WORD FAR *) *lplpstr)++;
  282. LogFont.lfItalic = *((BYTE FAR *) *lplpstr)++;
  283. LogFont.lfCharSet = *((BYTE FAR *) *lplpstr)++;
  284. }
  285. //
  286. // Per shell team request, the dialog who has DS_SETFONT
  287. // *and* DS_FIXEDSYS (=> DS_SHELLFONT2) should have a font
  288. // "MS Shell Dlg 2".
  289. //
  290. lpStrSubst = *lplpstr;
  291. //
  292. // Set the pointer to the next item.
  293. //
  294. *lplpstr = (WORD*)DWordSkipSz(*lplpstr);
  295. fUseShellFont = _wcsicmp(lpStrSubst, gwszShellFont) == 0;
  296. //
  297. // Later shell team request again, to use "Dlg 2" font only
  298. // when facename in the dialog template is "MS Shell Dlg".
  299. //
  300. fUseShellFont2 = fUseShellFont &&
  301. (lpdt->style & DS_SHELLFONT) == DS_SHELLFONT && Is400Compat(dwExpWinVer) && lpdt->wDlgVer != 0;
  302. if (fUseShellFont2) {
  303. TAGMSG0(DBGTAG_IMM, "CreateDlgFont: fUseShellFont2=TRUE");
  304. }
  305. //
  306. // Prepare the font character set.
  307. //
  308. if (!FixupDlgLogFont(hdcDlg, &LogFont, lpdt, fUseShellFont2, &fWillTryDefaultCharset)) {
  309. return NULL;
  310. }
  311. //
  312. // Prepare the font facename.
  313. //
  314. FixupDlgFaceName(&LogFont, fUseShellFont, fUseShellFont2, lpStrSubst);
  315. if (lpdt->wDlgVer < 2 && lpdt->style & DS_3DLOOK)
  316. LogFont.lfWeight = FW_NORMAL;
  317. TryDefaultCharset:
  318. if (LogFont.lfCharSet == DEFAULT_CHARSET) {
  319. //
  320. // Get character set for given facename.
  321. //
  322. EnumFonts(hdcDlg, LogFont.lfFaceName,
  323. (FONTENUMPROC)GetCharsetEnumProc, (LPARAM)(&LogFont));
  324. //
  325. // We already tried default charset.
  326. //
  327. fWillTryDefaultCharset = FALSE;
  328. }
  329. //
  330. // [Windows 3.1 FarEast version did this...]
  331. //
  332. // Use FW_NORMAL as default for DIALOG template. For DIALOGEX
  333. // template, we need to respect the value in the template.
  334. //
  335. if ((!(lpdt->wDlgVer)) && // not DIALOGEX template ?
  336. (IS_ANY_DBCS_CHARSET(LogFont.lfCharSet)) && // any FarEast font ?
  337. (LogFont.lfWeight != FW_NORMAL)) { // already FW_NORMAL ?
  338. //
  339. // Set weight to FW_NORMAL.
  340. //
  341. LogFont.lfWeight = FW_NORMAL;
  342. }
  343. if (!(hFont = CreateFontIndirect((LPLOGFONT) &LogFont)))
  344. return(NULL);
  345. fDeleteFont = FALSE;
  346. if ((hOldFont = SelectFont(hdcDlg, hFont)) == NULL) {
  347. fDeleteFont = TRUE;
  348. }
  349. else {
  350. //
  351. // If this dialog has DS_SHELLFONT style, or the font is
  352. // "MS Shell Dlg", we don't judge the font integrity,
  353. // for they have been given the ACP based character set.
  354. //
  355. if (!fUseShellFont) {
  356. if (!GetTextMetrics(hdcDlg, &tm)) {
  357. RIPMSG0(RIP_WARNING, "CreateDlgFont: GetTextMetrics failed");
  358. fDeleteFont = TRUE;
  359. }
  360. else {
  361. GetTextFaceAliasW(hdcDlg, sizeof(szTempBuffer)/sizeof(WCHAR), szTempBuffer);
  362. //
  363. // If this is a low res device, we need to check if the
  364. // font we're creating is smaller than the system font.
  365. // If so, just use the system font.
  366. //
  367. if (IsFontNotGood(szTempBuffer, lpStrSubst, &tm)) {
  368. //
  369. // Couldn't find a font with the height or facename
  370. // the app wanted so use the system font instead. Note
  371. // that we need to make sure the app knows it is
  372. // getting the system font via the WM_SETFONT message
  373. // so we still need to act as if a new font is being
  374. // sent to the dialog box.
  375. //
  376. fDeleteFont = TRUE;
  377. }
  378. }
  379. }
  380. UserAssert(hOldFont != NULL);
  381. SelectFont(hdcDlg, hOldFont);
  382. }
  383. if (fDeleteFont) {
  384. DeleteFont(hFont);
  385. //
  386. // Font is deleted, Prepare for reTry...
  387. //
  388. hFont = NULL;
  389. }
  390. // Font hack:
  391. //
  392. // 1. We fail to create font.
  393. // 2. We did *NOT* try to enumerate charset, yet.
  394. // 3. We want to try to enumerate charset
  395. //
  396. // if all of answer is 'Yes', we will try...
  397. //
  398. if (hFont == NULL && fWillTryDefaultCharset) {
  399. //
  400. // Try DEFAULT_CHARSET.
  401. //
  402. LogFont.lfCharSet = DEFAULT_CHARSET;
  403. goto TryDefaultCharset;
  404. }
  405. return hFont;
  406. }
  407. #undef GET_DESKTOP_CHARSET
  408. #define CD_VISIBLE 0x01
  409. #define CD_GLOBALEDIT 0x02
  410. #define CD_USERFONT 0x04
  411. #define CD_SETFOREGROUND 0x08
  412. #define CD_USEDEFAULTX 0x10
  413. #define CD_USEDEFAULTCX 0x20
  414. /***************************************************************************\
  415. * GetDialogMonitor
  416. *
  417. * Gets the monitor a dialog should be created on.
  418. *
  419. * Params:
  420. * hwndOwner - the owner of the dialog. May be NULL.
  421. *
  422. * History:
  423. * 10-Oct-1996 adams Created.
  424. \***************************************************************************/
  425. PMONITOR
  426. GetDialogMonitor(HWND hwndOwner, DWORD dwFlags)
  427. {
  428. PMONITOR pMonitor;
  429. PWND pwnd;
  430. HWND hwndForeground;
  431. DWORD pid;
  432. UserAssert(dwFlags == MONITOR_DEFAULTTONULL ||
  433. dwFlags == MONITOR_DEFAULTTOPRIMARY);
  434. pMonitor = NULL;
  435. if (hwndOwner) {
  436. pwnd = ValidateHwnd(hwndOwner);
  437. if (pwnd && GETFNID(pwnd) != FNID_DESKTOP) {
  438. pMonitor = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY);
  439. }
  440. } else {
  441. /*
  442. * HACK! They passed in no owner and are creating a top level
  443. * dialog window. Does this process own the foreground window?
  444. * If so, pin to that window's monitor. That way 16-bit apps
  445. * will work mostly as expected, and old multithreaded dudes just
  446. * might too. Especially the shell, for whom many system UI pieces
  447. * pop up random dialogs inside of API calls.
  448. */
  449. hwndForeground = NtUserGetForegroundWindow();
  450. if (hwndForeground) {
  451. GetWindowThreadProcessId(hwndForeground, &pid);
  452. if (pid == HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess)) {
  453. pwnd = ValidateHwnd(hwndForeground);
  454. if (pwnd) {
  455. pMonitor = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY);
  456. }
  457. }
  458. }
  459. }
  460. if (!pMonitor && dwFlags == MONITOR_DEFAULTTOPRIMARY) {
  461. pMonitor = GetPrimaryMonitor();
  462. }
  463. return pMonitor;
  464. }
  465. /***************************************************************************\
  466. * InternalCreateDialog
  467. *
  468. * Creates a dialog from a template. Uses passed in menu if there is one,
  469. * destroys menu if creation failed. Server portion of
  470. * CreateDialogIndirectParam.
  471. *
  472. * WARNING: This function cannot create any windows before creating the dialog
  473. * window. Otherwise, MFC apps will break because their hook assumes
  474. * the dialog is the first window to be created.
  475. *
  476. * History:
  477. * 04-10-91 ScottLu
  478. * 04-17-91 Mikehar Win31 Merge
  479. \***************************************************************************/
  480. HWND InternalCreateDialog(
  481. HANDLE hmod,
  482. LPDLGTEMPLATE lpdt,
  483. DWORD cb,
  484. HWND hwndOwner,
  485. DLGPROC lpfnDialog,
  486. LPARAM lParam,
  487. UINT fSCDLGFlags)
  488. {
  489. HWND hwnd;
  490. HWND hwnd2;
  491. PWND pwnd;
  492. HWND hwndNewFocus;
  493. HWND hwndEditFirst = NULL;
  494. RECT rc;
  495. WORD w;
  496. UTCHAR *lpszMenu,
  497. *lpszClass,
  498. *lpszText,
  499. *lpCreateParams,
  500. *lpStr;
  501. int cxChar,
  502. cyChar;
  503. BOOL f40Compat;
  504. HFONT hNewFont = NULL;
  505. HFONT hOldFont;
  506. LPDLGITEMTEMPLATE lpdit;
  507. HMENU hMenu;
  508. BOOL fSuccess;
  509. BOOL fWowWindow;
  510. HANDLE hmodCreate;
  511. LPBYTE lpCreateParamsData;
  512. DLGTEMPLATE2 dt;
  513. DLGITEMTEMPLATE2 dit;
  514. DWORD dwExpWinVer;
  515. DWORD dsStyleOld;
  516. DWORD bFlags = 0;
  517. HDC hdcDlg;
  518. LARGE_STRING strClassName;
  519. PLARGE_STRING pstrClassName;
  520. LARGE_STRING strWindowName;
  521. PMONITOR pMonitor;
  522. UNREFERENCED_PARAMETER(cb);
  523. ConnectIfNecessary(0);
  524. UserAssert(!(fSCDLGFlags & ~(SCDLG_CLIENT|SCDLG_ANSI|SCDLG_NOREVALIDATE|SCDLG_16BIT))); // These are the only valid flags
  525. /*
  526. * If the app is a Wow app then the LOWORD of the hmod (properly masked
  527. * with LDR_DATAFILE_TO_VIEW) will be non-zero.
  528. */
  529. if (LOWORD(LDR_DATAFILE_TO_VIEW(hmod)) == 0) {
  530. fWowWindow = FALSE;
  531. } else {
  532. fWowWindow = TRUE;
  533. }
  534. /*
  535. * Is this a Win4 extended dialog?
  536. */
  537. if (((LPDLGTEMPLATE2)lpdt)->wSignature == 0xffff) {
  538. UserAssert(((LPDLGTEMPLATE2)lpdt)->wDlgVer <= DLGRSC_VER_NT5COMPAT_RESERVE);
  539. RtlCopyMemory(&dt, lpdt, sizeof dt);
  540. } else {
  541. dt.wDlgVer = 0;
  542. dt.wSignature = 0;
  543. dt.dwHelpID = 0;
  544. dt.dwExStyle = lpdt->dwExtendedStyle;
  545. dt.style = lpdt->style;
  546. dt.cDlgItems = lpdt->cdit;
  547. dt.x = lpdt->x;
  548. dt.y = lpdt->y;
  549. dt.cx = lpdt->cx;
  550. dt.cy = lpdt->cy;
  551. }
  552. /*
  553. * If this is called from wow code, then the fWowWindow is TRUE.
  554. * In this case, allow any DS_ style bits that were passed in win3.1
  555. * to be legal in win32. Case in point: 16 bit quark xpress passes the
  556. * same bit as the win32 style DS_SETFOREGROUND. Also, VC++ sample
  557. * "scribble" does the same thing.
  558. *
  559. * For win32 apps test the DS_SETFOREGROUND bit; wow apps are not set
  560. * foreground (this is the new NT semantics)
  561. * We have to let no "valid" bits through because apps depend on them
  562. * bug 5232.
  563. */
  564. dsStyleOld = LOWORD(dt.style);
  565. /*
  566. * If the app is Win4 or greater, require correct dialog style bits.
  567. * Prevents conflicts with new bits introduced in Chicago
  568. */
  569. dwExpWinVer = GETEXPWINVER(hmod) | CW_FLAGS_VERSIONCLASS;
  570. if ( f40Compat = Is400Compat(dwExpWinVer) ) {
  571. dt.style &= (DS_VALID40 | 0xffff0000);
  572. //
  573. // For old applications:
  574. // If DS_COMMONDIALOG isn't set, don't touch DS_3DLOOK style
  575. // bit. If it's there, it stays there. If not, not. That way old
  576. // apps which pass in their own templates, not commdlg's, don't get
  577. // forced 3D.
  578. // If DS_COMMONDIALOG is there, remove DS_3DLOOK.
  579. //
  580. // For new applications:
  581. // Force 3D always.
  582. //
  583. if (GETAPPVER() < VER40) {
  584. if (dt.style & DS_COMMONDIALOG) {
  585. dt.style &= ~DS_3DLOOK;
  586. dsStyleOld &= ~DS_3DLOOK;
  587. }
  588. } else {
  589. dt.style |= DS_3DLOOK;
  590. dsStyleOld |= DS_3DLOOK;
  591. }
  592. } else {
  593. #if DBG
  594. if (dt.style != (dt.style & (DS_VALID31 | DS_3DLOOK | 0xffff0000))) {
  595. RIPMSG1(RIP_WARNING, "CreateDialog: stripping invalid bits %lX", dt.style);
  596. }
  597. #endif // DBG
  598. /*
  599. * Don't strip off bits for old apps, they depend on this. Especially 16 bit MFC apps!
  600. *
  601. * dt.dwStyle &= (DS_VALID31 | 0xffff0000);
  602. */
  603. }
  604. if (!fWowWindow) {
  605. if (dt.style & DS_SETFOREGROUND)
  606. bFlags |= CD_SETFOREGROUND;
  607. }
  608. if (dsStyleOld != LOWORD(dt.style))
  609. {
  610. RIPMSG1(f40Compat ? RIP_ERROR : RIP_WARNING,
  611. "Bad dialog style bits (%x) - please remove.",
  612. LOWORD(dt.style));
  613. // Fail new apps that pass in bogus bits!
  614. if (f40Compat) {
  615. return NULL;
  616. }
  617. }
  618. if ( dt.style & DS_MODALFRAME) {
  619. dt.dwExStyle |= WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE;
  620. }
  621. if (( dt.style & DS_CONTEXTHELP) && f40Compat) {
  622. dt.dwExStyle |= WS_EX_CONTEXTHELP;
  623. }
  624. if (dt.style & DS_CONTROL) {
  625. // Captions and system menus aren't allowed on "control" dialogs.
  626. // And strip DS_SYSMODAL.
  627. dt.style &= ~(WS_CAPTION | WS_SYSMENU | DS_SYSMODAL);
  628. } else if (dt.style & WS_DLGFRAME) {
  629. // Add on window edge same way that CreateWindowEx() will
  630. dt.dwExStyle |= WS_EX_WINDOWEDGE;
  631. }
  632. if (dt.style & DS_SYSMODAL) {
  633. dt.dwExStyle |= WS_EX_TOPMOST;
  634. }
  635. if (!(dt.style & WS_CHILD) || (dt.style & DS_CONTROL)) {
  636. // only a control parent if it's not a child dialog or if it's
  637. // explicitly marked as a recursive dialog
  638. dt.dwExStyle |= WS_EX_CONTROLPARENT;
  639. }
  640. if (dt.x == (short)CW2_USEDEFAULT) {
  641. bFlags |= CD_USEDEFAULTX;
  642. dt.x = 0;
  643. }
  644. if (dt.cx == (short)CW2_USEDEFAULT) {
  645. bFlags |= CD_USEDEFAULTCX;
  646. dt.cx = 0;
  647. } else if (dt.cx < 0) {
  648. dt.cx = 0;
  649. }
  650. if (dt.cy < 0) {
  651. dt.cy = 0;
  652. }
  653. // If there's a menu name string, load it.
  654. lpszMenu = (LPWSTR)(((PBYTE)(lpdt)) + (dt.wDlgVer ? sizeof(DLGTEMPLATE2):sizeof(DLGTEMPLATE)));
  655. /*
  656. * If the menu id is expressed as an ordinal and not a string,
  657. * skip all 4 bytes to get to the class string.
  658. */
  659. w = *(LPWORD)lpszMenu;
  660. /*
  661. * If there's a menu name string, load it.
  662. */
  663. if (w != 0) {
  664. if ((hMenu = LoadMenu(hmod, (w == 0xFFFF) ?
  665. MAKEINTRESOURCE(*(WORD *)((PBYTE)lpszMenu + 2)) : lpszMenu)) == NULL) {
  666. RIPMSG0(RIP_WARNING, "ServerCreateDialog() failed: couldn't load menu");
  667. goto DeleteFontAndMenuAndFail;
  668. }
  669. } else {
  670. hMenu = NULL;
  671. }
  672. if (w == 0xFFFF) {
  673. lpszClass = (LPWSTR)((LPBYTE)lpszMenu + 4);
  674. } else {
  675. lpszClass = (UTCHAR *)WordSkipSz(lpszMenu);
  676. }
  677. lpszText = (UTCHAR *)WordSkipSz(lpszClass);
  678. lpStr = (UTCHAR *)WordSkipSz(lpszText);
  679. hdcDlg = CreateCompatibleDC(NULL);
  680. if (hdcDlg == NULL)
  681. goto DeleteFontAndMenuAndFail;
  682. if (dt.style & DS_SETFONT) {
  683. hNewFont = CreateDlgFont(hdcDlg, &lpStr, &dt, dwExpWinVer, fSCDLGFlags);
  684. bFlags |= CD_USERFONT;
  685. lpdit = (LPDLGITEMTEMPLATE) NextDWordBoundary(lpStr);
  686. } else if (Is400Compat(dwExpWinVer) && (dt.style & DS_FIXEDSYS)) {
  687. //
  688. // B#2078 -- WISH for fixed width system font in dialog. We need
  689. // to tell the dialog that it's using a font different from the
  690. // standard system font, so set CD_USERFONT bit.
  691. //
  692. // We need the 400 compat. check for CorelDraw, since they use
  693. // this style bit for their own purposes.
  694. //
  695. hNewFont = GetStockObject(SYSTEM_FIXED_FONT);
  696. bFlags |= CD_USERFONT;
  697. lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(lpStr);
  698. } else {
  699. lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(lpStr);
  700. }
  701. /*
  702. * If the application requested a particular font and for some
  703. * reason we couldn't find it, we just use the system font. BUT we
  704. * need to make sure we tell him he gets the system font. Dialogs
  705. * which never request a particular font get the system font and we
  706. * don't bother telling them this (via the WM_SETFONT message).
  707. */
  708. // Is it anything other than the default system font? If we can't get
  709. // enough memory to select in the new font specified, just use the system
  710. // font.
  711. if (hNewFont && (hOldFont = SelectFont(hdcDlg, hNewFont))) {
  712. // Get the ave character width and height to be used
  713. cxChar = GdiGetCharDimensions(hdcDlg, NULL, &cyChar);
  714. SelectFont(hdcDlg, hOldFont);
  715. if (cxChar == 0) {
  716. RIPMSG0(RIP_WARNING, "InternalCreateDialog: GdiGetCharDimensions failed");
  717. goto UseSysFontMetrics;
  718. }
  719. }
  720. else
  721. {
  722. if (hNewFont || (bFlags & CD_USERFONT))
  723. hNewFont = ghFontSys;
  724. UseSysFontMetrics:
  725. cxChar = gpsi->cxSysFontChar;
  726. cyChar = gpsi->cySysFontChar;
  727. }
  728. DeleteDC(hdcDlg);
  729. if (dt.style & WS_VISIBLE) {
  730. bFlags |= CD_VISIBLE;
  731. dt.style &= ~WS_VISIBLE;
  732. }
  733. if (!(dt.style & DS_LOCALEDIT)) {
  734. bFlags |= CD_GLOBALEDIT;
  735. }
  736. /* Figure out dimensions of real window
  737. *
  738. * NOTE: We need to call the _Real_ AdjustWindowRectEx() function and not
  739. * the hooked one because Themes uses the initial size that the dialog comes
  740. * up to determine how much to enlarge it by.
  741. */
  742. rc.left = rc.top = 0;
  743. rc.right = XPixFromXDU(dt.cx, cxChar);
  744. rc.bottom = YPixFromYDU(dt.cy, cyChar);
  745. RealAdjustWindowRectEx(&rc, dt.style, w, dt.dwExStyle);
  746. dt.cx = (SHORT)(rc.right - rc.left);
  747. dt.cy = (SHORT)(rc.bottom - rc.top);
  748. if ((dt.style & DS_CENTERMOUSE) && SYSMET(MOUSEPRESENT) && f40Compat) {
  749. pMonitor = _MonitorFromPoint(gpsi->ptCursor, MONITOR_DEFAULTTONULL);
  750. UserAssert(pMonitor);
  751. *((LPPOINT)&rc.left) = gpsi->ptCursor;
  752. rc.left -= (dt.cx / 2);
  753. rc.top -= (dt.cy / 2);
  754. } else {
  755. BOOL fNoDialogMonitor;
  756. pMonitor = GetDialogMonitor(hwndOwner, MONITOR_DEFAULTTONULL);
  757. fNoDialogMonitor = pMonitor ? FALSE : TRUE;
  758. if (!pMonitor) {
  759. pMonitor = GetPrimaryMonitor();
  760. }
  761. if ((dt.style & (DS_CENTER | DS_CENTERMOUSE)) && f40Compat) {
  762. /*
  763. * Center to the work area of the owner monitor.
  764. */
  765. rc.left = (pMonitor->rcWork.left + pMonitor->rcWork.right - dt.cx) / 2;
  766. rc.top = (pMonitor->rcWork.top + pMonitor->rcWork.bottom - dt.cy) / 2;
  767. } else {
  768. rc.left = XPixFromXDU(dt.x, cxChar);
  769. rc.top = YPixFromYDU(dt.y, cyChar);
  770. if (!(dt.style & DS_ABSALIGN) && hwndOwner) {
  771. /*
  772. * Offset relative coordinates to the owner window. If it is
  773. * a child window, there is nothing to do.
  774. */
  775. if ((HIWORD(dt.style) & MaskWF(WFTYPEMASK)) != MaskWF(WFCHILD)) {
  776. //This is will considre rc.left form the right hand side of the owner window if it a mirrored one.
  777. ClientToScreen(hwndOwner, (LPPOINT)&rc.left);
  778. //It is not chiled then do Visual ClientToScreen
  779. //i.e. rc.left it is form the left hand side of the owner window
  780. if (MIRRORED_HWND(hwndOwner)) {
  781. rc.left -= dt.cx;
  782. }
  783. }
  784. } else {
  785. /*
  786. * Position the dialog in screen coordinates. If the dialog's
  787. * owner is on a different monitor than specified in the
  788. * template, move the dialog to the owner window. If the owner
  789. * doesn't exist, then use the monitor from the dialog's
  790. * template.
  791. */
  792. PMONITOR pMonitorTemplate;
  793. RECT rcTemplate;
  794. rcTemplate.left = rc.left;
  795. rcTemplate.top = rc.top;
  796. rcTemplate.right = rc.left + dt.cx;
  797. rcTemplate.bottom = rc.top + dt.cy;
  798. pMonitorTemplate = _MonitorFromRect(&rcTemplate, MONITOR_DEFAULTTOPRIMARY);
  799. if (fNoDialogMonitor) {
  800. pMonitor = pMonitorTemplate;
  801. } else if (pMonitorTemplate != pMonitor) {
  802. rc.left += pMonitor->rcMonitor.left - pMonitorTemplate->rcMonitor.left;
  803. rc.top += pMonitor->rcMonitor.top - pMonitorTemplate->rcMonitor.top;
  804. }
  805. }
  806. }
  807. }
  808. rc.right = rc.left + dt.cx;
  809. rc.bottom = rc.top + dt.cy;
  810. // If the right or bottom coordinate has overflowed, then pin it back to
  811. // a valid rectangle. Likely to happen if a minimized window is the owner of
  812. // the dialog.
  813. if (rc.left > rc.right || rc.top > rc.bottom) {
  814. OffsetRect(&rc, -dt.cx, -dt.cy);
  815. }
  816. //
  817. // Need to do this for ALL dialogs, not just top-level, since we used
  818. // to in 3.1.
  819. //
  820. // Clip top level dialogs within working area
  821. // Start child dialogs at least at (0, 0)
  822. RepositionRect(pMonitor, &rc, dt.style, dt.dwExStyle);
  823. dt.x = (SHORT)((bFlags & CD_USEDEFAULTX) ? CW2_USEDEFAULT : rc.left);
  824. dt.y = (SHORT)(rc.top);
  825. dt.cx = (SHORT)((bFlags & CD_USEDEFAULTCX) ? CW2_USEDEFAULT : rc.right - rc.left);
  826. dt.cy = (SHORT)(rc.bottom - rc.top);
  827. if (*lpszClass != 0) {
  828. if (IS_PTR(lpszClass)) {
  829. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strClassName,
  830. lpszClass, (UINT)-1);
  831. pstrClassName = &strClassName;
  832. } else {
  833. pstrClassName = (PLARGE_STRING)lpszClass;
  834. }
  835. } else {
  836. pstrClassName = (PLARGE_STRING)DIALOGCLASS;
  837. }
  838. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strWindowName,
  839. lpszText, (UINT)-1);
  840. UserAssert((dt.dwExStyle & WS_EX_MDICHILD) == 0);
  841. hwnd = VerNtUserCreateWindowEx(
  842. dt.dwExStyle | ((fSCDLGFlags & SCDLG_ANSI) ? WS_EX_ANSICREATOR : 0),
  843. pstrClassName,
  844. &strWindowName,
  845. dt.style,
  846. DefShortToInt(dt.x),
  847. dt.y,
  848. DefShortToInt(dt.cx),
  849. dt.cy,
  850. hwndOwner,
  851. hMenu,
  852. hmod,
  853. (LPVOID)NULL,
  854. dwExpWinVer);
  855. if (hwnd == NULL) {
  856. RIPMSG0(RIP_WARNING, "CreateDialog() failed: couldn't create window");
  857. DeleteFontAndMenuAndFail:
  858. if (hMenu != NULL)
  859. NtUserDestroyMenu(hMenu);
  860. /*
  861. * Only delete the font if we didn't grab it
  862. * from the dialog font cache.
  863. */
  864. if ((hNewFont != NULL)) {
  865. DeleteObject(hNewFont);
  866. }
  867. return NULL;
  868. }
  869. pwnd = ValidateHwnd(hwnd);
  870. // tell WOW the hDlg of the Window just created BEFORE they get any messages
  871. // at WOW32!w32win16wndprocex
  872. if(fSCDLGFlags & SCDLG_16BIT) {
  873. TellWOWThehDlg(hwnd);
  874. }
  875. /*
  876. * Before anything happens with this window, we need to mark it as a
  877. * dialog window!!!! So do that.
  878. */
  879. if (pwnd == NULL || !ValidateDialogPwnd(pwnd))
  880. goto DeleteFontAndMenuAndFail;
  881. if (dt.dwHelpID) {
  882. NtUserSetWindowContextHelpId(hwnd, dt.dwHelpID);
  883. }
  884. /*
  885. * Set up the system menu on this dialog box if it has one.
  886. */
  887. if (TestWF(pwnd, WFSYSMENU)) {
  888. /*
  889. * For a modal dialog box with a frame and caption, we want to
  890. * delete the unselectable items from the system menu.
  891. */
  892. UserAssert(HIBYTE(WFSIZEBOX) == HIBYTE(WFMINBOX));
  893. UserAssert(HIBYTE(WFMINBOX) == HIBYTE(WFMAXBOX));
  894. if (!TestWF(pwnd, WFSIZEBOX | WFMINBOX | WFMAXBOX)) {
  895. NtUserCallHwndLock(hwnd, SFI_XXXSETDIALOGSYSTEMMENU);
  896. } else {
  897. /*
  898. * We have to give this dialog its own copy of the system menu
  899. * in case it modifies the menu.
  900. */
  901. NtUserGetSystemMenu(hwnd, FALSE);
  902. }
  903. }
  904. /*
  905. * Set fDisabled to FALSE so EndDialog will Enable if dialog is ended
  906. * before returning to DialogBox (or if modeless).
  907. */
  908. PDLG(pwnd)->fDisabled = FALSE;
  909. PDLG(pwnd)->cxChar = cxChar;
  910. PDLG(pwnd)->cyChar = cyChar;
  911. PDLG(pwnd)->lpfnDlg = lpfnDialog;
  912. PDLG(pwnd)->fEnd = FALSE;
  913. PDLG(pwnd)->result = IDOK;
  914. /*
  915. * Need to remember Unicode status.
  916. */
  917. if (fSCDLGFlags & SCDLG_ANSI) {
  918. PDLG(pwnd)->flags |= DLGF_ANSI;
  919. }
  920. /*
  921. * If a user defined font is used, save the handle so that we can delete
  922. * it when the dialog is destroyed.
  923. */
  924. if (bFlags & CD_USERFONT) {
  925. PDLG(pwnd)->hUserFont = hNewFont;
  926. if (lpfnDialog != NULL) {
  927. /*
  928. * Tell the dialog that it will be using this font...
  929. */
  930. SendMessageWorker(pwnd, WM_SETFONT, (WPARAM)hNewFont, 0L, FALSE);
  931. }
  932. }
  933. if (!dt.wDlgVer) {
  934. dit.dwHelpID = 0;
  935. }
  936. /*
  937. * Loop through the dialog controls, doing a CreateWindowEx() for each of
  938. * them.
  939. */
  940. while (dt.cDlgItems-- != 0) {
  941. DWORD dwExpWinVer2;
  942. if (dt.wDlgVer) {
  943. RtlCopyMemory(&dit, lpdit, sizeof dit);
  944. } else {
  945. dit.dwHelpID = 0;
  946. dit.dwExStyle = lpdit->dwExtendedStyle;
  947. dit.style = lpdit->style;
  948. dit.x = lpdit->x;
  949. dit.y = lpdit->y;
  950. dit.cx = lpdit->cx;
  951. dit.cy = lpdit->cy;
  952. dit.dwID = lpdit->id;
  953. }
  954. dit.x = XPixFromXDU(dit.x, cxChar);
  955. dit.y = YPixFromYDU(dit.y, cyChar);
  956. dit.cx = XPixFromXDU(dit.cx, cxChar);
  957. dit.cy = YPixFromYDU(dit.cy, cyChar);
  958. lpszClass = (LPWSTR)(((PBYTE)(lpdit)) + (dt.wDlgVer ? sizeof(DLGITEMTEMPLATE2):sizeof(DLGITEMTEMPLATE)));
  959. /*
  960. * If the first WORD is 0xFFFF the second word is the encoded class name index.
  961. * Use it to look up the class name string.
  962. */
  963. if (*(LPWORD)lpszClass == 0xFFFF) {
  964. lpszText = lpszClass + 2;
  965. lpszClass = (LPWSTR)(gpsi->atomSysClass[*(((LPWORD)lpszClass)+1) & ~CODEBIT]);
  966. } else {
  967. lpszText = (UTCHAR *)SkipSz(lpszClass);
  968. }
  969. lpszText = (UTCHAR *)NextWordBoundary(lpszText); // UINT align lpszText
  970. dit.dwExStyle |= WS_EX_NOPARENTNOTIFY;
  971. //
  972. // Replace flat borders with 3D ones for DS_3DLOOK dialogs
  973. // We test the WINDOW style, not the template style now. This is so
  974. // that 4.0 apps--who get 3D stuff automatically--can turn it off on
  975. // create if they want.
  976. //
  977. //
  978. // HACK!
  979. // Treat DS_3DLOOK combos like they have a WS_EX_CLIENTEDGE. Why
  980. // should we have to draw the borders of a combobox ourselves?
  981. // We can't do the same thing for WS_BORDER though becaues of
  982. // PC Fools--they use the presence of WS_BORDER to distinguish
  983. // between lists and combos.
  984. //
  985. if (TestWF(pwnd, DF3DLOOK)) {
  986. if ( (dit.style & WS_BORDER) ||
  987. (lpszClass == MAKEINTRESOURCE(gpsi->atomSysClass[ICLS_COMBOBOX]))) {
  988. dit.style &= ~WS_BORDER;
  989. dit.dwExStyle |= WS_EX_CLIENTEDGE;
  990. }
  991. }
  992. /*
  993. * Get pointer to additional data. lpszText can point to an encoded
  994. * ordinal number for some controls (e.g. static icon control) so
  995. * we check for that here.
  996. */
  997. if (*(LPWORD)lpszText == 0xFFFF) {
  998. lpCreateParams = (LPWSTR)((PBYTE)lpszText + 4);
  999. strWindowName.Buffer = lpszText;
  1000. strWindowName.Length = 4;
  1001. strWindowName.MaximumLength = 4;
  1002. strWindowName.bAnsi = FALSE;
  1003. } else {
  1004. lpCreateParams = (LPWSTR)((PBYTE)WordSkipSz(lpszText));
  1005. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strWindowName,
  1006. lpszText, (UINT)-1);
  1007. }
  1008. /*
  1009. * If control is edit control and caller wants global storage
  1010. * of edit text, allocate object in WOW and pass instance
  1011. * handle to CreateWindowEx().
  1012. */
  1013. if (fWowWindow && (bFlags & CD_GLOBALEDIT) &&
  1014. ((!IS_PTR(lpszClass) &&
  1015. PTR_TO_ID(lpszClass) == (ATOM)(gpsi->atomSysClass[ICLS_EDIT])) ||
  1016. (IS_PTR(lpszClass) &&
  1017. (wcscmp(lpszClass, szEDITCLASS) == 0)))) {
  1018. /*
  1019. * Allocate only one global object (first time we see editctl.)
  1020. */
  1021. if (!(PDLG(pwnd)->hData)) {
  1022. PDLG(pwnd)->hData = GetEditDS();
  1023. if (!(PDLG(pwnd)->hData))
  1024. goto NoCreate;
  1025. }
  1026. hmodCreate = KHANDLE_TO_HANDLE(PDLG(pwnd)->hData);
  1027. dwExpWinVer2 = GETEXPWINVER(hmodCreate) | CW_FLAGS_VERSIONCLASS;
  1028. } else {
  1029. hmodCreate = hmod;
  1030. dwExpWinVer2 = dwExpWinVer;
  1031. }
  1032. #if DBG
  1033. if ((dit.dwExStyle & WS_EX_ANSICREATOR) != 0) {
  1034. RIPMSG1(RIP_WARNING, "Bad WS_EX_ style 0x%x for a control in the dialog",
  1035. dit.dwExStyle);
  1036. }
  1037. #endif // DBG
  1038. /*
  1039. * Get pointer to additional data.
  1040. *
  1041. * For WOW, instead of pointing lpCreateParams at the CreateParams
  1042. * data, set lpCreateParams to whatever DWORD is stored in the 32-bit
  1043. * DLGTEMPLATE's CreateParams. WOW has already made sure that that
  1044. * 32-bit value is indeed a 16:16 pointer to the CreateParams in the
  1045. * 16-bit DLGTEMPLATE.
  1046. */
  1047. if (*lpCreateParams) {
  1048. lpCreateParamsData = (LPBYTE)lpCreateParams;
  1049. if (fWowWindow || fSCDLGFlags & SCDLG_16BIT) {
  1050. lpCreateParamsData =
  1051. (LPBYTE)ULongToPtr( *(UNALIGNED DWORD *) /* Sundown WOW: zero-extension */
  1052. (lpCreateParamsData + sizeof(WORD)) );
  1053. }
  1054. } else {
  1055. lpCreateParamsData = NULL;
  1056. }
  1057. /*
  1058. * If the dialog template specifies a menu ID then TestwndChild(pwnd)
  1059. * must be TRUE or CreateWindowEx will think the ID is an hMenu rather
  1060. * than an ID (in a dialog template you'll never have an hMenu).
  1061. * However for compatibility reasons we let it go if the ID = 0.
  1062. */
  1063. if (dit.dwID) {
  1064. /*
  1065. * This makes TestwndChild(pwnd) on this window return TRUE.
  1066. */
  1067. dit.style |= WS_CHILD;
  1068. dit.style &= ~WS_POPUP;
  1069. }
  1070. if (IS_PTR(lpszClass)) {
  1071. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strClassName,
  1072. lpszClass, (UINT)-1);
  1073. pstrClassName = &strClassName;
  1074. } else {
  1075. pstrClassName = (PLARGE_STRING)lpszClass;
  1076. }
  1077. UserAssert((dit.dwExStyle & WS_EX_MDICHILD) == 0);
  1078. hwnd2 = VerNtUserCreateWindowEx(
  1079. dit.dwExStyle | ((fSCDLGFlags & SCDLG_ANSI) ? WS_EX_ANSICREATOR : 0),
  1080. pstrClassName,
  1081. &strWindowName,
  1082. dit.style,
  1083. DefShortToInt(dit.x),
  1084. dit.y,
  1085. DefShortToInt(dit.cx),
  1086. dit.cy,
  1087. hwnd,
  1088. (HMENU)LongToHandle( dit.dwID ),
  1089. hmodCreate,
  1090. lpCreateParamsData,
  1091. dwExpWinVer2);
  1092. if (hwnd2 == NULL) {
  1093. NoCreate:
  1094. /*
  1095. * Couldn't create the window -- return NULL.
  1096. */
  1097. if (!TestWF(pwnd, DFNOFAILCREATE)) {
  1098. RIPMSG0(RIP_WARNING, "CreateDialog() failed: couldn't create control");
  1099. NtUserDestroyWindow(hwnd);
  1100. return NULL;
  1101. }
  1102. } else {
  1103. if (dit.dwHelpID) {
  1104. NtUserSetWindowContextHelpId(hwnd2, dit.dwHelpID);
  1105. }
  1106. /*
  1107. * If it is a not a default system font, set the font for all the
  1108. * child windows of the dialogbox.
  1109. */
  1110. if (hNewFont != NULL) {
  1111. SendMessage(hwnd2, WM_SETFONT, (WPARAM)hNewFont, 0L);
  1112. }
  1113. /*
  1114. * Result gets ID of last (hopefully only) defpushbutton.
  1115. */
  1116. if (SendMessage(hwnd2, WM_GETDLGCODE, 0, 0L) & DLGC_DEFPUSHBUTTON) {
  1117. PDLG(pwnd)->result = dit.dwID;
  1118. }
  1119. }
  1120. /*
  1121. * Point at next item template
  1122. */
  1123. lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(
  1124. (LPBYTE)(lpCreateParams + 1) + *lpCreateParams);
  1125. }
  1126. if (!TestWF(pwnd, DFCONTROL)) {
  1127. PWND pwndT = _GetNextDlgTabItem(pwnd, NULL, FALSE);
  1128. hwndEditFirst = HW(pwndT);
  1129. }
  1130. if (lpfnDialog != NULL) {
  1131. fSuccess = (BOOL)SendMessageWorker(pwnd, WM_INITDIALOG,
  1132. (WPARAM)hwndEditFirst, lParam, FALSE);
  1133. //
  1134. // Make sure the window didn't get nuked during WM_INITDIALOG
  1135. //
  1136. if (!RevalidateHwnd(hwnd)) {
  1137. goto CreateDialogReturn;
  1138. }
  1139. if (fSuccess && !PDLG(pwnd)->fEnd) {
  1140. //
  1141. // To remove the two-default-push-buttons problem, we must make
  1142. // sure CheckDefPushButton() will remove default from other push
  1143. // buttons. This happens only if hwndEditFirst != hwndNewFocus;
  1144. // So, we make it NULL here. This breaks Designer's install
  1145. // program(which can't take a DM_GETDEFID. So, we do a version
  1146. // check here.
  1147. //
  1148. if (!TestWF(pwnd, DFCONTROL)) {
  1149. PWND pwndT;
  1150. if (!IsWindow(hwndEditFirst) || TestWF(pwnd, WFWIN40COMPAT))
  1151. hwndEditFirst = NULL;
  1152. //
  1153. // They could have disabled hwndEditFirst during WM_INITDIALOG.
  1154. // So, let use obtain the First Tab again.
  1155. //
  1156. pwndT = _GetNextDlgTabItem(pwnd, NULL, FALSE);
  1157. if (hwndNewFocus = HW(pwndT)) {
  1158. DlgSetFocus(hwndNewFocus);
  1159. }
  1160. xxxCheckDefPushButton(pwnd, hwndEditFirst, hwndNewFocus);
  1161. }
  1162. }
  1163. }
  1164. if (!IsWindow(hwnd))
  1165. {
  1166. // Omnis7 relies on a nonzero return even though they nuked this
  1167. // dialog during processing of the WM_INITDIALOG message
  1168. // -- jeffbog -- 2/24/95 -- Win95B B#12368
  1169. if (GETAPPVER() < VER40) {
  1170. return(hwnd);
  1171. }
  1172. return(NULL);
  1173. }
  1174. /*
  1175. * UISTATE: if keyboard indicators are on and this is a topmost dialog
  1176. * set the internal bit.
  1177. */
  1178. if (TEST_KbdCuesPUSIF) {
  1179. /*
  1180. * If property page, UISTATE bits were copied from parent when I was created
  1181. * Top level dialogs act as containers and initialize their state based on
  1182. * the type of the last input event, after sending UIS_INITIALIZE
  1183. */
  1184. if (!TestwndChild(pwnd)) {
  1185. SendMessageWorker(pwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0, FALSE);
  1186. }
  1187. }
  1188. /*
  1189. * Bring this dialog into the foreground
  1190. * if DS_SETFOREGROUND is set.
  1191. */
  1192. if (bFlags & CD_SETFOREGROUND) {
  1193. NtUserSetForegroundWindow(hwnd);
  1194. if (!IsWindow(hwnd)) {
  1195. hwnd = NULL;
  1196. goto CreateDialogReturn;
  1197. }
  1198. }
  1199. if ((bFlags & CD_VISIBLE) && !PDLG(pwnd)->fEnd && (!TestWF(pwnd, WFVISIBLE))) {
  1200. NtUserShowWindow(hwnd, SHOW_OPENWINDOW);
  1201. UpdateWindow(hwnd);
  1202. }
  1203. CreateDialogReturn:
  1204. /*
  1205. * 17609 Gupta's SQLWin deletes the window before CreateDialog returns
  1206. * but still expects non-zero return value from CreateDialog so we will
  1207. * do like win 3.1 and not revalidate for 16 bit apps
  1208. */
  1209. if (!(fSCDLGFlags & SCDLG_NOREVALIDATE) && !RevalidateHwnd(hwnd)) {
  1210. hwnd = NULL;
  1211. }
  1212. return hwnd;
  1213. }