示例#1
0
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);
}
示例#2
0
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);
    }
}
示例#3
0
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;
}
示例#4
0
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;
        }
    }
}
示例#5
0
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);
}
示例#6
0
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);
}
示例#7
0
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);
}
示例#8
0
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);

}
示例#9
0
文件: help.c 项目: conioh/os-design
/*
 * 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);
    }
}
示例#10
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;
}
示例#11
0
/****************************************************************************\
*
* _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;
}
示例#12
0
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;
}
示例#13
0
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;
}
示例#14
0
文件: icons.c 项目: Gaikokujin/WinNT4
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;
}
示例#15
0
/***************************************************************************\
* 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));
}
示例#16
0
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);
}
示例#17
0
/***************************************************************************\
*
*  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;
    }