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.

2488 lines
79 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: dwp.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains xxxDefWindowProc and related functions.
  7. *
  8. * History:
  9. * 10-22-90 DarrinM Created stubs.
  10. * 13-Feb-1991 mikeke Added Revalidation code
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. /***************************************************************************\
  15. *
  16. * DWP_DrawItem()
  17. *
  18. * Does default WM_DRAWITEM handling.
  19. *
  20. \***************************************************************************/
  21. void DWP_DrawItem(
  22. LPDRAWITEMSTRUCT lpdis)
  23. {
  24. if (lpdis->CtlType == ODT_LISTBOX) {
  25. /*
  26. * Default OwnerDraw Listbox Item Drawing
  27. */
  28. if ( (lpdis->itemAction == ODA_FOCUS)
  29. || ( lpdis->itemAction == ODA_DRAWENTIRE
  30. && lpdis->itemState & ODS_FOCUS)
  31. ) {
  32. ClientFrame(lpdis->hDC, &lpdis->rcItem, gpsi->hbrGray, PATINVERT, 1, 1);
  33. }
  34. }
  35. }
  36. /***************************************************************************\
  37. * xxxDWP_SetRedraw
  38. *
  39. * This routine sets/resets the VISIBLE flag for windows who don't want any
  40. * redrawing. Although a fast way of preventing paints, it is the apps
  41. * responsibility to reset this flag once they need painting. Otherwise,
  42. * the window will be rendered transparent (could leave turds on the
  43. * screen).
  44. *
  45. *
  46. * History:
  47. * 07-24-91 darrinm Ported from Win 3.1 sources.
  48. \***************************************************************************/
  49. void xxxDWP_SetRedraw(
  50. PWND pwnd,
  51. BOOL fRedraw)
  52. {
  53. CheckLock(pwnd);
  54. UserAssert(IsWinEventNotifyDeferredOK());
  55. if (fRedraw) {
  56. if (!TestWF(pwnd, WFVISIBLE)) {
  57. SetVisible(pwnd, SV_SET);
  58. /*
  59. * We made this window visible - if it is behind any SPBs,
  60. * then we need to go invalidate them.
  61. *
  62. * We do this AFTER we make the window visible, so that
  63. * SpbCheckHwnd won't ignore it.
  64. */
  65. if (AnySpbs())
  66. SpbCheckPwnd(pwnd);
  67. /*
  68. * Now we need to invalidate/recalculate any affected cache entries
  69. * This call must be AFTER the window state change
  70. * No need to DeferWinEventNotify() since pwnd is threadlocked.
  71. */
  72. zzzInvalidateDCCache(pwnd, IDC_DEFAULT);
  73. /*
  74. * Because 3.1 sometimes doesn't draw window frames when 3.0 did,
  75. * we need to ensure that the frame gets drawn if the window is
  76. * later invalidated after a WM_SETREDRAW(TRUE)
  77. */
  78. SetWF(pwnd, WFSENDNCPAINT);
  79. }
  80. } else {
  81. if (TestWF(pwnd, WFVISIBLE)) {
  82. /*
  83. * Invalidate any SPBs.
  84. *
  85. * We do this BEFORE we make the window invisible, so
  86. * SpbCheckHwnd() won't ignore it.
  87. */
  88. if (AnySpbs())
  89. SpbCheckPwnd(pwnd);
  90. /*
  91. * Clear WFVISIBLE and delete any update regions lying around.
  92. */
  93. SetVisible(pwnd, SV_UNSET | (TestWF(pwnd, WFWIN31COMPAT) ? SV_CLRFTRUEVIS : 0));
  94. /*
  95. * Now we need to invalidate/recalc affected cache entries
  96. * This call must be AFTER the window state change
  97. * No need to DeferWinEventNotify() since we're about to return.
  98. */
  99. zzzInvalidateDCCache(pwnd, IDC_DEFAULT);
  100. }
  101. }
  102. }
  103. /***************************************************************************\
  104. * DWP_GetEnabledPopup
  105. *
  106. * History:
  107. * 10-28-90 MikeHar Ported from Windows.
  108. \***************************************************************************/
  109. PWND DWP_GetEnabledPopup(
  110. PWND pwndStart)
  111. {
  112. PWND pwndT, pwnd;
  113. PTHREADINFO ptiStart;
  114. BOOL fVisitedFirstChild = FALSE;
  115. ptiStart = GETPTI(pwndStart);
  116. pwnd = pwndStart->spwndNext;
  117. #ifdef SYSMODALWINDOWS
  118. if (gspwndSysModal)
  119. return NULL;
  120. #endif
  121. /*
  122. * The user clicked on a window that is disabled. That window is pwndStart.
  123. * This loop is designed to evaluate what application this window is
  124. * associated with, and activate that "application", by finding what window
  125. * associated with that application can be activated. This is done by
  126. * enumerating top level windows, searching for a top level enabled
  127. * and visible ownee associated with this application.
  128. */
  129. while (pwnd != pwndStart) {
  130. if (pwnd == NULL) {
  131. /*
  132. * Warning! Win 3.1 had PWNDDESKTOP(pwndStart)->spwndChild
  133. * which could loop forever if pwndStart was a child window
  134. */
  135. if (fVisitedFirstChild) {
  136. /*
  137. * If we visited the first child before then do not loop
  138. * for ever, it is time to return.
  139. */
  140. return NULL;
  141. }
  142. pwnd = pwndStart->spwndParent->spwndChild;
  143. fVisitedFirstChild = TRUE;
  144. continue;
  145. }
  146. /*
  147. * We have two cases we need to watch out for here. The first is when
  148. * applications call AssociateThreadInput() to tie two threads
  149. * together to share input state. If the threads own the same queue,
  150. * then associate them together: this way, when two threads call
  151. * AttachThreadInput(), one created the main window, one created the
  152. * dialog window, when you click on the main window, they'll both
  153. * come to the top (rather than beeping). In this case we want to
  154. * compare queues. When Control Panel starts Setup in the Network
  155. * applet is one type of example of attached input.
  156. *
  157. * The second case is WOW apps. All wow apps have the same queue
  158. * so to retain Win 3.1 compatibility, we want to treat each app
  159. * as an individual task (Win 3.1 tests hqs), so we will compare
  160. * PTI's for WOW apps.
  161. *
  162. * To see this case start 16 bit notepad and 16 bit write. Do file
  163. * open on write and then give notepad the focus now click on write's
  164. * main window and the write file open dialog should activate.
  165. *
  166. * Another related case is powerpnt. This case is interesting because
  167. * it tests that we do not find another window to activate when nested
  168. * windows are up and you click on a owner's owner. Run Powerpnt, do
  169. * Edit-Insert-Picture and Object-Recolor Picture will bring up a
  170. * dialog with combos, drop down one of the color combo and then click
  171. * on powerpnt's main window - focus should stay with the dialogs
  172. * combo and it should stay dropped down.
  173. */
  174. if (((ptiStart->TIF_flags & TIF_16BIT) && (GETPTI(pwnd) == ptiStart)) ||
  175. (!(ptiStart->TIF_flags & TIF_16BIT) && (GETPTI(pwnd)->pq == ptiStart->pq))) {
  176. if (!TestWF(pwnd, WFDISABLED) && TestWF(pwnd, WFVISIBLE)) {
  177. pwndT = pwnd->spwndOwner;
  178. /*
  179. * If this window is the parent of a popup window,
  180. * bring up only one.
  181. */
  182. while (pwndT) {
  183. if (pwndT == pwndStart)
  184. return pwnd;
  185. pwndT = pwndT->spwndOwner;
  186. }
  187. /*
  188. * Win9x continues looping only if pwnd is WEFTOPMOST. NT4 just returns, like Win3.1
  189. * As soon as we find a window on the queue, we stop. So if the queue owns
  190. * multiple top level unowned windows, then this code will probably not find
  191. * the enabled popup. Note that owned windows are supposed to be on top of the
  192. * owner, usally right on top of it (ie, pwnd->spwndNext == pwnd->spwndOwner)
  193. * so this code used to find any other top level unowned windows before the enabled
  194. * popup and bail. Odd.
  195. * So let's continue looping. Hopefully this won't cause any compatibility problems
  196. */
  197. // return NULL;
  198. }
  199. }
  200. pwnd = pwnd->spwndNext;
  201. }
  202. return NULL;
  203. }
  204. /***************************************************************************\
  205. * xxxDWP_ProcessVirtKey
  206. *
  207. * History:
  208. * 10-28-90 MikeHar Ported from Windows.
  209. \***************************************************************************/
  210. void xxxDWP_ProcessVirtKey(
  211. UINT wKey)
  212. {
  213. PTHREADINFO pti;
  214. TL tlpwndActive;
  215. pti = PtiCurrent();
  216. if (pti->pq->spwndActive == NULL)
  217. return;
  218. switch (wKey) {
  219. case VK_F4:
  220. if (TestCF(pti->pq->spwndActive, CFNOCLOSE))
  221. break;
  222. /*
  223. * Don't change the focus if the child window has it.
  224. */
  225. if (pti->pq->spwndFocus == NULL ||
  226. GetTopLevelWindow(pti->pq->spwndFocus) !=
  227. pti->pq->spwndActive) {
  228. ThreadLockAlwaysWithPti(pti, pti->pq->spwndActive, &tlpwndActive);
  229. xxxSetFocus(pti->pq->spwndActive);
  230. ThreadUnlock(&tlpwndActive);
  231. }
  232. _PostMessage(pti->pq->spwndActive, WM_SYSCOMMAND, SC_CLOSE, 0L);
  233. break;
  234. case VK_TAB:
  235. /*
  236. * If alt-tab is reserved by console, don't bring up the alt-tab
  237. * window.
  238. */
  239. if (GETPTI(pti->pq->spwndActive)->fsReserveKeys & CONSOLE_ALTTAB)
  240. break;
  241. case VK_ESCAPE:
  242. case VK_F6:
  243. ThreadLockAlwaysWithPti(pti, pti->pq->spwndActive, &tlpwndActive);
  244. xxxSendMessage(pti->pq->spwndActive, WM_SYSCOMMAND,
  245. (UINT)(_GetKeyState(VK_SHIFT) < 0 ? SC_NEXTWINDOW : SC_PREVWINDOW),
  246. (LONG)(DWORD)(WORD)wKey);
  247. ThreadUnlock(&tlpwndActive);
  248. break;
  249. }
  250. }
  251. /***************************************************************************\
  252. * xxxDWP_Paint
  253. *
  254. * Handle WM_PAINT and WM_PAINTICON messages.
  255. *
  256. * History:
  257. * 07-24-91 darrinm Ported from Win 3.1 sources.
  258. \***************************************************************************/
  259. void xxxDWP_Paint(
  260. PWND pwnd)
  261. {
  262. PAINTSTRUCT ps;
  263. CheckLock(pwnd);
  264. /*
  265. * Bad handling of a WM_PAINT message, the application called
  266. * BeginPaint/EndPaint and is now calling DefWindowProc for the same
  267. * WM_PAINT message. Just return so we don't get full drag problems.
  268. * (Word and Excel do this).
  269. *
  270. * Added the check for empty-client-rects. ObjectVision has a problem
  271. * with empty-windows being invalidated during a full-drag. They used
  272. * to get blocked at the STARTPAINT and couldn't get through to
  273. * xxxBeginPaint to validate their update-rgn.
  274. *
  275. * i.e.
  276. * a) Parent has a child-window with an empty rect. On a full
  277. * drag of the parent, we process SetWindowPos() to paint
  278. * the new position.
  279. *
  280. * b) During the parents processing of WM_PAINT, it calls
  281. * GetUpdateRect() on the empty-child, which sets the STARTPAINT
  282. * on its window.
  283. *
  284. * c) On return to the parent WM_PAINT handler, it calls
  285. * UpdateWindow() on the child, and used to get blocked here
  286. * because the STARTPAINT bit was set. The Child never gets
  287. * updated, causing an infinite loop.
  288. *
  289. * *) By checking for an empty-rectangle, we will let it through
  290. * to validate.
  291. *
  292. */
  293. if (TestWF(pwnd, WFSTARTPAINT) && !IsRectEmpty(&(pwnd->rcClient))) {
  294. return;
  295. }
  296. if (xxxBeginPaint(pwnd, &ps)) {
  297. xxxEndPaint(pwnd, &ps);
  298. }
  299. }
  300. /***************************************************************************\
  301. * xxxDWP_EraseBkgnd
  302. *
  303. *
  304. * History:
  305. * 07-24-91 darrinm Ported from Win 3.1 sources.
  306. \***************************************************************************/
  307. BOOL xxxDWP_EraseBkgnd(
  308. PWND pwnd,
  309. UINT msg,
  310. HDC hdc)
  311. {
  312. HBRUSH hbr;
  313. CheckLock(pwnd);
  314. switch (msg) {
  315. case WM_ICONERASEBKGND:
  316. //
  317. // Old compatibility: Many hack apps use this to paint the
  318. // desktop wallpaper. We never send WM_ICONERASEBKGND anymore
  319. // because we don't have client areas in our minimized windows.
  320. //
  321. if (!TestWF(pwnd, WFCHILD)) {
  322. xxxInternalPaintDesktop(pwnd, hdc, TRUE);
  323. } else {
  324. return FALSE;
  325. }
  326. break;
  327. case WM_ERASEBKGND:
  328. if (hbr = pwnd->pcls->hbrBackground) {
  329. // Convert sys colors to proper brush
  330. if (hbr <= (HBRUSH)COLOR_MAX)
  331. hbr = SYSHBRUSH((ULONG_PTR)hbr - 1);
  332. /*
  333. * Remove call to UnrealizeObject. GDI handles this
  334. * for brushes on NT.
  335. *
  336. * if (hbr != SYSHBR(DESKTOP))
  337. * GreUnrealizeObject(hbr);
  338. */
  339. xxxFillWindow(pwnd, pwnd, hdc, hbr);
  340. } else {
  341. return FALSE;
  342. }
  343. }
  344. return TRUE;
  345. }
  346. /***************************************************************************\
  347. * xxxDWP_SetCursorInfo
  348. *
  349. *
  350. * History:
  351. * 26-Apr-1994 mikeke Created
  352. \***************************************************************************/
  353. /***************************************************************************\
  354. * xxxDWP_SetCursor
  355. *
  356. *
  357. * History:
  358. * 07-24-91 darrinm Ported from Win 3.1 sources.
  359. \***************************************************************************/
  360. BOOL xxxDWP_SetCursor(
  361. PWND pwnd,
  362. HWND hwndHit,
  363. int codeHT,
  364. UINT msg)
  365. {
  366. PWND pwndParent, pwndPopup, pwndHit;
  367. PCURSOR pcur;
  368. LRESULT lt;
  369. TL tlpwndParent;
  370. TL tlpwndPopup;
  371. CheckLock(pwnd);
  372. UserAssert(IsWinEventNotifyDeferredOK());
  373. /*
  374. * wParam == pwndHit == pwnd that cursor is over
  375. * lParamL == ht == Hit test area code (result of WM_NCHITTEST)
  376. * lParamH == msg == Mouse message number
  377. */
  378. if (msg)
  379. {
  380. switch (codeHT)
  381. {
  382. case HTLEFT:
  383. case HTRIGHT:
  384. pcur = SYSCUR(SIZEWE);
  385. break;
  386. case HTTOP:
  387. case HTBOTTOM:
  388. pcur = SYSCUR(SIZENS);
  389. break;
  390. case HTTOPLEFT:
  391. case HTBOTTOMRIGHT:
  392. pcur = SYSCUR(SIZENWSE);
  393. break;
  394. case HTTOPRIGHT:
  395. case HTBOTTOMLEFT:
  396. pcur = SYSCUR(SIZENESW);
  397. break;
  398. default:
  399. goto NotSize;
  400. }
  401. pwndHit = RevalidateHwnd(hwndHit);
  402. if (pwndHit == NULL)
  403. return FALSE;
  404. if (TestWF(pwndHit, WFSYSMENU)) {
  405. TL tlpwndHit;
  406. DWORD dwState;
  407. ThreadLockAlways(pwndHit, &tlpwndHit);
  408. dwState = _GetMenuState(
  409. xxxGetSysMenu(pwndHit, TRUE), SC_SIZE, MF_BYCOMMAND);
  410. ThreadUnlock(&tlpwndHit);
  411. if ((dwState != (DWORD) -1) && (dwState & MFS_GRAYED))
  412. goto UseNormalCursor;
  413. }
  414. /*
  415. * No need to DeferWinEventNotify() - we're about to return
  416. */
  417. zzzSetCursor(pcur);
  418. return TRUE;
  419. }
  420. NotSize:
  421. pwndParent = GetChildParent(pwnd);
  422. /*
  423. * Some windows (like the list boxes of comboboxes), are marked with
  424. * the child bit but are actually child of the desktop (can happen
  425. * if you call SetParent()). Make this special case check for
  426. * the desktop here.
  427. */
  428. if (pwndParent == PWNDDESKTOP(pwnd))
  429. pwndParent = NULL;
  430. if (pwndParent != NULL) {
  431. ThreadLockAlways(pwndParent, &tlpwndParent);
  432. lt = xxxSendMessage(pwndParent, WM_SETCURSOR, (WPARAM)hwndHit,
  433. MAKELONG(codeHT, msg));
  434. ThreadUnlock(&tlpwndParent);
  435. if (lt != 0)
  436. return TRUE;
  437. }
  438. if (msg == 0) {
  439. /*
  440. * No need to DeferWinEventNotify() - we're about to return
  441. */
  442. zzzSetCursor(SYSCUR(ARROW));
  443. } else {
  444. pwndHit = RevalidateHwnd(hwndHit);
  445. if (pwndHit == NULL)
  446. return FALSE;
  447. switch (codeHT) {
  448. case HTCLIENT:
  449. if (pwndHit->pcls->spcur != NULL) {
  450. /*
  451. * No need to DeferWinEventNotify() - we're about to return
  452. */
  453. zzzSetCursor(pwndHit->pcls->spcur);
  454. }
  455. break;
  456. #ifdef LAME_BUTTON
  457. case HTLAMEBUTTON:
  458. /*
  459. * Show the hand cursor if we are over the Lame! text
  460. * in the caption.
  461. */
  462. zzzSetCursor(SYSCUR(HAND));
  463. break;
  464. #endif // LAME_BUTTON
  465. case HTERROR:
  466. switch (msg) {
  467. case WM_MOUSEMOVE:
  468. if (TestUP(ACTIVEWINDOWTRACKING)) {
  469. xxxActiveWindowTracking(pwnd, WM_SETCURSOR, codeHT);
  470. }
  471. break;
  472. case WM_LBUTTONDOWN:
  473. if ((pwndPopup = DWP_GetEnabledPopup(pwnd)) != NULL) {
  474. if (pwndPopup != PWNDDESKTOP(pwnd)->spwndChild) {
  475. PWND pwndActiveOld;
  476. pwndActiveOld = PtiCurrent()->pq->spwndActive;
  477. ThreadLockAlways(pwndPopup, &tlpwndPopup);
  478. xxxSetWindowPos(pwnd, NULL, 0, 0, 0, 0,
  479. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  480. xxxSetActiveWindow(pwndPopup);
  481. ThreadUnlock(&tlpwndPopup);
  482. if (pwndActiveOld != PtiCurrent()->pq->spwndActive)
  483. break;
  484. /*
  485. *** ELSE FALL THRU **
  486. */
  487. }
  488. }
  489. /*
  490. *** FALL THRU **
  491. */
  492. case WM_RBUTTONDOWN:
  493. case WM_MBUTTONDOWN:
  494. case WM_XBUTTONDOWN:
  495. {
  496. PWND pwndDlg;
  497. pwndDlg = DWP_GetEnabledPopup(pwnd);
  498. if (pwndDlg != NULL) {
  499. ThreadLockAlways(pwndDlg, &tlpwndPopup);
  500. xxxFlashWindow(pwndDlg,
  501. MAKELONG(FLASHW_ALL, UP(FOREGROUNDFLASHCOUNT)),
  502. (gpsi->dtCaretBlink >> 3));
  503. ThreadUnlock(&tlpwndPopup);
  504. }
  505. xxxMessageBeep(0);
  506. break;
  507. }
  508. }
  509. /*
  510. *** FALL THRU **
  511. */
  512. default:
  513. UseNormalCursor:
  514. /*
  515. * No need to DeferWinEventNotify() - we're about to return
  516. */
  517. zzzSetCursor(SYSCUR(ARROW));
  518. break;
  519. }
  520. }
  521. return FALSE;
  522. }
  523. /***************************************************************************\
  524. * xxxDWP_NCMouse
  525. *
  526. *
  527. * History:
  528. * 07-24-91 darrinm Ported from Win 3.1 sources.
  529. \***************************************************************************/
  530. void xxxDWP_NCMouse(
  531. PWND pwnd,
  532. UINT msg,
  533. UINT ht,
  534. LPARAM lParam)
  535. {
  536. UINT cmd;
  537. CheckLock(pwnd);
  538. cmd = 0;
  539. switch (msg) {
  540. case WM_NCLBUTTONDOWN:
  541. switch (ht) {
  542. case HTZOOM:
  543. case HTREDUCE:
  544. case HTCLOSE:
  545. case HTHELP:
  546. cmd = xxxTrackCaptionButton(pwnd, ht);
  547. break;
  548. default:
  549. // Change into a MV/SZ command
  550. if (ht >= HTSIZEFIRST && ht <= HTSIZELAST)
  551. cmd = SC_SIZE + (ht - HTSIZEFIRST + WMSZ_SIZEFIRST);
  552. break;
  553. }
  554. if (cmd != 0) {
  555. //
  556. // For SysCommands on system menu, don't do if menu item is
  557. // disabled.
  558. //
  559. if ( cmd != SC_CONTEXTHELP
  560. && TestWF(pwnd, WFSYSMENU)
  561. && !TestwndChild(pwnd)
  562. ) {
  563. if (_GetMenuState(xxxGetSysMenu(pwnd, TRUE), cmd & 0xFFF0,
  564. MF_BYCOMMAND) & MFS_GRAYED)
  565. break;
  566. }
  567. xxxSendMessage(pwnd, WM_SYSCOMMAND, cmd, lParam);
  568. break;
  569. }
  570. // FALL THRU
  571. case WM_NCLBUTTONUP:
  572. case WM_NCLBUTTONDBLCLK:
  573. xxxHandleNCMouseGuys(pwnd, msg, ht, lParam);
  574. break;
  575. }
  576. }
  577. /***************************************************************************\
  578. *
  579. * History:
  580. * 09-Mar-1992 mikeke From win3.1
  581. \***************************************************************************/
  582. UINT AreNonClientAreasToBePainted(
  583. PWND pwnd)
  584. {
  585. WORD wRetValue = 0;
  586. /*
  587. * Check if Active and Inactive captions have same color
  588. */
  589. if (SYSRGB(ACTIVECAPTION) != SYSRGB(INACTIVECAPTION) ||
  590. SYSRGB(CAPTIONTEXT) != SYSRGB(INACTIVECAPTIONTEXT)) {
  591. wRetValue = DC_CAPTION;
  592. }
  593. /*
  594. * We want to repaint the borders if we're not minimized and
  595. * we have a sizing border and the active/inactive colors are
  596. * different.
  597. */
  598. if (!TestWF(pwnd, WFMINIMIZED) && TestWF(pwnd, WFSIZEBOX) &&
  599. (SYSRGB(ACTIVEBORDER) != SYSRGB(INACTIVEBORDER))) {
  600. // We need to redraw the sizing border.
  601. wRetValue |= DC_FRAME;
  602. }
  603. return wRetValue;
  604. }
  605. /***************************************************************************\
  606. *
  607. * History:
  608. * 09-Mar-1992 mikeke From win3.1
  609. * 07-Aug-1996 vadimg Added menu grayout and underline code
  610. \***************************************************************************/
  611. VOID xxxDWP_DoNCActivate(
  612. PWND pwnd,
  613. DWORD dwFlags,
  614. HRGN hrgnClip)
  615. {
  616. UINT wFlags = DC_CAPTION;
  617. CheckLock(pwnd);
  618. /*
  619. * Later5.0 Gerardob. Since activation must follow focus, modeless
  620. * menu windows are activated so they can receive keyboard input;
  621. * however, we want the notification frame on, even when inactive.
  622. * (so it looks just like regular menus).
  623. * There are other scenarios when we want focus and activation on
  624. * different parent-child chains so we should consider allowing this.
  625. */
  626. if ((dwFlags & NCA_ACTIVE)
  627. || (!(dwFlags & NCA_FORCEFRAMEOFF)
  628. && IsModelessMenuNotificationWindow(pwnd))) {
  629. SetWF(pwnd, WFFRAMEON);
  630. wFlags |= DC_ACTIVE;
  631. } else {
  632. ClrWF(pwnd, WFFRAMEON);
  633. }
  634. if ((hrgnClip != HRGN_NONE) && TestWF(pwnd, WFVISIBLE) && !TestWF(pwnd, WFNONCPAINT)) {
  635. HDC hdc;
  636. WORD wBorderOrCap = (WORD)AreNonClientAreasToBePainted(pwnd);
  637. if (wBorderOrCap) {
  638. /*
  639. * Validate and Copy the region for our use. Since we
  640. * hand this off to GetWindowDC() we won't have to delete
  641. * the region (done in ReleaseDC()). Regardless, the region
  642. * passed in from the user is its responsibility to delete.
  643. */
  644. hrgnClip = UserValidateCopyRgn(hrgnClip);
  645. if (hdc = _GetDCEx(pwnd, hrgnClip, DCX_WINDOW | DCX_USESTYLE)) {
  646. /*
  647. * Draw the menu for grayout and underlines
  648. */
  649. if (TestWF(pwnd, WFMPRESENT)) {
  650. int cxFrame, cyFrame;
  651. cxFrame = cyFrame = GetWindowBorders(pwnd->style,
  652. pwnd->ExStyle, TRUE, FALSE);
  653. cxFrame *= SYSMET(CXBORDER);
  654. cyFrame *= SYSMET(CYBORDER);
  655. xxxMenuBarDraw(pwnd, hdc, cxFrame, cyFrame);
  656. }
  657. xxxDrawCaptionBar(pwnd, hdc, wBorderOrCap | wFlags);
  658. _ReleaseDC(hdc);
  659. } else {
  660. GreDeleteObject(hrgnClip);
  661. }
  662. }
  663. }
  664. }
  665. /***************************************************************************\
  666. *
  667. * History:
  668. * 09-Mar-1992 mikeke From win3.1
  669. \***************************************************************************/
  670. BOOL xxxRedrawTitle(
  671. PWND pwnd, UINT wFlags)
  672. {
  673. BOOL fDrawn = TRUE;
  674. CheckLock(pwnd);
  675. if (TestWF(pwnd, WFVISIBLE)) {
  676. if (TestWF(pwnd, WFBORDERMASK) == (BYTE)LOBYTE(WFCAPTION)) {
  677. if (TestwndFrameOn(pwnd)) {
  678. wFlags |= DC_ACTIVE;
  679. }
  680. if (IsInsideUserApiHook()) {
  681. xxxSendMessage(pwnd, WM_NCUAHDRAWCAPTION, wFlags, 0);
  682. } else {
  683. HDC hdc = _GetWindowDC(pwnd);
  684. xxxDrawCaptionBar(pwnd, hdc, wFlags);
  685. _ReleaseDC(hdc);
  686. }
  687. } else {
  688. fDrawn = FALSE;
  689. }
  690. }
  691. if ( IsTrayWindow(pwnd) && (wFlags & (DC_ICON | DC_TEXT)) ) {
  692. HWND hw = HWq(pwnd);
  693. xxxCallHook(HSHELL_REDRAW, (WPARAM)hw, 0L, WH_SHELL);
  694. PostShellHookMessages(HSHELL_REDRAW, (LPARAM)hw);
  695. }
  696. return(fDrawn);
  697. }
  698. /***************************************************************************\
  699. *
  700. * History:
  701. * 09-Mar-1992 mikeke From win3.1
  702. \***************************************************************************/
  703. void xxxDWP_DoCancelMode(
  704. PWND pwnd)
  705. {
  706. PTHREADINFO pti = PtiCurrent();
  707. PWND pwndCapture = pti->pq->spwndCapture;
  708. PMENUSTATE pMenuState;
  709. /*
  710. * If the below menu lines are changed in any way, then SQLWin
  711. * won't work if in design mode you drop some text, double click on
  712. * it, then try to use the heirarchical menus.
  713. */
  714. pMenuState = GetpMenuState(pwnd);
  715. if ((pMenuState != NULL)
  716. && (pwnd == pMenuState->pGlobalPopupMenu->spwndNotify)
  717. && !pMenuState->fModelessMenu) {
  718. xxxEndMenu(pMenuState);
  719. }
  720. if (pwndCapture == pwnd) {
  721. PSBTRACK pSBTrack = PWNDTOPSBTRACK(pwnd);
  722. if (pSBTrack && (pSBTrack->xxxpfnSB != NULL))
  723. xxxEndScroll(pwnd, TRUE);
  724. if (pti->pmsd != NULL) {
  725. pti->pmsd->fTrackCancelled = TRUE;
  726. pti->TIF_flags &= ~TIF_MOVESIZETRACKING;
  727. /*
  728. * Also clip the cursor back to the whole screen
  729. * so we don't get confused in xxxMoveSize.
  730. * This fix bug 64166.
  731. */
  732. zzzClipCursor((LPRECT)NULL);
  733. }
  734. /*
  735. * If the capture is still set, just release at this point.
  736. */
  737. xxxReleaseCapture();
  738. }
  739. }
  740. BOOL xxxDWPPrint(
  741. PWND pwnd,
  742. HDC hdc,
  743. LPARAM lParam)
  744. {
  745. POINT pt;
  746. int iDC;
  747. LPRECT lprc;
  748. PWND pwndSave = pwnd;
  749. LPARAM lParamSave = lParam;
  750. BOOL fNotVisible;
  751. PBWL pbwl;
  752. HWND *phwnd;
  753. TL tlpwnd;
  754. DWORD dwOldLayout;
  755. BOOL bMirrorDC;
  756. CheckLock(pwnd);
  757. if ((lParam & PRF_CHECKVISIBLE) && !_IsWindowVisible(pwnd))
  758. return(FALSE);
  759. bMirrorDC = (TestWF(pwnd, WEFLAYOUTRTL) && !MIRRORED_HDC(hdc));
  760. if (lParam & PRF_NONCLIENT) {
  761. /*
  762. * draw non-client area first
  763. */
  764. if (fNotVisible = !TestWF(pwnd, WFVISIBLE))
  765. SetVisible(pwnd, SV_SET);
  766. SetWF(pwnd, WFMENUDRAW);
  767. if (bMirrorDC) {
  768. LONG wox = pwnd->rcWindow.right - pwnd->rcWindow.left - 1;
  769. dwOldLayout = GreSetLayout(hdc, wox, LAYOUT_RTL);
  770. if(IsInsideUserApiHook()) {
  771. xxxSendMessage(pwnd, WM_NCUAHDRAWFRAME, (WPARAM)hdc, TestWF(pwnd, WFFRAMEON) ? DF_ACTIVE : 0L);
  772. } else {
  773. xxxDrawWindowFrame(pwnd, hdc, TestWF(pwnd, WFFRAMEON) ? DF_ACTIVE : 0L);
  774. }
  775. GreSetLayout(hdc, wox, dwOldLayout);
  776. } else {
  777. if(IsInsideUserApiHook()) {
  778. xxxSendMessage(pwnd, WM_NCUAHDRAWFRAME, (WPARAM)hdc, TestWF(pwnd, WFFRAMEON) ? DF_ACTIVE : 0L);
  779. } else {
  780. xxxDrawWindowFrame(pwnd, hdc, TestWF(pwnd, WFFRAMEON) ? DF_ACTIVE : 0L);
  781. }
  782. }
  783. ClrWF(pwnd, WFMENUDRAW);
  784. if (fNotVisible)
  785. SetVisible(pwnd, SV_UNSET);
  786. }
  787. if (lParam & PRF_CLIENT) {
  788. /*
  789. * draw client area second
  790. */
  791. iDC = GreSaveDC(hdc);
  792. GreGetWindowOrg(hdc, &pt);
  793. if (lParam & PRF_NONCLIENT) {
  794. int xBorders, yBorders;
  795. /*
  796. * adjust for non-client area
  797. */
  798. xBorders = pwnd->rcClient.left - pwnd->rcWindow.left;
  799. yBorders = pwnd->rcClient.top - pwnd->rcWindow.top;
  800. GreSetWindowOrg(hdc, pt.x - xBorders, pt.y - yBorders, NULL);
  801. }
  802. lprc = &pwnd->rcClient;
  803. GreIntersectClipRect(hdc, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top);
  804. if (bMirrorDC) {
  805. LONG wox = pwnd->rcClient.right - pwnd->rcClient.left - 1;
  806. dwOldLayout = GreSetLayout(hdc, wox, LAYOUT_RTL);
  807. if (lParam & PRF_ERASEBKGND)
  808. xxxSendMessage(pwnd, WM_ERASEBKGND, (WPARAM) hdc, 0L);
  809. xxxSendMessage(pwnd, WM_PRINTCLIENT, (WPARAM) hdc, lParam);
  810. GreSetLayout(hdc, wox, dwOldLayout);
  811. } else {
  812. if (lParam & PRF_ERASEBKGND)
  813. xxxSendMessage(pwnd, WM_ERASEBKGND, (WPARAM) hdc, 0L);
  814. xxxSendMessage(pwnd, WM_PRINTCLIENT, (WPARAM) hdc, lParam);
  815. }
  816. GreRestoreDC(hdc, iDC);
  817. pt.x += pwnd->rcWindow.left;
  818. pt.y += pwnd->rcWindow.top;
  819. if (lParam & PRF_CHILDREN) {
  820. /*
  821. * when drawing children, always include nonclient area
  822. */
  823. lParam |= PRF_NONCLIENT | PRF_ERASEBKGND;
  824. lParam &= ~PRF_CHECKVISIBLE;
  825. /*
  826. * draw children last
  827. */
  828. pbwl = BuildHwndList(pwnd->spwndChild, BWL_ENUMLIST, NULL);
  829. if (pbwl != NULL) {
  830. for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
  831. if ((pwnd = RevalidateHwnd(*phwnd)) == NULL)
  832. continue;
  833. if (TestWF(pwnd, WFVISIBLE)) {
  834. lprc = &pwnd->rcWindow;
  835. iDC = GreSaveDC(hdc);
  836. GreSetWindowOrg(hdc, pt.x - lprc->left, pt.y - lprc->top, NULL);
  837. if (!TestCF(pwnd, CFPARENTDC)) {
  838. GreIntersectClipRect(hdc, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top);
  839. }
  840. ThreadLockAlways(pwnd, &tlpwnd);
  841. xxxSendMessage(pwnd, WM_PRINT, (WPARAM) hdc, lParam);
  842. ThreadUnlock(&tlpwnd);
  843. GreRestoreDC(hdc, iDC);
  844. }
  845. }
  846. FreeHwndList(pbwl);
  847. }
  848. }
  849. if (lParam & PRF_OWNED) {
  850. pbwl = BuildHwndList((PWNDDESKTOP(pwnd))->spwndChild, BWL_ENUMLIST, NULL);
  851. if (pbwl != NULL) {
  852. for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
  853. if ((pwnd = RevalidateHwnd(*phwnd)) == NULL)
  854. continue;
  855. if ((pwnd->spwndOwner == pwndSave) && TestWF(pwnd, WFVISIBLE)) {
  856. iDC = GreSaveDC(hdc);
  857. GreSetWindowOrg(hdc, pt.x - pwnd->rcWindow.left, pt.y - pwnd->rcWindow.top, NULL);
  858. ThreadLockAlways(pwnd, &tlpwnd);
  859. xxxSendMessage(pwnd, WM_PRINT, (WPARAM) hdc, lParamSave);
  860. ThreadUnlock(&tlpwnd);
  861. GreRestoreDC(hdc, iDC);
  862. }
  863. }
  864. FreeHwndList(pbwl);
  865. }
  866. }
  867. }
  868. return TRUE;
  869. }
  870. /***************************************************************************\
  871. *
  872. * DWP_GetIcon()
  873. *
  874. * Gets the small or big icon for a window. For small icons, if we created
  875. * the thing, we don't let the app see it.
  876. *
  877. \***************************************************************************/
  878. HICON DWP_GetIcon(
  879. PWND pwnd,
  880. UINT uType)
  881. {
  882. HICON hicoTemp;
  883. ATOM atom;
  884. if (uType > ICON_SMALL2) {
  885. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "WM_GETICON: Invalid wParam value (0x%X)", uType);
  886. return (HICON)NULL;
  887. }
  888. if (uType == ICON_BIG) {
  889. atom = gpsi->atomIconProp;
  890. } else {
  891. UserAssert(uType == ICON_SMALL || uType == ICON_SMALL2);
  892. atom = gpsi->atomIconSmProp;
  893. }
  894. /*
  895. * Get the icon from the window
  896. */
  897. hicoTemp = (HICON)_GetProp(pwnd, MAKEINTATOM(atom), PROPF_INTERNAL);
  898. /*
  899. * If it's a USER created small icon don't return it.
  900. */
  901. if (uType == ICON_SMALL && hicoTemp) {
  902. PCURSOR pcurTemp;
  903. pcurTemp = (PCURSOR)HMValidateHandleNoRip((HCURSOR)hicoTemp, TYPE_CURSOR);
  904. if (pcurTemp != NULL && (pcurTemp->CURSORF_flags & CURSORF_SECRET)) {
  905. hicoTemp = (HICON)NULL;
  906. }
  907. }
  908. return hicoTemp;
  909. }
  910. /***************************************************************************\
  911. *
  912. * DestroyWindowSmIcon()
  913. *
  914. * Destroys the small icon of a window if we've created a cached one.
  915. * This is because it's called in winrare.c when the caption height
  916. * changes.
  917. *
  918. \***************************************************************************/
  919. BOOL DestroyWindowSmIcon(
  920. PWND pwnd)
  921. {
  922. HCURSOR hcursor;
  923. PCURSOR pcursor;
  924. //
  925. // Get the small icon property first...
  926. //
  927. hcursor = (HCURSOR)_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp), PROPF_INTERNAL);
  928. if (hcursor == NULL)
  929. return FALSE;
  930. pcursor = (PCURSOR)HMValidateHandleNoRip(hcursor, TYPE_CURSOR);
  931. if (pcursor == NULL)
  932. return FALSE;
  933. //
  934. // Remove it if it's a secretly created one
  935. //
  936. if (pcursor->CURSORF_flags & CURSORF_SECRET)
  937. {
  938. ClrWF(pwnd, WFSMQUERYDRAGICON);
  939. InternalRemoveProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp), PROPF_INTERNAL);
  940. _DestroyCursor(pcursor, CURSOR_ALWAYSDESTROY);
  941. return(TRUE);
  942. }
  943. else
  944. return(FALSE);
  945. }
  946. /***************************************************************************\
  947. *
  948. * xxxDWP_SetIcon()
  949. *
  950. * Sets the small or big icon for a window, and returns back the previous
  951. * one.
  952. *
  953. \***************************************************************************/
  954. HICON xxxDWP_SetIcon(
  955. PWND pwnd,
  956. WPARAM wType,
  957. HICON hicoNew)
  958. {
  959. HICON hIcon;
  960. HICON hIconSm;
  961. HICON hOld;
  962. BOOL fRedraw;
  963. CheckLock(pwnd);
  964. #if DBG
  965. if (hicoNew && !IS_PTR(hicoNew)) {
  966. RIPMSG1(RIP_WARNING, "WM_SETICON: Icon handle missing HIWORD (0x%08X)", hicoNew);
  967. }
  968. #endif
  969. if (wType > ICON_RECREATE)
  970. {
  971. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "WM_SETICON: Invalid wParam value (0x%0X)", wType);
  972. return (HICON)NULL;
  973. }
  974. /*
  975. * Regenerate small icons if requested.
  976. */
  977. if (wType == ICON_RECREATE) {
  978. xxxRecreateSmallIcons(pwnd);
  979. return 0L;
  980. }
  981. /*
  982. * Save old icon
  983. */
  984. hIcon = (HICON)_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconProp), PROPF_INTERNAL);
  985. hIconSm = (HICON)_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp), PROPF_INTERNAL);
  986. hOld = ((wType == ICON_SMALL) ? hIconSm : hIcon);
  987. /*
  988. * Only update the icons if they have changed
  989. */
  990. if (hOld != hicoNew)
  991. {
  992. PCURSOR pcursor;
  993. BOOL fWasCache = FALSE;
  994. fRedraw = TRUE;
  995. /*
  996. * Always remove the small icon because it is either being replaced or
  997. * will be recreated if the big icon is being set.
  998. */
  999. pcursor = (PCURSOR)HMValidateHandleNoRip(hIconSm, TYPE_CURSOR);
  1000. if (pcursor && (pcursor->CURSORF_flags & CURSORF_SECRET)) {
  1001. fWasCache = TRUE;
  1002. _DestroyCursor(pcursor, CURSOR_ALWAYSDESTROY);
  1003. }
  1004. if (wType == ICON_SMALL) {
  1005. /*
  1006. * Apps never see the icons that USER creates behind their backs
  1007. * from big icons.
  1008. */
  1009. if (fWasCache)
  1010. hOld = NULL;
  1011. hIconSm = hicoNew;
  1012. } else {
  1013. if (fWasCache) {
  1014. /*
  1015. * Force us to recalc the small icon to match the new big icon
  1016. */
  1017. hIconSm = NULL;
  1018. } else if (hIconSm) {
  1019. /*
  1020. * Redraw of the caption isn't needed because the small icon
  1021. * didn't change.
  1022. */
  1023. fRedraw = FALSE;
  1024. }
  1025. hIcon = hicoNew;
  1026. }
  1027. /*
  1028. * Store the icons off the window as properties
  1029. */
  1030. InternalSetProp(pwnd, MAKEINTATOM(gpsi->atomIconProp), (HANDLE)hIcon, PROPF_INTERNAL | PROPF_NOPOOL);
  1031. InternalSetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp), (HANDLE)hIconSm, PROPF_INTERNAL | PROPF_NOPOOL);
  1032. /*
  1033. * Create the small icon if it doesn't exist.
  1034. */
  1035. if (hIcon && !hIconSm)
  1036. xxxCreateWindowSmIcon(pwnd, hIcon, TRUE);
  1037. /*
  1038. * Redraw caption if the small icon has changed
  1039. */
  1040. if (fRedraw)
  1041. xxxRedrawTitle(pwnd, DC_ICON);
  1042. }
  1043. return hOld;
  1044. }
  1045. // --------------------------------------------------------------------------
  1046. //
  1047. // CreateWindowSmIcon()
  1048. //
  1049. // Makes a per-window small icon copy of a big icon.
  1050. //
  1051. // --------------------------------------------------------------------------
  1052. HICON xxxCreateWindowSmIcon(
  1053. PWND pwnd,
  1054. HICON hIconBig,
  1055. BOOL fNotQueryDrag)
  1056. {
  1057. HICON hIconSm = NULL;
  1058. PCURSOR pcurs = NULL,pcursBig;
  1059. CheckLock(pwnd);
  1060. UserAssert(hIconBig);
  1061. pcursBig = (PCURSOR)HMValidateHandleNoRip(hIconBig, TYPE_CURSOR);
  1062. if (pcursBig) {
  1063. pcurs = xxxClientCopyImage(PtoHq(pcursBig),
  1064. pcursBig->rt == PTR_TO_ID(RT_ICON) ? IMAGE_ICON : IMAGE_CURSOR,
  1065. SYSMET(CXSMICON),
  1066. SYSMET(CYSMICON),
  1067. LR_DEFAULTCOLOR | (fNotQueryDrag ? LR_COPYFROMRESOURCE : 0));
  1068. if (pcurs != NULL)
  1069. hIconSm = PtoHq(pcurs);
  1070. }
  1071. if (hIconSm) {
  1072. pcurs->CURSORF_flags |= CURSORF_SECRET;
  1073. InternalSetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp), (HANDLE)hIconSm, PROPF_INTERNAL | PROPF_NOPOOL);
  1074. if (!fNotQueryDrag)
  1075. SetWF(pwnd, WFSMQUERYDRAGICON);
  1076. }
  1077. return(hIconSm);
  1078. }
  1079. /***************************************************************************\
  1080. * xxxDefWindowProc (API)
  1081. *
  1082. * History:
  1083. * 10-23-90 MikeHar Ported from WaWaWaWindows.
  1084. * 12-07-90 IanJa CTLCOLOR handling round right way
  1085. \***************************************************************************/
  1086. LRESULT xxxDefWindowProc(
  1087. PWND pwnd,
  1088. UINT message,
  1089. WPARAM wParam,
  1090. LPARAM lParam)
  1091. {
  1092. /*
  1093. * If we've got a registered UserApiHook handler loaded in this process,
  1094. * pass the message off to it. For server side wndproc, we need to make an exception
  1095. * passing WM_NCDESTROY so that themes can get a chance to do cleanup since they will not
  1096. * see if in the post hook for those type of windows
  1097. */
  1098. if (IsInsideUserApiHook() &&
  1099. (!TestWF(pwnd, WFDESTROYED) || ((message == WM_NCDESTROY) && TestWF(pwnd, WFSERVERSIDEPROC) && !(pwnd->fnid & FNID_DELETED_BIT))) &&
  1100. (!(PtiCurrent()->TIF_flags & TIF_INCLEANUP)) &&
  1101. xxxLoadUserApiHook()) {
  1102. /*
  1103. * Call back to the appropriate DefWindowProc handler.
  1104. */
  1105. if (TestWF(pwnd, WFANSIPROC)) {
  1106. return ScSendMessage(pwnd,
  1107. message,
  1108. wParam,
  1109. lParam,
  1110. 0,
  1111. gpsi->apfnClientA.pfnDispatchDefWindowProc,
  1112. SCMS_FLAGS_ANSI);
  1113. } else {
  1114. return ScSendMessage(pwnd,
  1115. message,
  1116. wParam,
  1117. lParam,
  1118. 0,
  1119. gpsi->apfnClientW.pfnDispatchDefWindowProc,
  1120. 0);
  1121. }
  1122. }
  1123. return xxxRealDefWindowProc(pwnd, message, wParam, lParam);
  1124. }
  1125. LRESULT xxxRealDefWindowProc(
  1126. PWND pwnd,
  1127. UINT message,
  1128. WPARAM wParam,
  1129. LPARAM lParam)
  1130. {
  1131. LRESULT lt;
  1132. PWND pwndT;
  1133. TL tlpwndParent;
  1134. TL tlpwndT;
  1135. int icolBack;
  1136. int icolFore;
  1137. int i;
  1138. CheckLock(pwnd);
  1139. if (pwnd == (PWND)-1) {
  1140. return 0;
  1141. }
  1142. if (message > WM_USER) {
  1143. return 0;
  1144. }
  1145. /*
  1146. * Important: If you add cases to the switch statement below,
  1147. * and those messages can originate on the client
  1148. * side, add the messages to server.c's gawDefWindowMsgs
  1149. * array or else the client will short-circuit the call
  1150. * and return 0.
  1151. */
  1152. switch (message) {
  1153. case WM_CLIENTSHUTDOWN:
  1154. return xxxClientShutdown(pwnd, wParam);
  1155. case WM_NCACTIVATE:
  1156. xxxDWP_DoNCActivate(pwnd, (LOWORD(wParam) ? NCA_ACTIVE : 0), (HRGN)lParam);
  1157. return (LONG)TRUE;
  1158. case WM_NCHITTEST:
  1159. return FindNCHit(pwnd, (LONG)lParam);
  1160. case WM_NCCALCSIZE:
  1161. /*
  1162. * wParam = fCalcValidRects
  1163. * lParam = LPRECT rgrc[3]:
  1164. * lprc[0] = rcWindowNew = New window rectangle
  1165. * if fCalcValidRects:
  1166. * lprc[1] = rcWindowOld = Old window rectangle
  1167. * lprc[2] = rcClientOld = Old client rectangle
  1168. *
  1169. * On return:
  1170. * rgrc[0] = rcClientNew = New client rect
  1171. * if fCalcValidRects:
  1172. * rgrc[1] = rcValidDst = Destination valid rectangle
  1173. * rgrc[2] = rcValidSrc = Source valid rectangle
  1174. */
  1175. xxxCalcClientRect(pwnd, (LPRECT)lParam, FALSE);
  1176. break;
  1177. case WM_NCLBUTTONDOWN:
  1178. case WM_NCLBUTTONUP:
  1179. case WM_NCLBUTTONDBLCLK:
  1180. xxxDWP_NCMouse(pwnd, message, (UINT)wParam, lParam);
  1181. break;
  1182. case WM_CANCELMODE:
  1183. {
  1184. /*
  1185. * Terminate any modes the system might
  1186. * be in, such as scrollbar tracking, menu mode,
  1187. * button capture, etc.
  1188. */
  1189. xxxDWP_DoCancelMode(pwnd);
  1190. }
  1191. break;
  1192. case WM_NCCREATE:
  1193. if (TestWF(pwnd, (WFHSCROLL | WFVSCROLL))) {
  1194. if (_InitPwSB(pwnd) == NULL)
  1195. return (LONG)FALSE;
  1196. }
  1197. #ifdef FE_SB // xxxDefWindowProc()
  1198. /*
  1199. * If CREATESTRUCTEX.strName contains resource id, we don't
  1200. * need to call DefSetText(). because it is a numeric number,
  1201. * it does not need Ansi <-> Unicode translation.
  1202. */
  1203. if (lParam) {
  1204. PLARGE_STRING pstr = &((PCREATESTRUCTEX)lParam)->strName;
  1205. if (pwnd->head.rpdesk == NULL || pstr == NULL || pstr->Buffer == NULL) {
  1206. pwnd->strName.Length = 0;
  1207. return TRUE;
  1208. }
  1209. if ((pstr->bAnsi && (pstr->Length >= sizeof(BYTE)) &&
  1210. (*(PBYTE)(pstr->Buffer) == 0xff)) ||
  1211. (!pstr->bAnsi && (pstr->Length >= sizeof(WCHAR)) &&
  1212. (*(PWCHAR)(pstr->Buffer) == 0xffff))) {
  1213. /*
  1214. * This is Resource ID, we just return here with TRUE.
  1215. */
  1216. return (LONG)TRUE;
  1217. }
  1218. }
  1219. #endif // FE_SB
  1220. SetWF(pwnd, WFTITLESET);
  1221. return (LONG)DefSetText(pwnd, &((PCREATESTRUCTEX)lParam)->strName);
  1222. case WM_PRINT:
  1223. return((LRESULT)xxxDWPPrint(pwnd, (HDC) wParam, lParam));
  1224. case WM_NCPAINT:
  1225. {
  1226. HDC hdc;
  1227. /*
  1228. * Force the drawing of the menu.
  1229. */
  1230. SetWF(pwnd, WFMENUDRAW);
  1231. /*
  1232. * Get a window DC intersected with hrgnClip,
  1233. * but make sure that hrgnClip doesn't get deleted.
  1234. */
  1235. hdc = _GetDCEx(pwnd,
  1236. (HRGN)wParam,
  1237. DCX_USESTYLE |
  1238. DCX_WINDOW |
  1239. DCX_INTERSECTRGN |
  1240. DCX_NODELETERGN |
  1241. DCX_LOCKWINDOWUPDATE);
  1242. xxxDrawWindowFrame(pwnd,
  1243. hdc,
  1244. (TestWF(pwnd, WFFRAMEON) &&
  1245. (GETPTI(pwnd)->pq == gpqForeground)) ? DF_ACTIVE : 0L);
  1246. _ReleaseDC(hdc);
  1247. ClrWF(pwnd, WFMENUDRAW);
  1248. }
  1249. break;
  1250. case WM_UAHINIT:
  1251. /*
  1252. * If the theme is becoming active, we need to "prime" the UAH's to
  1253. * ensure that they get loaded. This can happen if an existing app
  1254. * becomes themed but doesn't call xxxCreateWindow() or
  1255. * xxxDefWindowProc()
  1256. */
  1257. if (IsInsideUserApiHook()) {
  1258. if (!(PtiCurrent()->TIF_flags & TIF_INCLEANUP)) {
  1259. return xxxLoadUserApiHook();
  1260. }
  1261. }
  1262. break;
  1263. case WM_NCUAHDRAWCAPTION:
  1264. {
  1265. HDC hdc = _GetWindowDC(pwnd);
  1266. xxxDrawCaptionBar(pwnd, hdc, (UINT) wParam);
  1267. _ReleaseDC(hdc);
  1268. }
  1269. break;
  1270. case WM_NCUAHDRAWFRAME:
  1271. {
  1272. xxxDrawWindowFrame(pwnd,(HDC)wParam, (UINT)lParam);
  1273. }
  1274. break;
  1275. case WM_ISACTIVEICON:
  1276. return TestWF(pwnd, WFFRAMEON) != 0;
  1277. case WM_SETTEXT:
  1278. /*
  1279. * At one time we added an optimization to do nothing if the new
  1280. * text was the same as the old text but found that QCcase does not work
  1281. * because it calls SetWindowText not to change the text but
  1282. * cause the title bar to redraw after it had added the sysmenu
  1283. * through SetWindowLong
  1284. */
  1285. if (lt = DefSetText(pwnd, (PLARGE_STRING)lParam)) {
  1286. /*
  1287. * Text was set, so redraw title bar
  1288. */
  1289. xxxRedrawTitle(pwnd, DC_TEXT);
  1290. xxxWindowEvent(EVENT_OBJECT_NAMECHANGE, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, 0);
  1291. }
  1292. return lt;
  1293. case WM_GETTEXT:
  1294. if (wParam != 0) {
  1295. PLARGE_STRING pstr = (PLARGE_STRING)lParam;
  1296. if (pwnd->strName.Length) {
  1297. if (pstr->bAnsi) {
  1298. i = WCSToMB(pwnd->strName.Buffer,
  1299. pwnd->strName.Length / sizeof(WCHAR),
  1300. (LPSTR *)&pstr->Buffer, pstr->MaximumLength - 1, FALSE);
  1301. ((LPSTR)pstr->Buffer)[i] = 0;
  1302. pstr->Length = i;
  1303. } else {
  1304. i = TextCopy(&pwnd->strName, pstr->Buffer, (UINT)wParam);
  1305. pstr->Length = i * sizeof(WCHAR);
  1306. }
  1307. return i;
  1308. }
  1309. /*
  1310. * else Null terminate the text buffer since there is no text.
  1311. */
  1312. if (pstr->bAnsi) {
  1313. *(LPSTR)pstr->Buffer = 0;
  1314. } else {
  1315. *(LPWSTR)pstr->Buffer = 0;
  1316. }
  1317. }
  1318. return 0L;
  1319. case WM_GETTEXTLENGTH:
  1320. if (pwnd->strName.Length) {
  1321. UINT cch;
  1322. if (lParam) {
  1323. RtlUnicodeToMultiByteSize(&cch,
  1324. pwnd->strName.Buffer,
  1325. pwnd->strName.Length);
  1326. } else {
  1327. cch = pwnd->strName.Length / sizeof(WCHAR);
  1328. }
  1329. return cch;
  1330. }
  1331. return 0L;
  1332. case WM_CLOSE:
  1333. xxxDestroyWindow(pwnd);
  1334. break;
  1335. case WM_PAINT:
  1336. case WM_PAINTICON:
  1337. xxxDWP_Paint(pwnd);
  1338. break;
  1339. case WM_ERASEBKGND:
  1340. case WM_ICONERASEBKGND:
  1341. return (LONG)xxxDWP_EraseBkgnd(pwnd, message, (HDC)wParam);
  1342. case WM_SYNCPAINT:
  1343. /*
  1344. * Clear our sync-paint pending flag.
  1345. */
  1346. ClrWF(pwnd, WFSYNCPAINTPENDING);
  1347. /*
  1348. * This message is sent when SetWindowPos() is trying
  1349. * to get the screen looking nice after window rearrangement,
  1350. * and one of the windows involved is of another task.
  1351. * This message avoids lots of inter-app message traffic
  1352. * by switching to the other task and continuing the
  1353. * recursion there.
  1354. *
  1355. * wParam = flags
  1356. * LOWORD(lParam) = hrgnClip
  1357. * HIWORD(lParam) = pwndSkip (not used; always NULL)
  1358. *
  1359. * pwndSkip is now always NULL.
  1360. *
  1361. * NOTE: THIS MESSAGE IS FOR INTERNAL USE ONLY! ITS BEHAVIOR
  1362. * IS DIFFERENT IN 3.1 THAN IN 3.0!!
  1363. */
  1364. xxxInternalDoSyncPaint(pwnd, (DWORD)wParam);
  1365. break;
  1366. case WM_QUERYOPEN:
  1367. case WM_QUERYENDSESSION:
  1368. case WM_DEVICECHANGE:
  1369. case WM_POWERBROADCAST:
  1370. return (LONG)TRUE;
  1371. // Default handling for WM_CONTEXTMENU support
  1372. case WM_RBUTTONUP:
  1373. if (TestWF(pwnd, WEFLAYOUTRTL)) {
  1374. lParam = MAKELPARAM(pwnd->rcClient.right - GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) + pwnd->rcClient.top);
  1375. } else {
  1376. lParam = MAKELONG(GET_X_LPARAM(lParam) + pwnd->rcClient.left, GET_Y_LPARAM(lParam) + pwnd->rcClient.top);
  1377. }
  1378. xxxSendMessage(pwnd, WM_CONTEXTMENU, (WPARAM) HWq(pwnd), lParam);
  1379. break;
  1380. case WM_NCRBUTTONDOWN:
  1381. {
  1382. int nHit;
  1383. MSG msg;
  1384. LONG spt;
  1385. PTHREADINFO pti = PtiCurrent();
  1386. nHit = FindNCHit(pwnd, (LONG)lParam);
  1387. if (nHit == HTVSCROLL || nHit == HTHSCROLL) {
  1388. if (!_IsDescendant(pti->pq->spwndActive, pwnd)) {
  1389. break;
  1390. }
  1391. } else if (nHit == HTCAPTION || nHit == HTSYSMENU) {
  1392. if (pwnd != pti->pq->spwndActive) {
  1393. break;
  1394. }
  1395. } else {
  1396. break;
  1397. }
  1398. xxxSetCapture(pwnd);
  1399. while (TRUE)
  1400. {
  1401. if (xxxPeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
  1402. {
  1403. if (msg.message == WM_RBUTTONUP)
  1404. {
  1405. xxxReleaseCapture();
  1406. spt = POINTTOPOINTS(msg.pt);
  1407. nHit = FindNCHit(pwnd, spt);
  1408. if ((nHit == HTCAPTION) || (nHit == HTSYSMENU) ||
  1409. (nHit == HTVSCROLL) || (nHit == HTHSCROLL)) {
  1410. xxxSendMessage(pwnd, WM_CONTEXTMENU, (WPARAM) HWq(pwnd), spt);
  1411. }
  1412. break;
  1413. }
  1414. }
  1415. if (pwnd != pti->pq->spwndCapture)
  1416. // Someone else grabbed the capture. Bail out.
  1417. break;
  1418. // xxxWaitMessage();
  1419. if (!xxxSleepThread(QS_MOUSE, 0, TRUE))
  1420. break;
  1421. }
  1422. }
  1423. break;
  1424. /*
  1425. * Default handling for WM_APPCOMMAND support
  1426. */
  1427. case WM_NCXBUTTONUP:
  1428. case WM_XBUTTONUP:
  1429. {
  1430. WORD cmd;
  1431. WORD keystate;
  1432. LPARAM lParamAppCommand;
  1433. cmd = 0;
  1434. switch (GET_XBUTTON_WPARAM(wParam)) {
  1435. case XBUTTON1:
  1436. cmd = APPCOMMAND_BROWSER_BACKWARD;
  1437. break;
  1438. case XBUTTON2:
  1439. cmd = APPCOMMAND_BROWSER_FORWARD;
  1440. break;
  1441. default:
  1442. break;
  1443. }
  1444. if (cmd == 0) {
  1445. break;
  1446. }
  1447. cmd |= FAPPCOMMAND_MOUSE;
  1448. if (message == WM_XBUTTONUP) {
  1449. keystate = GET_KEYSTATE_WPARAM(wParam);
  1450. } else {
  1451. keystate = (WORD)GetMouseKeyFlags(PtiCurrent()->pq);
  1452. }
  1453. lParamAppCommand = MAKELPARAM(keystate, cmd);
  1454. xxxSendMessage(pwnd, WM_APPCOMMAND, (WPARAM) HWq(pwnd), lParamAppCommand);
  1455. break;
  1456. }
  1457. case WM_MOUSEWHEEL:
  1458. if (TestwndChild(pwnd)) {
  1459. ThreadLockAlways(pwnd->spwndParent, &tlpwndParent);
  1460. xxxSendMessage(pwnd->spwndParent, WM_MOUSEWHEEL, wParam, lParam);
  1461. ThreadUnlock(&tlpwndParent);
  1462. }
  1463. break;
  1464. case WM_CONTEXTMENU:
  1465. {
  1466. int nHit;
  1467. nHit = FindNCHit(pwnd, (LONG)lParam);
  1468. /*
  1469. * Put up a context menu if we clicked on a scroll bar
  1470. */
  1471. if ((nHit == HTVSCROLL) || (nHit == HTHSCROLL)) {
  1472. if (_IsDescendant(PtiCurrent()->pq->spwndActive, pwnd)) {
  1473. xxxDoScrollMenu(pwnd, NULL, nHit - HTHSCROLL, lParam);
  1474. }
  1475. break;
  1476. }
  1477. if (TestwndChild(pwnd)) {
  1478. ThreadLockAlways(pwnd->spwndParent, &tlpwndParent);
  1479. xxxSendMessage(pwnd->spwndParent, WM_CONTEXTMENU, (WPARAM) HWq(pwnd), lParam);
  1480. ThreadUnlock(&tlpwndParent);
  1481. } else {
  1482. /*
  1483. * Do default context menu if right clicked on caption
  1484. */
  1485. if (pwnd == PtiCurrent()->pq->spwndActive)
  1486. {
  1487. if (nHit == HTCAPTION)
  1488. goto DoTheDefaultThang;
  1489. else if (nHit == HTSYSMENU)
  1490. {
  1491. i = SC_CLOSE;
  1492. goto DoTheSysMenuThang;
  1493. }
  1494. /*
  1495. * If this was generated by the keyboard (apps key), then simulate a shift-f10
  1496. * for old apps so they get a crack at putting up their context menu.
  1497. */
  1498. if (lParam == KEYBOARD_MENU && !TestWF(pwnd, WFWIN40COMPAT))
  1499. xxxSimulateShiftF10();
  1500. }
  1501. }
  1502. }
  1503. break;
  1504. case WM_APPCOMMAND:
  1505. /*
  1506. * Bubble the message to the parent
  1507. */
  1508. if (TestwndChild(pwnd)) {
  1509. ThreadLockAlways(pwnd->spwndParent, &tlpwndParent);
  1510. lt = xxxSendMessage(pwnd->spwndParent, WM_APPCOMMAND, wParam, lParam);
  1511. ThreadUnlock(&tlpwndParent);
  1512. return lt;
  1513. } else if (pwnd != PWNDDESKTOP(pwnd) ) {
  1514. BOOL bEatMe = FALSE;
  1515. /*
  1516. * Notify listeners on the SHELLHOOK that a WM_APPCOMMAND message was not handled
  1517. * We also post this message to the shell queue so they don't need to load themselves
  1518. * into every process with a hook.
  1519. * We don't bother about the desktop since csrss services it and it doesn't accept
  1520. * shell hooks so there is no point.
  1521. */
  1522. if (IsHooked(PtiCurrent(), WHF_SHELL))
  1523. bEatMe = (xxxCallHook(HSHELL_APPCOMMAND, wParam, lParam, WH_SHELL) != 0);
  1524. /*
  1525. * The shell only wants to get this notification if no one in
  1526. * the hook chain handled this WM_APPCOMMAND, so we check the
  1527. * return value of the hook (if there was one). See RAID #54863.
  1528. */
  1529. if(!bEatMe)
  1530. PostShellHookMessages(HSHELL_APPCOMMAND, lParam);
  1531. }
  1532. break;
  1533. case WM_KEYF1:
  1534. xxxSendHelpMessage(pwnd, HELPINFO_WINDOW,
  1535. (int) (TestwndChild(pwnd) ? PTR_TO_ID(pwnd->spmenu) : 0),
  1536. HWq(pwnd), GetContextHelpId(pwnd));
  1537. break;
  1538. case WM_SYSCOMMAND:
  1539. xxxSysCommand(pwnd, (UINT)wParam, lParam);
  1540. break;
  1541. case WM_KEYDOWN:
  1542. if (wParam == VK_F10) {
  1543. PtiCurrent()->pq->QF_flags |= QF_FF10STATUS;
  1544. HandleF10:
  1545. /*
  1546. * Generate a WM_CONTEXTMENU for new apps for shift-f10.
  1547. */
  1548. if (_GetKeyState(VK_SHIFT) < 0 && TestWF(pwnd, WFWIN40COMPAT)) {
  1549. xxxSendMessage(pwnd, WM_CONTEXTMENU, (WPARAM)HWq(pwnd), KEYBOARD_MENU);
  1550. }
  1551. }
  1552. break;
  1553. case WM_HELP:
  1554. // If this window is a child window, Help message must be passed on
  1555. // to it's parent; Else, this must be passed on to the owner window.
  1556. pwndT = (TestwndChild(pwnd)? pwnd->spwndParent : pwnd->spwndOwner);
  1557. if (pwndT && (pwndT != _GetDesktopWindow())) {
  1558. ThreadLockAlways(pwndT, &tlpwndT);
  1559. lt = xxxSendMessage(pwndT, WM_HELP, wParam, lParam);
  1560. ThreadUnlock(&tlpwndT);
  1561. return lt;
  1562. }
  1563. return 0L;
  1564. case WM_SYSKEYDOWN:
  1565. {
  1566. PTHREADINFO pti = PtiCurrent();
  1567. /*
  1568. * Is the ALT key down?
  1569. */
  1570. if (HIWORD(lParam) & SYS_ALTERNATE) {
  1571. /*
  1572. * Toggle QF_FMENUSTATUS iff this is NOT a repeat KEYDOWN
  1573. * message; Only if the prev key state was 0, then this is the
  1574. * first KEYDOWN message and then we consider toggling menu
  1575. * status; Fix for Bugs #4531 & #4566 --SANKAR-- 10-02-89.
  1576. */
  1577. if ((HIWORD(lParam) & SYS_PREVKEYSTATE) == 0) {
  1578. /*
  1579. * Don't have to lock pwndActive because it's
  1580. * processing this key.
  1581. */
  1582. if ((wParam == VK_MENU) &&
  1583. !(pti->pq->QF_flags & QF_FMENUSTATUS)) {
  1584. pti->pq->QF_flags |= QF_FMENUSTATUS;
  1585. xxxDrawMenuBarUnderlines(pwnd, TRUE);
  1586. } else {
  1587. pti->pq->QF_flags &= ~(QF_FMENUSTATUS|QF_FMENUSTATUSBREAK);
  1588. }
  1589. }
  1590. pti->pq->QF_flags &= ~QF_FF10STATUS;
  1591. xxxDWP_ProcessVirtKey((UINT)wParam);
  1592. } else {
  1593. if (wParam == VK_F10) {
  1594. pti->pq->QF_flags |= QF_FF10STATUS;
  1595. goto HandleF10;
  1596. }
  1597. }
  1598. }
  1599. break;
  1600. case WM_SYSKEYUP:
  1601. case WM_KEYUP:
  1602. {
  1603. PTHREADINFO pti = PtiCurrent();
  1604. /*
  1605. * press and release F10 or ALT. Send this only to top-level windows,
  1606. * otherwise MDI gets confused. The fix in which DefMDIChildProc()
  1607. * passed up the message was insufficient in the case a child window
  1608. * of the MDI child had the focus.
  1609. * Also make sure the sys-menu activation wasn't broken by a mouse
  1610. * up or down when the Alt was down (QF_MENUSTATUSBREAK).
  1611. */
  1612. if ((wParam == VK_MENU && !(pti->pq->QF_flags & QF_TABSWITCHING) && ((pti->pq->QF_flags &
  1613. (QF_FMENUSTATUS | QF_FMENUSTATUSBREAK)) == QF_FMENUSTATUS)) ||
  1614. (wParam == VK_F10 && (pti->pq->QF_flags & QF_FF10STATUS ))) {
  1615. pwndT = GetTopLevelWindow(pwnd);
  1616. if (gspwndFullScreen != pwndT) {
  1617. ThreadLockWithPti(pti, pwndT, &tlpwndT);
  1618. /*
  1619. * Draw the underlines for F10. This was already down for ALT
  1620. * when the key went down.
  1621. */
  1622. if (wParam == VK_F10) {
  1623. xxxDrawMenuBarUnderlines(pwnd, TRUE);
  1624. }
  1625. xxxSendMessage(pwndT, WM_SYSCOMMAND, SC_KEYMENU, 0);
  1626. ThreadUnlock(&tlpwndT);
  1627. }
  1628. }
  1629. /*
  1630. * Turn off bit for tab-switching. This is set in the _KeyEvent()
  1631. * routine when it's been determined we're doing switching. This
  1632. * is necessary for cases where the ALT-KEY is release before the
  1633. * TAB-KEY. In which case, the FMENUSTATUS bit would be cleared
  1634. * by the ALT-KEY-UP and would have forced us into a syscommand
  1635. * loop. This guarentees that we don't enter that condition.
  1636. */
  1637. if (wParam == VK_MENU) {
  1638. pti->pq->QF_flags &= ~QF_TABSWITCHING;
  1639. xxxDrawMenuBarUnderlines(pwnd, FALSE);
  1640. }
  1641. pti->pq->QF_flags &= ~(QF_FMENUSTATUS | QF_FMENUSTATUSBREAK | QF_FF10STATUS);
  1642. }
  1643. break;
  1644. case WM_SYSCHAR:
  1645. {
  1646. PTHREADINFO pti = PtiCurrent();
  1647. /*
  1648. * If syskey is down and we have a char...
  1649. */
  1650. pti->pq->QF_flags &= ~(QF_FMENUSTATUS | QF_FMENUSTATUSBREAK);
  1651. if (wParam == VK_RETURN && TestWF(pwnd, WFMINIMIZED)) {
  1652. /*
  1653. * If the window is iconic and user hits RETURN, we want to
  1654. * restore this window.
  1655. */
  1656. _PostMessage(pwnd, WM_SYSCOMMAND, SC_RESTORE, 0L);
  1657. break;
  1658. }
  1659. if ((HIWORD(lParam) & SYS_ALTERNATE) && wParam) {
  1660. if (wParam == VK_TAB || wParam == VK_ESCAPE)
  1661. break;
  1662. /*
  1663. * Send ALT-SPACE only to top-level windows.
  1664. */
  1665. if ((wParam == MENUSYSMENU) && (TestwndChild(pwnd))) {
  1666. ThreadLockAlwaysWithPti(pti, pwnd->spwndParent, &tlpwndParent);
  1667. xxxSendMessage(pwnd->spwndParent, message, wParam, lParam);
  1668. ThreadUnlock(&tlpwndParent);
  1669. } else {
  1670. xxxSendMessage(pwnd, WM_SYSCOMMAND, SC_KEYMENU, (DWORD)wParam);
  1671. }
  1672. } else {
  1673. /*
  1674. * Ctrl-Esc produces a WM_SYSCHAR, But should not beep;
  1675. */
  1676. if (wParam != VK_ESCAPE)
  1677. xxxMessageBeep(0);
  1678. }
  1679. }
  1680. break;
  1681. case WM_UNICHAR:
  1682. if (wParam == UNICODE_NOCHAR) {
  1683. return FALSE;
  1684. } else {
  1685. _PostMessage(pwnd, WM_CHAR, wParam, lParam);
  1686. }
  1687. break;
  1688. case WM_CHARTOITEM:
  1689. case WM_VKEYTOITEM:
  1690. /*
  1691. * Do default processing for keystrokes into owner draw listboxes.
  1692. */
  1693. return -1L;
  1694. case WM_ACTIVATE:
  1695. if (wParam)
  1696. xxxSetFocus(pwnd);
  1697. break;
  1698. case WM_INPUTLANGCHANGEREQUEST:
  1699. {
  1700. PWND pwndFocus = PtiCurrent()->pq->spwndFocus;
  1701. /*
  1702. * #115190
  1703. * Dialog does not forward I.L.Reqest to the focused window.
  1704. * (Memphis compatible issue)
  1705. */
  1706. if (pwndFocus && (pwndFocus != pwnd) &&
  1707. pwnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_DIALOG]) {
  1708. /*
  1709. * pass message to focus'ed window. Old app, pass on to
  1710. * focus'ed window which may be ML aware. (edit class
  1711. * for example).
  1712. */
  1713. ThreadLockAlways(pwndFocus, &tlpwndT);
  1714. xxxSendMessage(pwndFocus, message, wParam, lParam);
  1715. ThreadUnlock(&tlpwndT);
  1716. } else if (!xxxActivateKeyboardLayout(_GetProcessWindowStation(NULL),
  1717. (HKL)lParam, KLF_SETFORPROCESS, pwnd)) {
  1718. RIPERR1(ERROR_INVALID_KEYBOARD_HANDLE, RIP_WARNING, "WM_INPUTLANGCHANGEREQUEST: Invalid keyboard handle (0x%08lx)", lParam);
  1719. }
  1720. break;
  1721. }
  1722. case WM_INPUTLANGCHANGE:
  1723. {
  1724. PBWL pbwl;
  1725. HWND *phwnd;
  1726. TL tlpwnd;
  1727. pbwl = BuildHwndList(pwnd->spwndChild, BWL_ENUMLIST, NULL);
  1728. if (pbwl == NULL)
  1729. return 0;
  1730. for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
  1731. /*
  1732. * Make sure this hwnd is still around.
  1733. */
  1734. if ((pwnd = RevalidateHwnd(*phwnd)) == NULL)
  1735. continue;
  1736. ThreadLockAlways(pwnd, &tlpwnd);
  1737. RIPMSG1(RIP_VERBOSE, "WM_INPUTLANGCHANGE: Sending message to pwnd %#p", pwnd);
  1738. xxxSendMessage(pwnd, message, wParam, lParam);
  1739. ThreadUnlock(&tlpwnd);
  1740. }
  1741. FreeHwndList(pbwl);
  1742. break;
  1743. }
  1744. case WM_SETREDRAW:
  1745. xxxDWP_SetRedraw(pwnd, wParam != 0);
  1746. break;
  1747. case WM_WINDOWPOSCHANGING:
  1748. {
  1749. /*
  1750. * If the window's size is changing, adjust the passed-in size
  1751. */
  1752. WINDOWPOS *ppos = ((WINDOWPOS *)lParam);
  1753. if (!(ppos->flags & SWP_NOSIZE)) {
  1754. xxxAdjustSize(pwnd, &ppos->cx, &ppos->cy);
  1755. }
  1756. }
  1757. break;
  1758. case WM_WINDOWPOSCHANGED:
  1759. xxxHandleWindowPosChanged(pwnd, (PWINDOWPOS)lParam);
  1760. break;
  1761. case WM_CTLCOLORSCROLLBAR:
  1762. if (gpsi->BitCount < 8 ||
  1763. SYSRGB(3DHILIGHT) != SYSRGB(SCROLLBAR) ||
  1764. SYSRGB(3DHILIGHT) == SYSRGB(WINDOW))
  1765. {
  1766. /*
  1767. * Remove call to UnrealizeObject. GDI handles this
  1768. * for brushes on NT.
  1769. *
  1770. * GreUnrealizeObject(ghbrGray);
  1771. */
  1772. GreSetBkColor((HDC)wParam, SYSRGB(3DHILIGHT));
  1773. GreSetTextColor((HDC)wParam, SYSRGB(3DFACE));
  1774. return((LRESULT)gpsi->hbrGray);
  1775. }
  1776. icolBack = COLOR_3DHILIGHT;
  1777. icolFore = COLOR_BTNTEXT;
  1778. goto SetColor;
  1779. case WM_CTLCOLORBTN:
  1780. if (TestWF(pwnd, WFWIN40COMPAT)) {
  1781. icolBack = COLOR_3DFACE;
  1782. icolFore = COLOR_BTNTEXT;
  1783. } else {
  1784. goto ColorDefault;
  1785. }
  1786. goto SetColor;
  1787. case WM_CTLCOLORSTATIC:
  1788. case WM_CTLCOLORDLG:
  1789. case WM_CTLCOLORMSGBOX:
  1790. // We want static controls in dialogs to have the 3D
  1791. // background color, but statics in windows to inherit
  1792. // their parents' background.
  1793. if (TestWF(pwnd, WFWIN40COMPAT)
  1794. ) {
  1795. icolBack = COLOR_3DFACE;
  1796. icolFore = COLOR_WINDOWTEXT;
  1797. goto SetColor;
  1798. }
  1799. // ELSE FALL THRU...
  1800. case WM_CTLCOLOR: // here for WOW only
  1801. case WM_CTLCOLORLISTBOX:
  1802. case WM_CTLCOLOREDIT:
  1803. ColorDefault:
  1804. icolBack = COLOR_WINDOW;
  1805. icolFore = COLOR_WINDOWTEXT;
  1806. SetColor:
  1807. GreSetBkColor((HDC)wParam, gpsi->argbSystem[icolBack]);
  1808. GreSetTextColor((HDC)wParam, gpsi->argbSystem[icolFore]);
  1809. return (LRESULT)(SYSHBRUSH(icolBack));
  1810. case WM_SETCURSOR:
  1811. /*
  1812. * wParam == pwndHit == pwnd that cursor is over
  1813. * lParamL == ht == Hit test area code (result of WM_NCHITTEST)
  1814. * lParamH == msg == Mouse message number
  1815. */
  1816. return (LONG)xxxDWP_SetCursor(pwnd, (HWND)wParam, (int)(SHORT)lParam,
  1817. HIWORD(lParam));
  1818. case WM_MOUSEACTIVATE:
  1819. pwndT = GetChildParent(pwnd);
  1820. if (pwndT != NULL) {
  1821. ThreadLockAlways(pwndT, &tlpwndT);
  1822. lt = xxxSendMessage(pwndT, WM_MOUSEACTIVATE, wParam, lParam);
  1823. ThreadUnlock(&tlpwndT);
  1824. if (lt != 0)
  1825. return lt;
  1826. }
  1827. /*
  1828. * Moving, sizing or minimizing? Activate AFTER we take action.
  1829. * If the user LEFT clicked in the title bar, don't activate now:
  1830. */
  1831. return ( (LOWORD(lParam) == HTCAPTION)
  1832. && (HIWORD(lParam) == WM_LBUTTONDOWN)
  1833. )
  1834. ? (LONG)MA_NOACTIVATE
  1835. : (LONG)MA_ACTIVATE;
  1836. case WM_SHOWWINDOW:
  1837. /*
  1838. * If we are being called because our owner window is being shown,
  1839. * hidden, minimized, or un-minimized, then we must hide or show
  1840. * show ourself as appropriate.
  1841. *
  1842. * This behavior occurs for popup windows or owned windows only.
  1843. * It's not designed for use with child windows.
  1844. */
  1845. if (LOWORD(lParam) != 0 && (TestwndPopup(pwnd) || pwnd->spwndOwner)) {
  1846. /*
  1847. * The WFHIDDENPOPUP flag is an internal flag that indicates
  1848. * that the window was hidden because its owner was hidden.
  1849. * This way we only show windows that were hidden by this code,
  1850. * not intentionally by the application.
  1851. *
  1852. * Go ahead and hide or show this window, but only if:
  1853. *
  1854. * a) we need to be hidden, or
  1855. * b) we need to be shown, and we were hidden by
  1856. * an earlier WM_SHOWWINDOW message
  1857. */
  1858. if ((!wParam && TestWF(pwnd, WFVISIBLE)) ||
  1859. (wParam && !TestWF(pwnd, WFVISIBLE) &&
  1860. TestWF(pwnd, WFHIDDENPOPUP))) {
  1861. /*
  1862. * Remember that we were hidden by WM_SHOWWINDOW processing
  1863. */
  1864. ClrWF(pwnd, WFHIDDENPOPUP);
  1865. if (!wParam)
  1866. SetWF(pwnd, WFHIDDENPOPUP);
  1867. xxxShowWindow(
  1868. pwnd,
  1869. (wParam ? SW_SHOWNOACTIVATE : SW_HIDE) | TEST_PUDF(PUDF_ANIMATE));
  1870. }
  1871. }
  1872. break;
  1873. case WM_SYSMENU:
  1874. if ( !TestWF(pwnd, WFDISABLED)
  1875. && ( (GETPTI(pwnd)->pq == gpqForeground)
  1876. || xxxSetForegroundWindow(pwnd, FALSE))
  1877. )
  1878. {
  1879. PMENU pMenu;
  1880. TL tpmenu;
  1881. DoTheDefaultThang:
  1882. if (TestWF(pwnd, WFMAXIMIZED) || TestWF(pwnd, WFMINIMIZED))
  1883. i = SC_RESTORE;
  1884. else
  1885. i = SC_MAXIMIZE;
  1886. DoTheSysMenuThang:
  1887. if ((pMenu = xxxGetSysMenu(pwnd, TRUE)) != NULL)
  1888. {
  1889. _SetMenuDefaultItem(pMenu, i, MF_BYCOMMAND);
  1890. // Tell the shell we are bringing it up the system menu
  1891. PostShellHookMessages(HSHELL_SYSMENU, (LPARAM)HWq(pwnd));
  1892. ThreadLockAlways(pMenu, &tpmenu);
  1893. if (lParam == 0xFFFFFFFF)
  1894. {
  1895. // this is a keyboard generated WM_SYSMENU
  1896. if (FDoTray())
  1897. {
  1898. TPMPARAMS tpm;
  1899. tpm.cbSize = sizeof(TPMPARAMS);
  1900. if (xxxSendMinRectMessages(pwnd, &tpm.rcExclude)) {
  1901. xxxTrackPopupMenuEx(pMenu, TPM_SYSMENU | TPM_VERTICAL,
  1902. tpm.rcExclude.left, tpm.rcExclude.top, pwnd, &tpm);
  1903. }
  1904. }
  1905. }
  1906. else
  1907. {
  1908. xxxTrackPopupMenuEx(pMenu, TPM_RIGHTBUTTON | TPM_SYSMENU,
  1909. GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pwnd, NULL);
  1910. }
  1911. ThreadUnlock(&tpmenu);
  1912. }
  1913. }
  1914. break;
  1915. case WM_DRAWITEM:
  1916. DWP_DrawItem((LPDRAWITEMSTRUCT)lParam);
  1917. break;
  1918. case WM_GETHOTKEY:
  1919. return (LONG)DWP_GetHotKey(pwnd);
  1920. break;
  1921. case WM_SETHOTKEY:
  1922. return (LONG)DWP_SetHotKey(pwnd, (DWORD)wParam);
  1923. break;
  1924. case WM_GETICON:
  1925. return (LRESULT)DWP_GetIcon(pwnd, (BOOL)wParam);
  1926. case WM_SETICON:
  1927. return (LRESULT)xxxDWP_SetIcon(pwnd, wParam, (HICON)lParam);
  1928. case WM_COPYGLOBALDATA:
  1929. /*
  1930. * This message is used to thunk WM_DROPFILES messages along
  1931. * with other things. If we end up here with it, directly
  1932. * call the client back to finish processing of this message.
  1933. * This assumes that the ultimate destination of the
  1934. * WM_DROPFILES message is in the client side's process context.
  1935. */
  1936. return(SfnCOPYGLOBALDATA(NULL, 0, wParam, lParam, 0, 0, 0, NULL));
  1937. case WM_QUERYDROPOBJECT:
  1938. /*
  1939. * if the app has registered interest in drops, return TRUE
  1940. */
  1941. return (LRESULT)(TestWF(pwnd, WEFACCEPTFILES) ? TRUE : FALSE);
  1942. case WM_DROPOBJECT:
  1943. return DO_DROPFILE;
  1944. case WM_ACCESS_WINDOW:
  1945. if (ValidateHwnd((HWND)wParam)) {
  1946. // SECURITY: set ACL for this window to no-access
  1947. return TRUE;
  1948. }
  1949. return FALSE;
  1950. case WM_NOTIFYFORMAT:
  1951. if(lParam == NF_QUERY)
  1952. return(TestWF(pwnd, WFANSICREATOR) ? NFR_ANSI : NFR_UNICODE);
  1953. break;
  1954. case WM_CHANGEUISTATE:
  1955. {
  1956. WORD wAction = LOWORD(wParam);
  1957. WORD wFlags = HIWORD(wParam);
  1958. BOOL bRealChange = FALSE;
  1959. /*
  1960. * Validate parameters and determine the flags that should actually be changed.
  1961. */
  1962. if ((wFlags & ~UISF_VALID) || (wAction > UIS_LASTVALID) || lParam) {
  1963. return 0;
  1964. }
  1965. if (wAction == UIS_INITIALIZE) {
  1966. wFlags = 0;
  1967. if (TEST_KbdCuesPUSIF) {
  1968. if (TEST_SRVIF(SRVIF_LASTRITWASKEYBOARD)) {
  1969. wAction = UIS_CLEAR;
  1970. } else {
  1971. wAction = UIS_SET;
  1972. }
  1973. wFlags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
  1974. wParam = MAKEWPARAM(wAction, wFlags);
  1975. }
  1976. } else if (!TEST_KbdCuesPUSIF) {
  1977. wFlags &= ~(UISF_HIDEFOCUS | UISF_HIDEACCEL);
  1978. }
  1979. if (wFlags == 0) {
  1980. return 0;
  1981. }
  1982. UserAssert(wAction == UIS_SET || wAction == UIS_CLEAR);
  1983. /*
  1984. * If the state is not going to change, there's nothing to do here
  1985. */
  1986. if (wFlags & UISF_HIDEFOCUS) {
  1987. bRealChange = (!!TestWF(pwnd, WEFPUIFOCUSHIDDEN)) ^ (wAction == UIS_SET);
  1988. }
  1989. if (wFlags & UISF_HIDEACCEL) {
  1990. bRealChange |= (!!TestWF(pwnd, WEFPUIACCELHIDDEN)) ^ (wAction == UIS_SET);
  1991. }
  1992. if (wFlags & UISF_ACTIVE) {
  1993. bRealChange |= (!!TestWF(pwnd, WEFPUIACTIVE)) ^ (wAction == UIS_SET);
  1994. }
  1995. if (!bRealChange) {
  1996. break;
  1997. }
  1998. /*
  1999. * Children pass this message up
  2000. * Top level windows update their children's state and
  2001. * send down to their imediate children WM_UPDATEUISTATE.
  2002. */
  2003. if (TestwndChild(pwnd)) {
  2004. ThreadLockAlways(pwnd->spwndParent, &tlpwndParent);
  2005. lt = xxxSendMessage(pwnd->spwndParent, WM_CHANGEUISTATE, wParam, lParam);
  2006. ThreadUnlock(&tlpwndParent);
  2007. return lt;
  2008. } else {
  2009. return xxxSendMessage(pwnd, WM_UPDATEUISTATE, wParam, lParam);
  2010. }
  2011. }
  2012. break;
  2013. case WM_QUERYUISTATE:
  2014. return (TestWF(pwnd, WEFPUIFOCUSHIDDEN) ? UISF_HIDEFOCUS : 0) |
  2015. (TestWF(pwnd, WEFPUIACCELHIDDEN) ? UISF_HIDEACCEL : 0) |
  2016. (TestWF(pwnd, WEFPUIACTIVE) ? UISF_ACTIVE : 0);
  2017. break;
  2018. case WM_UPDATEUISTATE:
  2019. {
  2020. WORD wAction = LOWORD(wParam);
  2021. WORD wFlags = HIWORD(wParam);
  2022. /*
  2023. * Validate parameters and determine the flags that should actually be changed.
  2024. */
  2025. if ((wFlags & ~UISF_VALID) || (wAction > UIS_LASTVALID) || lParam) {
  2026. return 0;
  2027. }
  2028. if (wAction == UIS_INITIALIZE) {
  2029. wFlags = 0;
  2030. if (TEST_KbdCuesPUSIF) {
  2031. if (TEST_SRVIF(SRVIF_LASTRITWASKEYBOARD)) {
  2032. wAction = UIS_CLEAR;
  2033. } else {
  2034. wAction = UIS_SET;
  2035. }
  2036. wFlags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
  2037. wParam = MAKEWPARAM(wAction, wFlags);
  2038. }
  2039. } else if (!TEST_KbdCuesPUSIF) {
  2040. wFlags &= ~(UISF_HIDEFOCUS | UISF_HIDEACCEL);
  2041. }
  2042. if (wFlags == 0) {
  2043. return 0;
  2044. }
  2045. switch (wAction) {
  2046. case UIS_INITIALIZE:
  2047. /*
  2048. * UISTATE: UIS_INITIALIZE sets the UIState bits for
  2049. * HIDEACCEL AND HIDEFOCUS based on the last input type.
  2050. *
  2051. * ACTIVE will not be changed.
  2052. */
  2053. if (!TEST_SRVIF(SRVIF_LASTRITWASKEYBOARD)) {
  2054. SetWF(pwnd, WEFPUIFOCUSHIDDEN);
  2055. SetWF(pwnd, WEFPUIACCELHIDDEN);
  2056. wParam = MAKEWPARAM(UIS_SET, UISF_HIDEACCEL | UISF_HIDEFOCUS);
  2057. } else {
  2058. ClrWF(pwnd, WEFPUIFOCUSHIDDEN);
  2059. ClrWF(pwnd, WEFPUIACCELHIDDEN);
  2060. wParam = MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS);
  2061. }
  2062. break;
  2063. case UIS_SET:
  2064. if (wFlags & UISF_HIDEACCEL) {
  2065. SetWF(pwnd, WEFPUIACCELHIDDEN);
  2066. }
  2067. if (wFlags & UISF_HIDEFOCUS) {
  2068. SetWF(pwnd, WEFPUIFOCUSHIDDEN);
  2069. }
  2070. if (wFlags & UISF_ACTIVE) {
  2071. SetWF(pwnd, WEFPUIACTIVE);
  2072. }
  2073. break;
  2074. case UIS_CLEAR:
  2075. if (wFlags & UISF_HIDEACCEL) {
  2076. ClrWF(pwnd, WEFPUIACCELHIDDEN);
  2077. }
  2078. if (wFlags & UISF_HIDEFOCUS) {
  2079. ClrWF(pwnd, WEFPUIFOCUSHIDDEN);
  2080. }
  2081. if (wFlags & UISF_ACTIVE) {
  2082. ClrWF(pwnd, WEFPUIACTIVE);
  2083. }
  2084. break;
  2085. default:
  2086. break;
  2087. }
  2088. /*
  2089. * Send it down to its immediate children if any
  2090. */
  2091. if (pwnd->spwndChild) {
  2092. PBWL pbwl;
  2093. HWND *phwnd;
  2094. TL tlpwnd;
  2095. pbwl = BuildHwndList(pwnd->spwndChild, BWL_ENUMLIST, NULL);
  2096. if (pbwl == NULL)
  2097. return 0;
  2098. for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
  2099. /*
  2100. * Make sure this hwnd is still around.
  2101. */
  2102. if ((pwnd = RevalidateHwnd(*phwnd)) == NULL)
  2103. continue;
  2104. ThreadLockAlways(pwnd, &tlpwnd);
  2105. xxxSendMessage(pwnd, message, wParam, lParam);
  2106. ThreadUnlock(&tlpwnd);
  2107. }
  2108. FreeHwndList(pbwl);
  2109. }
  2110. }
  2111. break;
  2112. #ifdef PENWIN20
  2113. // LATER mikeke
  2114. default:
  2115. // BOGUS
  2116. // 32-bit ize DefPenWindowProc
  2117. //
  2118. // call DefPenWindowProc if penwin is loaded
  2119. if ( (message >= WM_HANDHELDFIRST)
  2120. && (message <= WM_HANDHELDLAST)
  2121. ) {
  2122. if (lpfnHandHeld != NULL)
  2123. return (*lpfnHandHeld)(HW16(pwnd), message, wParamLo, lParam);
  2124. } else if ( (message >= WM_PENWINFIRST)
  2125. && (message <= WM_PENWINLAST)
  2126. ) {
  2127. if (SYSMET(PENWINDOWS))
  2128. return DefPenWindowProc(pwnd, message, wParamLo, lParam);
  2129. }
  2130. #endif // PENWIN20
  2131. }
  2132. return 0;
  2133. }