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.

937 lines
29 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: winmgr.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains routines common to client and kernel.
  7. *
  8. * History:
  9. * 02-20-92 DarrinM Pulled functions from user\server.
  10. * 11-11-94 JimA Separated from client.
  11. \***************************************************************************/
  12. /***************************************************************************\
  13. * FindNCHit
  14. *
  15. * History:
  16. * 11-09-90 DavidPe Ported.
  17. \***************************************************************************/
  18. int FindNCHit(
  19. PWND pwnd,
  20. LONG lPt)
  21. {
  22. POINT pt;
  23. RECT rcWindow;
  24. RECT rcClient;
  25. RECT rcClientAdj;
  26. int cBorders;
  27. int dxButton;
  28. pt.x = GET_X_LPARAM(lPt);
  29. pt.y = GET_Y_LPARAM(lPt);
  30. if (!PtInRect(KPRECT_TO_PRECT(&pwnd->rcWindow), pt))
  31. return HTNOWHERE;
  32. if (TestWF(pwnd, WFMINIMIZED)) {
  33. CopyInflateRect(&rcWindow, KPRECT_TO_PRECT(&pwnd->rcWindow),
  34. -(SYSMETRTL(CXFIXEDFRAME) + SYSMETRTL(CXBORDER)), -(SYSMETRTL(CYFIXEDFRAME) + SYSMETRTL(CYBORDER)));
  35. if (!PtInRect(&rcWindow, pt))
  36. return HTCAPTION;
  37. goto CaptionHit;
  38. }
  39. // Get client rectangle
  40. rcClient = pwnd->rcClient;
  41. if (PtInRect(&rcClient, pt))
  42. return HTCLIENT;
  43. // Are we in "pseudo" client, i.e. the client & scrollbars & border
  44. if (TestWF(pwnd, WEFCLIENTEDGE))
  45. CopyInflateRect(&rcClientAdj, &rcClient, SYSMETRTL(CXEDGE), SYSMETRTL(CYEDGE));
  46. else
  47. rcClientAdj = rcClient;
  48. if (TestWF(pwnd, WFVPRESENT)) {
  49. if ((!!TestWF(pwnd, WEFLEFTSCROLL)) ^ (!!TestWF(pwnd, WEFLAYOUTRTL)))
  50. rcClientAdj.left -= SYSMETRTL(CXVSCROLL);
  51. else
  52. rcClientAdj.right += SYSMETRTL(CXVSCROLL);
  53. }
  54. if (TestWF(pwnd, WFHPRESENT))
  55. rcClientAdj.bottom += SYSMETRTL(CYHSCROLL);
  56. if (!PtInRect(&rcClientAdj, pt))
  57. {
  58. // Subtract out window borders
  59. cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
  60. CopyInflateRect(&rcWindow, KPRECT_TO_PRECT(&pwnd->rcWindow),
  61. -cBorders*SYSMETRTL(CXBORDER), -cBorders*SYSMETRTL(CYBORDER));
  62. // Are we on the border?
  63. if (!PtInRect(&rcWindow, pt))
  64. {
  65. // On a sizing border?
  66. if (!TestWF(pwnd, WFSIZEBOX)) {
  67. //
  68. // Old compatibility thing: For 3.x windows that just had
  69. // a border, we returned HTNOWHERE, believe it or not,
  70. // because our hit-testing code wasn't very good.
  71. //
  72. if (!TestWF(pwnd, WFWIN40COMPAT) &&
  73. !TestWF(pwnd, WFDLGFRAME) &&
  74. !TestWF(pwnd, WEFDLGMODALFRAME)) {
  75. return HTNOWHERE;
  76. } else {
  77. return HTBORDER; // We are on a dlg frame.
  78. }
  79. } else {
  80. int ht;
  81. //
  82. // Note this improvement. The HT codes are numbered so that
  83. // if you subtract HTSIZEFIRST-1 from them all, they sum up. I.E.,
  84. // (HTLEFT - HTSIZEFIRST + 1) + (HTTOP - HTSIZEFIRST + 1) ==
  85. // (HTTOPLEFT - HTSIZEFIRST + 1).
  86. //
  87. if (TestWF(pwnd, WEFTOOLWINDOW))
  88. InflateRect(&rcWindow, -SYSMETRTL(CXSMSIZE), -SYSMETRTL(CYSMSIZE));
  89. else
  90. InflateRect(&rcWindow, -SYSMETRTL(CXSIZE), -SYSMETRTL(CYSIZE));
  91. if (pt.y < rcWindow.top)
  92. ht = (HTTOP - HTSIZEFIRST + 1);
  93. else if (pt.y >= rcWindow.bottom)
  94. ht = (HTBOTTOM - HTSIZEFIRST + 1);
  95. else
  96. ht = 0;
  97. if (pt.x < rcWindow.left)
  98. ht += (HTLEFT - HTSIZEFIRST + 1);
  99. else if (pt.x >= rcWindow.right)
  100. ht += (HTRIGHT - HTSIZEFIRST + 1);
  101. return (ht + HTSIZEFIRST - 1);
  102. }
  103. }
  104. // Are we above the client area?
  105. if (pt.y < rcClientAdj.top)
  106. {
  107. // Are we in the caption?
  108. if (TestWF(pwnd, WFBORDERMASK) == LOBYTE(WFCAPTION))
  109. {
  110. CaptionHit:
  111. if (TestWF(pwnd, WEFLAYOUTRTL)) {
  112. pt.x = pwnd->rcWindow.right - (pt.x - pwnd->rcWindow.left);
  113. }
  114. if (pt.y >= rcWindow.top)
  115. {
  116. if (TestWF(pwnd, WEFTOOLWINDOW))
  117. {
  118. rcWindow.top += SYSMETRTL(CYSMCAPTION);
  119. dxButton = SYSMETRTL(CXSMSIZE);
  120. }
  121. else
  122. {
  123. rcWindow.top += SYSMETRTL(CYCAPTION);
  124. dxButton = SYSMETRTL(CXSIZE);
  125. }
  126. if ((pt.y >= rcWindow.top) && TestWF(pwnd, WFMPRESENT))
  127. return HTMENU;
  128. if ((pt.x >= rcWindow.left) &&
  129. (pt.x < rcWindow.right) &&
  130. (pt.y < rcWindow.top))
  131. {
  132. // Are we in the window menu?
  133. if (TestWF(pwnd, WFSYSMENU))
  134. {
  135. rcWindow.left += dxButton;
  136. if (pt.x < rcWindow.left)
  137. {
  138. if (!_HasCaptionIcon(pwnd))
  139. // iconless windows have no sysmenu hit rect
  140. return HTCAPTION;
  141. return HTSYSMENU;
  142. }
  143. } else if (TestWF(pwnd, WFWIN40COMPAT)) {
  144. #ifdef LAME_BUTTON
  145. /*
  146. * The old code assumed that a 4.0 compatible app
  147. * would not have "anything" else in the caption if
  148. * it doesn't have a system menu. With the lame
  149. * button, this is no longer true. The code will
  150. * work fine if the else-if block below is removed.
  151. * However, if we do that then we do a whole bunch
  152. * of unnecessary checks below (looking for the
  153. * minimize button, which we know isn't there, for
  154. * example). Hence, this quick-and-dirty goto. This
  155. * allows lame button hit tracking to work on
  156. * windows with no system menu, as well as not
  157. * change hit test behavior in the shipped bits
  158. * (which we most definitely do NOT want to break!)
  159. */
  160. goto LameButtonHitTest;
  161. #else
  162. return HTCAPTION;
  163. #endif // LAME_BUTTON
  164. }
  165. // Are we in the close button?
  166. rcWindow.right -= dxButton;
  167. if (pt.x >= rcWindow.right)
  168. return HTCLOSE;
  169. if ((pt.x < rcWindow.right) && !TestWF(pwnd, WEFTOOLWINDOW))
  170. {
  171. // Are we in the maximize/restore button?
  172. if (TestWF(pwnd, (WFMAXBOX | WFMINBOX)))
  173. {
  174. // Note that sizing buttons are same width for both
  175. // big captions and small captions.
  176. rcWindow.right -= dxButton;
  177. if (pt.x >= rcWindow.right)
  178. return HTZOOM;
  179. // Are we in the minimize button?
  180. rcWindow.right -= dxButton;
  181. if (pt.x >= rcWindow.right)
  182. return HTREDUCE;
  183. }
  184. else if (TestWF(pwnd, WEFCONTEXTHELP))
  185. {
  186. rcWindow.right -= dxButton;
  187. if (pt.x >= rcWindow.right)
  188. return HTHELP;
  189. }
  190. #ifdef LAME_BUTTON
  191. LameButtonHitTest:
  192. if (TestWF(pwnd, WEFLAMEBUTTON)) {
  193. rcWindow.right -= (gpsi->ncxLame + 2 * SYSMET(CXEDGE));
  194. if (TestWF(pwnd, WEFRIGHT)) {
  195. if (pt.x >= rcWindow.left &&
  196. pt.x < rcWindow.left + gpsi->ncxLame) {
  197. return HTLAMEBUTTON;
  198. }
  199. } else {
  200. if (pt.x >= rcWindow.right &&
  201. pt.x < rcWindow.right + gpsi->ncxLame) {
  202. return HTLAMEBUTTON;
  203. }
  204. }
  205. }
  206. #endif // LAME_BUTTON
  207. }
  208. }
  209. }
  210. // We're in the caption proper
  211. return HTCAPTION;
  212. }
  213. //
  214. // Are we in the menu?
  215. //
  216. if (TestWF(pwnd, WFMPRESENT)) {
  217. return HTMENU;
  218. }
  219. }
  220. } else {
  221. //
  222. // NOTE:
  223. // We can only be here if we are on the client edge, horz scroll,
  224. // sizebox, or vert scroll. Hence, if we are not on the first 3,
  225. // we must be on the last one.
  226. //
  227. //
  228. // Are we on the client edge?
  229. //
  230. if (TestWF(pwnd, WEFCLIENTEDGE)) {
  231. InflateRect(&rcClientAdj, -SYSMETRTL(CXEDGE), -SYSMETRTL(CYEDGE));
  232. if (!PtInRect(&rcClientAdj, pt)) {
  233. return HTBORDER;
  234. }
  235. }
  236. //
  237. // Are we on the scrollbars?
  238. //
  239. if (TestWF(pwnd, WFHPRESENT) && (pt.y >= rcClient.bottom)) {
  240. int iHitTest = HTHSCROLL;
  241. UserAssert(pt.y < rcClientAdj.bottom);
  242. if (TestWF(pwnd, WFVPRESENT)) {
  243. PWND pwndSizeBox = SizeBoxHwnd(pwnd);
  244. if (pt.x >= rcClient.right) {
  245. return pwndSizeBox ? HTBOTTOMRIGHT : HTGROWBOX;
  246. } else if (TestWF(pwnd, WEFLAYOUTRTL) && (pt.x < rcClient.left)) {
  247. //
  248. // Mirror the grip box location so that it becomes
  249. // on the bottom-left side if this is a RTL mirrrored
  250. // windows.
  251. //
  252. return pwndSizeBox ? HTBOTTOMLEFT : HTGROWBOX;
  253. }
  254. }
  255. return iHitTest;
  256. } else {
  257. UserAssert(TestWF(pwnd, WFVPRESENT));
  258. if ((!!TestWF(pwnd, WEFLEFTSCROLL)) ^ (!!TestWF(pwnd, WEFLAYOUTRTL))) {
  259. UserAssert(pt.x < rcClient.left);
  260. UserAssert(pt.x >= rcClientAdj.left);
  261. } else {
  262. UserAssert(pt.x >= rcClient.right);
  263. UserAssert(pt.x < rcClientAdj.right);
  264. }
  265. return HTVSCROLL;
  266. }
  267. }
  268. //
  269. // We give up.
  270. //
  271. // Win31 returned HTNOWHERE in this case; For compatibility, we will
  272. // keep it that way.
  273. //
  274. return HTNOWHERE;
  275. }
  276. BOOL _FChildVisible(
  277. PWND pwnd)
  278. {
  279. while (TestwndChild(pwnd)) {
  280. pwnd = REBASEPWND(pwnd, spwndParent);
  281. if (pwnd == NULL) {
  282. break;
  283. } else if (!TestWF(pwnd, WFVISIBLE)) {
  284. return FALSE;
  285. }
  286. }
  287. return TRUE;
  288. }
  289. /***************************************************************************\
  290. * _MapWindowPoints
  291. *
  292. *
  293. * History:
  294. * 03-03-92 JimA Ported from Win 3.1 sources.
  295. \***************************************************************************/
  296. int _MapWindowPoints(
  297. PWND pwndFrom,
  298. PWND pwndTo,
  299. LPPOINT lppt,
  300. DWORD cpt)
  301. {
  302. int dx = 0, dy = 0;
  303. int SaveLeft, Sign = 1;
  304. RECT *pR = (RECT *)lppt;
  305. BOOL bMirrored = FALSE;
  306. /*
  307. * If a window is NULL, use the desktop window.
  308. * If the window is the desktop, don't offset by
  309. * the client rect, since it won't work if the screen
  310. * origin is not (0,0) - use zero instead.
  311. */
  312. /*
  313. * Compute deltas
  314. */
  315. if (pwndFrom && GETFNID(pwndFrom) != FNID_DESKTOP) {
  316. if (TestWF(pwndFrom, WEFLAYOUTRTL)) {
  317. Sign = -Sign;
  318. dx = -pwndFrom->rcClient.right;
  319. bMirrored = (cpt == 2);
  320. } else {
  321. dx = pwndFrom->rcClient.left;
  322. }
  323. dy = pwndFrom->rcClient.top;
  324. }
  325. if (pwndTo && GETFNID(pwndTo) != FNID_DESKTOP) {
  326. if (TestWF(pwndTo, WEFLAYOUTRTL)) {
  327. Sign = -Sign;
  328. dx = dx + Sign * pwndTo->rcClient.right;
  329. bMirrored = (cpt == 2);
  330. } else {
  331. dx = dx - Sign * pwndTo->rcClient.left;
  332. }
  333. dy = dy - pwndTo->rcClient.top;
  334. }
  335. /*
  336. * Map the points
  337. */
  338. while (cpt--) {
  339. lppt->x += dx;
  340. lppt->x *= Sign;
  341. lppt->y += dy;
  342. ++lppt;
  343. }
  344. if (bMirrored) { //Special case for Rect
  345. SaveLeft = min (pR->left, pR->right);
  346. pR->right = max (pR->left, pR->right);
  347. pR->left = SaveLeft;
  348. }
  349. return MAKELONG(dx, dy);
  350. }
  351. /***************************************************************************\
  352. *
  353. * GetRealClientRect()
  354. *
  355. * Gets real client rectangle, inc. scrolls and excl. one row or column
  356. * of minimized windows.
  357. *
  358. * If hwndParent is the desktop, then
  359. * * If pMonitor is NULL, use the primary monitor
  360. * * Otherwise use the appropriate monitor's rectangles
  361. *
  362. \***************************************************************************/
  363. VOID GetRealClientRect(
  364. PWND pwnd,
  365. LPRECT prc,
  366. UINT uFlags,
  367. PMONITOR pMonitor)
  368. {
  369. if (GETFNID(pwnd) == FNID_DESKTOP) {
  370. if (!pMonitor) {
  371. pMonitor = GetPrimaryMonitor();
  372. }
  373. *prc = (uFlags & GRC_FULLSCREEN) ? pMonitor->rcMonitor : pMonitor->rcWork;
  374. } else {
  375. GetRect(pwnd, prc, GRECT_CLIENT | GRECT_CLIENTCOORDS);
  376. if (uFlags & GRC_SCROLLS) {
  377. if (TestWF(pwnd, WFHPRESENT)) {
  378. prc->bottom += SYSMETRTL(CYHSCROLL);
  379. }
  380. if (TestWF(pwnd, WFVPRESENT)) {
  381. prc->right += SYSMETRTL(CXVSCROLL);
  382. }
  383. }
  384. }
  385. if (uFlags & GRC_MINWNDS) {
  386. switch (SYSMETRTL(ARRANGE) & ~ARW_HIDE) {
  387. case ARW_TOPLEFT | ARW_RIGHT:
  388. case ARW_TOPRIGHT | ARW_LEFT:
  389. //
  390. // Leave space on top for one row of min windows
  391. //
  392. prc->top += SYSMETRTL(CYMINSPACING);
  393. break;
  394. case ARW_TOPLEFT | ARW_DOWN:
  395. case ARW_BOTTOMLEFT | ARW_UP:
  396. //
  397. // Leave space on left for one column of min windows
  398. //
  399. prc->left += SYSMETRTL(CXMINSPACING);
  400. break;
  401. case ARW_TOPRIGHT | ARW_DOWN:
  402. case ARW_BOTTOMRIGHT | ARW_UP:
  403. //
  404. // Leave space on right for one column of min windows
  405. //
  406. prc->right -= SYSMETRTL(CXMINSPACING);
  407. break;
  408. case ARW_BOTTOMLEFT | ARW_RIGHT:
  409. case ARW_BOTTOMRIGHT | ARW_LEFT:
  410. //
  411. // Leave space on bottom for one row of min windows
  412. //
  413. prc->bottom -= SYSMETRTL(CYMINSPACING);
  414. break;
  415. }
  416. }
  417. }
  418. /***************************************************************************\
  419. * _GetLastActivePopup (API)
  420. *
  421. *
  422. *
  423. * History:
  424. * 11-27-90 darrinm Ported from Win 3.0 sources.
  425. * 02-19-91 JimA Added enum access check
  426. \***************************************************************************/
  427. PWND _GetLastActivePopup(
  428. PWND pwnd)
  429. {
  430. if (pwnd->spwndLastActive == NULL)
  431. return pwnd;
  432. return REBASEPWND(pwnd, spwndLastActive);
  433. }
  434. /***************************************************************************\
  435. * IsDescendant
  436. *
  437. * Internal version if IsChild that is a bit faster and ignores the WFCHILD
  438. * business.
  439. *
  440. * Returns TRUE if pwndChild == pwndParent (IsChild doesn't).
  441. *
  442. * History:
  443. * 07-22-91 darrinm Translated from Win 3.1 ASM code.
  444. * 03-03-94 Johnl Moved from server
  445. \***************************************************************************/
  446. BOOL _IsDescendant(
  447. PWND pwndParent,
  448. PWND pwndChild)
  449. {
  450. while (1) {
  451. if (pwndParent == pwndChild)
  452. return TRUE;
  453. if (GETFNID(pwndChild) == FNID_DESKTOP)
  454. break;
  455. pwndChild = REBASEPWND(pwndChild, spwndParent);
  456. }
  457. return FALSE;
  458. }
  459. /***************************************************************************\
  460. * IsVisible
  461. *
  462. * Return whether or not a given window can be drawn in or not.
  463. *
  464. * History:
  465. * 07-22-91 darrinm Translated from Win 3.1 ASM code.
  466. \***************************************************************************/
  467. BOOL IsVisible(
  468. PWND pwnd)
  469. {
  470. PWND pwndT;
  471. for (pwndT = pwnd; pwndT; pwndT = REBASEPWND(pwndT, spwndParent)) {
  472. /*
  473. * Invisible windows are always invisible
  474. */
  475. if (!TestWF(pwndT, WFVISIBLE))
  476. return FALSE;
  477. if (TestWF(pwndT, WFMINIMIZED)) {
  478. /*
  479. * Children of minimized windows are always invisible.
  480. */
  481. if (pwndT != pwnd)
  482. return FALSE;
  483. }
  484. /*
  485. * If we're at the desktop, then we don't want to go any further.
  486. */
  487. if (GETFNID(pwndT) == FNID_DESKTOP)
  488. break;
  489. }
  490. return TRUE;
  491. }
  492. /***************************************************************************\
  493. *
  494. * Function: GetWindowBorders
  495. *
  496. * Synopsis: Calculates # of borders around window
  497. *
  498. * Algorithm: Calculate # of window borders and # of client borders
  499. *
  500. * This routine is ported from Chicago wmclient.c -- FritzS
  501. *
  502. \***************************************************************************/
  503. int GetWindowBorders(LONG lStyle, DWORD dwExStyle, BOOL fWindow, BOOL fClient)
  504. {
  505. int cBorders = 0;
  506. if (fWindow) {
  507. //
  508. // Is there a 3D border around the window?
  509. //
  510. if (dwExStyle & WS_EX_WINDOWEDGE)
  511. cBorders += 2;
  512. else if (dwExStyle & WS_EX_STATICEDGE)
  513. ++cBorders;
  514. //
  515. // Is there a single flat border around the window? This is true for
  516. // WS_BORDER, WS_DLGFRAME, and WS_EX_DLGMODALFRAME windows.
  517. //
  518. if ( (lStyle & WS_CAPTION) || (dwExStyle & WS_EX_DLGMODALFRAME) )
  519. ++cBorders;
  520. //
  521. // Is there a sizing flat border around the window?
  522. //
  523. if (lStyle & WS_SIZEBOX)
  524. cBorders += gpsi->gclBorder;
  525. }
  526. if (fClient) {
  527. //
  528. // Is there a 3D border around the client?
  529. //
  530. if (dwExStyle & WS_EX_CLIENTEDGE)
  531. cBorders += 2;
  532. }
  533. return cBorders;
  534. }
  535. /***************************************************************************\
  536. * SizeBoxHwnd()
  537. *
  538. * Returns the HWND that will be sized if the user drags in the given window's
  539. * sizebox -- If NULL, then the sizebox is not needed
  540. *
  541. * Criteria for choosing what window will be sized:
  542. * find first sizeable parent; if that parent is not maximized and the child's
  543. * bottom, right corner is within a scroll bar height and width of the parent's
  544. * bottom, right corner, that parent will be sized.
  545. *
  546. * From Chicago
  547. \***************************************************************************/
  548. PWND SizeBoxHwnd(
  549. PWND pwnd)
  550. {
  551. BOOL bMirroredSizeBox = (BOOL) TestWF(pwnd, WEFLAYOUTRTL);
  552. int xbrChild;
  553. int ybrChild = pwnd->rcWindow.bottom;
  554. if (bMirroredSizeBox) {
  555. xbrChild = pwnd->rcWindow.left;
  556. } else {
  557. xbrChild = pwnd->rcWindow.right;
  558. }
  559. while (GETFNID(pwnd) != FNID_DESKTOP) {
  560. if (TestWF(pwnd, WFSIZEBOX)) {
  561. // First sizeable parent found
  562. int xbrParent;
  563. int ybrParent;
  564. if (TestWF(pwnd, WFMAXIMIZED))
  565. return NULL;
  566. if (bMirroredSizeBox) {
  567. xbrParent = pwnd->rcClient.left;
  568. } else {
  569. xbrParent = pwnd->rcClient.right;
  570. }
  571. ybrParent = pwnd->rcClient.bottom;
  572. /* If the sizebox dude is within an EDGE of the client's bottom
  573. * right corner (left corner for mirrored windows), let this succeed.
  574. * That way people who draw their own sunken clients will be happy.
  575. */
  576. if (bMirroredSizeBox) {
  577. if ((xbrChild - SYSMETRTL(CXEDGE) > xbrParent) || (ybrChild + SYSMETRTL(CYEDGE) < ybrParent)) {
  578. //
  579. // Child's bottom, left corner of SIZEBOX isn't close enough
  580. // to bottom left of parent's client.
  581. //
  582. return NULL;
  583. }
  584. } else {
  585. if ((xbrChild + SYSMETRTL(CXEDGE) < xbrParent) || (ybrChild + SYSMETRTL(CYEDGE) < ybrParent)) {
  586. //
  587. // Child's bottom, right corner of SIZEBOX isn't close enough
  588. // to bottom right of parent's client.
  589. //
  590. return NULL;
  591. }
  592. }
  593. return pwnd;
  594. }
  595. if (!TestWF(pwnd, WFCHILD) || TestWF(pwnd, WFCPRESENT))
  596. break;
  597. pwnd = REBASEPWND(pwnd, spwndParent);
  598. }
  599. return NULL;
  600. }
  601. // --------------------------------------------------------------------------
  602. //
  603. // NeedsWindowEdge()
  604. //
  605. // Modifies style/extended style to enforce WS_EX_WINDOWEDGE when we want
  606. // it.
  607. //
  608. //
  609. // When do we want WS_EX_WINDOWEDGE on a window?
  610. // (1) If the window has a caption
  611. // (2) If the window has the WS_DLGFRAME or WS_EX_DLGFRAME style (note
  612. // that this takes care of (1))
  613. // (3) If the window has WS_THICKFRAME
  614. //
  615. // --------------------------------------------------------------------------
  616. BOOL NeedsWindowEdge(
  617. DWORD dwStyle,
  618. DWORD dwExStyle,
  619. BOOL fNewApp)
  620. {
  621. BOOL fGetsWindowEdge = FALSE;
  622. if (dwExStyle & WS_EX_DLGMODALFRAME) {
  623. fGetsWindowEdge = TRUE;
  624. } else if (dwExStyle & WS_EX_STATICEDGE) {
  625. fGetsWindowEdge = FALSE;
  626. } else if (dwStyle & WS_THICKFRAME) {
  627. fGetsWindowEdge = TRUE;
  628. } else {
  629. switch (dwStyle & WS_CAPTION) {
  630. case WS_DLGFRAME:
  631. fGetsWindowEdge = TRUE;
  632. break;
  633. case WS_CAPTION:
  634. fGetsWindowEdge = fNewApp;
  635. break;
  636. }
  637. }
  638. return fGetsWindowEdge;
  639. }
  640. // --------------------------------------------------------------------------
  641. //
  642. // HasCaptionIcon()
  643. //
  644. // TRUE if this is a window that should have an icon drawn in its caption
  645. // FALSE otherwise
  646. //
  647. // --------------------------------------------------------------------------
  648. BOOL _HasCaptionIcon(
  649. PWND pwnd)
  650. {
  651. HICON hIcon;
  652. PCLS pcls;
  653. if (TestWF(pwnd, WEFTOOLWINDOW)) {
  654. // it's a tool window -- it doesn't get an icon
  655. return FALSE;
  656. }
  657. if ((TestWF(pwnd, WFBORDERMASK) != (BYTE)LOBYTE(WFDLGFRAME)) &&
  658. !TestWF(pwnd, WEFDLGMODALFRAME)) {
  659. // they are not trying to look like a dialog, they get an icon
  660. return TRUE;
  661. }
  662. if (!TestWF(pwnd, WFWIN40COMPAT) &&
  663. (((PCLS)REBASEALWAYS(pwnd, pcls))->atomClassName == (ATOM)(ULONG_PTR)DIALOGCLASS)) {
  664. /*
  665. * It's an older REAL dialog -- it doesn't get an icon.
  666. */
  667. return FALSE;
  668. }
  669. hIcon = (HICON) _GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp), TRUE);
  670. if (hIcon) {
  671. // It's a 4.0 dialog with a small icon -- if that small icon is
  672. // something other than the generic small windows icon, it gets an icon.
  673. return hIcon != gpsi->hIconSmWindows;
  674. }
  675. hIcon = (HICON) _GetProp(pwnd, MAKEINTATOM(gpsi->atomIconProp), TRUE);
  676. if (hIcon && (hIcon != gpsi->hIcoWindows)) {
  677. // It's a 4.0 dialog with no small icon, but instead a large icon
  678. // that's not the generic windows icon -- it gets an icon.
  679. return TRUE;
  680. }
  681. pcls = REBASEALWAYS(pwnd, pcls);
  682. if (pcls->spicnSm) {
  683. if (pcls->spicnSm != HMObjectFromHandle(gpsi->hIconSmWindows)) {
  684. // It's a 4.0 dialog with a class icon that's not the generic
  685. // windows icon -- it gets an icon.
  686. return TRUE;
  687. }
  688. }
  689. // It's a 4.0 dialog with no small or large icon -- it doesn't get an icon.
  690. return FALSE;
  691. }
  692. /***************************************************************************\
  693. * GetTopLevelWindow
  694. *
  695. * History:
  696. * 10-19-90 darrinm Ported from Win 3.0 sources.
  697. \***************************************************************************/
  698. PWND GetTopLevelWindow(
  699. PWND pwnd)
  700. {
  701. if (pwnd != NULL) {
  702. while (TestwndChild(pwnd)) {
  703. pwnd = REBASEPWND(pwnd, spwndParent);
  704. }
  705. }
  706. return pwnd;
  707. }
  708. /***************************************************************************\
  709. * GetRect
  710. *
  711. * Returns a rect from pwnd (client or window) and returns it in
  712. * one of these coordinate schemes:
  713. *
  714. * (a) Own Client
  715. * (b) Own Window
  716. * (c) Parent Client
  717. *
  718. * Moreover, it does the right thing for case (d) when pwnd is top level.
  719. * In that case, we never want to offset by origin of the parent, which is the
  720. * desktop, since that will not work when the virtual screen has a
  721. * negative origin. And it does the right thing for cases (b) and (c)
  722. * if pwnd is the desktop.
  723. *
  724. * NOTE: The Win95 version of this function had a flag GRECT_SCREENCOORDS,
  725. * which would return the rectangle in screen coords. There's no reason to
  726. * call a function to do this, since the smallest and fastest to copy a
  727. * rectangle is simple assignment. Therefore, I removed GRECT_SCREENCOORDS.
  728. *
  729. * History:
  730. * 19-Sep-1996 adams Created.
  731. \***************************************************************************/
  732. VOID GetRect(
  733. PWND pwnd,
  734. LPRECT lprc,
  735. UINT uCoords)
  736. {
  737. PWND pwndParent;
  738. LPRECT lprcOffset;
  739. UserAssert(lprc);
  740. UserAssert((uCoords & ~(GRECT_COORDMASK | GRECT_RECTMASK)) == 0);
  741. UserAssert(uCoords & GRECT_COORDMASK);
  742. UserAssert(uCoords & GRECT_RECTMASK);
  743. *lprc = (uCoords & GRECT_WINDOW) ? pwnd->rcWindow : pwnd->rcClient;
  744. /*
  745. * If this is the desktop window, we have what we want, whether we
  746. * are asking for GRECT_PARENTCOORDS, WINDOWCOORD or CLIENTCOORDS
  747. */
  748. if (GETFNID(pwnd) == FNID_DESKTOP) {
  749. return;
  750. }
  751. switch (uCoords & GRECT_COORDMASK) {
  752. case GRECT_PARENTCOORDS:
  753. pwndParent = REBASEPWND(pwnd, spwndParent);
  754. if (GETFNID(pwndParent) == FNID_DESKTOP) {
  755. return;
  756. }
  757. lprcOffset = KPRECT_TO_PRECT(&pwndParent->rcClient);
  758. //
  759. // Let's mirror the edges of the child's window since the parent
  760. // is mirrored, so should the child window be. [samera]
  761. //
  762. if (TestWF(pwndParent,WEFLAYOUTRTL) &&
  763. (uCoords & GRECT_WINDOW) &&
  764. (TestWF(pwnd,WFCHILD))) {
  765. int iLeft;
  766. //
  767. // I am using OffsetRect instead of implementing a new
  768. // OffsetMirrorRect API since this is the only place I am
  769. // doing it in.
  770. //
  771. // Since screen coordinates are not mirrored, the rect offsetting
  772. // should be done relative to prcOffset->right since it is the
  773. // leading edge for mirrored windows. [samera]
  774. //
  775. UserVerify(OffsetRect(lprc, -lprcOffset->right, -lprcOffset->top));
  776. iLeft = lprc->left;
  777. lprc->left = (lprc->right * -1);
  778. lprc->right = (iLeft * -1);
  779. return;
  780. }
  781. break;
  782. case GRECT_WINDOWCOORDS:
  783. lprcOffset = KPRECT_TO_PRECT(&pwnd->rcWindow);
  784. break;
  785. case GRECT_CLIENTCOORDS:
  786. lprcOffset = KPRECT_TO_PRECT(&pwnd->rcClient);
  787. break;
  788. default:
  789. RIPMSG1(RIP_ERROR,
  790. "Logic error in GetRect - invalid uCoords 0x%x",
  791. uCoords);
  792. return;
  793. }
  794. UserVerify(OffsetRect(lprc, -lprcOffset->left, -lprcOffset->top));
  795. }
  796. #ifdef _USERK_
  797. #if DBG
  798. DWORD GetDbgTagFlags(
  799. int tag)
  800. {
  801. return (gpsi != NULL ? gpsi->adwDBGTAGFlags[tag] : 0);
  802. }
  803. DWORD GetRipFlags(
  804. VOID)
  805. {
  806. return (gpsi != NULL ? gpsi->dwRIPFlags : RIPF_DEFAULT);
  807. }
  808. #endif
  809. #endif