BOOL _HasCaptionIcon(PWND pwnd) { HICON hIcon; PCLS pcls; if (TestWF(pwnd, WEFTOOLWINDOW)) // it's a tool window -- it doesn't get an icon return(FALSE); if ((TestWF(pwnd, WFBORDERMASK) != (BYTE)LOBYTE(WFDLGFRAME)) && !TestWF(pwnd, WEFDLGMODALFRAME)) // they are not trying to look like a dialog, they get an icon return TRUE; if (!TestWF(pwnd, WFWIN40COMPAT) && (((PCLS)REBASEALWAYS(pwnd, pcls))->atomClassName == (ATOM)DIALOGCLASS)) // it's an older REAL dialog -- it doesn't get an icon return(FALSE); hIcon = (HICON) _GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp), TRUE); if (hIcon) { // it's a 4.0 dialog with a small icon -- if that small icon is // something other than the generic small windows icon, it gets an icon return(hIcon != gpsi->hIconSmWindows); } hIcon = (HICON) _GetProp(pwnd, MAKEINTATOM(gpsi->atomIconProp), TRUE); if (hIcon && (hIcon != gpsi->hIcoWindows)) // it's a 4.0 dialog with no small icon, but instead a large icon // that's not the generic windows icon -- it gets an icon return(TRUE); pcls = REBASEALWAYS(pwnd, pcls); if (pcls->spicnSm) { if (pcls->spicnSm != HMObjectFromHandle(gpsi->hIconSmWindows)) { // it's a 4.0 dialog with a class icon that's not the generic windows // icon -- it gets an icon return(TRUE); } } // it's a 4.0 dialog with no small or large icon -- it doesn't get an icon return(FALSE); }
VOID xxxRecreateSmallIcons(PWND pwnd) { BOOL fSmQueryDrag; CheckLock(pwnd); if (DestroyClassSmIcon(pwnd->pcls)) xxxCreateClassSmIcon(pwnd->pcls); fSmQueryDrag = (TestWF(pwnd, WFSMQUERYDRAGICON) != 0); if (DestroyWindowSmIcon(pwnd) && !fSmQueryDrag) xxxCreateWindowSmIcon(pwnd, (HICON)_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconProp), PROPF_INTERNAL), TRUE); }
DWORD GetContextHelpId( PWND pwnd) { DWORD dwContextId; while (!(dwContextId = (DWORD)_GetProp(pwnd, MAKEINTATOM(gpsi->atomContextHelpIdProp), PROPF_INTERNAL))) { pwnd = (TestwndChild(pwnd) ? REBASEPWND(pwnd, spwndParent) : REBASEPWND(pwnd, spwndOwner)); if (!pwnd || (GETFNID(pwnd) == FNID_DESKTOP)) break; } return dwContextId; }
/* * Modal loop for when the user has selected the help icon from the titlebar * */ VOID xxxHelpLoop(PWND pwnd) { HWND hwndChild; PWND pwndChild; PWND pwndControl; MSG msg; RECT rc; int cBorders; PTHREADINFO ptiCurrent = PtiCurrent(); DLGENUMDATA DlgEnumData; TL tlpwndChild; CheckLock(pwnd); UserAssert(IsWinEventNotifyDeferredOK()); if (FWINABLE()) { xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPSTART, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, 0); } zzzSetCursor(SYSCUR(HELP)); xxxCapture(ptiCurrent, pwnd, SCREEN_CAPTURE); cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); CopyInflateRect(&rc, &pwnd->rcWindow, -cBorders * SYSMET(CXBORDER), -cBorders * SYSMET(CYBORDER)); while (ptiCurrent->pq->spwndCapture == pwnd) { if (!xxxPeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_NOREMOVE)) { xxxWaitMessage(); continue; } if (msg.message == WM_NCLBUTTONDOWN) { break; } else if (msg.message == WM_LBUTTONDOWN) { /* * If user clicked outside of window client, bail out now. */ if (!PtInRect(&rc, msg.pt)) break; /* * WindowHitTest() won't return a static control's handle */ hwndChild = xxxWindowHitTest(pwnd, msg.pt, NULL, 0); pwndChild = ValidateHwnd( hwndChild ); ThreadLock(pwndChild, &tlpwndChild); if (pwndChild && FIsParentDude(pwndChild)) { /* * If this is a dialog class, then one of three things has * happened: * * o This is a static text control * o This is the background of the dialog box. * * What we do is enumerate the child windows and see if * any of them contain the current cursor point. If they do, * change our window handle and continue on. Otherwise, * return doing nothing -- we don't want context-sensitive * help for a dialog background. * * If this is a group box, then we might have clicked on a * disabled control, so we enumerate child windows to see * if we get another control. */ /* * We're enumerating a dialog's children. So, if we don't * find any matches, hwndChild will be NULL and the check * below will drop out. */ DlgEnumData.pwndDialog = pwndChild; DlgEnumData.pwndControl = NULL; DlgEnumData.ptCurHelp = msg.pt; xxxInternalEnumWindow(pwndChild, EnumPwndDlgChildProc, (LPARAM)&DlgEnumData, BWL_ENUMCHILDREN); pwndControl = DlgEnumData.pwndControl; } else { pwndControl = pwndChild; } /* * If we click on nothing, just exit. */ if (pwndControl == pwnd) { pwndControl = NULL; } /* * HACK ALERT (Visual Basic 4.0) - they have their own non-window * based controls that draw directly on the main dialog. In order * to provide help for these controls, we pass along the WM_HELP * message iff the main dialog has a context id assigned. * * If the top level window has its own context help ID, * then pass it in the context help message. */ if (!pwndControl) { if (_GetProp(pwnd, MAKEINTATOM(gpsi->atomContextHelpIdProp), TRUE)) pwndControl = pwnd; } if (pwndControl) { PWND pwndSend; int id; TL tlpwndSend; TL tlpwndControl; ThreadLockAlways(pwndControl, &tlpwndControl); zzzSetCursor(SYSCUR(ARROW)); xxxReleaseCapture(); xxxRedrawTitle(pwnd, DC_BUTTONS); ClrWF(pwnd, WFHELPBUTTONDOWN); xxxGetMessage(&msg, NULL, 0, 0); if (FWINABLE()) { xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR, INDEX_TITLEBAR_HELPBUTTON, FALSE); xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPEND, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, FALSE); } /* * Determine the ID of the control * We used to always sign extend, but Win98 doesn't do that * so we only sign extend 0xffff. MCostea #218711 */ if (TestwndChild(pwndControl)) { id = PTR_TO_ID(pwndControl->spmenu); if (id == 0xffff) { id = -1; } } else { id = -1; } /* * Disabled controls and static controls won't pass this * on to their parent, so instead, we send the message to * their parent. */ if (TestWF(pwndControl, WFDISABLED)) { PWND pwndParent = _GetParent(pwndControl); if (!pwndParent) { ThreadUnlock( &tlpwndControl ); ThreadUnlock( &tlpwndChild ); return; } pwndSend = pwndParent; } else { pwndSend = pwndControl; } ThreadLockAlways(pwndSend, &tlpwndSend); xxxSendHelpMessage( pwndSend, HELPINFO_WINDOW, id, (HANDLE)HWq(pwndControl), GetContextHelpId(pwndControl)); ThreadUnlock(&tlpwndSend); ThreadUnlock(&tlpwndControl); ThreadUnlock(&tlpwndChild); return; } ThreadUnlock(&tlpwndChild); break; } else if ((msg.message == WM_RBUTTONDOWN) || (msg.message == WM_MBUTTONDOWN) || (msg.message == WM_XBUTTONDOWN)) { /* * fix bug 29852; break the loop for right and middle buttons * and pass along the messages to the control */ break; } else if (msg.message == WM_MOUSEMOVE) { if (PtInRect(&rc, msg.pt)) zzzSetCursor(SYSCUR(HELP)); else zzzSetCursor(SYSCUR(ARROW)); } else if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) { xxxGetMessage( &msg, NULL, 0, 0 ); break; } xxxGetMessage(&msg, NULL, 0, 0); xxxTranslateMessage(&msg, 0); xxxDispatchMessage(&msg); } xxxReleaseCapture(); zzzSetCursor(SYSCUR(ARROW)); xxxRedrawTitle(pwnd, DC_BUTTONS); ClrWF(pwnd, WFHELPBUTTONDOWN); if (FWINABLE()) { xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR, INDEX_TITLEBAR_HELPBUTTON, 0); xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPEND, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, 0); } }
DWORD _GetWindowContextHelpId(PWND pWnd) { return (DWORD)(ULONG_PTR)_GetProp(pWnd, MAKEINTATOM(gpsi->atomContextHelpIdProp), PROPF_INTERNAL); }
UINT xxxArrangeIconicWindows( PWND pwnd) { PBWL pbwl; PSMWP psmwp; PWND pwndTest, pwndSort, pwndSwitch; HWND *phwnd, *phwndSort; CHECKPOINT *pcp, *pcpSort; POINT ptSort, ptSrc; WORD nIcons = 0; RECT rc; POINT ptMin; int xOrg, yOrg; int dx, dy; int dxSlot, dySlot; int cIconsPerPass, iIconPass; BOOL fHorizontal, fBreak; TL tlpwndTest; BOOL fHideMe; CheckLock(pwnd); /* * Create a window list of all children of pwnd */ if ((pbwl = BuildHwndList(pwnd->spwndChild, BWL_ENUMLIST, NULL)) == NULL) return 0; fHideMe = IsTrayWindow(pwnd->spwndChild); // // Put these into local vars for efficiency (see ParkIcon()) // dxSlot = SYSMET(CXMINSPACING); dySlot = SYSMET(CYMINSPACING); // // We need to adjust the client rectangle if the parent has scrollbars. // GetRealClientRect(pwnd, &rc, GRC_SCROLLS); /* * find all icons */ pwndSwitch = RevalidateHwnd(ghwndSwitch); for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) { if (((pwndTest = RevalidateHwnd(*phwnd)) == NULL) || !TestWF(pwndTest , WFVISIBLE) || pwndTest == pwndSwitch || (pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT, PROPF_INTERNAL)) == NULL) { *phwnd = NULL; continue; } if (!TestWF(pwndTest, WFMINIMIZED)) { pcp->fMinInitialized = FALSE; pcp->ptMin.x = pcp->ptMin.y = -1; *phwnd = NULL; continue; } /* * inc count of icons */ nIcons++; /* * we will park in default position again... */ pcp->fDragged = FALSE; /* * ensure the original position is up to date */ pcp->ptMin.x = pwndTest->rcWindow.left - pwnd->rcClient.left; pcp->ptMin.y = pwndTest->rcWindow.top - pwnd->rcClient.top; // Slide into the nearest row or column switch (SYSMET(ARRANGE) & ~ARW_HIDE) { case ARW_TOPLEFT | ARW_RIGHT: case ARW_TOPRIGHT | ARW_LEFT: // Slide into top row pcp->ptMin.y += dySlot / 2; pcp->ptMin.y -= pcp->ptMin.y % dySlot; break; case ARW_TOPLEFT | ARW_DOWN: case ARW_BOTTOMLEFT | ARW_UP: // Slide into left column pcp->ptMin.x += dxSlot / 2; pcp->ptMin.x -= pcp->ptMin.x % dxSlot; break; case ARW_BOTTOMLEFT | ARW_RIGHT: case ARW_BOTTOMRIGHT | ARW_LEFT: // Slide into bottom row pcp->ptMin.y = rc.bottom - pcp->ptMin.y; pcp->ptMin.y += dySlot / 2; pcp->ptMin.y -= pcp->ptMin.y % dySlot; pcp->ptMin.y = rc.bottom - pcp->ptMin.y; break; case ARW_BOTTOMRIGHT | ARW_UP: case ARW_TOPRIGHT | ARW_DOWN: // Slide into right column pcp->ptMin.x = rc.right - pcp->ptMin.x; pcp->ptMin.x += dxSlot / 2; pcp->ptMin.x -= pcp->ptMin.x % dxSlot; pcp->ptMin.x = rc.right - pcp->ptMin.x; break; } } if (nIcons == 0) { /* * no icons were found... break out */ FreeHwndList(pbwl); return 0; } if (fHideMe) { ptMin.x = WHERE_NOONE_CAN_SEE_ME; ptMin.y = WHERE_NOONE_CAN_SEE_ME; goto JustParkEm; } // // Get gravity && move vars // if (SYSMET(ARRANGE) & ARW_STARTRIGHT) { // Starting on right side ptMin.x = xOrg = rc.right - dxSlot; dx = -dxSlot; } else { // Starting on left ptMin.x = xOrg = rc.left + DX_GAP; dx = dxSlot; } if (SYSMET(ARRANGE) & ARW_STARTTOP) { // Starting on top ptMin.y = yOrg = rc.top + DY_GAP; dy = dySlot; } else { // Starting on bottom ptMin.y = yOrg = rc.bottom - dySlot; dy = -dySlot; } // // Get arrange dir // fHorizontal = ( (SYSMET(ARRANGE) & ARW_DOWN) ? FALSE : TRUE ); iIconPass = fHorizontal ? (rc.right / dxSlot) : (rc.bottom / dySlot); cIconsPerPass = iIconPass = max(1, iIconPass); /* * insertion sort of windows by y, and by x within a row. */ for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) { /* * Check for 0 (window was not icon) and * Check for invalid HWND (window has been destroyed) */ if (*phwnd == NULL || (pwndTest = RevalidateHwnd(*phwnd)) == NULL) continue; pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT, PROPF_INTERNAL); ptSrc = pcp->ptMin; fBreak = FALSE; for (phwndSort = pbwl->rghwnd; phwndSort < phwnd; phwndSort++) { if (*phwndSort == NULL || (pwndSort = RevalidateHwnd(*phwndSort)) == NULL) continue; pcpSort = (CHECKPOINT*)_GetProp(pwndSort, PROP_CHECKPOINT, PROPF_INTERNAL); ptSort = pcpSort->ptMin; // // Is this the position in which to sort this min window? // switch (SYSMET(ARRANGE) & ~ARW_HIDE) { case ARW_BOTTOMLEFT | ARW_RIGHT: // Lower left, moving horizontally if (((ptSort.y == ptSrc.y) && (ptSort.x > ptSrc.x)) || (ptSort.y < ptSrc.y)) fBreak = TRUE; break; case ARW_BOTTOMLEFT | ARW_UP: // Lower left, moving vertically if (((ptSort.x == ptSrc.x) && (ptSort.y < ptSrc.y)) || (ptSort.x > ptSrc.x)) fBreak = TRUE; break; case ARW_BOTTOMRIGHT | ARW_LEFT: // Lower right, moving horizontally if (((ptSort.y == ptSrc.y) && (ptSort.x < ptSrc.x)) || (ptSort.y < ptSrc.y)) fBreak = TRUE; break; case ARW_BOTTOMRIGHT | ARW_UP: // Lower right, moving vertically if (((ptSort.x == ptSrc.x) && (ptSort.y < ptSrc.y)) || (ptSort.x < ptSrc.x)) fBreak = TRUE; break; case ARW_TOPLEFT | ARW_RIGHT: // Top left, moving horizontally if (((ptSort.y == ptSrc.y) && (ptSort.x > ptSrc.x)) || (ptSort.y > ptSrc.y)) fBreak = TRUE; break; case ARW_TOPLEFT | ARW_DOWN: // Top left, moving vertically if (((ptSort.x == ptSrc.x) && (ptSort.y > ptSrc.y)) || (ptSort.x > ptSrc.x)) fBreak = TRUE; break; case ARW_TOPRIGHT | ARW_LEFT: // Top right, moving horizontally if (((ptSort.y == ptSrc.y) && (ptSort.x < ptSrc.x)) || (ptSort.y > ptSrc.y)) fBreak = TRUE; break; case ARW_TOPRIGHT | ARW_DOWN: // Top right, moving vertically if (((ptSort.x == ptSrc.x) && (ptSort.y > ptSrc.y)) || (ptSort.x < ptSrc.x)) fBreak = TRUE; break; } if (fBreak) break; } /* * insert the window at this position by sliding the rest up. * LATER IanJa, use hwnd intermediate variables, avoid PW() & HW() */ while (phwndSort < phwnd) { pwndSort = PW(*phwndSort); *phwndSort = HW(pwndTest); pwndTest = pwndSort; phwndSort++; } /* * replace the window handle in the original position */ *phwnd = HW(pwndTest); } // // Now park the icons. // JustParkEm: for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) { if (*phwnd == NULL || (pwndTest = RevalidateHwnd(*phwnd)) == NULL) continue; if (fHideMe) { pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT, PROPF_INTERNAL); if (pcp != NULL) { pcp->fMinInitialized = TRUE; pcp->ptMin.x = ptMin.x; pcp->ptMin.y = ptMin.y; } continue; } pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT, PROPF_INTERNAL); if (pcp != NULL) { pcp->fMinInitialized = TRUE; pcp->ptMin.x = ptMin.x; pcp->ptMin.y = ptMin.y; } // Setup to process the next position if (--iIconPass <= 0) { // Need to setup next pass iIconPass = cIconsPerPass; if (fHorizontal) { ptMin.x = xOrg; ptMin.y += dy; } else { ptMin.x += dx; ptMin.y = yOrg; } } else { // Same pass if (fHorizontal) ptMin.x += dx; else ptMin.y += dy; } } psmwp = _BeginDeferWindowPos(2 * nIcons); if (psmwp == NULL) goto ParkExit; for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) { /* * Check for a NULL (window has gone away) */ if (*phwnd == NULL || (pwndTest = RevalidateHwnd(*phwnd)) == NULL) continue; pcp = (CHECKPOINT *)_GetProp(pwndTest, PROP_CHECKPOINT, PROPF_INTERNAL); ThreadLockAlways(pwndTest, &tlpwndTest); psmwp = _DeferWindowPos(psmwp, pwndTest, NULL, pcp->ptMin.x, pcp->ptMin.y, rgptMinMaxWnd[MMI_MINSIZE].x, rgptMinMaxWnd[MMI_MINSIZE].y, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS); ThreadUnlock(&tlpwndTest); if (psmwp == NULL) break; } if (psmwp != NULL) { /* * Make the swp async so we don't hang waiting for hung apps. */ xxxEndDeferWindowPosEx(psmwp, TRUE); } ParkExit: FreeHwndList(pbwl); return nIcons; }