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.

949 lines
26 KiB

  1. //depot/Lab06_N/Windows/Core/ntuser/client/mdimenu.c#1 - branch change 13 (text)
  2. /***************************************************************************\
  3. *
  4. * MDIMENU.C -
  5. *
  6. * Copyright (c) 1985 - 1999, Microsoft Corporation
  7. *
  8. * MDI "Window" Menu Support
  9. *
  10. * History
  11. * 11-14-90 MikeHar Ported from windows
  12. * 14-Feb-1991 mikeke Added Revalidation code
  13. /****************************************************************************/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. /***************************************************************************\
  17. * FindPwndChild
  18. *
  19. * History:
  20. * 11-14-90 MikeHar Ported from windows
  21. \***************************************************************************/
  22. PWND FindPwndChild(
  23. PWND pwndMDI,
  24. UINT wChildID)
  25. {
  26. PWND pwndT;
  27. for (pwndT = REBASEPWND(pwndMDI, spwndChild);
  28. pwndT && (pwndT->spwndOwner || PtrToUlong(pwndT->spmenu) != wChildID);
  29. pwndT = REBASEPWND(pwndT, spwndNext))
  30. ;
  31. return pwndT;
  32. }
  33. /***************************************************************************\
  34. * MakeMenuItem
  35. *
  36. * History:
  37. * 11-14-90 MikeHar Ported from windows
  38. * 4-16-91 Win31 Merge
  39. \***************************************************************************/
  40. int MakeMenuItem(
  41. LPWSTR lpOut,
  42. PWND pwnd)
  43. {
  44. PMDI pmdi;
  45. DWORD rgParm;
  46. int cch = 0;
  47. WCHAR string[160];
  48. LPWSTR lpstr;
  49. int i = 0;
  50. int max = sizeof(string) / sizeof(WCHAR) - 1;
  51. /*
  52. * Get a pointer to the MDI structure
  53. */
  54. pmdi = ((PMDIWND)(REBASEPWND(pwnd, spwndParent)))->pmdi;
  55. *lpOut = 0;
  56. rgParm = PtrToUlong(pwnd->spmenu) - (DWORD)FIRST(pmdi) + 1;
  57. if (pwnd->strName.Length) {
  58. lpstr = REBASEALWAYS(pwnd, strName.Buffer);
  59. /*
  60. * Search for an & in the title string and duplicate it so that we don't
  61. * get bogus accelerators.
  62. */
  63. while (*lpstr && i < max) {
  64. string[i] = *lpstr;
  65. i++;
  66. if (*lpstr == TEXT('&')) {
  67. if (i == max) {
  68. /*
  69. * We're at the end of the string and we need to double this
  70. * ampersand. If we do that, we're going to overflow the
  71. * buffer below when we NULL-terminate it. We also don't
  72. * want to leave a single ampersand - as it'll be mistakenl
  73. * used as an accelerator - so move back one character so
  74. * that when we NULL-terminate we'll be wiping out the
  75. * original ampersand. Bug #35673.
  76. */
  77. --i;
  78. break;
  79. }
  80. string[i++] = TEXT('&');
  81. }
  82. lpstr++;
  83. }
  84. string[i] = 0;
  85. cch = wsprintfW(lpOut, L"&%d %ws", rgParm, string);
  86. } else {
  87. /*
  88. * Handle the case of MDI children without any window title text.
  89. */
  90. cch = wsprintfW(lpOut, L"&%d ", rgParm);
  91. }
  92. return cch;
  93. }
  94. /***************************************************************************\
  95. * ModifyMenuItem
  96. *
  97. * History:
  98. * 11-14-90 MikeHar Ported from windows
  99. \***************************************************************************/
  100. void ModifyMenuItem(
  101. PWND pwnd)
  102. {
  103. PMDI pmdi;
  104. WCHAR sz[200];
  105. MENUITEMINFO mii;
  106. PWND pwndParent;
  107. PMENU pmenu;
  108. /*
  109. * Get a pointer to the MDI structure
  110. */
  111. pwndParent = REBASEPWND(pwnd, spwndParent);
  112. pmdi = ((PMDIWND)pwndParent)->pmdi;
  113. if (PtrToUlong(pwnd->spmenu) > FIRST(pmdi) + (UINT)8)
  114. return;
  115. mii.cbSize = sizeof(MENUITEMINFO);
  116. mii.fMask = MIIM_STRING;
  117. mii.dwTypeData = sz;
  118. /*
  119. * Parent is MDI Client.
  120. */
  121. MakeMenuItem(sz, pwnd);
  122. /*
  123. * Changing the active child? Check it.
  124. */
  125. if (HWq(pwnd) == ACTIVE(pmdi)) {
  126. mii.fMask |= MIIM_STATE;
  127. mii.fState = MFS_CHECKED;
  128. }
  129. pwndParent = REBASEPWND(pwndParent, spwndParent);
  130. if (pwndParent->spmenu) {
  131. /*
  132. * Bug# 21566. If spmenu is NULL we used to fail
  133. * because REBASEALWAYS is trying to get the kernel
  134. * address of NULL based on pwndParent
  135. */
  136. pmenu = REBASEALWAYS(pwndParent, spmenu);
  137. /*
  138. * Internal call to SetMenuItemInfo
  139. */
  140. ThunkedMenuItemInfo(PtoH(pmenu), PtrToUlong(pwnd->spmenu), FALSE, FALSE, &mii, FALSE);
  141. }
  142. }
  143. /***************************************************************************\
  144. * MDIAddSysMenu
  145. *
  146. * Insert the MDI child's system menu onto the existing Menu.
  147. *
  148. * History:
  149. * 11-14-90 MikeHar Ported from windows
  150. \***************************************************************************/
  151. BOOL MDIAddSysMenu(
  152. HMENU hMenuFrame,
  153. HWND hwndChild)
  154. {
  155. PWND pwndChild;
  156. MENUITEMINFO mii;
  157. PMENU pMenuChild;
  158. // LATER -- look at passing pwndChild in -- FritzS
  159. UserAssert(IsWindow(hwndChild));
  160. pwndChild = ValidateHwnd(hwndChild);
  161. if (!hMenuFrame || !pwndChild || !pwndChild->spmenuSys) {
  162. return FALSE;
  163. }
  164. /*
  165. * We don't need the pMenuChild pointer but the handle. However, if you
  166. * do PtoH(_GetSubMenu()), you end up calling the function twice
  167. */
  168. pMenuChild = _GetSubMenu (REBASEALWAYS(pwndChild, spmenuSys), 0);
  169. if (!pMenuChild) {
  170. return FALSE;
  171. }
  172. // Add MDI system button as first menu item
  173. mii.cbSize = sizeof(MENUITEMINFO);
  174. mii.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP; // Add MIIM_DATA because of hack described below
  175. mii.hSubMenu = PtoH(pMenuChild);
  176. // Fritzs -- this won't work.
  177. // mii.dwTypeData = (LPSTR) MAKELONG(MENUHBM_SYSTEM, GetWindowSmIcon(hwndChild));
  178. mii.hbmpItem = HBMMENU_SYSTEM;
  179. // FritzS -- so, we sneak the icon into ItemData
  180. mii.dwItemData = (ULONG_PTR)hwndChild;
  181. if (!InternalInsertMenuItem(hMenuFrame, 0, TRUE, &mii))
  182. return FALSE;
  183. // TimeLine 6.1 gets confused by the extra Min/Close buttons,
  184. // don't add them if WFOLDUI
  185. mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_BITMAP;
  186. mii.fType = MFT_RIGHTJUSTIFY;
  187. pwndChild = ValidateHwnd(hwndChild);
  188. if (!pwndChild) {
  189. NtUserRemoveMenu(hMenuFrame, 0, MF_BYPOSITION);
  190. return FALSE;
  191. }
  192. if (!TestWF(pwndChild, WFOLDUI))
  193. {
  194. // Add Minimize button as last menu item
  195. mii.hbmpItem = (TestWF(pwndChild, WFMINBOX) ? HBMMENU_MBAR_MINIMIZE : HBMMENU_MBAR_MINIMIZE_D);
  196. mii.wID = SC_MINIMIZE;
  197. if (!InternalInsertMenuItem(hMenuFrame, MFMWFP_NOITEM, TRUE, &mii))
  198. {
  199. NtUserRemoveMenu(hMenuFrame, 0, MF_BYPOSITION);
  200. return FALSE;
  201. }
  202. mii.fType &= ~MFT_RIGHTJUSTIFY;
  203. }
  204. // Add Restore button as last menu item
  205. mii.hbmpItem = HBMMENU_MBAR_RESTORE;
  206. mii.wID = SC_RESTORE;
  207. if (!InternalInsertMenuItem(hMenuFrame, MFMWFP_NOITEM, TRUE, &mii)) {
  208. // BOGUS -- we gotta remove the MINIMIZE button too
  209. NtUserRemoveMenu(hMenuFrame, 0, MF_BYPOSITION);
  210. return FALSE;
  211. }
  212. pwndChild = ValidateHwnd(hwndChild);
  213. if (!pwndChild) {
  214. NtUserRemoveMenu(hMenuFrame, 0, MF_BYPOSITION);
  215. return FALSE;
  216. }
  217. if (!TestWF(pwndChild, WFOLDUI))
  218. {
  219. // Add Close button as last menu item
  220. mii.hbmpItem = (xxxMNCanClose(pwndChild) ? HBMMENU_MBAR_CLOSE : HBMMENU_MBAR_CLOSE_D);
  221. mii.wID = SC_CLOSE;
  222. if (!InternalInsertMenuItem(hMenuFrame, MFMWFP_NOITEM, TRUE, &mii))
  223. {
  224. // BOGUS -- we gotta remove the MINIMIZE and RESTORE buttons too
  225. NtUserRemoveMenu(hMenuFrame, 0, MF_BYPOSITION);
  226. return FALSE;
  227. }
  228. }
  229. /*
  230. * Set the menu items to proper state since we just maximized it. Note
  231. * setsysmenu doesn't work if we've cleared the sysmenu bit so do it now...
  232. */
  233. NtUserSetSysMenu(hwndChild);
  234. /*
  235. * This is so that if the user brings up the child sysmenu, it's sure
  236. * to be that in the frame menu bar...
  237. */
  238. ClearWindowState(pwndChild, WFSYSMENU);
  239. /*
  240. * Make sure that the child's frame is redrawn to reflect the removed
  241. * system menu.
  242. */
  243. MDIRedrawFrame(hwndChild, TRUE);
  244. return TRUE;
  245. }
  246. /***************************************************************************\
  247. * MDIRemoveSysMenu
  248. *
  249. * History:
  250. * 11-14-90 MikeHar Ported from windows
  251. \***************************************************************************/
  252. BOOL MDIRemoveSysMenu(
  253. HMENU hMenuFrame,
  254. HWND hwndChild)
  255. {
  256. int iLastItem;
  257. UINT iLastCmd;
  258. PWND pwndChild;
  259. // LATER -- look at passing pwndChild in -- FritzS
  260. if (hMenuFrame == NULL)
  261. return FALSE;
  262. pwndChild = ValidateHwnd(hwndChild);
  263. if (pwndChild == NULL)
  264. return FALSE;
  265. iLastItem = GetMenuItemCount(hMenuFrame) - 1;
  266. iLastCmd = TestWF(pwndChild, WFOLDUI) ? SC_RESTORE : SC_CLOSE;
  267. if ((UINT) GetMenuItemID(hMenuFrame, iLastItem) != iLastCmd)
  268. return FALSE;
  269. /*
  270. * Enable the sysmenu in the child window.
  271. */
  272. SetWindowState(pwndChild, WFSYSMENU);
  273. /*
  274. * Take the child sysmenu popup out of the frame menu.
  275. */
  276. NtUserRemoveMenu(hMenuFrame, 0, MF_BYPOSITION);
  277. /*
  278. * Delete the restore button from the menu bar.
  279. */
  280. NtUserDeleteMenu(hMenuFrame, iLastItem - 1, MF_BYPOSITION);
  281. pwndChild = ValidateHwnd(hwndChild);
  282. if (pwndChild == NULL)
  283. return FALSE;
  284. if (!TestWF(pwndChild, WFOLDUI)) {
  285. NtUserDeleteMenu(hMenuFrame, iLastItem - 2, MF_BYPOSITION);
  286. NtUserDeleteMenu(hMenuFrame, iLastItem - 3, MF_BYPOSITION);
  287. }
  288. /*
  289. * Make sure that the child's frame is redrawn to reflect the added
  290. * system menu.
  291. */
  292. MDIRedrawFrame(hwndChild, FALSE);
  293. return TRUE;
  294. }
  295. /***************************************************************************\
  296. * AppendToWindowsMenu
  297. *
  298. * Add the title of the MDI child window 'hwndChild' to the bottom of the
  299. * "Window" menu (or add the "More Windows ..." item) if there's room.
  300. *
  301. * MDI Child # Add
  302. * ------------- --------------------
  303. * < MAXITEMS Child # and Title
  304. * = MAXITEMS "More Windows ..."
  305. * > MAXITEMS nothing
  306. *
  307. * History:
  308. * 17-Mar-1992 mikeke from win31
  309. \***************************************************************************/
  310. BOOL FAR PASCAL AppendToWindowsMenu(
  311. PWND pwndMDI,
  312. PWND pwndChild)
  313. {
  314. PMDI pmdi;
  315. WCHAR szMenuItem[165];
  316. int item;
  317. MENUITEMINFO mii;
  318. /*
  319. * Get a pointer to the MDI structure
  320. */
  321. pmdi = ((PMDIWND)pwndMDI)->pmdi;
  322. item = PtrToUlong(pwndChild->spmenu) - FIRST(pmdi);
  323. if (WINDOW(pmdi) && (item < MAXITEMS)) {
  324. mii.cbSize = sizeof(MENUITEMINFO);
  325. if (!item) {
  326. /*
  327. * Add separator before first item
  328. */
  329. mii.fMask = MIIM_FTYPE;
  330. mii.fType = MFT_SEPARATOR;
  331. if (!InternalInsertMenuItem(WINDOW(pmdi), MFMWFP_NOITEM, TRUE, &mii))
  332. return FALSE;
  333. }
  334. if (item == (MAXITEMS - 1))
  335. LoadString(hmodUser, STR_MOREWINDOWS, szMenuItem,
  336. sizeof(szMenuItem) / sizeof(WCHAR));
  337. else
  338. MakeMenuItem(szMenuItem, pwndChild);
  339. mii.fMask = MIIM_ID | MIIM_STRING;
  340. mii.wID = PtrToUlong(pwndChild->spmenu);
  341. mii.dwTypeData = szMenuItem;
  342. mii.cch = (UINT)-1;
  343. if (!InternalInsertMenuItem(WINDOW(pmdi), MFMWFP_NOITEM, TRUE, &mii))
  344. return FALSE;
  345. }
  346. return TRUE;
  347. }
  348. /***************************************************************************\
  349. * SwitchWindowsMenus
  350. *
  351. * Switch the "Window" menu in the frame menu bar 'hMenu' from
  352. * 'hOldWindow' to 'hNewWindow'
  353. *
  354. * History:
  355. * 17-Mar-1992 mikeke from win31
  356. \***************************************************************************/
  357. BOOL SwitchWindowsMenus(
  358. HMENU hmenu,
  359. HMENU hOldWindow,
  360. HMENU hNewWindow)
  361. {
  362. int i;
  363. HMENU hsubMenu;
  364. WCHAR szMenuName[128];
  365. MENUITEMINFO mii;
  366. if (hOldWindow == hNewWindow)
  367. return TRUE;
  368. mii.cbSize = sizeof(MENUITEMINFO);
  369. /*
  370. * Determine position of old "Window" menu
  371. */
  372. for (i = 0; hsubMenu = GetSubMenu(hmenu, i); i++) {
  373. if (hsubMenu == hOldWindow)
  374. {
  375. // Extract the name of the old menu to use it for the new menu
  376. mii.fMask = MIIM_STRING;
  377. mii.dwTypeData = szMenuName;
  378. mii.cch = sizeof(szMenuName)/sizeof(WCHAR);
  379. GetMenuItemInfoInternalW(hmenu, i, TRUE, &mii);
  380. // Out with the old, in with the new
  381. if (!NtUserRemoveMenu(hmenu, i, MF_BYPOSITION))
  382. return(FALSE);
  383. mii.fMask |= MIIM_SUBMENU;
  384. mii.hSubMenu = hNewWindow;
  385. return(InternalInsertMenuItem(hmenu, i, TRUE, &mii));
  386. }
  387. }
  388. return(FALSE);
  389. }
  390. /***************************************************************************\
  391. * ShiftMenuIDs
  392. *
  393. * Shift the id's of the MDI child windows of the MDI client window 'hWnd'
  394. * down by 1 (id--) starting with the child window 'hwndVictim' -- moving
  395. * 'hwndVictim' to the end of the list
  396. *
  397. * History:
  398. * 17-Mar-1992 mikeke from win31
  399. \***************************************************************************/
  400. void ShiftMenuIDs(
  401. PWND pwnd,
  402. PWND pwndVictim)
  403. {
  404. PMDI pmdi;
  405. PWND pwndChild;
  406. PWND pwndParent;
  407. /*
  408. * Get a pointer to the MDI structure
  409. */
  410. pmdi = ((PMDIWND)pwnd)->pmdi;
  411. pwndParent = REBASEPWND(pwndVictim, spwndParent);
  412. pwndChild = REBASEPWND(pwndParent, spwndChild);
  413. while (pwndChild) {
  414. if (!pwndChild->spwndOwner && (pwndChild->spmenu > pwndVictim->spmenu)) {
  415. SetWindowLongPtr(HWq(pwndChild), GWLP_ID, PtrToUlong(pwndChild->spmenu) - 1);
  416. }
  417. pwndChild = REBASEPWND(pwndChild, spwndNext);
  418. }
  419. SetWindowLongPtr(HWq(pwndVictim), GWLP_ID, FIRST(pmdi) + CKIDS(pmdi) - 1);
  420. }
  421. /***************************************************************************\
  422. * MDISetMenu
  423. *
  424. * History:
  425. * 11-14-90 MikeHar Ported from windows
  426. \***************************************************************************/
  427. HMENU MDISetMenu(
  428. PWND pwndMDI,
  429. BOOL fRefresh,
  430. HMENU hNewSys,
  431. HMENU hNewWindow)
  432. {
  433. int i;
  434. int iFirst;
  435. int item;
  436. PMDI pmdi;
  437. PWND pwndParent;
  438. HMENU hOldSys;
  439. HMENU hOldWindow;
  440. PWND pwndChild;
  441. /*
  442. * Get a pointer to the MDI structure
  443. */
  444. pmdi = ((PMDIWND)pwndMDI)->pmdi;
  445. /*
  446. * Save the old values
  447. */
  448. pwndParent = REBASEPWND(pwndMDI, spwndParent);
  449. hOldSys = GetMenu(HW(pwndParent));
  450. hOldWindow = WINDOW(pmdi);
  451. if (fRefresh) {
  452. hNewSys = hOldSys;
  453. hNewWindow = hOldWindow;
  454. }
  455. /*
  456. * Change the Frame Menu.
  457. */
  458. if (hNewSys && (hNewSys != hOldSys)) {
  459. if (MAXED(pmdi))
  460. MDIRemoveSysMenu(hOldSys, MAXED(pmdi));
  461. NtUserSetMenu(HW(pwndParent), hNewSys, FALSE);
  462. if (MAXED(pmdi))
  463. MDIAddSysMenu(hNewSys, MAXED(pmdi));
  464. } else
  465. hNewSys = hOldSys;
  466. /*
  467. * Now update the Window menu.
  468. */
  469. if (fRefresh || (hOldWindow != hNewWindow)) {
  470. iFirst = FIRST(pmdi);
  471. if (hOldWindow) {
  472. int cItems = GetMenuItemCount(hOldWindow);
  473. for (i = cItems - 1; i >= 0; i--) {
  474. if (GetMenuState(hOldWindow, i, MF_BYPOSITION) & MF_SEPARATOR)
  475. break;
  476. }
  477. if ((i >= 0) && (GetMenuItemID(hOldWindow, i + 1) == (UINT)iFirst)) {
  478. int idTrim = i;
  479. for (i = idTrim; i < cItems; i++)
  480. NtUserDeleteMenu(hOldWindow, idTrim, MF_BYPOSITION);
  481. }
  482. }
  483. Lock(&WINDOW(pmdi), hNewWindow);
  484. if (hNewWindow != NULL) {
  485. /*
  486. * Add the list of child windows to the new window
  487. */
  488. for (i = 0, item = 0; ((UINT)i < CKIDS(pmdi)) && (item < MAXITEMS);
  489. i++) {
  490. pwndChild = FindPwndChild(pwndMDI, iFirst + item);
  491. if (pwndChild != NULL) {
  492. if ((!TestWF(pwndChild, WFVISIBLE) &&
  493. (LOWORD(pwndMDI->style) & 0x0001)) ||
  494. TestWF(pwndChild, WFDISABLED)) {
  495. ShiftMenuIDs(pwndMDI, pwndChild);
  496. } else {
  497. AppendToWindowsMenu(pwndMDI, pwndChild);
  498. item++;
  499. }
  500. }
  501. }
  502. /*
  503. * Add checkmark by the active child's menu item
  504. */
  505. if (ACTIVE(pmdi))
  506. CheckMenuItem(hNewWindow, (WORD)GetWindowID(ACTIVE(pmdi)),
  507. MF_BYCOMMAND | MF_CHECKED);
  508. }
  509. /*
  510. * Out with the old, in with the new
  511. */
  512. SwitchWindowsMenus(hNewSys, hOldWindow, hNewWindow);
  513. }
  514. return hOldSys;
  515. }
  516. /***************************************************************************\
  517. * xxxInitActivateDlg
  518. *
  519. * History:
  520. * 11-14-90 MikeHar Ported from windows
  521. \***************************************************************************/
  522. void xxxInitActivateDlg(
  523. HWND hwnd,
  524. PWND pwndMDI)
  525. {
  526. PMDI pmdi;
  527. UINT wKid;
  528. HWND hwndT;
  529. PWND pwndT;
  530. WCHAR szTitle[CCHTITLEMAX];
  531. TL tlpwndT;
  532. SIZE Size;
  533. HDC hDC;
  534. DWORD width = 0;
  535. CheckLock(pwndMDI);
  536. /*
  537. * Get a pointer to the MDI structure
  538. */
  539. pmdi = ((PMDIWND)pwndMDI)->pmdi;
  540. hDC = NtUserGetDC(hwnd);
  541. /*
  542. * Insert the list of titles.
  543. * Note the wKid-th item in the listbox has ID wKid+FIRST(pwnd), so that
  544. * the listbox is in creation order (like the menu). This is also
  545. * helpful when we go to select one...
  546. */
  547. for (wKid = 0; wKid < CKIDS(pmdi); wKid++) {
  548. pwndT = FindPwndChild(pwndMDI, (UINT)(wKid + FIRST(pmdi)));
  549. if (pwndT && TestWF(pwndT, WFVISIBLE) && !TestWF(pwndT, WFDISABLED)) {
  550. ThreadLockAlways(pwndT, &tlpwndT);
  551. GetWindowText(HWq(pwndT), szTitle, CCHTITLEMAX);
  552. SendDlgItemMessage(hwnd, 100, LB_ADDSTRING, 0, (LPARAM)szTitle);
  553. GetTextExtentPoint(hDC, szTitle, lstrlen(szTitle), &Size);
  554. if (Size.cx > (LONG)width) {
  555. width = Size.cx;
  556. }
  557. ThreadUnlock(&tlpwndT);
  558. }
  559. }
  560. /*
  561. * Select the currently active window.
  562. */
  563. SendDlgItemMessage(hwnd, 100, LB_SETTOPINDEX, MAXITEMS - 1, 0L);
  564. SendDlgItemMessage(hwnd, 100, LB_SETCURSEL, MAXITEMS - 1, 0L);
  565. /*
  566. * Set the horizontal extent of the list box to the longest window title.
  567. */
  568. SendDlgItemMessage(hwnd, 100, LB_SETHORIZONTALEXTENT, width, 0L);
  569. NtUserReleaseDC(hwnd, hDC);
  570. /*
  571. * Set the focus to the listbox.
  572. */
  573. hwndT = GetDlgItem(hwnd, 100);
  574. NtUserSetFocus(hwndT);
  575. }
  576. /***************************************************************************\
  577. * MDIActivateDlgSize
  578. *
  579. * The minimum allowed size and the previous one are saved as properties
  580. * of the parent window.
  581. *
  582. * History:
  583. * Oct 97 MCostea Created
  584. \***************************************************************************/
  585. VOID MDIActivateDlgSize(HWND hwnd, int width, int height)
  586. {
  587. PMDIACTIVATEPOS pPos;
  588. PWND pwnd, pwndList, pwndButtonLeft, pwndButtonRight;
  589. HDWP hdwp;
  590. int deltaX, deltaY;
  591. pPos = (PMDIACTIVATEPOS)GetProp(GetParent(hwnd), MAKEINTATOM(atomMDIActivateProp));
  592. if (pPos == NULL) {
  593. return;
  594. }
  595. /*
  596. * Retrieve the children
  597. */
  598. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  599. return;
  600. }
  601. pwndList = REBASEPWND(pwnd, spwndChild);
  602. pwndButtonLeft = REBASEPWND(pwndList, spwndNext);
  603. pwndButtonRight = REBASEPWND(pwndButtonLeft, spwndNext);
  604. UserAssert(GETFNID(pwndList) == FNID_LISTBOX);
  605. UserAssert(GETFNID(pwndButtonLeft) == FNID_BUTTON);
  606. UserAssert(GETFNID(pwndButtonRight) == FNID_BUTTON);
  607. UserAssert(pwndButtonRight->rcWindow.left > pwndButtonLeft->rcWindow.left);
  608. deltaX = width - pPos->cx;
  609. deltaY = height - pPos->cy;
  610. pPos->cx = width;
  611. pPos->cy = height;
  612. /*
  613. * Move/resize the child windows accordingly
  614. */
  615. hdwp = NtUserBeginDeferWindowPos(3);
  616. if (hdwp)
  617. {
  618. hdwp = NtUserDeferWindowPos( hdwp,
  619. PtoH(pwndList),
  620. NULL,
  621. 0,
  622. 0,
  623. deltaX + pwndList->rcWindow.right - pwndList->rcWindow.left,
  624. deltaY + pwndList->rcWindow.bottom - pwndList->rcWindow.top,
  625. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
  626. if (hdwp)
  627. {
  628. hdwp = NtUserDeferWindowPos(hdwp,
  629. PtoH(pwndButtonLeft),
  630. NULL,
  631. pwndButtonLeft->rcWindow.left - pwnd->rcClient.left,
  632. deltaY + pwndButtonLeft->rcWindow.top - pwnd->rcClient.top,
  633. 0,
  634. 0,
  635. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
  636. if (hdwp)
  637. {
  638. hdwp = NtUserDeferWindowPos( hdwp,
  639. PtoH(pwndButtonRight),
  640. NULL,
  641. pwndButtonRight->rcWindow.left - pwnd->rcClient.left,
  642. deltaY + pwndButtonRight->rcWindow.top - pwnd->rcClient.top,
  643. 0,
  644. 0,
  645. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
  646. }
  647. }
  648. if (hdwp) {
  649. NtUserEndDeferWindowPosEx(hdwp, FALSE);
  650. }
  651. }
  652. }
  653. /***************************************************************************\
  654. * MDIActivateDlgInit
  655. *
  656. * The minimum allowed size and the previous one are saved as properties
  657. * of the parent window.
  658. *
  659. * History:
  660. * Oct 97 MCostea Created
  661. \***************************************************************************/
  662. VOID MDIActivateDlgInit(HWND hwnd, LPARAM lParam)
  663. {
  664. PMDIACTIVATEPOS pPos;
  665. HWND hwndParent;
  666. RECT rc;
  667. xxxInitActivateDlg(hwnd, (PWND)lParam);
  668. hwndParent = GetParent(hwnd);
  669. /*
  670. * Preserve the previous size of the dialog, if any
  671. */
  672. if (atomMDIActivateProp == 0) {
  673. atomMDIActivateProp = AddAtomW(MDIACTIVATE_PROP_NAME);
  674. UserAssert(atomMDIActivateProp);
  675. }
  676. GetWindowRect(hwnd, &rc);
  677. pPos = (PMDIACTIVATEPOS)GetProp(hwndParent, MAKEINTATOM(atomMDIActivateProp));
  678. /*
  679. * If the dialog was used before, retrieve it's size
  680. */
  681. if (pPos != NULL) {
  682. int cxBorder, cyBorder, cx, cy;
  683. /*
  684. * The stored size and the ones in WM_SIZE are client window coordinates
  685. * Need to adjust them for NtUserSetWindowPos and WM_INITDIALOG
  686. */
  687. cxBorder = rc.right - rc.left;
  688. cyBorder = rc.bottom - rc.top;
  689. GetClientRect(hwnd, &rc);
  690. cxBorder -= rc.right - rc.left;
  691. cyBorder -= rc.bottom - rc.top;
  692. NtUserSetWindowPos(hwnd, NULL, 0, 0,
  693. pPos->cx + cxBorder,
  694. pPos->cy + cyBorder,
  695. SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER
  696. | SWP_NOSENDCHANGING | SWP_NOREDRAW);
  697. cx = pPos->cx;
  698. cy = pPos->cy;
  699. pPos->cx = pPos->cxMin - cxBorder;
  700. pPos->cy = pPos->cyMin - cyBorder;
  701. MDIActivateDlgSize(hwnd, cx, cy);
  702. } else {
  703. /*
  704. *
  705. */
  706. pPos = UserLocalAlloc(0, sizeof(MDIACTIVATEPOS));
  707. if (pPos == NULL) {
  708. return;
  709. }
  710. pPos->cxMin = rc.right - rc.left;
  711. pPos->cyMin = rc.bottom - rc.top;
  712. GetClientRect(hwnd, &rc);
  713. pPos->cx = rc.right - rc.left;
  714. pPos->cy = rc.bottom - rc.top;
  715. SetProp(hwndParent, MAKEINTATOM(atomMDIActivateProp), (HANDLE)pPos);
  716. }
  717. }
  718. /***************************************************************************\
  719. * MDIActivateDlgProc
  720. *
  721. * History:
  722. * 11-14-90 MikeHar Ported from windows
  723. \***************************************************************************/
  724. INT_PTR MDIActivateDlgProcWorker(
  725. HWND hwnd,
  726. UINT wMsg,
  727. WPARAM wParam,
  728. LPARAM lParam)
  729. {
  730. int i;
  731. switch (wMsg) {
  732. case WM_INITDIALOG:
  733. /*
  734. * NOTE: Code above uses DialogBoxParam, passing pwndMDI in the low
  735. * word of the parameter...
  736. */
  737. MDIActivateDlgInit(hwnd, lParam);
  738. return FALSE;
  739. case WM_COMMAND:
  740. i = -2;
  741. switch (LOWORD(wParam)) {
  742. /*
  743. * Listbox doubleclicks act like OK...
  744. */
  745. case 100:
  746. if (HIWORD(wParam) != LBN_DBLCLK)
  747. break;
  748. /*
  749. ** FALL THRU **
  750. */
  751. case IDOK:
  752. i = (UINT)SendDlgItemMessage(hwnd, 100, LB_GETCURSEL, 0, 0L);
  753. /*
  754. ** FALL THRU **
  755. */
  756. case IDCANCEL:
  757. EndDialog(hwnd, i);
  758. break;
  759. default:
  760. return FALSE;
  761. }
  762. break;
  763. case WM_SIZE:
  764. MDIActivateDlgSize(hwnd, LOWORD(lParam), HIWORD(lParam));
  765. return FALSE;
  766. case WM_GETMINMAXINFO:
  767. {
  768. PMDIACTIVATEPOS pPos;
  769. if (pPos = (PMDIACTIVATEPOS)GetProp(GetParent(hwnd), MAKEINTATOM(atomMDIActivateProp))) {
  770. ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = pPos->cxMin;
  771. ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = pPos->cyMin;
  772. }
  773. return FALSE;
  774. }
  775. default:
  776. return FALSE;
  777. }
  778. return TRUE;
  779. }
  780. INT_PTR WINAPI MDIActivateDlgProcA(
  781. HWND hwnd,
  782. UINT message,
  783. WPARAM wParam,
  784. LPARAM lParam)
  785. {
  786. return MDIActivateDlgProcWorker(hwnd, message, wParam, lParam);
  787. }
  788. INT_PTR WINAPI MDIActivateDlgProcW(
  789. HWND hwnd,
  790. UINT message,
  791. WPARAM wParam,
  792. LPARAM lParam)
  793. {
  794. return MDIActivateDlgProcWorker(hwnd, message, wParam, lParam);
  795. }