示例#1
0
文件: paint.c 项目: conioh/os-design
VOID xxxSendNCPaint(
    PWND pwnd,
    HRGN hrgnUpdate)
{
    CheckLock(pwnd);

    /*
     * Clear the WFSENDNCPAINT bit...
     */
    ClrWF(pwnd, WFSENDNCPAINT);

    /*
     * If the window is active, but its FRAMEON bit hasn't
     * been set yet, set it and make sure that the entire frame
     * gets redrawn when we send the NCPAINT.
     */
    if ((pwnd == PtiCurrent()->pq->spwndActive) && !TestWF(pwnd, WFFRAMEON)) {
        SetWF(pwnd, WFFRAMEON);
        hrgnUpdate = HRGN_FULL;
        ClrWF(pwnd, WFNONCPAINT);
    }

    /*
     * If PixieHack() has set the WM_NCPAINT bit, we must be sure
     * to send with hrgnClip == HRGN_FULL.  (see PixieHack() in wmupdate.c)
     */
    if (TestWF(pwnd, WFPIXIEHACK)) {
        ClrWF(pwnd, WFPIXIEHACK);
        hrgnUpdate = HRGN_FULL;
    }

    if (hrgnUpdate)
        xxxSendMessage(pwnd, WM_NCPAINT, (WPARAM)hrgnUpdate, 0L);
}
示例#2
0
文件: paint.c 项目: conioh/os-design
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;
}
示例#3
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);
}
示例#4
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);
    }


}
示例#5
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;
}
示例#6
0
文件: paint.c 项目: conioh/os-design
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);
            }
        }
    }
}
示例#7
0
文件: paint.c 项目: conioh/os-design
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;
}
示例#8
0
文件: paint.c 项目: conioh/os-design
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;
}
示例#9
0
文件: paint.c 项目: conioh/os-design
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;
}
示例#10
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);
    }
}
示例#11
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);
}