void TooltipRender(PTOOLTIPWND pttwnd, HDC hdc) { COLORREF crBk; UINT uFlags; RECT rc; if (pttwnd->pstr == NULL) return; GreSelectFont(hdc, ghStatusFont); GreSetTextColor(hdc, gpsi->argbSystem[COLOR_INFOTEXT]); crBk = gpsi->argbSystem[COLOR_INFOBK]; CopyOffsetRect(&rc, &pttwnd->rcClient, -pttwnd->rcClient.left, -pttwnd->rcClient.top); /* * We don't want dithered colors, so FillRect with the nearest color. */ if (crBk == GreGetNearestColor(hdc, crBk)) { GreSetBkColor(hdc, crBk); uFlags = ETO_OPAQUE; } else { FillRect(hdc, &rc, SYSHBR(INFOBK)); GreSetBkMode(hdc, TRANSPARENT); uFlags = ETO_CLIPPED; } GreExtTextOutW(hdc, SYSMET(CXBORDER) * TT_XOFFSET, SYSMET(CYBORDER) * TT_YOFFSET, uFlags, &rc, pttwnd->pstr, wcslen(pttwnd->pstr), NULL); }
void xxxMNRecomputeBarIfNeeded( PWND pwndNotify, PMENU pMenu) { int cxFrame; int cyFrame; UserAssert(!TestMF(pMenu, MFISPOPUP)); CheckLock(pwndNotify); CheckLock(pMenu); if (!TestMF(pMenu, MFSYSMENU) && ((pMenu->spwndNotify != pwndNotify) || !pMenu->cxMenu || !pMenu->cyMenu)) { int cBorders; cBorders = GetWindowBorders(pwndNotify->style, pwndNotify->ExStyle, TRUE, FALSE); cxFrame = cBorders * SYSMET(CXBORDER); cyFrame = cBorders * SYSMET(CYBORDER); cyFrame += GetCaptionHeight(pwndNotify); // The width passed in this call was larger by cxFrame; // Fix for Bug #11466 - Fixed by SANKAR - 01/06/92 -- xxxMenuBarCompute(pMenu, pwndNotify, cyFrame, cxFrame, (pwndNotify->rcWindow.right - pwndNotify->rcWindow.left) - cxFrame * 2); } }
void TooltipGetSize(PTOOLTIPWND pttwnd, SIZE *psize) { HDC hdc = GetTooltipDC(pttwnd); GreGetTextExtentW(hdc, pttwnd->pstr, wcslen(pttwnd->pstr), psize, GGTE_WIN3_EXTENT); _ReleaseDC(hdc); psize->cx += SYSMET(CXEDGE) + 2 * SYSMET(CXBORDER) * TT_XOFFSET; psize->cy += SYSMET(CYEDGE) + 2 * SYSMET(CYBORDER) * TT_YOFFSET; }
void GetRealClientRect( PWND pwnd, LPRECT prc, UINT uFlags) { if (GETFNID(pwnd) == FNID_DESKTOP) { *prc = (uFlags & GRC_FULLSCREEN) ? pwnd->rcWindow : gpsi->rcWork; } else { _GetClientRect(pwnd, prc); if (uFlags & GRC_SCROLLS) { if (TestWF(pwnd, WFHPRESENT)) prc->bottom += SYSMET(CYHSCROLL); if (TestWF(pwnd, WFVPRESENT)) prc->right += SYSMET(CXVSCROLL); } } if (uFlags & GRC_MINWNDS) { switch (SYSMET(ARRANGE) & ~ARW_HIDE) { case ARW_TOPLEFT | ARW_RIGHT: case ARW_TOPRIGHT | ARW_LEFT: // // Leave space on top for one row of min windows // prc->top += SYSMET(CYMINSPACING); break; case ARW_TOPLEFT | ARW_DOWN: case ARW_BOTTOMLEFT | ARW_UP: // // Leave space on left for one column of min windows // prc->left += SYSMET(CXMINSPACING); break; case ARW_TOPRIGHT | ARW_DOWN: case ARW_BOTTOMRIGHT | ARW_UP: // // Leave space on right for one column of min windows // prc->right -= SYSMET(CXMINSPACING); break; case ARW_BOTTOMLEFT | ARW_RIGHT: case ARW_BOTTOMRIGHT | ARW_LEFT: // // Leave space on bottom for one row of min windows // prc->bottom -= SYSMET(CYMINSPACING); break; } } }
PWND SizeBoxHwnd( PWND pwnd) { int xbrChild = pwnd->rcWindow.right; int ybrChild = pwnd->rcWindow.bottom; while (GETFNID(pwnd) != FNID_DESKTOP) { if (TestWF(pwnd, WFSIZEBOX)) { // First sizeable parent found int xbrParent; int ybrParent; if (TestWF(pwnd, WFMAXIMIZED)) return(NULL); xbrParent = pwnd->rcClient.right; ybrParent = pwnd->rcClient.bottom; /* If the sizebox dude is within an EDGE of the client's bottom * right corner, let this succeed. That way people who draw * their own sunken clients will be happy. */ if ((xbrChild + SYSMET(CXEDGE) < xbrParent) || (ybrChild + SYSMET(CYEDGE) < ybrParent)) { // // Child's bottom, right corner of SIZEBOX isn't close enough // to bottom right of parent's client. // return(NULL); } return(pwnd); } if (!TestWF(pwnd, WFCHILD) || TestWF(pwnd, WFCPRESENT)) break; pwnd = REBASEPWND(pwnd, spwndParent); } return(NULL); }
void MNPositionSysMenu( PWND pwnd, PMENU pmenusys) { RECT rc; PITEM pItem; if (pmenusys == NULL) { RIPERR0(ERROR_INVALID_HANDLE, RIP_WARNING, "Invalid menu handle pmenusys (NULL) to MNPositionSysMenu"); return; } /* * Setup the SysMenu hit rectangle. */ rc.top = rc.left = 0; if (TestWF(pwnd, WEFTOOLWINDOW)) { rc.right = SYSMET(CXSMSIZE); rc.bottom = SYSMET(CYSMSIZE); } else { rc.right = SYSMET(CXSIZE); rc.bottom = SYSMET(CYSIZE); } if (!TestWF(pwnd, WFMINIMIZED)) { int cBorders; cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); OffsetRect(&rc, cBorders*SYSMET(CXBORDER), cBorders*SYSMET(CYBORDER)); } /* * Offset the System popup menu. */ Lock(&pmenusys->spwndNotify, pwnd); if (!TestMF(pmenusys, MF_POPUP) && (pmenusys->cItems > 0)) { pItem = pmenusys->rgItems; if (pItem) { pItem->yItem = rc.top; pItem->xItem = rc.left; pItem->cyItem = rc.bottom - rc.top; pItem->cxItem = rc.right - rc.left; } } else // BOGUS -- MF_POPUP should never be set on a MENU -- only a MENU ITEM UserAssert(FALSE); }
int xxxMenuBarCompute( PMENU pMenu, PWND pwndNotify, DWORD yMenuTop, DWORD xMenuLeft, int cxMax) { int size; /* menuHeight is set by MNCompute when dealing with a top level menu and * not all items in the menu bar have the same height. Thus, by setting * menuHeight, MNCompute is called a second time to set every item to the * same height. The actual value stored in menuHeight is the maximum * height of all the menu bar items */ DWORD menuHeight = 0; CheckLock(pwndNotify); CheckLock(pMenu); size = xxxMNCompute(pMenu, pwndNotify, yMenuTop, xMenuLeft, cxMax, &menuHeight); if (!TestMF(pMenu, MFISPOPUP)) { if (menuHeight != 0) { /* * Add a border for the multi-row case. */ size = xxxMNCompute(pMenu, pwndNotify, yMenuTop, xMenuLeft, cxMax, &menuHeight); } /* * Right justification of HELP items is only needed on top level * menus. */ MBC_RightJustifyMenu(pMenu); } /* * There's an extra border underneath the menu bar, if it's not empty! */ return(size ? size + SYSMET(CYBORDER) : size); }
int FindNCHit( PWND pwnd, LONG lPt) { POINT pt; RECT rcWindow; RECT rcClient; RECT rcClientAdj; int cBorders; int dxButton; pt.x = LOWORD(lPt); pt.y = HIWORD(lPt); if (!PtInRect(&pwnd->rcWindow, pt)) return HTNOWHERE; if (TestWF(pwnd, WFMINIMIZED)) { CopyInflateRect(&rcWindow, &pwnd->rcWindow, -(SYSMET(CXFIXEDFRAME) + SYSMET(CXBORDER)), -(SYSMET(CYFIXEDFRAME) + SYSMET(CYBORDER))); if (!PtInRect(&rcWindow, pt)) return HTCAPTION; goto CaptionHit; } // Get client rectangle rcClient = pwnd->rcClient; if (PtInRect(&rcClient, pt)) return HTCLIENT; // Are we in "pseudo" client, i.e. the client & scrollbars & border if (TestWF(pwnd, WEFCLIENTEDGE)) CopyInflateRect(&rcClientAdj, &rcClient, SYSMET(CXEDGE), SYSMET(CYEDGE)); else rcClientAdj = rcClient; if (TestWF(pwnd, WFVPRESENT)) rcClientAdj.right += SYSMET(CXVSCROLL); if (TestWF(pwnd, WFHPRESENT)) rcClientAdj.bottom += SYSMET(CYHSCROLL); if (!PtInRect(&rcClientAdj, pt)) { // Subtract out window borders cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); CopyInflateRect(&rcWindow, &pwnd->rcWindow, -cBorders*SYSMET(CXBORDER), -cBorders*SYSMET(CYBORDER)); // Are we on the border? if (!PtInRect(&rcWindow, pt)) { // On a sizing border? if (!TestWF(pwnd, WFSIZEBOX)) { // // Old compatibility thing: For 3.x windows that just had // a border, we returned HTNOWHERE, believe it or not, // because our hit-testing code was so brain dead. // if (!TestWF(pwnd, WFWIN40COMPAT) && !TestWF(pwnd, WFDLGFRAME) && !TestWF(pwnd, WEFDLGMODALFRAME)) { return(HTNOWHERE); } else { return(HTBORDER); // We are on a dlg frame. } } else { int ht; // // Note this improvement. The HT codes are numbered so that // if you subtract HTSIZEFIRST-1 from them all, they sum up. I.E., // (HTLEFT - HTSIZEFIRST + 1) + (HTTOP - HTSIZEFIRST + 1) == // (HTTOPLEFT - HTSIZEFIRST + 1). // if (TestWF(pwnd, WEFTOOLWINDOW)) InflateRect(&rcWindow, -SYSMET(CXSMSIZE), -SYSMET(CYSMSIZE)); else InflateRect(&rcWindow, -SYSMET(CXSIZE), -SYSMET(CYSIZE)); if (pt.y < rcWindow.top) ht = (HTTOP - HTSIZEFIRST + 1); else if (pt.y >= rcWindow.bottom) ht = (HTBOTTOM - HTSIZEFIRST + 1); else ht = 0; if (pt.x < rcWindow.left) ht += (HTLEFT - HTSIZEFIRST + 1); else if (pt.x >= rcWindow.right) ht += (HTRIGHT - HTSIZEFIRST + 1); return (ht + HTSIZEFIRST - 1); } } // Are we above the client area? if (pt.y < rcClientAdj.top) { // Are we in the caption? if (TestWF(pwnd, WFBORDERMASK) == LOBYTE(WFCAPTION)) { CaptionHit: if (pt.y >= rcWindow.top) { if (TestWF(pwnd, WEFTOOLWINDOW)) { rcWindow.top += SYSMET(CYSMCAPTION); dxButton = SYSMET(CXSMSIZE); } else { rcWindow.top += SYSMET(CYCAPTION); dxButton = SYSMET(CXSIZE); } if ((pt.y >= rcWindow.top) && TestWF(pwnd, WFMPRESENT)) return(HTMENU); if ((pt.x >= rcWindow.left) && (pt.x < rcWindow.right) && (pt.y < rcWindow.top)) { // Are we in the window menu? if (TestWF(pwnd, WFSYSMENU)) { rcWindow.left += dxButton; if (pt.x < rcWindow.left) { if (!_HasCaptionIcon(pwnd)) // iconless windows have no sysmenu hit rect return(HTCAPTION); return(HTSYSMENU); } } else if (TestWF(pwnd, WFWIN40COMPAT)) return(HTCAPTION); // only a close button if window has a system menu // Are we in the close button? rcWindow.right -= dxButton; if (pt.x >= rcWindow.right) return HTCLOSE; if ((pt.x < rcWindow.right) && !TestWF(pwnd, WEFTOOLWINDOW)) { // Are we in the maximize/restore button? if (TestWF(pwnd, (WFMAXBOX | WFMINBOX))) { // Note that sizing buttons are same width for both // big captions and small captions. rcWindow.right -= dxButton; if (pt.x >= rcWindow.right) return HTZOOM; // Are we in the minimize button? rcWindow.right -= dxButton; if (pt.x >= rcWindow.right) return HTREDUCE; } else if (TestWF(pwnd, WEFCONTEXTHELP)) { rcWindow.right -= dxButton; if (pt.x >= rcWindow.right) return HTHELP; } } } } // We're in the caption proper return HTCAPTION; } // // Are we in the menu? // if (TestWF(pwnd, WFMPRESENT)) return HTMENU; } } else { // // NOTE: // We can only be here if we are on the client edge, horz scroll, // sizebox, or vert scroll. Hence, if we are not on the first 3, // we must be on the last one. // // // Are we on the client edge? // if (TestWF(pwnd, WEFCLIENTEDGE)) { InflateRect(&rcClientAdj, -SYSMET(CXEDGE), -SYSMET(CYEDGE)); if (!PtInRect(&rcClientAdj, pt)) return(HTBORDER); } // // Are we on the scrollbars? // if (TestWF(pwnd, WFHPRESENT) && (pt.y >= rcClient.bottom)) { UserAssert(pt.y < rcClientAdj.bottom); if (TestWF(pwnd, WFVPRESENT) && (pt.x >= rcClient.right)) return(SizeBoxHwnd(pwnd) ? HTBOTTOMRIGHT : HTGROWBOX); else return(HTHSCROLL); } else { UserAssert(TestWF(pwnd, WFVPRESENT)); UserAssert(pt.x >= rcClient.right); UserAssert(pt.x < rcClientAdj.right); return(HTVSCROLL); } } // // We give up. // // Win31 returned HTNOWHERE in this case; For compatibility, we will // keep it that way. // return(HTNOWHERE); }
/* * 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); } }
/*****************************************************************************\ * xxxGetMenuBarInfo() * * This succeeds if the menu/menu item exists. * * Parameters: * pwnd window * idObject this can be OBJID_MENU, OBJID_SYSMENU, or OBJID_CLIENT * idItem which thing do we need info on? 0..cItems. 0 indicates * the menu itself, 1 is the first item on the menu... * pmbi Pointer to a MENUBARINFO structure that gets filled in * \*****************************************************************************/ BOOL WINAPI xxxGetMenuBarInfo(PWND pwnd, long idObject, long idItem, PMENUBARINFO pmbi) { PMENU pMenu; int cBorders; PITEM pItem; PPOPUPMENU ppopup; CheckLock(pwnd); /* * Validate menubarinfo structure */ if (pmbi->cbSize != sizeof(MENUBARINFO)) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "MENUBARINFO.cbSize %d is wrong", pmbi->cbSize); return FALSE; } /* * Initialize the fields */ SetRectEmpty(&pmbi->rcBar); pmbi->hMenu = NULL; pmbi->hwndMenu = NULL; pmbi->fBarFocused = FALSE; pmbi->fFocused = FALSE; /* * Get the menu handle we will deal with. */ if (idObject == OBJID_MENU) { int cBorders; if (TestWF(pwnd, WFCHILD) || !pwnd->spmenu) return FALSE; pMenu = pwnd->spmenu; if (!pMenu) return FALSE; // If we have an item, is it in the valid range? if ((idItem < 0) || ((DWORD)idItem > pMenu->cItems)) return FALSE; /* * Menu handle */ pmbi->hMenu = PtoHq(pMenu); /* * Menu rect */ if (pMenu->cxMenu && pMenu->cyMenu) { if (!idItem) { cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); pmbi->rcBar.left = pwnd->rcWindow.left + cBorders * SYSMET(CXBORDER); pmbi->rcBar.top = pwnd->rcWindow.top + cBorders * SYSMET(CYBORDER); if (TestWF(pwnd, WFCPRESENT)) { pmbi->rcBar.top += (TestWF(pwnd, WEFTOOLWINDOW) ? SYSMET(CYSMCAPTION) : SYSMET(CYCAPTION)); } pmbi->rcBar.right = pmbi->rcBar.left + pMenu->cxMenu; pmbi->rcBar.bottom = pmbi->rcBar.top + pMenu->cyMenu; } else { pItem = pMenu->rgItems + idItem - 1; pmbi->rcBar.left = pwnd->rcWindow.left + pItem->xItem; pmbi->rcBar.top = pwnd->rcWindow.top + pItem->yItem; pmbi->rcBar.right = pmbi->rcBar.left + pItem->cxItem; pmbi->rcBar.bottom = pmbi->rcBar.top + pItem->cyItem; } } /* * Are we currently in app menu bar mode? */ ppopup = GetpGlobalPopupMenu(pwnd); if (ppopup && ppopup->fHasMenuBar && !ppopup->fIsSysMenu && (ppopup->spwndNotify == pwnd)) { // Yes, we are. pmbi->fBarFocused = TRUE; if (!idItem) { pmbi->fFocused = TRUE; } else if (ppopup->ppopupmenuRoot->posSelectedItem == (UINT)idItem-1) { pmbi->fFocused = TRUE; UserAssert(ppopup->ppopupmenuRoot); pmbi->hwndMenu = HW(ppopup->ppopupmenuRoot->spwndNextPopup); } } } else if (idObject == OBJID_SYSMENU) { if (!TestWF(pwnd, WFSYSMENU)) return FALSE; pMenu = xxxGetSysMenu(pwnd, FALSE); if (!pMenu) return FALSE; // If we have an item, is it in the valid range? if ((idItem < 0) || ((DWORD)idItem > pMenu->cItems)) return FALSE; pmbi->hMenu = PtoHq(pMenu); /* * Menu rect */ if (_HasCaptionIcon(pwnd)) { // The menu and single item take up the same space cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); pmbi->rcBar.left = pwnd->rcWindow.left + cBorders * SYSMET(CXBORDER); pmbi->rcBar.top = pwnd->rcWindow.top + cBorders * SYSMET(CYBORDER); pmbi->rcBar.right = pmbi->rcBar.left + (TestWF(pwnd, WEFTOOLWINDOW) ? SYSMET(CXSMSIZE) : SYSMET(CXSIZE)); pmbi->rcBar.bottom = pmbi->rcBar.top + (TestWF(pwnd, WEFTOOLWINDOW) ? SYSMET(CYSMSIZE) : SYSMET(CYSIZE)); } /* * Are we currently in system menu bar mode? */ ppopup = GetpGlobalPopupMenu(pwnd); if (ppopup && ppopup->fHasMenuBar && ppopup->fIsSysMenu && (ppopup->spwndNotify == pwnd)) { // Yes, we are. pmbi->fBarFocused = TRUE; if (!idItem) { pmbi->fFocused = TRUE; } else if (ppopup->ppopupmenuRoot->posSelectedItem == (UINT)idItem - 1) { pmbi->fFocused = TRUE; UserAssert(ppopup->ppopupmenuRoot); pmbi->hwndMenu = HW(ppopup->ppopupmenuRoot->spwndNextPopup); } } } else if (idObject == OBJID_CLIENT) { HMENU hMenu; hMenu = (HMENU)xxxSendMessage(pwnd, MN_GETHMENU, 0, 0); pMenu = HtoP(hMenu); if (!pMenu) return FALSE; // If we have an item, is it in the valid range? if ((idItem < 0) || ((DWORD)idItem > pMenu->cItems)) return FALSE; pmbi->hMenu = hMenu; if (!idItem) { pmbi->rcBar = pwnd->rcClient; } else { pItem = pMenu->rgItems + idItem - 1; pmbi->rcBar.left = pwnd->rcClient.left + pItem->xItem; pmbi->rcBar.top = pwnd->rcClient.top + pItem->yItem; pmbi->rcBar.right = pmbi->rcBar.left + pItem->cxItem; pmbi->rcBar.bottom = pmbi->rcBar.top + pItem->cyItem; } /* * Are we currently in popup mode with us as one of the popups * showing? */ ppopup = ((PMENUWND)pwnd)->ppopupmenu; if (ppopup && (ppopup->ppopupmenuRoot == GetpGlobalPopupMenu(pwnd))) { pmbi->fBarFocused = TRUE; if (!idItem) { pmbi->fFocused = TRUE; } else if ((UINT)idItem == ppopup->posSelectedItem + 1) { pmbi->fFocused = TRUE; pmbi->hwndMenu = HW(ppopup->spwndNextPopup); } } } else { return FALSE; } return TRUE; }
/****************************************************************************\ * * _GetTitleBarInfo() * * Gets info about a window's title bar. If the window is bogus or * doesn't have a titlebar, this will fail. * \****************************************************************************/ BOOL WINAPI xxxGetTitleBarInfo(PWND pwnd, PTITLEBARINFO ptbi) { int cxB; CheckLock(pwnd); /* * Validate titlebarinfo structure */ if (ptbi->cbSize != sizeof(TITLEBARINFO)) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "TITLEBARINFO.cbSize %d is wrong", ptbi->cbSize); return FALSE; } RtlZeroMemory(&ptbi->rgstate, sizeof(ptbi->rgstate)); ptbi->rgstate[INDEX_TITLEBAR_SELF] |= STATE_SYSTEM_FOCUSABLE; if (TestWF(pwnd, WFBORDERMASK) != LOBYTE(WFCAPTION)) { // No titlebar. ptbi->rgstate[INDEX_TITLEBAR_SELF] |= STATE_SYSTEM_INVISIBLE; return TRUE; } if (!TestWF(pwnd, WFMINIMIZED) && !TestWF(pwnd, WFCPRESENT)) { // Off screen (didn't fit) ptbi->rgstate[INDEX_TITLEBAR_SELF] |= STATE_SYSTEM_OFFSCREEN; SetRectEmpty(&ptbi->rcTitleBar); return TRUE; } /* * Get titlebar rect */ ptbi->rcTitleBar = pwnd->rcWindow; cxB = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); InflateRect(&ptbi->rcTitleBar, -cxB * SYSMET(CXBORDER), -cxB * SYSMET(CYBORDER)); if (TestWF(pwnd, WEFTOOLWINDOW)) { ptbi->rcTitleBar.bottom = ptbi->rcTitleBar.top + SYSMET(CYSMCAPTION); } else { ptbi->rcTitleBar.bottom = ptbi->rcTitleBar.top + SYSMET(CYCAPTION); } /* * Don't include the system menu area! */ if (TestWF(pwnd, WFSYSMENU) && _HasCaptionIcon(pwnd)) ptbi->rcTitleBar.left += (ptbi->rcTitleBar.bottom - ptbi->rcTitleBar.top - SYSMET(CYBORDER)); /* * Close button */ if (!TestWF(pwnd, WFSYSMENU) && TestWF(pwnd, WFWIN40COMPAT)) { ptbi->rgstate[INDEX_TITLEBAR_CLOSEBUTTON] |= STATE_SYSTEM_INVISIBLE; } else { if (!xxxMNCanClose(pwnd)) ptbi->rgstate[INDEX_TITLEBAR_CLOSEBUTTON] |= STATE_SYSTEM_UNAVAILABLE; if (TestWF(pwnd, WFCLOSEBUTTONDOWN)) ptbi->rgstate[INDEX_TITLEBAR_CLOSEBUTTON] |= STATE_SYSTEM_PRESSED; } /* * Max button */ if (! TestWF(pwnd, WFSYSMENU) && TestWF(pwnd, WFWIN40COMPAT)) { ptbi->rgstate[INDEX_TITLEBAR_MAXBUTTON] |= STATE_SYSTEM_INVISIBLE; } else { if (! TestWF(pwnd, WFMAXBOX)) { if (! TestWF(pwnd, WFMINBOX)) { ptbi->rgstate[INDEX_TITLEBAR_MAXBUTTON] |= STATE_SYSTEM_INVISIBLE; } else { ptbi->rgstate[INDEX_TITLEBAR_MAXBUTTON] |= STATE_SYSTEM_UNAVAILABLE; } } if (TestWF(pwnd, WFZOOMBUTTONDOWN)) ptbi->rgstate[INDEX_TITLEBAR_MAXBUTTON] |= STATE_SYSTEM_PRESSED; } /* * Min button */ if (! TestWF(pwnd, WFSYSMENU) && TestWF(pwnd, WFWIN40COMPAT)) { ptbi->rgstate[INDEX_TITLEBAR_MINBUTTON] |= STATE_SYSTEM_INVISIBLE; } else { if (! TestWF(pwnd, WFMINBOX)) { if (! TestWF(pwnd, WFMAXBOX)) { ptbi->rgstate[INDEX_TITLEBAR_MINBUTTON] |= STATE_SYSTEM_INVISIBLE; } else { ptbi->rgstate[INDEX_TITLEBAR_MINBUTTON] |= STATE_SYSTEM_UNAVAILABLE; } } if (TestWF(pwnd, WFREDUCEBUTTONDOWN)) ptbi->rgstate[INDEX_TITLEBAR_MINBUTTON] |= STATE_SYSTEM_PRESSED; } /* * Help button */ if (!TestWF(pwnd, WEFCONTEXTHELP) || TestWF(pwnd, WFMINBOX) || TestWF(pwnd, WFMAXBOX)) { ptbi->rgstate[INDEX_TITLEBAR_HELPBUTTON] |= STATE_SYSTEM_INVISIBLE; } else { if (TestWF(pwnd, WFHELPBUTTONDOWN)) ptbi->rgstate[INDEX_TITLEBAR_HELPBUTTON] |= STATE_SYSTEM_PRESSED; } // IME button BOGUS! ptbi->rgstate[INDEX_TITLEBAR_IMEBUTTON] = STATE_SYSTEM_INVISIBLE; #if 0 /* * System menu */ if (!TestWF(pwnd, WFSYSMENU) || !_HasCaptionIcon(pwnd)) ptbi->stateSysMenu |= STATE_SYSTEM_INVISIBLE; #endif return TRUE; }
int xxxMNCompute( PMENU pMenu, PWND pwndNotify, DWORD yMenuTop, DWORD xMenuLeft, DWORD cxMax, LPDWORD lpdwMenuHeight) { UINT cItem; DWORD cxItem; DWORD cyItem; DWORD cyItemKeep; DWORD yPopupTop; INT cMaxWidth; DWORD cMaxHeight; UINT cItemBegCol; DWORD temp; int ret; PITEM pCurItem; POINT ptMNItemSize; BOOL fOwnerDrawItems; BOOL fMenuBreak; LPWSTR lpsz; BOOL fPopupMenu; DWORD menuHeight = 0; HDC hdc; HFONT hOldFont; PTHREADINFO ptiCurrent = PtiCurrent(); BOOL fStringAndBitmapItems; CheckLock(pMenu); CheckLock(pwndNotify); /* * Whoever computes the menu, becomes the owner. */ if (pwndNotify != pMenu->spwndNotify) { Lock(&pMenu->spwndNotify, pwndNotify); } if (lpdwMenuHeight != NULL) menuHeight = *lpdwMenuHeight; /* * Empty menus have a height of zero. */ ret = 0; if (pMenu->cItems == 0) return ret; hdc = _GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE); hOldFont = GreSelectFont(hdc, ghMenuFont); /* * Try to make a non-multirow menu first. */ pMenu->fFlags &= (~MFMULTIROW); fPopupMenu = TestMF(pMenu, MFISPOPUP); if (fPopupMenu) { /* * Reset the menu bar height to 0 if this is a popup since we are * being called from menu.c MN_SIZEWINDOW. */ menuHeight = 0; } else if (pwndNotify != NULL) { pMenu->cxMenu = cxMax; } /* * Initialize the computing variables. */ cMaxWidth = cyItemKeep = 0L; cItemBegCol = 0; cyItem = yPopupTop = yMenuTop; cxItem = xMenuLeft; pCurItem = (PITEM)&pMenu->rgItems[0]; /* * cxTextAlign is used to align the text in all items; this is useful * in popup menus that mix text only items with bitmap-text items. It's * set to the max bitmap width plus some spacing. * Do this for new menus wich use string AND bitmaps on the same item */ fStringAndBitmapItems = FALSE; pMenu->cxTextAlign = 0; /* * Process each item in the menu. */ fOwnerDrawItems = FALSE; for (cItem = 0; cItem < pMenu->cItems; cItem++) { /* * If it's not a separator, find the dimensions of the object. */ if (TestMFT(pCurItem, MFT_SEPARATOR) && ( !TestMFT(pCurItem, MFT_OWNERDRAW) || (LOWORD(ptiCurrent->dwExpWinVer) < VER40)) ) { /* * If version is less than 4.0 don't test the MFT_OWNERDRAW * flag. Bug 21922; App MaxEda has both separator and Ownerdraw * flags on. In 3.51 we didn't test the OwnerDraw flag */ // // This is a separator. It's drawn as wide as the menu area, // leaving some space above and below. Since the menu area is // the max of the items' widths, we set our width to 0 so as not // to affect the result. // pCurItem->cxItem = 0; pCurItem->cyItem = SYSMET(CYMENUSIZE) / 2; } else { /* * Are we using NT5 strings and bitmaps? */ fStringAndBitmapItems |= ((pCurItem->hbmp != NULL) && (pCurItem->lpstr != NULL)); /* * Get the item's X and Y dimensions. */ if (xxxMNItemSize(pMenu, pwndNotify, hdc, pCurItem, fPopupMenu, &ptMNItemSize)) fOwnerDrawItems = TRUE; pCurItem->cxItem = ptMNItemSize.x; pCurItem->cyItem = ptMNItemSize.y; if (!fPopupMenu && ((pCurItem->hbmp == NULL) || (pCurItem->lpstr != NULL))) { pCurItem->cxItem += gcxMenuFontChar * 2; } } if (menuHeight != 0) pCurItem->cyItem = menuHeight; /* * If this is the first item, initialize cMaxHeight. */ if (cItem == 0) cMaxHeight = pCurItem->cyItem; /* * Is this a Pull-Down menu? */ if (fPopupMenu) { /* * If this item has a break or is the last item... */ if ((fMenuBreak = TestMFT(pCurItem, MFT_BREAK)) || pMenu->cItems == cItem + (UINT)1) { /* * Keep cMaxWidth around if this is not the last item. */ temp = cMaxWidth; if (pMenu->cItems == cItem + (UINT)1) { if ((int)(pCurItem->cxItem) > cMaxWidth) temp = pCurItem->cxItem; } /* * Get new width of string from RecalcTabStrings. */ temp = MNRecalcTabStrings(hdc, pMenu, cItemBegCol, (UINT)(cItem + (fMenuBreak ? 0 : 1)), temp, cxItem); /* * If this item has a break, account for it. */ if (fMenuBreak) { // // Add on space for the etch and a border on either side. // NOTE: For old apps that do weird stuff with owner // draw, keep 'em happy by adding on the same amount // of space we did in 3.1. // if (fOwnerDrawItems && !TestWF(pwndNotify, WFWIN40COMPAT)) cxItem = temp + SYSMET(CXBORDER); else cxItem = temp + 2 * SYSMET(CXEDGE); /* * Reset the cMaxWidth to the current item. */ cMaxWidth = pCurItem->cxItem; /* * Start at the top. */ cyItem = yPopupTop; /* * Save the item where this column begins. */ cItemBegCol = cItem; /* * If this item is also the last item, recalc for this * column. */ if (pMenu->cItems == (UINT)(cItem + 1)) { temp = MNRecalcTabStrings(hdc, pMenu, cItem, (UINT)(cItem + 1), cMaxWidth, cxItem); } } /* * If this is the last entry, supply the width. */ if (pMenu->cItems == cItem + (UINT)1) pMenu->cxMenu = temp; } pCurItem->xItem = cxItem; pCurItem->yItem = cyItem; cyItem += pCurItem->cyItem; if (cyItemKeep < cyItem) cyItemKeep = cyItem; } else { /* * This a Top Level menu, not a Pull-Down. */ /* * Adjust right aligned items before testing for multirow */ if (pCurItem->lpstr != NULL) { lpsz = TextPointer(pCurItem->lpstr); if ((lpsz != NULL) && (*lpsz == CH_HELPPREFIX)) { pCurItem->cxItem -= gcxMenuFontChar; } } /* * If this is a new line or a menu break. */ if ((TestMFT(pCurItem, MFT_BREAK)) || (((cxItem + pCurItem->cxItem + gcxMenuFontChar) > pMenu->cxMenu) && (cItem != 0))) { cyItem += cMaxHeight; cxItem = xMenuLeft; cMaxHeight = pCurItem->cyItem; pMenu->fFlags |= MFMULTIROW; } pCurItem->yItem = cyItem; pCurItem->xItem = cxItem; cxItem += pCurItem->cxItem; } if (cMaxWidth < (int)(pCurItem->cxItem)) cMaxWidth = pCurItem->cxItem; if (cMaxHeight != pCurItem->cyItem) { if (cMaxHeight < pCurItem->cyItem) cMaxHeight = pCurItem->cyItem; if (!fPopupMenu) menuHeight = cMaxHeight; } if (!fPopupMenu) cyItemKeep = cyItem + cMaxHeight; pCurItem++; } /* of for loop */ /* * Determine where the strings should be drawn so they are aligned * The alignment is only for popup (vertical) menus (see xxxRealDrawMenuItem) * The actual space depends on the MNS_NOCHECK and MNS_CHECKORBMP styles * Multicolumn menus don't get aligment (now that we have scrollbars, multicolum is out) */ if (!fStringAndBitmapItems || (cItemBegCol != 0)) { pMenu->cxTextAlign = 0; } else if (TestMF(pMenu, MNS_NOCHECK)) { pMenu->cxTextAlign += MNXSPACE; } else if (TestMF(pMenu, MNS_CHECKORBMP)) { pMenu->cxTextAlign = max(pMenu->cxTextAlign, (UINT)gpsi->oembmi[OBI_MENUCHECK].cx); pMenu->cxTextAlign += MNXSPACE; } else { pMenu->cxTextAlign += gpsi->oembmi[OBI_MENUCHECK].cx + MNXSPACE; } /* * Add the left margin */ if (pMenu->cxTextAlign != 0) { pMenu->cxTextAlign += MNLEFTMARGIN; } if (cItemBegCol && pMenu->cItems && TestMFT(((PITEM)&pMenu->rgItems[0]), MFT_RIGHTJUSTIFY)) { // // multi-column, if we are in RtoL mode, reverse the columns // pCurItem = (PITEM)&pMenu->rgItems[0]; for (cItem = 0; cItem < pMenu->cItems; cItem++) { pCurItem->xItem = pMenu->cxMenu - (pCurItem->xItem + pCurItem->cxItem); pCurItem++; } } GreSelectFont(hdc, hOldFont); _ReleaseDC(hdc); pMenu->cyMenu = cyItemKeep - yMenuTop; ret = pMenu->cyMenu; if (lpdwMenuHeight != NULL) *lpdwMenuHeight = menuHeight; return ret; }
BOOL xxxSnapWindow( PWND pwnd) { PTHREADINFO ptiCurrent; RECT rc; HDC hdcScr = NULL; HDC hdcMem = NULL; BOOL fRet; HBITMAP hbmOld; HBITMAP hbm; HANDLE hPal; LPLOGPALETTE lppal; int palsize; int iFixedPaletteEntries; BOOL fSuccess; PWND pwndT; TL tlpwndT; PWINDOWSTATION pwinsta; TL tlpwinsta; CheckLock(pwnd); UserAssert(pwnd); ptiCurrent = PtiCurrent(); /* * If this is a thread of winlogon, don't do the snapshot. */ if (GetCurrentProcessId() == gpidLogon) return FALSE; /* * Get the affected windowstation */ if (!NT_SUCCESS(ReferenceWindowStation( PsGetCurrentThread(), NULL, WINSTA_READSCREEN, &pwinsta, TRUE)) || pwinsta->dwWSF_Flags & WSF_NOIO) { return FALSE; } /* * If the window is on another windowstation, do nothing */ if (pwnd->head.rpdesk->rpwinstaParent != pwinsta) return FALSE; /* * Get the parent of any child windows. */ while ((pwnd != NULL) && TestWF(pwnd, WFCHILD)) { pwnd = pwnd->spwndParent; } /* * Lock the windowstation before we leave the critical section */ ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta); /* * Open the clipboard and empty it. * * pwndDesktop is made the owner of the clipboard, instead of the * currently active window; -- SANKAR -- 20th July, 1989 -- */ pwndT = ptiCurrent->rpdesk->pDeskInfo->spwnd; ThreadLockWithPti(ptiCurrent, pwndT, &tlpwndT); fSuccess = xxxOpenClipboard(pwndT, NULL); ThreadUnlock(&tlpwndT); if (!fSuccess) { ThreadUnlockWinSta(ptiCurrent, &tlpwinsta); return FALSE; } xxxEmptyClipboard(pwinsta); /* * Use the whole window. */ CopyRect(&rc, &pwnd->rcWindow); /* * Only snap what is on the screen. */ if (!IntersectRect(&rc, &rc, &gpDispInfo->rcScreen)) { fRet = FALSE; goto SnapExit; } rc.right -= rc.left; rc.bottom -= rc.top; /* * Figure out how far offset from window origin visible part is */ if (pwnd != PWNDDESKTOP(pwnd)) { rc.left -= pwnd->rcWindow.left; rc.top -= pwnd->rcWindow.top; } /* * Get the entire window's DC. */ hdcScr = _GetWindowDC(pwnd); if (!hdcScr) goto MemoryError; /* * Create the memory DC. */ hdcMem = GreCreateCompatibleDC(hdcScr); if (!hdcMem) goto MemoryError; /* * Create the destination bitmap. If it fails, then attempt * to create a monochrome bitmap. * Did we have enough memory? */ if (SYSMET(SAMEDISPLAYFORMAT)) { hbm = GreCreateCompatibleBitmap(hdcScr, rc.right, rc.bottom); } else { hbm = GreCreateBitmap(rc.right, rc.bottom, 1, gpDispInfo->BitCountMax, NULL); } if (!hbm) { hbm = GreCreateBitmap(rc.right, rc.bottom, 1, 1, NULL); if (!hbm) goto MemoryError; } /* * Select the bitmap into the memory DC. */ hbmOld = GreSelectBitmap(hdcMem, hbm); /* * Snap!!! * Check the return value because the process taking the snapshot * may not have access to read the screen. */ fRet = GreBitBlt(hdcMem, 0, 0, rc.right, rc.bottom, hdcScr, rc.left, rc.top, SRCCOPY | CAPTUREBLT, 0); /* * Restore the old bitmap into the memory DC. */ GreSelectBitmap(hdcMem, hbmOld); /* * If the blt failed, leave now. */ if (!fRet) goto SnapExit; _SetClipboardData(CF_BITMAP, hbm, FALSE, TRUE); /* * If this is a palette device, let's throw the current system palette * into the clipboard also. Useful if the user just snapped a window * containing palette colors... */ if (TEST_PUSIF(PUSIF_PALETTEDISPLAY)) { int i; int iPalSize; palsize = GreGetDeviceCaps(hdcScr, SIZEPALETTE); /* * Determine the number of system colors. */ if (GreGetSystemPaletteUse(hdcScr) == SYSPAL_STATIC) iFixedPaletteEntries = GreGetDeviceCaps(hdcScr, NUMRESERVED); else iFixedPaletteEntries = 2; lppal = (LPLOGPALETTE)UserAllocPoolWithQuota( (LONG)(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * palsize), TAG_CLIPBOARD); if (lppal != NULL) { lppal->palVersion = 0x300; lppal->palNumEntries = (WORD)palsize; if (GreGetSystemPaletteEntries(hdcScr, 0, palsize, lppal->palPalEntry)) { iPalSize = palsize - iFixedPaletteEntries / 2; for (i = iFixedPaletteEntries / 2; i < iPalSize; i++) { /* * Any non system palette enteries need to have the NOCOLLAPSE * flag set otherwise bitmaps containing different palette * indices but same colors get messed up. */ lppal->palPalEntry[i].peFlags = PC_NOCOLLAPSE; } if (hPal = GreCreatePalette(lppal)) _SetClipboardData(CF_PALETTE, hPal, FALSE, TRUE); } UserFreePool(lppal); } } PlayEventSound(USER_SOUND_SNAPSHOT); fRet = TRUE; SnapExit: /* * Release the window/client DC. */ if (hdcScr) { _ReleaseDC(hdcScr); } xxxCloseClipboard(pwinsta); Unlock(&pwinsta->spwndClipOwner); /* * Delete the memory DC. */ if (hdcMem) { GreDeleteDC(hdcMem); } ThreadUnlockWinSta(ptiCurrent, &tlpwinsta); return fRet; MemoryError: /* * Display an error message box. */ ClientNoMemoryPopup(); fRet = FALSE; goto SnapExit; }
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; }
/***************************************************************************\ * xxxItemSize * * Calc the dimensions of bitmaps and strings. Loword of returned * value contains width, high word contains height of item. * * History: * 07-23-96 GerardoB - fixed up for 5.0 \***************************************************************************/ BOOL xxxMNItemSize( PMENU pMenu, PWND pwndNotify, HDC hdc, PITEM pItem, BOOL fPopup, LPPOINT lppt) { BITMAP bmp; int width = 0; int height = 0; DWORD xRightJustify; LPWSTR lpMenuString; HFONT hfnOld; int tcExtra; UNREFERENCED_PARAMETER(pMenu); CheckLock(pMenu); CheckLock(pwndNotify); if (!fPopup) { /* * Save off the height of the top menu bar since we will used this often * if the pItem is not in a popup. (ie. it is in the top level menu bar) */ height = SYSMET(CYMENUSIZE); } hfnOld = NULL; if (TestMFS(pItem, MFS_DEFAULT)) { if (ghMenuFontDef) hfnOld = GreSelectFont(hdc, ghMenuFontDef); else { tcExtra = GreGetTextCharacterExtra(hdc); GreSetTextCharacterExtra(hdc, tcExtra + 1 + (gcxMenuFontChar / gpsi->cxSysFontChar)); } } /* * Compute bitmap dimensions if needed */ if (pItem->hbmp != NULL) { if (pItem->hbmp == HBMMENU_CALLBACK) { xxxMNGetBitmapSize(pItem, pwndNotify); } else if (pItem->cxBmp == MNIS_MEASUREBMP) { if (TestMFS(pItem, MFS_CACHEDBMP)) { pItem->cxBmp = SYSMET(CXMENUSIZE); pItem->cyBmp = SYSMET(CYMENUSIZE); if (pItem->hbmp == HBMMENU_SYSTEM) { pItem->cxBmp += SYSMET(CXEDGE); /* * Chicago/Memphis only stretch the width, * not the height. NT Bug 124779. FritzS */ // pItem->cyBmp += SYSMET(CXEDGE); } } else { if (GreExtGetObjectW(pItem->hbmp, sizeof(BITMAP), (LPSTR)&bmp)) { pItem->cxBmp = bmp.bmWidth; pItem->cyBmp = bmp.bmHeight; } else { /* * If the bitmap is not useable, this is as good a default * as any. */ pItem->cxBmp = SYSMET(CXMENUSIZE); pItem->cyBmp = SYSMET(CYMENUSIZE); } } } width = pItem->cxBmp; /* * Remember the max bitmap width to align the text in all items. */ pMenu->cxTextAlign = max(pMenu->cxTextAlign, (DWORD)width); /* * In menu bars, we force the item to be at least CYMNSIZE. * Fixes many, many problems w/ apps that fake own MDI. */ if (fPopup) { height = pItem->cyBmp; } else { height = max((int)pItem->cyBmp, height); } } else if (TestMFT(pItem, MFT_OWNERDRAW)) { // This is an ownerdraw item -- the width and height are stored in // cxBmp and cyBmp xxxMNGetBitmapSize(pItem, pwndNotify); width = pItem->cxBmp; // // Ignore height with menu bar now--that's set by user. // if (fPopup) { height = pItem->cyBmp; // If this item has a popup (hierarchical) menu associated with it, then // reserve room for the bitmap that tells the user that a hierarchical // menu exists here. // B#2966, t-arthb UserAssert(fPopup == (TestMF(pMenu, MFISPOPUP) != 0)); width = width + (gcxMenuFontChar << 1); } } if ((pItem->lpstr != NULL) && (!TestMFT(pItem, MFT_OWNERDRAW)) ) { SIZE size; /* * This menu item contains a string */ /* * We want to keep the menu bar height if this isn't a popup. */ if (fPopup) { /* The thickness of mnemonic underscore is CYBORDER and the gap * between the characters and the underscore is another CYBORDER */ height = max(height, gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYEDGE)); } lpMenuString = TextPointer(pItem->lpstr); xRightJustify = FindCharPosition(lpMenuString, TEXT('\t')); xxxPSMGetTextExtent(hdc, lpMenuString, xRightJustify, &size); if (width) { width += MNXSPACE + size.cx; } else { width = size.cx; } } if (fPopup && !TestMFT(pItem, MFT_OWNERDRAW)) { /* * Add on space for checkmark, then horz spacing for default & disabled * plus some left margin. */ if (TestMF(pMenu, MNS_CHECKORBMP) || !TestMF(pMenu, MNS_NOCHECK)) { width += gpsi->oembmi[OBI_MENUCHECK].cx; } width += MNXSPACE + MNLEFTMARGIN + 2; height += 2; } if (TestMFS(pItem, MFS_DEFAULT)) { if (hfnOld) GreSelectFont(hdc, hfnOld); else GreSetTextCharacterExtra(hdc, tcExtra); } /* * Loword contains width, high word contains height of item. */ lppt->x = width; lppt->y = height; return(TestMFT(pItem, MFT_OWNERDRAW)); }
void xxxCalcClientRect( PWND pwnd, LPRECT lprc, BOOL fHungRedraw) { int cxFrame, yTopOld; RECT rcTemp; PMENU pMenu; TL tlpmenu; int cBorders; BOOL fEmptyClient; CheckLock(pwnd); /* * Clear all the frame bits. NOTE: The HIBYTE of all these #defines * must stay the same for this line to work. */ ClrWF(pwnd, (WFHPRESENT | WFVPRESENT | WFCPRESENT | WFMPRESENT)); // // We need to clear the client border bits also. Otherwise, when the // window gets really small, the client border will draw over the menu // and caption. // ClrWF(pwnd, WFCEPRESENT); /* * If the window is iconic, the client area is empty. */ if (TestWF(pwnd, WFMINIMIZED)) { // SetRectEmpty(lprc); // We must make it an empty rectangle. // But, that empty rectangle should be at the top left corner of the // window rect. Else, ScreenToClient() will return bad values. lprc->right = lprc->left; lprc->bottom = lprc->top; return; } // Save rect into rcTemp for easy local calculations. CopyRect(&rcTemp, lprc); // Save the top so we'll know how tall the caption was yTopOld = rcTemp.top; // Adjustment for the caption if (TestWF(pwnd, WFBORDERMASK) == LOBYTE(WFCAPTION)) { SetWF(pwnd, WFCPRESENT); rcTemp.top += TestWF(pwnd, WEFTOOLWINDOW) ? SYSMET(CYSMCAPTION) : SYSMET(CYCAPTION); } // Subtract out window borders cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE); cxFrame = cBorders * SYSMET(CXBORDER); InflateRect(&rcTemp, -cxFrame, -cBorders*SYSMET(CYBORDER)); if (!TestwndChild(pwnd) && (pMenu = pwnd->spmenu)) { SetWF(pwnd, WFMPRESENT); if (!fHungRedraw) { ThreadLockAlways(pMenu, &tlpmenu); rcTemp.top += xxxMenuBarCompute(pMenu, pwnd, rcTemp.top - yTopOld, cxFrame, rcTemp.right - rcTemp.left); ThreadUnlock(&tlpmenu); } } // // Fix for B#1425 -- Sizing window really small used to move children's // rects because the client calculations were wrong. So we make the // bottom of the client match up with the top (the bottom of the menu // bar). // fEmptyClient = FALSE; if (rcTemp.top >= rcTemp.bottom) { rcTemp.bottom = rcTemp.top; fEmptyClient = TRUE; } // // BOGUS BOGUS BOGUS // Hack for Central Point PC Tools. // Possibly for M5 only. // B#8445 // // They check for div-by-zero all over, but they jump to the wrong place // if a zero divisor is encountered, and end up faulting anyway. So this // code path was never tested basically. There's a period when starting // up where the window rect of their drives ribbon is empty. In Win3.x, // the client would be shrunk to account for the border it had, and it // would look like it wasn't empty because the width would be negative, // signed! So we version-switch this code, since other apps have // reported the non-emptiness as an annoying bug. // if (TestWF(pwnd, WFWIN40COMPAT) && (rcTemp.left >= rcTemp.right)) { rcTemp.right = rcTemp.left; fEmptyClient = TRUE; } if (fEmptyClient) goto ClientCalcEnd; // // Subtract client edge if we have space // if (TestWF(pwnd, WEFCLIENTEDGE) && (rcTemp.right - rcTemp.left >= (2 * SYSMET(CXEDGE))) && (rcTemp.bottom - rcTemp.top >= (2 * SYSMET(CYEDGE))) ) { SetWF(pwnd, WFCEPRESENT); InflateRect(&rcTemp, -SYSMET(CXEDGE), -SYSMET(CYEDGE)); } // // Subtract scrollbars // Note compatibility with 3.1: // * You don't get a horizontal scrollbar unless you have MORE // space (> ) in your client than you need for one. // * You get a vertical scrollbar if you have AT LEAST ENOUGH // space (>=) in your client for one. // if (TestWF(pwnd, WFHSCROLL) && (rcTemp.bottom - rcTemp.top > SYSMET(CYHSCROLL))) { SetWF(pwnd, WFHPRESENT); if (!fHungRedraw) rcTemp.bottom -= SYSMET(CYHSCROLL); } if (TestWF(pwnd, WFVSCROLL) && (rcTemp.right - rcTemp.left >= SYSMET(CXVSCROLL))) { SetWF(pwnd, WFVPRESENT); if (!fHungRedraw) rcTemp.right -= SYSMET(CXVSCROLL); } ClientCalcEnd: CopyRect(lprc, &rcTemp); }
/***************************************************************************\ * * DrawState() * * Generic state drawing routine. Does simple drawing into same DC if * normal state; uses offscreen bitmap otherwise. * * We do drawing for these simple types ourselves: * (1) Text * lData is string pointer. * wData is string length * (2) Icon * LOWORD(lData) is hIcon * (3) Bitmap * LOWORD(lData) is hBitmap * (4) Glyph (internal) * LOWORD(lData) is OBI_ value, one of * OBI_CHECKMARK * OBI_BULLET * OBI_MENUARROW * right now * * Other types are required to draw via the callback function, and are * allowed to stick whatever they want in lData and wData. * * We apply the following effects onto the image: * (1) Normal (nothing) * (2) Default (drop shadow) * (3) Union (gray string dither) * (4) Disabled (embossed) * * Note that we do NOT stretch anything. We just clip. * \***************************************************************************/ BOOL _DrawState( HDC hdcDraw, HBRUSH hbrFore, DRAWSTATEPROC qfnCallBack, LPARAM lData, WPARAM wData, int x, int y, int cx, int cy, UINT uFlags) { HFONT hFont; HFONT hFontSave = NULL; HDC hdcT; HBITMAP hbmpT; POINT ptOrg; BOOL fResult; /* * These require monochrome conversion * * Enforce monochrome: embossed doesn't look great with 2 color displays */ if ((uFlags & DSS_DISABLED) && ((oemInfo.BitCount == 1) || SYSMET(SLOWMACHINE))) { uFlags &= ~DSS_DISABLED; uFlags |= DSS_UNION; } if (uFlags & (DSS_DISABLED | DSS_DEFAULT | DSS_UNION)) uFlags |= DSS_MONO; /* * Get drawing sizes etc. AND VALIDATE. */ switch (uFlags & DST_TYPEMASK) { case DST_GLYPH: /* * LOWORD(lData) is OBI_ value. */ UserAssert(LOWORD(lData) < (WORD)OBI_COUNT); if (!cx) cx = oemInfo.bm[LOWORD(lData)].cx; if (!cy) cy = oemInfo.bm[LOWORD(lData)].cy; break; case DST_BITMAP: /* * (lData) is hbmp. */ // if (IsGDIObject((HBITMAP)LOWORD(lData)) != GDIOBJ_BITMAP) // return FALSE; if (!cx || !cy) { BITMAP bmp; try { GreExtGetObjectW((HBITMAP)lData, sizeof(BITMAP), &bmp); if (!cx) cx = bmp.bmWidth; if (!cy) cy = bmp.bmHeight; } except (EXCEPTION_EXECUTE_HANDLER) { return FALSE; } } break; case DST_ICON: /* * lData is picon. */ if (!cx || !cy) { if (!cx) cx = ((PICON)lData)->cx; if (!cy) cy = ((PICON)lData)->cy / 2; // Icons are double height in NT } break; case DST_TEXT: /* * lData is LPSTR * NOTE THAT WE DO NOT VALIDATE lData, DUE TO COMPATIBILITY * WITH GRAYSTRING(). THIS _SHOULD_ FAULT IF YOU PASS IN NULL. * * wData is cch. */ if (!wData) wData = wcslen((LPWSTR)lData); if (!cx || !cy) { SIZE size; /* * Make sure we use right dc w/ right font. */ GreGetTextExtentW(hdcDraw, (LPWSTR)lData, wData, &size, GGTE_WIN3_EXTENT); if (!cx) cx = size.cx; if (!cy) cy = size.cy; } /* * Now, pretend we're complex if qfnCallBack is supplied AND * we're supporting GrayString(). */ // if ((uFlags & DST_GRAYSTRING) && SELECTOROF(qfnCallBack)) { // uFlags &= ~DST_TYPEMASK; // uFlags |= DST_COMPLEX; // } break; case DST_PREFIXTEXT: if (lData==0) { RIPMSG0(RIP_ERROR, "DrawState: NULL DST_PREFIXTEXT string"); return FALSE; } if (!wData) wData = wcslen((LPWSTR)lData); if (!cx || !cy) { SIZE size; PSMGetTextExtent(hdcDraw, (LPWSTR)lData, wData, &size); if (!cx) cx = size.cx; if (!cy) cy = size.cy; } /* * Add on height for prefix */ cy += 2*SYSMET(CYBORDER); break; case DST_COMPLEX: if (qfnCallBack == NULL) { RIPMSG0(RIP_ERROR, "DrawState: invalid callback for DST_COMPLEX"); return(FALSE); } break; default: RIPMSG0(RIP_ERROR, "DrawState: invalid DST_ type"); return FALSE; }