Beispiel #1
0
PWND _GetNextDlgGroupItem(
    PWND pwndDlg,
    PWND pwnd,
    BOOL fPrev)
{
    PWND pwndCurrent;
    BOOL fOnceAround = FALSE;

    pwnd = pwndCurrent = _GetChildControl(pwndDlg, pwnd);

    do {
        pwnd = (fPrev ? UT_PrevGroupItem(pwndDlg, pwnd) :
                        UT_NextGroupItem(pwndDlg, pwnd));

        if (pwnd == pwndCurrent)
            fOnceAround = TRUE;

        if (!pwndCurrent)
            pwndCurrent = pwnd;
    }
    while (!fOnceAround && ((TestWF(pwnd, WFDISABLED) || !TestWF(pwnd, WFVISIBLE))));

    return pwnd;
}
Beispiel #2
0
BOOL xxxEndPaint(
    PWND          pwnd,
    LPPAINTSTRUCT lpps)
{
    CheckLock(pwnd);

    ReleaseCacheDC(lpps->hdc, TRUE);

    if (TestWF(pwnd, WFDONTVALIDATE)) {

        if (ghrgnUpdateSave != NULL) {

            InternalInvalidate3(pwnd,
                                ghrgnUpdateSave,
                                RDW_INVALIDATE | RDW_ERASE);

            if (--gnUpdateSave == 0) {
                GreDeleteObject(ghrgnUpdateSave);
                ghrgnUpdateSave = NULL;
            }
        }

        ClrWF(pwnd, WFDONTVALIDATE);
    }

    ClrWF(pwnd, WFWMPAINTSENT);

    /*
     * This used to check that the update-region was empty before
     * doing the clear.  However, this caused a problem with WOW
     * amipro/approach hanging.  They were invalidating rects in
     * their WM_PAINT handler, and allowing the defwindowproc to
     * perform the validation for them.  Since we were blocking
     * the BeginPaint in this case, it sent them into a infinite
     * loop (see bug 19036).
     */
    ClrWF(pwnd, WFSTARTPAINT);

    /*
     * Reshow the caret if needed, but AFTER we've released the DC.
     * This way ShowCaret() can reuse the DC we just released.
     */
    if (pwnd == PtiCurrent()->pq->caret.spwnd)
        zzzInternalShowCaret();

    return TRUE;
}
Beispiel #3
0
/***************************************************************************\
*
*  _NextSibblingOrAncestor
*
* Called by _NextControl. It returns the next control to pwndStart. If there
* is a next window (pwndStart->spwndNext), then that is it.
* Otherwise, the next control is up the parent chain. However, if it's already
* at the top of the chain (pwndRoot == pwndStart->spwndParent), then the next
* control is the first child of pwndRoot. But if it's not at the top of the chain,
* then the next control is pwndStart->spwndParent or an ancestor.
*
\***************************************************************************/
PWND _NextSibblingOrAncestor (PWND pwndRoot, PWND pwndStart)
{
    PWND pwndParent;
#ifdef DEBUG
    PWND pwndNext;
#endif

    // If there is a sibbling, go for it
    if (pwndStart->spwndNext != NULL) {
        return (REBASEALWAYS(pwndStart, spwndNext));
    }

    // If it cannot go up the parent chain, then return the first sibbling.
    pwndParent = REBASEALWAYS(pwndStart, spwndParent);
    if (pwndParent == pwndRoot) {
        // Note that if pwndStart doesn't have any sibblings,
        //  this will return pwndStart again
        return (REBASEALWAYS(pwndParent, spwndChild));
    }


    // Otherwise walk up the parent chain looking for the first window with
    // a WS_EX_CONTROLPARENT parent.

#ifdef DEBUG
    pwndNext =
#else
    return
#endif
        _GetChildControl(pwndRoot, pwndParent);

#ifdef DEBUG
    if ((pwndNext != pwndParent) || !TestWF(pwndParent, WEFCONTROLPARENT)) {
        // Code looping through the controls in a dialog might go into an infinite
        //  loop because of this (i.e., xxxRemoveDefaultButton, _GetNextDlgTabItem,..)
        // We've walked up the parent chain but will never walk down the child chain again
        //  because there is a NON WS_EX_CONTROLPARENT parent window somewhere in the chain.
        RIPMSG0 (RIP_ERROR, "_NextSibblingOrAncestor: Non WS_EX_CONTROLPARENT window in parent chain");
    }
    return pwndNext;
#endif
}
Beispiel #4
0
BOOL xxxSetSystemMenu(
    PWND pwnd,
    PMENU pMenu)
{
    CheckLock(pwnd);
    CheckLock(pMenu);

    if (TestWF(pwnd, WFSYSMENU)) {
        PMENU pmenuT = pwnd->spmenuSys;
        if (LockWndMenu(pwnd, &pwnd->spmenuSys, pMenu))
            _DestroyMenu(pmenuT);

        MNPositionSysMenu(pwnd, pMenu);

        return TRUE;
    }

    RIPERR0(ERROR_NO_SYSTEM_MENU, RIP_VERBOSE, "");
    return FALSE;
}
Beispiel #5
0
VOID xxxSendChildNCPaint(
    PWND pwnd)
{
    TL tlpwnd;

    CheckLock(pwnd);

    ThreadLockNever(&tlpwnd);
    pwnd = pwnd->spwndChild;
    while (pwnd != NULL) {
        if ((pwnd->hrgnUpdate == NULL) && TestWF(pwnd, WFSENDNCPAINT)) {
            ThreadLockExchangeAlways(pwnd, &tlpwnd);
            xxxSendNCPaint(pwnd, HRGN_FULL);
        }

        pwnd = pwnd->spwndNext;
    }

    ThreadUnlock(&tlpwnd);
}
Beispiel #6
0
VOID _ScreenToClient(
    PWND pwnd,
    PPOINT ppt)
{
    /*
     * Client and screen coordinates are the same for the
     * desktop window.
     */
    if (GETFNID(pwnd) != FNID_DESKTOP) {
#ifdef USE_MIRRORING
        if (TestWF(pwnd, WEFLAYOUTRTL)) {
            ppt->x  = pwnd->rcClient.right - ppt->x;
        } else
#endif
        {
            ppt->x -= pwnd->rcClient.left;
        }
        ppt->y -= pwnd->rcClient.top;
    }
}
Beispiel #7
0
void xxxCreateTooltip(PTOOLTIPWND pttwnd, LPWSTR pstr)
{
    CheckLock(pttwnd);

    /*
     * Store new text
     */
    pttwnd->pstr = pstr;
    /*
     * If already visible, hide it and show it in new place.
     *  Otherwise, set timer to show.
     */
    if (TestWF(pttwnd, WFVISIBLE)) {
        xxxSetWindowPos((PWND)pttwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE |
                SWP_NOMOVE | SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING);
        xxxShowTooltip(pttwnd);
    } else {
        SetTooltipTimer(pttwnd, TTT_SHOW, pttwnd->dwShowDelay);
    }
}
Beispiel #8
0
BOOL xxxRemoveFullScreen(PWND pwnd)
{
    PDESKTOP pdesk = pwnd->head.rpdesk;
    BOOL    fYielded;

    fYielded = FALSE;

    if (pdesk == NULL) return fYielded;

    if (TestWF(pwnd, WFFULLSCREEN) && FCallTray(pdesk))
    {
        ClrWF(pwnd, WFFULLSCREEN);
        
        if (!(--pdesk->cFullScreen)) {
            xxxSetTrayWindow(pdesk, STW_SAME);
            fYielded = TRUE;
        }
        UserAssert(pdesk->cFullScreen >= 0);
    }
    return(fYielded);
}
Beispiel #9
0
PWND HotKeyToWindow(
    DWORD key)
{
    PHOTKEYSTRUCT phk;
    int ckeys;

    ckeys = gcHotKey;

    if (ckeys == 0)
        return 0;

    phk = gpHotKeyList;

    while (ckeys) {
        if (phk->key == key)
            return TestWF(phk->spwnd, WFVISIBLE) ? phk->spwnd : NULL;
        phk++;
        ckeys--;
    }

    return 0;
}
Beispiel #10
0
void xxxResetTooltip(PTOOLTIPWND pttwnd)
{
    KillTooltipTimer(pttwnd);

    CheckLock(pttwnd);

    if (TestWF(pttwnd, WFVISIBLE)) {
        PWND spwndMessage;
        TL tlpwnd;

        xxxSetWindowPos((PWND)pttwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE |
                SWP_NOMOVE | SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER);

        spwndMessage = PWNDMESSAGE(pttwnd);
        ThreadLockAlways(spwndMessage, &tlpwnd);
        xxxSetParent((PWND)pttwnd, spwndMessage);
        ThreadUnlock(&tlpwnd);
    }

    ZeroTooltip(pttwnd);
    pttwnd->head.rpdesk->dwDTFlags &= ~DF_TOOLTIP;
}
Beispiel #11
0
BOOL _IsWindowVisible(
    PWND pwnd)
{
    /*
     * Check if this is the iconic window being moved around with a mouse
     * If so, return a TRUE, though, strictly speaking, it is hidden.
     * This helps the Tracer guys from going crazy!
     * Fix for Bug #57 -- SANKAR -- 08-08-89 --
     */
    if (pwnd == NULL)
        return TRUE;

    for (;;) {
        if (!TestWF(pwnd, WFVISIBLE))
            return FALSE;
        if (GETFNID(pwnd) == FNID_DESKTOP)
            break;
        pwnd = REBASEPWND(pwnd, spwndParent);
    }

    return TRUE;
}
Beispiel #12
0
/***************************************************************************\
* _PrevControl
*
* History:
\***************************************************************************/
PWND _PrevControl(
    PWND pwndRoot,
    PWND pwndStart,
    UINT uFlags)
{
    BOOL fFirstFound;
    PWND pwndNext;
    PWND pwnd, pwndFirst;

    if (!pwndStart)
        return(NULL);

    UserAssert(pwndRoot != pwndStart);
    UserAssert(!TestWF(pwndStart, WEFCONTROLPARENT));

    pwnd = _NextControl(pwndRoot, NULL, uFlags);

    pwndFirst = pwnd;
    fFirstFound = FALSE;
    while (pwndNext = _NextControl(pwndRoot, pwnd, uFlags)) {

        if (pwndNext == pwndStart)
            break;

        if (pwndNext == pwndFirst) {
            if (fFirstFound) {
                RIPMSG0(RIP_WARNING, "_PrevControl: Loop Detected");
                break;
            } else {
                fFirstFound = TRUE;
            }
        }

        pwnd = pwndNext;
    }

    return pwnd;
}
Beispiel #13
0
VOID SetDialogPointer(PWND pwnd, LONG_PTR lPtr) {

    if ((pwnd->cbwndExtra < DLGWINDOWEXTRA)
            || TestWF(pwnd, WFSERVERSIDEPROC)
            || (PpiCurrent() != GETPTI(pwnd)->ppi)) {
        RIPMSG1(RIP_WARNING, "SetDialogPointer: Unexpected pwnd:%#p", pwnd);
        return;
    }

    ((PDIALOG)pwnd)->pdlg = (PDLG)lPtr;

    if (lPtr == 0) {
        pwnd->fnid |= FNID_CLEANEDUP_BIT;
        ClrWF(pwnd, WFDIALOGWINDOW);
    } else {
        if (pwnd->fnid == 0) {
            pwnd->fnid = FNID_DIALOG;
        }
        SetWF(pwnd, WFDIALOGWINDOW);
    }


}
Beispiel #14
0
// --------------------------------------------------------------------------
//
//  GetInitMenuParam()
//
//  Gets the HMENU sent as the wParam of WM_INITMENU, and for menu bars, is
//  the actual menu to be interacted with.
//
// --------------------------------------------------------------------------
PMENU GetInitMenuParam(PWND pwndMenu, BOOL * lpfSystem)
{
    //
    // Find out what menu we should be sending in WM_INITMENU:
    //      If minimized/child/empty menubar, use system menu
    //
    if (TestWF(pwndMenu, WFMINIMIZED) ||
        TestwndChild(pwndMenu) ||
        (pwndMenu->spmenu == NULL) ||
        !pwndMenu->spmenu->cItems)
    {
        if (lpfSystem != NULL)
            *lpfSystem = TRUE;

        return(GetSysMenu(pwndMenu, FALSE));
    }
    else
    {
        if (lpfSystem != NULL)
            *lpfSystem = FALSE;

        return(pwndMenu->spmenu);
    }
}
Beispiel #15
0
HDC xxxBeginPaint(
    PWND          pwnd,
    LPPAINTSTRUCT lpps)
{
    HRGN hrgnUpdate;
    HDC  hdc;
    BOOL fSendEraseBkgnd;

    CheckLock(pwnd);
    UserAssert(IsWinEventNotifyDeferredOK());

    if (TEST_PUDF(PUDF_DRAGGINGFULLWINDOW))
        SetWF(pwnd, WFSTARTPAINT);

    /*
     * We're processing a WM_PAINT message: clear this flag.
     */
    ClrWF(pwnd, WFPAINTNOTPROCESSED);

    /*
     * If this bit gets set while we are drawing the frame we will need
     * to redraw it.
     *
     * If necessary, send our WM_NCPAINT message now.
     *
     * please heed these notes
     *
     * We have to send this message BEFORE we diddle hwnd->hrgnUpdate,
     * because an app may call ValidateRect or InvalidateRect in its
     * handler, and it expects what it does to affect what gets drawn
     * in the later WM_PAINT.
     *
     * It is possible to get an invalidate when we leave the critical
     * section below, therefore we loop until UPDATEDIRTY is clear
     * meaning there were no additional invalidates.
     */
    if (TestWF(pwnd, WFSENDNCPAINT)) {

        do {
            ClrWF(pwnd, WFUPDATEDIRTY);
            hrgnUpdate = GetNCUpdateRgn(pwnd, FALSE);
            xxxSendNCPaint(pwnd, hrgnUpdate);
            DeleteMaybeSpecialRgn(hrgnUpdate);
        } while (TestWF(pwnd, WFUPDATEDIRTY));

    } else {
        ClrWF(pwnd, WFUPDATEDIRTY);
    }

    /*
     * Hide the caret if needed.  Do this before we get the DC so
     * that if HideCaret() gets and releases a DC we will be able
     * to reuse it later here.
     * No need to DeferWinEventNotify() since pwnd is locked.
     */
    if (pwnd == PtiCurrent()->pq->caret.spwnd)
        zzzInternalHideCaret();

    /*
     * Send the check for sending an WM_ERASEBKGND to the
     * window.
     */
    if (fSendEraseBkgnd = TestWF(pwnd, WFSENDERASEBKGND)) {
        ClrWF(pwnd, WFERASEBKGND);
        ClrWF(pwnd, WFSENDERASEBKGND);
    }

    /*
     * Validate the entire window.
     */
    if (NEEDSPAINT(pwnd))
        DecPaintCount(pwnd);

    ClrWF(pwnd, WFINTERNALPAINT);

    hrgnUpdate = pwnd->hrgnUpdate;
    pwnd->hrgnUpdate = NULL;

    if (TestWF(pwnd, WFDONTVALIDATE)) {

        if (ghrgnUpdateSave == NULL) {
            ghrgnUpdateSave = CreateEmptyRgn();
        }

        if (ghrgnUpdateSave != NULL) {
            UnionRgn(ghrgnUpdateSave, ghrgnUpdateSave, hrgnUpdate);
            gnUpdateSave++;
        }
    }

    /*
     * Clear these flags for backward compatibility
     */
    lpps->fIncUpdate =
    lpps->fRestore   = FALSE;

    lpps->hdc =
    hdc       = _GetDCEx(pwnd,
                         hrgnUpdate,
                         DCX_USESTYLE | DCX_INTERSECTRGN);

    if (UT_GetParentDCClipBox(pwnd, hdc, &lpps->rcPaint)) {

        /*
         * If necessary, erase our background, and possibly deal with
         * our children's frames and backgrounds.
         */
        if (fSendEraseBkgnd)
            xxxSendEraseBkgnd(pwnd, hdc, hrgnUpdate);
    }

    /*
     * Now that we're completely erased, see if there are any children
     * that couldn't draw their own frames because their update regions
     * got deleted.
     */
    xxxSendChildNCPaint(pwnd);

    /*
     * The erase and frame operation has occured. Clear the WFREDRAWIFHUNG
     * bit here. We don't want to clear it until we know the erase and
     * frame has occured, so we know we always have a consistent looking
     * window.
     */
    ClearHungFlag(pwnd, WFREDRAWIFHUNG);

    lpps->fErase = (TestWF(pwnd, WFERASEBKGND) != 0);

    return hdc;
}
Beispiel #16
0
HRGN GetNCUpdateRgn(
    PWND pwnd,
    BOOL fValidateFrame)
{
    HRGN hrgnUpdate;

    if (pwnd->hrgnUpdate > HRGN_FULL) {

        /*
         * We must make a copy of our update region, because
         * it could change if we send a message, and we want to
         * make sure the whole thing is used for drawing our
         * frame and background.  We can't use a global
         * temporary region, because more than one app may
         * be calling this routine.
         */
        hrgnUpdate = CreateEmptyRgnPublic();

        if (hrgnUpdate == NULL) {
            hrgnUpdate = HRGN_FULL;
        } else if (CopyRgn(hrgnUpdate, pwnd->hrgnUpdate) == ERROR) {
            GreDeleteObject(hrgnUpdate);
            hrgnUpdate = HRGN_FULL;
        }

        if (fValidateFrame) {

            /*
             * Now that we've taken care of any frame drawing,
             * intersect the update region with the window's
             * client area.  Otherwise, apps that do ValidateRects()
             * to draw themselves (e.g., WinWord) won't ever
             * subtract off the part of the update region that
             * overlaps the frame but not the client.
             */
            CalcWindowRgn(pwnd, ghrgnInv2, TRUE);

            switch (IntersectRgn(pwnd->hrgnUpdate,
                                 pwnd->hrgnUpdate,
                                 ghrgnInv2)) {
            case ERROR:
                /*
                 * If an error occured, we can't leave things as
                 * they are: invalidate the whole window and let
                 * BeginPaint() take care of it.
                 */
                GreDeleteObject(pwnd->hrgnUpdate);
                pwnd->hrgnUpdate = HRGN_FULL;
                break;

            case NULLREGION:
                /*
                 * There is nothing in the client area to repaint.
                 * Blow the region away, and decrement the paint count
                 * if possible.
                 */
                GreDeleteObject(pwnd->hrgnUpdate);
                pwnd->hrgnUpdate = NULL;
                ClrWF(pwnd, WFUPDATEDIRTY);
                if (!TestWF(pwnd, WFINTERNALPAINT))
                    DecPaintCount(pwnd);
                break;
            }
        }

    } else {
        hrgnUpdate = pwnd->hrgnUpdate;
    }

    return hrgnUpdate;
}
Beispiel #17
0
BOOL xxxSendEraseBkgnd(
    PWND pwnd,
    HDC  hdcBeginPaint,
    HRGN hrgnUpdate)
{
    PTHREADINFO ptiCurrent;
    BOOL        fErased;
    HDC         hdc;

    CheckLock(pwnd);

    /*
     * For minimized dudes in win3.1, we would've sent an
     * WM_ICONERASEBKGND and cleared the erase bit.  Now that min
     * windows in 4.0 are all nonclient, don't bother erasing at
     * all.  Pretend like we did.
     *
     * NOTE:
     * For < 4.0 windows, we may have to send a fake WM_ICONERASEKBGND
     * to keep 'em happy.  Saves time not to though.  Getting a DC and
     * sending the message ain't speedy.
     */
    if ((hrgnUpdate == NULL) || TestWF(pwnd, WFMINIMIZED))
        return FALSE;

    /*
     * If a DC to use was not passed in, get one.
     * We want one clipped to this window's update region.
     */
    if (hdcBeginPaint == NULL) {

       hdc = _GetDCEx(pwnd,
                      hrgnUpdate,
                      DCX_USESTYLE | DCX_INTERSECTRGN | DCX_NODELETERGN);
    } else {

        hdc = hdcBeginPaint;
    }

    /*
     * If we're send the WM_ERASEBKGND to another process
     * we need to change the DC owner.
     *
     * We'd like to change the owner to pwnd->pti->idProcess, but
     * GDI won't let us assign ownership back to ourselves later.
     */
    ptiCurrent = PtiCurrent();

    if (GETPTI(pwnd)->ppi != ptiCurrent->ppi)
        GreSetDCOwner(hdc, OBJECT_OWNER_PUBLIC);

    /*
     * Send the event to the window.  This contains the DC clipped to
     * the update-region.
     */
    fErased = (BOOL)xxxSendMessage(pwnd, WM_ERASEBKGND, (WPARAM)hdc, 0L);

    /*
     * If we've changed the DC owner, change it back to
     * the current process.
     */
    if (GETPTI(pwnd)->ppi != ptiCurrent->ppi)
        GreSetDCOwner(hdc, OBJECT_OWNER_CURRENT);

    /*
     * If the WM_ERASEBKGND message did not erase the
     * background, then set this flag to let BeginPaint()
     * know to ask the caller to do it via the fErase
     * flag in the PAINTSTRUCT.
     */
    if (!fErased) {
        SetWF(pwnd, WFERASEBKGND);
        if (!TestWF(pwnd, WFWIN31COMPAT))
            SetWF(pwnd, WFSENDERASEBKGND);
    }

    /*
     * If we got a cache DC in this routine, release it.
     */
    if (hdcBeginPaint == NULL) {
        ReleaseCacheDC(hdc, TRUE);
    }

    return fErased;
}
Beispiel #18
0
/*
 * 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);
    }
}
Beispiel #19
0
VOID xxxInternalDoSyncPaint(
    PWND  pwnd,
    DWORD flags)
{
    CheckLock(pwnd);

    /*
     * Do the paint for this window.
     */
    xxxSimpleDoSyncPaint(pwnd);

    /*
     * Normally we like to enumerate all of this window's children and have
     * them erase their backgrounds synchronously.  However, this is a bad
     * thing to do if the window is NOT CLIPCHLIDREN.  Here's the scenario
     * we want to to avoid:
     *
     * 1) Window 'A' is invalidated
     * 2) 'A' erases itself (or not, doesn't matter)
     * 3) 'A's children are enumerated and they erase themselves.
     * 4) 'A' paints over its children (remember, 'A' isn't CLIPCHILDREN)
     * 5) 'A's children paint but their backgrounds aren't their ERASEBKND
     *    color (because 'A' painted over them) and everything looks like
     *    dirt.
     */
    if ((flags & DSP_ALLCHILDREN) ||
        ((flags & DSP_ENUMCLIPPEDCHILDREN) && TestWF(pwnd, WFCLIPCHILDREN))) {

        TL   tlpwnd;
        PBWL pbwl;
        HWND *phwnd;

        if (pbwl = BuildHwndList(pwnd->spwndChild, BWL_ENUMLIST, NULL)) {

            PTHREADINFO ptiCurrent = PtiCurrent();
            HWND        hwnd;

            /*
             * If the client dies during a callback, the hwnd list
             * will be freed in xxxDestroyThreadInfo.
             */
            for (phwnd = pbwl->rghwnd; (hwnd = *phwnd) != (HWND)1; phwnd++) {

                if (hwnd == NULL)
                    continue;

                if ((pwnd = (PWND)RevalidateHwnd(hwnd)) == NULL)
                    continue;

                /*
                 * Note: testing if a window is a child automatically
                 * excludes the desktop window.
                 */
                if (TestWF(pwnd, WFCHILD) && (ptiCurrent != GETPTI(pwnd))) {

                    /*
                     * Don't cause any more intertask sendmessages cause it
                     * does bad things to cbt's windowproc hooks.  (Due to
                     * SetParent allowing child windows in the topwindow
                     * hierarchy.
                     */
                    continue;
                }

                /*
                 * Note that we pass only certain bits down as we recurse:
                 * the other bits pertain to the current window only.
                 */
                ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
                xxxInternalDoSyncPaint(pwnd, flags);
                ThreadUnlock(&tlpwnd);
            }

            FreeHwndList(pbwl);
        }
    }
}
Beispiel #20
0
BOOL
TWIN_DriverMessage(LPMSG lpMsg, HWND hWnd,
	      UINT uMin, UINT uMax,UINT uFlg,BOOL bNoWait)
{
    DWORD   dwerv;
    HANDLE  hTask;
    LPQUEUE lpQueue;

    if (hWnd && !IsWindow(hWnd))
	hWnd = 0;

    if (hWnd)
	hTask = GetWindowTask(hWnd);
    else
	hTask = GetCurrentTask();
    lpQueue = QueueGetPtr(hTask);

    /******************************************/
    /* what is this?  it is not called...     */
    /*hFocusTask = GetWindowTask(GetFocus()); */
    /******************************************/

  lpMsg->hwnd = 0;
  labLoop:
    while(1) {
	while (lpSendMessageStack && 
	       lpSendMessageStack->hReceivingTask == GetCurrentTask() &&
	       !lpSendMessageStack->bSendReceived)
	{
	    TWIN_ReceiveMessage(FALSE);
	}

	/* try for a message from application queue */
	if (QueueGetMsg(lpQueue, lpMsg, hWnd, uMin, uMax, uFlg)) {
	    break;
	}

	/* try for a message from system queue */
	if (QueueGetMsg(0,lpMsg,hWnd,uMin,uMax,uFlg)) {
	    break;
	}

	if (uMin <= WM_PAINT && (!uMax || uMax >= WM_PAINT)) {
	    /* finally, check if the window needs a paint message */
	    if(lpQueue->wQueueFlags & QFPAINT) {
	      labTryNext:
		if((lpMsg->hwnd = InternalUpdateWindows())) {
		    if (TestWF(lpMsg->hwnd, WFNCDIRTY)) {
			if (NonEmptyNCRect(lpMsg->hwnd)) {
			    lpMsg->message = WM_NCPAINT;
			    lpMsg->wParam = 0;
			    lpMsg->lParam = 0L;
			    break;
			}
			else {
			    ClearWF(lpMsg->hwnd, WFNCDIRTY);
			}
		    }
		    if (TestWF(lpMsg->hwnd, WFDIRTY)) {
			if (IsIconic(lpMsg->hwnd) && 
			    GetClassIcon(lpMsg->hwnd)) {
			    lpMsg->message = WM_PAINTICON;
			    lpMsg->wParam = 1;
			}
			else {
			    lpMsg->message = WM_PAINT;
			    lpMsg->wParam = 0;
			}
			lpMsg->lParam = 0L;
			break;
		    }
		    else
			goto labTryNext;
		}
		lpQueue->wQueueFlags &= ~QFPAINT;
	    }
	}

	if ((uMin <= WM_TIMER && (!uMax || uMax >= WM_TIMER)) ||
	    (uMin <= WM_SYSTIMER && (!uMax || uMax >= WM_SYSTIMER))) {
	    if(lpQueue->wQueueFlags & QFTIMER) {
		if (TWIN_GetTimerMsg(hWnd,hTask,lpMsg,uFlg)) {
		    break;
		}
	    }
	}

	/* none of the above, so see if system is ready. */
	if (!TWIN_InDriverWait)
	{

	    TWIN_InDriverWait = TRUE;
	    dwerv = DriverWaitEvent(TRUE);
	    TWIN_InDriverWait = FALSE;

	    if (!dwerv && !bNoWait)
	    {
		/*
		 *  The code here used to call ReadyTask(GetCurrentTask())
		 *  before calling InternalYield(), but that results in
		 *  a solid-run condition if more than one task is
		 *  defined, because it results in the other task looking
		 *  like it's ready to run, when all tasks should be waiting
		 *  on a driver event.  So we yield if necessary, but do
		 *  not set ourselves as ready-to-run if we do.  We will
		 *  be run again when we first get a message in our queue.
		 */
#if defined(MAC_TASKING_PATCH)
		ReadyTask(GetCurrentTask());
#endif
		if (!InternalYield())
		{
		    TWIN_InDriverWait = TRUE;
		    (void)DriverWaitEvent(FALSE);
		    TWIN_InDriverWait = FALSE;
		}
	    }
	    else if (!(uFlg & PM_NOYIELD))
		Yield();
	}
	else if (!(uFlg & PM_NOYIELD))
	    InternalYield();

	if(bNoWait)
	    return FALSE;
    }
    if (CallGetMessageHooks(lpMsg,uFlg & PM_REMOVE))
	goto labLoop;
    return TRUE;
}
Beispiel #21
0
void xxxShowOwnedWindows(
    PWND pwndOwner,
    UINT cmdShow)
{
    BOOL fShow;
    int cmdZoom;
    HWND *phwnd;
    PBWL pbwl;
    PWND pwnd, pwndTopOwner;
    TL tlpwnd;

    CheckLock(pwndOwner);

    /*
     * Not interested in child windows
     */
    if (TestwndChild(pwndOwner))
        return;

    if ((pbwl = BuildHwndList(PWNDDESKTOP(pwndOwner)->spwndChild, BWL_ENUMLIST, NULL)) == NULL)
        return;

    /*
     * NOTE: The following code assumes the values of SW_* are 1, 2, 3, and 4
     */
    fShow = (cmdShow >= SW_PARENTOPENING);

    cmdZoom = 0;
    if (cmdShow == SW_OTHERZOOM)
        cmdZoom = SIZEZOOMHIDE;

    if (cmdShow == SW_OTHERUNZOOM)
        cmdZoom = SIZEZOOMSHOW;

    /*
     * If zoom/unzoom, then open/close all popups owned by all other
     * windows.  Otherwise, open/close popups owned by pwndOwner.
     */
    for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {

        /*
         * Lock the window before we play with it.
         * If the window handle is invalid, skip it
         */
        if ((pwnd = RevalidateHwnd(*phwnd)) == NULL)
            continue;

        /*
         * Kanji windows can't be owned, so skip it.
         */
        if (TestCF(pwnd, CFKANJIWINDOW))
            continue;

        /*
         * If same as window passed in, skip it.
         */
        if (pwnd == pwndOwner)
            continue;

        /*
         * Find ultimate owner of popup, but only go up as far as pwndOwner.
         */
        if ((pwndTopOwner = pwnd->spwndOwner) != NULL) {

            /*
             * The TestwndHI is needed since if it has an icon, pwndOwner
             * is invalid.
             */
            while (!TestwndHI(pwndTopOwner) && pwndTopOwner != pwndOwner &&
                    pwndTopOwner->spwndOwner != NULL)
                pwndTopOwner = pwndTopOwner->spwndOwner;
        }

        /*
         * Zoom/Unzoom case.
         */
        if (cmdZoom != 0) {

            /*
             * If no parent, or parents are the same, skip.
             */
            if (pwndTopOwner == NULL || pwndTopOwner == pwndOwner)
                continue;

            /*
             * If owner is iconic, then this window should stay hidden,
             * UNLESS the minimized window is disabled, in which case we'd
             * better show the window.
             */
            if (   cmdShow == SW_OTHERUNZOOM
                && pwndTopOwner != NULL
                && TestWF(pwndTopOwner, WFMINIMIZED)
                && !TestWF(pwndTopOwner, WFDISABLED)
               )
                continue;
        } else {
            /*
             * Hide/Iconize/Show/Open case.
             */
            /*
             * If parents aren't the same, skip.
             */
            if (pwndTopOwner != pwndOwner)
                continue;
        }

        /*
         * Hide or show if:
         * Showing & this is a hidden popup
         *   OR
         * Hiding & this is a visible window
         */
        if ((fShow && TestWF(pwnd, WFHIDDENPOPUP)) ||
                (!fShow && TestWF(pwnd, WFVISIBLE))) {
            ThreadLockAlways(pwnd, &tlpwnd);
            xxxSendMessage(pwnd, WM_SHOWWINDOW, fShow, (LONG)cmdShow);
            ThreadUnlock(&tlpwnd);
        }
    }

    /*
     * Free the window list.
     */
    FreeHwndList(pbwl);
}
Beispiel #22
0
PWND _GetWindow(
    PWND pwnd,
    UINT cmd)
{
    PWND pwndT;
    BOOL fRebase = FALSE;

    /*
     * If this is a desktop window, return NULL for sibling or
     * parent information.
     */
    if (GETFNID(pwnd) == FNID_DESKTOP) {
        switch (cmd) {
        case GW_CHILD:
            break;

        default:
            return NULL;
            break;
        }
    }

    /*
     * Rebase the returned window at the end of the routine
     * to avoid multiple test for pwndT == NULL.
     */
    pwndT = NULL;
    switch (cmd) {
    case GW_HWNDNEXT:
        pwndT = pwnd->spwndNext;
        fRebase = TRUE;
        break;

    case GW_HWNDFIRST:
        if (pwnd->spwndParent) {
            pwndT = REBASEPWND(pwnd, spwndParent);
            pwndT = REBASEPWND(pwndT, spwndChild);
            if (GetAppCompatFlags(NULL) & GACF_IGNORETOPMOST) {
                while (pwndT != NULL) {
                    if (!TestWF(pwndT, WEFTOPMOST))
                        break;
                    pwndT = REBASEPWND(pwndT, spwndNext);
                }
            }
        }
        break;

    case GW_HWNDLAST:
        pwndT = GetPrevPwnd(pwnd, NULL);
        break;

    case GW_HWNDPREV:
        pwndT = GetPrevPwnd(pwnd, pwnd);
        break;

    case GW_OWNER:
        pwndT = pwnd->spwndOwner;
        fRebase = TRUE;
        break;

    case GW_CHILD:
        pwndT = pwnd->spwndChild;
        fRebase = TRUE;
        break;

#if !defined(_USERK_)
    case GW_ENABLEDPOPUP:
       pwndT = (PWND)NtUserCallHwnd(PtoHq(pwnd), SFI_DWP_GETENABLEDPOPUP);
       fRebase = TRUE;
       break;
#endif

    default:
        RIPERR0(ERROR_INVALID_GW_COMMAND, RIP_VERBOSE, "");
        return NULL;
    }

    if (pwndT != NULL && fRebase)
        pwndT = REBASEPTR(pwnd, pwndT);

    return pwndT;
}
Beispiel #23
0
BOOL DoPaint(
    PWND  pwndFilter,
    LPMSG lpMsg)
{
    PWND        pwnd;
    PWND        pwndT;
    PTHREADINFO ptiCurrent = PtiCurrent();


#if 0 // CHRISWIL: WIN95 SPECIFIC

    /*
     * If there is a system modal up and it is attached to another task,
     * DON'T do paints.  We don't want to return a message for a window in
     * another task!
     */
    if (hwndSysModal && (hwndSysModal->hq != hqCurrent)) {

        /*
         * Poke this guy so he wakes up at some point in the future,
         * otherwise he may never wake up to realize he should paint.
         * Causes hangs - e.g. Photoshop installation program
         *   PostThreadMessage32(Lpq(hqCurrent)->idThread, WM_NULL, 0, 0, 0);
         */
        return FALSE;
    }

#endif

    /*
     * If this is a system thread, then walk the windowstation desktop-list
     * to find the window which needs painting.  For other threads, we
     * reference off the thread-desktop.
     */
    if (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD) {

        PWINDOWSTATION pwinsta;
        PDESKTOP       pdesk;

        if ((pwinsta = ptiCurrent->pwinsta) == NULL) {
            RIPMSG0(RIP_ERROR, "DoPaint: SYSTEMTHREAD does not have (pwinsta)");
            return FALSE;
        }

        pwnd = NULL;
        for(pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) {

            if (pwnd = InternalDoPaint(pdesk->pDeskInfo->spwnd, ptiCurrent))
                break;
        }

    } else {
        pwnd = InternalDoPaint(ptiCurrent->rpdesk->pDeskInfo->spwnd,
                               ptiCurrent);
    }

    if (pwnd != NULL) {

        if (!CheckPwndFilter(pwnd, pwndFilter))
            return FALSE;

        /*
         * We're returning a WM_PAINT message, so clear WFINTERNALPAINT so
         * it won't get sent again later.
         */
        if (TestWF(pwnd, WFINTERNALPAINT)) {

            ClrWF(pwnd, WFINTERNALPAINT);

            /*
             * If there is no update region, then no more paint for this
             * window.
             */
            if (pwnd->hrgnUpdate == NULL)
                DecPaintCount(pwnd);
        }

        /*
         * Set the STARTPAINT so that any other calls to BeginPaint while
         * painting is begin performed, will prevent painting on those
         * windows.
         *
         * Clear the UPDATEDIRTY since some apps (DBFast) don't call
         * GetUpdateRect, BeginPaint/EndPaint.
         */
        ClrWF(pwnd, WFSTARTPAINT);
        ClrWF(pwnd, WFUPDATEDIRTY);

        /*
         * If we get an invalidate between now and the time the app calls
         * BeginPaint() and the windows parent is not CLIPCHILDREN, then
         * the parent will paint in the wrong order.  So we are going to
         * cause the child to paint again.  Look in beginpaint and internal
         * invalidate for other parts of this fix.
         *
         * Set a flag to signify that we are in the bad zone.
         *
         * Must go up the parent links to make sure all parents have
         * WFCLIPCHILDREN set otherwise set the WFWMPAINTSENT flag.
         * This is to fix Excel spreadsheet and fulldrag. The speadsheet
         * parent window (class XLDESK) has WFCLIPCHILDREN set but it's
         * parent (class XLMAIN) doesn't. So the main window erases  the
         * background after the child window paints.
         *
         * JOHANNEC : 27-Jul-1994
         */
        
        /*
         * NT Bug 400167: As we walk up the tree, we need to stop short of
         * desktop windows and mother desktop windows.  We can't do a test
         * for WFCLIPCHILDREN on the mother desktop window's parent because
         * it doesn't exist.  This means that no desktop window will get 
         * WFWMPAINTSENT set, but the message window will be able to get 
         * WFWMPAINTSENT set.
         */
        
        pwndT = pwnd;
        while (pwndT && (GETFNID(pwndT) != FNID_DESKTOP)) {

            if (!TestWF(pwndT->spwndParent, WFCLIPCHILDREN)) {
                SetWF(pwnd, WFWMPAINTSENT);
                break;
            }

            pwndT = pwndT->spwndParent;
        }

        /*
         * If the top level "tiled" owner/parent of this window is iconed,
         * send a WM_PAINTICON rather than a WM_PAINT.  The wParam
         * is TRUE if this is the tiled window and FALSE if it is a
         * child/owned popup of the minimized window.
         *
         * BACKWARD COMPATIBILITY HACK
         *
         * 3.0 sent WM_PAINTICON with wParam == TRUE for no apparent
         * reason.  Lotus Notes 2.1 depends on this for some reason
         * to properly change its icon when new mail arrives.
         */
        if (!TestWF(pwnd, WFWIN40COMPAT) &&
            TestWF(pwnd, WFMINIMIZED)    &&
            (pwnd->pcls->spicn != NULL)) {

            StoreMessage(lpMsg, pwnd, WM_PAINTICON, (DWORD)TRUE, 0L, 0L);

        } else {

            StoreMessage(lpMsg, pwnd, WM_PAINT, 0, 0L, 0L);
        }

        return TRUE;
    }

    return FALSE;
}
Beispiel #24
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);

}
Beispiel #25
0
VOID xxxSimpleDoSyncPaint(
    PWND pwnd)
{
    HRGN  hrgnUpdate;
    DWORD flags = 0;

    CheckLock(pwnd);

    /*
     * Since we're taking care of the frame drawing, we can consider
     * this WM_PAINT message processed.
     */
    ClrWF(pwnd, WFPAINTNOTPROCESSED);

    /*
     * Make copies of these flags, because their state might
     * change after we send a message, and we don't want
     * to "lose" them.
     */
    if (TestWF(pwnd, WFSENDNCPAINT))
        flags |= DSP_FRAME;

    if (TestWF(pwnd, WFSENDERASEBKGND))
        flags |= DSP_ERASE;

    if (flags & (DSP_ERASE | DSP_FRAME)) {

        if (!TestWF(pwnd, WFVISIBLE)) {

            /*
             * If there is no update region, just clear the bits.
             */
            ClrWF(pwnd, WFSENDNCPAINT);
            ClrWF(pwnd, WFSENDERASEBKGND);
            ClrWF(pwnd, WFPIXIEHACK);
            ClrWF(pwnd, WFERASEBKGND);
            ClearHungFlag(pwnd, WFREDRAWIFHUNG);

        } else {

            PTHREADINFO ptiCurrent = PtiCurrent();

            /*
             * If there is no update region, we don't have to
             * do any erasing, but we may need to send an NCPAINT.
             */
            if (pwnd->hrgnUpdate == NULL) {
                ClrWF(pwnd, WFSENDERASEBKGND);
                ClrWF(pwnd, WFERASEBKGND);
                flags &= ~DSP_ERASE;
            }

            /*
             * Only mess with windows owned by the current thread.
             * NOTE: This means that WM_NCPAINT and WM_ERASEBKGND are
             *       only sent intra-thread.
             */
            if (GETPTI(pwnd) == ptiCurrent) {

                hrgnUpdate = GetNCUpdateRgn(pwnd, TRUE);

                if (flags & DSP_FRAME) {

                    /*
                     * If the message got sent before we got here then do
                     * nothing.
                     */
                    if (TestWF(pwnd, WFSENDNCPAINT))
                        xxxSendNCPaint(pwnd, hrgnUpdate);
                }

                if (flags & DSP_ERASE) {

                    if (TestWF(pwnd, WFSENDNCPAINT)) {
                        /*
                         * If we got another invalidate during the NCPAINT
                         * callback get the new update region
                         */
                        DeleteMaybeSpecialRgn(hrgnUpdate);
                        hrgnUpdate = GetNCUpdateRgn(pwnd, FALSE);
                    }

                    /*
                     * If the message got sent before we got here
                     * (e.g.: an UpdateWindow() inside WM_NCPAINT handler,
                     * for example), don't do anything.
                     *
                     * WINPROJ.EXE (version 1.0) calls UpdateWindow() in
                     * the WM_NCPAINT handlers for its subclassed listboxes
                     * in the open dialog.
                     */
                    if (TestWF(pwnd, WFSENDERASEBKGND)) {
                        ClrWF(pwnd, WFSENDERASEBKGND);
                        ClrWF(pwnd, WFERASEBKGND);
                        xxxSendEraseBkgnd(pwnd, NULL, hrgnUpdate);
                    }

                    /*
                     * The erase and frame operation has occured. Clear the
                     * WFREDRAWIFHUNG bit here. We don't want to clear it until we
                     * know the erase and frame has occured, so we know we always
                     * have a consistent looking window.
                     */
                    ClearHungFlag(pwnd, WFREDRAWIFHUNG);
                }

                DeleteMaybeSpecialRgn(hrgnUpdate);

            } else if (!TestwndChild(pwnd)                         &&
                       (pwnd != grpdeskRitInput->pDeskInfo->spwnd) &&
                       FHungApp(GETPTI(pwnd), CMSHUNGAPPTIMEOUT)   &&
                       TestWF(pwnd, WFREDRAWIFHUNG)) {

                ClearHungFlag(pwnd, WFREDRAWIFHUNG);
                xxxRedrawHungWindow(pwnd, NULL);
            }
        }
    }
}
Beispiel #26
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;
}
Beispiel #27
0
VOID DoQueuedSyncPaint(
    PWND        pwnd,
    DWORD       flags,
    PTHREADINFO pti)
{
    PTHREADINFO ptiPwnd = GETPTI(pwnd);

    if ((ptiPwnd != pti)          &&
        TestWF(pwnd, WFSENDNCPAINT)    &&
        TestWF(pwnd, WFSENDERASEBKGND) &&
        TestWF(pwnd, WFVISIBLE)) {

        PSMS psms = ptiPwnd->psmsReceiveList;

        /*
         * If this window already has a WM_SYNCPAINT queue'd up, then there's
         * no need to send another one.  Also protects our heap from getting
         * chewed up.
         */
        while (psms != NULL) {

            if ((psms->message == WM_SYNCPAINT) && (psms->spwnd == pwnd)) {
                break;
            }

            psms = psms->psmsReceiveNext;
        }

        if (psms == NULL) {
            /*
             * This will give this message the semantics of a notify
             * message (sendmessage no wait), without calling back
             * the WH_CALLWNDPROC hook. We don't want to do that
             * because that'll let all these processes with invalid
             * windows to process paint messages before they process
             * "synchronous" erasing or framing needs.
             *
             * Hi word of wParam must be zero or wow will drop it
             *
             * LATER mikeke
             * Do we need to send down the flags with DWP_ERASE and DSP_FRAME
             * in it?
             */
            UserAssert(HIWORD(flags) == 0);
            QueueNotifyMessage(pwnd, WM_SYNCPAINT, flags, 0);

            /*
             * Set our syncpaint-pending flag, since we queued one up.  This
             * will be used to check when we validate-parents for windows
             * without clipchildren.
             */
            SetWF(pwnd, WFSYNCPAINTPENDING);
        }

        /*
         * If we posted a WM_SYNCPAINT for a top-level window that is not
         * of the current thread we're done; we'll pick up the children
         * when we process the message for real.  If we're the desktop
         * however make sure we get all it children.
         */
        if (pwnd != PWNDDESKTOP(pwnd))
            return;
    }

    /*
     * Normally we like to enumerate all of this window's children and have
     * them erase their backgrounds synchronously.  However, this is a bad
     * thing to do if the window is NOT CLIPCHLIDREN.  Here's the scenario
     * we want to to avoid:
     *
     * 1.  Window 'A' is invalidated
     * 2.  'A' erases itself (or not, doesn't matter)
     * 3.  'A's children are enumerated and they erase themselves.
     * 4.  'A' paints over its children (remember, 'A' isn't CLIPCHILDREN)
     * 5.  'A's children paint but their backgrounds aren't their ERASEBKND
     *    color (because 'A' painted over them) and everything looks like
     *    dirt.
     */
    if ((flags & DSP_ALLCHILDREN) ||
        ((flags & DSP_ENUMCLIPPEDCHILDREN) && TestWF(pwnd, WFCLIPCHILDREN))) {

        PWND pwndT;

        for (pwndT = pwnd->spwndChild; pwndT; pwndT = pwndT->spwndNext) {

            /*
             * Don't cause any more intertask sendmessages cause it does
             * bad things to cbt's windowproc hooks.  (Due to SetParent
             * allowing child windows in the topwindow hierarchy.
             * The child bit also catches the desktop window; we want to
             */
            if (TestWF(pwndT, WFCHILD) && (pti != GETPTI(pwndT)))
                continue;

            /*
             * Note that we pass only certain bits down as we recurse:
             * the other bits pertain to the current window only.
             */
            DoQueuedSyncPaint(pwndT, flags, pti);
        }
    }
}
Beispiel #28
0
/***************************************************************************\
*
*  SetShellWindow()
*
*  Returns true if shell window is successfully set.  Note that we return
*  FALSE if a shell window already exists.  I.E., this works on a first
*  come, first serve basis.
*
*  We also do NOT allow child windows to be shell windows.  Other than that,
*  it's up to the caller to size her window appropriately.
*
*  The pwndBkGnd is provided for the explorer shell.  Since the shellwnd
*  and the window which does the drawing of background wallpapers are
*  different, we need to provide means by which we can draw directly on
*  the background window during hung-app drawing.  The pwnd and pwndBkGnd
*  will be identical if called through the SetShellWindow() api.
*
*
\***************************************************************************/
BOOL xxxSetShellWindow(PWND pwnd, PWND pwndBkGnd)
{
    PTHREADINFO  ptiCurrent = PtiCurrent();
    PDESKTOPINFO pdeskinfo = GETDESKINFO(ptiCurrent);

    PPROCESSINFO ppiShellProcess;

    UserAssert(pwnd);

    /*
     * Fail the call if another shell window exists
     */
    if (pdeskinfo->spwndShell != NULL)
        return(FALSE);

    /*
     * The shell window must be
     *      (1) Top-level
     *      (2) Unowned
     *      (3) Not topmost
     */
    if (TestwndChild(pwnd)             ||
            (pwnd->spwndOwner != NULL) ||
            TestWF(pwnd, WEFTOPMOST)) {

        RIPMSG0(RIP_WARNING, "xxxSetShellWindow: Invalid type of window");
        return(FALSE);
    }

    /*
     * Chicago has a totally different input model which has special code
     * that checks for Ctrl-Esc and sends it to the shell.  We can get
     * the same functionality, without totally re-writing our input model
     * by just automatically installing the Ctrl-Esc as a hotkey for the
     * shell window.  The hotkey delivery code has a special case which
     * turns this into a WM_SYSCOMMAND message instead of a WM_HOTKEY
     * message.
     *
     * We don't both checking for failure.  Somebody could already have
     * a Ctrl-Esc handler installed.
     */
    _RegisterHotKey(pwnd,SC_TASKLIST,MOD_CONTROL,VK_ESCAPE);

    /*
     * This is the shell window wright.
     * So get the process id for the shell.
     */
    ppiShellProcess = GETPTI(pwnd)->ppi;

    /*
     * Set the shell process id to the desktop only if it's the first instance
     */
    if ((ppiShellProcess != NULL) && (pdeskinfo->ppiShellProcess == NULL)) {
        pdeskinfo->ppiShellProcess = ppiShellProcess;
    }

    Lock(&pdeskinfo->spwndShell, pwnd);
    Lock(&pdeskinfo->spwndBkGnd, pwndBkGnd);

    /*
     * Push window to bottom of stack.
     */
    SetWF(pdeskinfo->spwndShell, WFBOTTOMMOST);
    xxxSetWindowPos(pdeskinfo->spwndShell,
                    PWND_BOTTOM,
                    0,
                    0,
                    0,
                    0,
                    SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

    return(TRUE);
}
Beispiel #29
0
BOOL xxxShowWindow(
    PWND pwnd,
    DWORD cmdShowAnimate)
{
    BOOL fVisOld, fVisNew;
    UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE;
    PTHREADINFO pti;
    BOOL bFirstMain = FALSE;
    int cmdShow = LOWORD(cmdShowAnimate);

    CheckLock(pwnd);

    fVisOld = TestWF(pwnd, WFVISIBLE);
    pti = PtiCurrent();

    /*
     * See if this is the first "main" top level
     * window being created by this application - if show, assume it
     * is showing with the SW_SHOWDEFAULT command.
     *
     * Checks for:
     * - cmdShow is a "default" show command
     * - we haven't done startupinfo yet (we only use it once)
     * - this is not a child (it is a top level window)
     * - this has a titlebar (indicator of the main window)
     * - it isn't owned (indicator of the main window)
     */
    if ((pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) &&
            !TestwndChild(pwnd) &&
            (TestWF(pwnd, WFBORDERMASK) == (BYTE)LOBYTE(WFCAPTION)) &&
            (pwnd->spwndOwner == NULL)) {

        bFirstMain = TRUE;

        switch (cmdShow) {
        case SW_SHOWNORMAL:
        case SW_SHOW:

            /*
             * Then assume default!
             */
            cmdShow = SW_SHOWDEFAULT;
            break;
        }
    }

    /*
     * If this application specified SW_SHOWDEFAULT, then we get the
     * real SW_* command from the application's STARTUPINFO structure
     * (STARTUPINFO is passed to CreateProcess() when this application
     * was launched).
     */
    if (cmdShow == SW_SHOWDEFAULT) {

        /*
         * Call the client to get the SW_* command from the STARTUPINFO
         * for this process.
         */
        if (pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) {

            bFirstMain = TRUE;

            cmdShow = pti->ppi->usi.wShowWindow;
#if 0
            switch (cmdShow) {
            case SW_SHOWMINIMIZED:
            case SW_MINIMIZE:

                /*
                 * If the default show was "minimized", then make sure it doesn't
                 * become active.  Minimized is effectively "background".
                 */
                cmdShow = SW_SHOWMINNOACTIVE;
                break;
            }
#endif
        }
    }

    //
    // This is in case someone said SW_SHOWDEFAULT but has no startupinfo.
    // Or in case cmdShow inside of STARTUPINFO is SW_SHOWDEFAULT.
    //
    if (cmdShow == SW_SHOWDEFAULT)
        cmdShow = SW_SHOWNORMAL;

    /*
     * Turn off startup info.  We turn this off after the first call to
     * ShowWindow.  If we don't apps can be started by progman with
     * the start info being minimized and then be restored and then
     * call ShowWindow(SW_SHOW) and the app would minimize again.
     * Notepad had that problem 2985.
     */
    if (bFirstMain) {
        pti->ppi->usi.dwFlags &= ~(STARTF_USESHOWWINDOW|STARTF_USESIZE \
                | STARTF_USEPOSITION);
    }


    /*
     * Take care of all the OLD show commands with columns & iconslot.
     */
    if (cmdShow & 0xFF00) {
        if ((cmdShow & 0xFF80) == (int)0xFF80)
            cmdShow = SW_SHOWMINNOACTIVE;
        else
            cmdShow = SW_SHOW;
    }

    /*
     * Change to new fullscreen if needed and in same desktop
     */
    if ((pwnd->bFullScreen != WINDOWED)
            && (pwnd->head.rpdesk == grpdeskRitInput)) {
        if ((cmdShow == SW_SHOWNORMAL) ||
            (cmdShow == SW_RESTORE) ||
            (cmdShow == SW_MAXIMIZE) ||
            (cmdShow == SW_SHOWMAXIMIZED)) {
            cmdShow = SW_SHOWMINIMIZED;

            if (pwnd->bFullScreen == FULLSCREENMIN) {
                pwnd->bFullScreen = FULLSCREEN;
            }

            if (gpqForeground != NULL &&
                gpqForeground->spwndActive == pwnd) {
                xxxMakeWindowForegroundWithState(NULL, 0);
            }
        }
    }

    switch (cmdShow) {
    case SW_SHOWNOACTIVATE:
    case SW_SHOWNORMAL:
    case SW_RESTORE:

        /*
         * If min/max, let xxxMinMaximize() do all the work.
         */
        if (TestWF(pwnd, WFMINIMIZED) || TestWF(pwnd, WFMAXIMIZED)) {
            xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE);
            return fVisOld;

        } else {

            /*
             * Ignore if the window is already visible.
             */
            if (fVisOld) {
                return fVisOld;
            }

            swpFlags |= SWP_SHOWWINDOW;
            if (   cmdShow == SW_SHOWNOACTIVATE) {
                swpFlags |= SWP_NOZORDER;
#ifdef NEVER
                /*
                 * This is what win3.1 does. On NT, since each "queue" has
                 * its own active window, there is often no active window.
                 * In this case, win3.1 turns a SHOWNOACTIVATE into a "SHOW
                 * with activate". Since win3.1 almost always has an active
                 * window, this almost never happens. So on NT, we're not
                 * going to do this check - that way we'll be more compatible
                 * with win3.1 because we'll usally not activate (like win3.1).
                 * With this check, this causes FoxPro 2.5 for Windows to not
                 * properly activate its command window when first coming up.
                 */
                if (pti->pq->spwndActive != NULL)
                    swpFlags |= SWP_NOACTIVATE;
#else
                swpFlags |= SWP_NOACTIVATE;
#endif
            }
        }
        break;

    case SW_SHOWMINNOACTIVE:
    case SW_SHOWMINIMIZED:
    case SW_SHOWMAXIMIZED:
    case SW_MINIMIZE:
        xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE);
        return fVisOld;

    case SW_SHOWNA:
        swpFlags |= SWP_SHOWWINDOW | SWP_NOACTIVATE;

        // LATER removed this to be compatible with SHOWNOACTIVATE
        //if (pti->pq->spwndActive != NULL)
        //    swpFlags |= SWP_NOACTIVATE;
        break;

    case SW_SHOW:

        /*
         * Don't bother if it is already visible.
         */
        if (fVisOld)
            return fVisOld;

        swpFlags |= SWP_SHOWWINDOW;
        if (cmdShow == SW_SHOWNOACTIVATE)
        {
            swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE;
        }
        break;

    case SW_HIDE:

        /*
         * Don't bother if it is already hidden.
         */
        if (!fVisOld)
            return fVisOld;

        swpFlags |= SWP_HIDEWINDOW;
        if (pwnd != pti->pq->spwndActive)
            swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER);
        break;

    default:
        RIPERR0(ERROR_INVALID_SHOWWIN_COMMAND, RIP_VERBOSE, "");
        return fVisOld;
    }

    /*
     * If we're changing from visible to hidden or vise-versa, send
     * WM_SHOWWINDOW.
     */
    fVisNew = !(cmdShow == SW_HIDE);
    if (fVisNew != fVisOld) {
        xxxSendMessage(pwnd, WM_SHOWWINDOW, fVisNew, 0L);
        if (!TestWF(pwnd, WFWIN31COMPAT)) {
            xxxSendMessage(pwnd, WM_SETVISIBLE, fVisNew, 0L);
        }
    }

    if (!TestwndChild(pwnd)) {
        if (TestCF(pwnd, CFSAVEBITS)) {

            /*
             * Activate to prevent discarding saved bits???
             */
            if (cmdShow == SW_SHOW || cmdShow == SW_SHOWNORMAL) {
                xxxActivateWindow(pwnd, AW_USE);
                swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE;
            }
        }
    } else {

        /*
         * Children can't get activation...
         */
        swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER);
    }

    /*
     * If our parent is hidden, don't bother to call xxxSetWindowPos.
     */
    if (_FChildVisible(pwnd)) {
        xxxSetWindowPos(pwnd, (PWND)NULL, 0, 0, 0, 0, swpFlags);
    } else {
        if (cmdShow == SW_HIDE)
            ClrWF(pwnd, WFVISIBLE);
        else
            SetWF(pwnd, WFVISIBLE);
    }

    /*
     * Send size and move messages AFTER repainting
     */
    if (TestWF(pwnd, WFSENDSIZEMOVE)) {
        ClrWF(pwnd, WFSENDSIZEMOVE);
        if (TestWF(pwnd, WFMINIMIZED)) {
            xxxSendSizeMessage(pwnd, SIZEICONIC);
        } else if (TestWF(pwnd, WFMAXIMIZED)) {
            xxxSendSizeMessage(pwnd, SIZEFULLSCREEN);
        } else {
            xxxSendSizeMessage(pwnd, SIZENORMAL);
        }
        if (pwnd->spwndParent) {
            xxxSendMessage(pwnd, WM_MOVE, 0, MAKELONG(
                    pwnd->rcClient.left - pwnd->spwndParent->rcClient.left,
                    pwnd->rcClient.top - pwnd->spwndParent->rcClient. top));
        } else {
            /*
             * NULL parent implies this window is a zombie
             */
            xxxSendMessage(pwnd, WM_MOVE, 0, MAKELONG(
                    pwnd->rcClient.left, pwnd->rcClient.top));
        }
    }

    /*
     * If hiding and is active-foreground window, activate someone else.
     * If hiding a active window make someone active.
     */
    if (cmdShow == SW_HIDE) {
        if ((pwnd == pti->pq->spwndActive) && (pti->pq == gpqForeground)) {
            xxxActivateWindow(pwnd, AW_SKIP);
        } else {
            xxxCheckFocus(pwnd);
        }
    }

    return fVisOld;
}
Beispiel #30
0
VOID xxxCapture(
    PTHREADINFO pti,
    PWND        pwnd,
    UINT        code)
{
    if ((gspwndScreenCapture == NULL) ||
        (code == FULLSCREEN_CAPTURE) ||
        ((pwnd == NULL) && (code == NO_CAP_CLIENT) && (pti->pq != GETPTI(gspwndScreenCapture)->pq))) {

        PQ   pq;
        PWND pwndCaptureOld = NULL;

        if (code == FULLSCREEN_CAPTURE) {
            if (pwnd) {

                Lock(&gspwndScreenCapture, pwnd);

                /*
                 * We're going full screen so clear the mouse owner
                 */
                Unlock(&gspwndMouseOwner);

            } else {

                Unlock(&gspwndScreenCapture);
            }
        }

        /*
         * Internal capture works like Win 3.1 capture unlike the NT capture
         * which can be lost if the user clicks down on another application
         */
        if (code == CLIENT_CAPTURE_INTERNAL) {
            Lock(&gspwndInternalCapture, pwnd);
            code = CLIENT_CAPTURE;
        }

        /*
         * Free the internal capture if the app (thread) that did the internal
         * capture is freeing the capture.
         */
        if ((code == NO_CAP_CLIENT) &&
            gspwndInternalCapture   &&
            (pti == GETPTI(gspwndInternalCapture))) {

            Unlock(&gspwndInternalCapture);
        }

        if ((pq = pti->pq) != NULL) {

            /*
             * Make consistent picture of mouse tracking stuff for apps
             */
            if ((pq->spwndLastMouseMessage != NULL) &&
                    ((pwnd == pq->spwndLastMouseMessage) &&
                     (code != CLIENT_CAPTURE)) ||
                    ((pq->spwndCapture == pq->spwndLastMouseMessage) &&
                     (pq->codeCapture != CLIENT_CAPTURE))) {
                ResetMouseTracking(pq, NULL);
            }

            pwndCaptureOld = pq->spwndCapture;
            Lock(&pq->spwndCapture, pwnd);
            pq->codeCapture = code;
        }

        /*
         * If there was a capture window and we're releasing it, post
         * a WM_MOUSEMOVE to the window we're over so they can know about
         * the current mouse position.
         */
        if ((pwnd == NULL) && (pwndCaptureOld != NULL))
            SetFMouseMoved();

        /*
         * New for win95 - send  WM_CAPTURECHANGED.
         *
         * The FNID_DELETED_BIT is set in xxxFreeWindow which means we
         * DON'T want to send the message.
         */
        if (pwndCaptureOld                        &&
            TestWF(pwndCaptureOld, WFWIN40COMPAT) &&
            !(pwndCaptureOld->fnid & FNID_DELETED_BIT)) {

            TL tlpwnd;

            ThreadLock(pwndCaptureOld, &tlpwnd);
            xxxSendMessageCallback(pwndCaptureOld,
                    WM_CAPTURECHANGED,
                    FALSE,
                    (LPARAM)HW(pwnd),
                    NULL,
                    0,
                    FALSE);
            ThreadUnlock(&tlpwnd);
        }
    }
}