Пример #1
0
BOOL xxxSetMenu(
    PWND  pwnd,
    PMENU pMenu,
    BOOL  fRedraw)
{
    CheckLock(pwnd);
    CheckLock(pMenu);

    if (!TestwndChild(pwnd)) {

        LockWndMenu(pwnd, &pwnd->spmenu, pMenu);

        /*
         * only redraw the frame if the window is non-minimized --
         * even if it's not visible, we need RedrawFrame to recalc the NC size
         *
         * Added a check for (redraw) since the MDISetMenu() only needs to
         * set the menu and not perform any redraws.
         */
        if (!TestWF(pwnd, WFMINIMIZED) && fRedraw)
            xxxRedrawFrame(pwnd);

        return TRUE;
    }

    RIPERR0(ERROR_CHILD_WINDOW_MENU, RIP_VERBOSE, "");
    return FALSE;
}
Пример #2
0
PWND GetTopLevelWindow(
    PWND pwnd)
{
    if (pwnd != NULL) {
        while (TestwndChild(pwnd))
            pwnd = REBASEPWND(pwnd, spwndParent);
    }

    return pwnd;
}
Пример #3
0
BOOL _FChildVisible(
    PWND pwnd)
{
    while (TestwndChild(pwnd)) {
        pwnd = REBASEPWND(pwnd, spwndParent);
        if (pwnd == NULL)
            break;
        if (!TestWF(pwnd, WFVISIBLE))
            return FALSE;
    }

    return TRUE;
}
Пример #4
0
PWND  _GetChildControl(PWND pwndRoot, PWND pwndChild) {
    PWND    pwndControl = NULL;

    while (pwndChild && TestwndChild(pwndChild) && (pwndChild != pwndRoot)) {
        pwndControl = pwndChild;
        pwndChild = REBASEPWND(pwndChild, spwndParent);

        if (TestWF(pwndChild, WEFCONTROLPARENT))
            break;
    }

    return(pwndControl);
}
Пример #5
0
DWORD GetContextHelpId(
    PWND pwnd)
{
    DWORD  dwContextId;

    while (!(dwContextId = (DWORD)_GetProp(pwnd,
            MAKEINTATOM(gpsi->atomContextHelpIdProp), PROPF_INTERNAL))) {
        pwnd = (TestwndChild(pwnd) ?
                REBASEPWND(pwnd, spwndParent) :
                REBASEPWND(pwnd, spwndOwner));
        if (!pwnd || (GETFNID(pwnd) == FNID_DESKTOP))
            break;
    }

    return dwContextId;
}
Пример #6
0
BOOL _IsChild(
    PWND pwndParent,
    PWND pwnd)
{
    /*
     * Don't need a test to get out of the loop because the
     * desktop is not a child.
     */
    while (pwnd != NULL) {
        if (!TestwndChild(pwnd))
            return FALSE;

        pwnd = REBASEPWND(pwnd, spwndParent);
        if (pwndParent == pwnd)
            return TRUE;
    }
    return FALSE;
}
Пример #7
0
PWND _GetParent(
    PWND pwnd)
{
    /*
     * For 1.03 compatibility reasons, we should return NULL
     * for top level "tiled" windows and owner for other popups.
     * pwndOwner is set to NULL in xxxCreateWindow for top level
     * "tiled" windows.
     */
    if (!(TestwndTiled(pwnd))) {
        if (TestwndChild(pwnd))
            pwnd = REBASEPWND(pwnd, spwndParent);
        else
            pwnd = REBASEPWND(pwnd, spwndOwner);
        return pwnd;
    }

    /*
     * The window was not a child window; they may have been just testing
     * if it was
     */
    return NULL;
}
Пример #8
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);
    }
}
Пример #9
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;
}
Пример #10
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);
}
Пример #11
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);
            }
        }
    }
}
Пример #12
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);
    }
}
Пример #13
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);
}
Пример #14
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);
}
Пример #15
0
/***************************************************************************\
* xxxMNStartMenuState
*
* This function is called when the menu bar is about to be activated (the
*  app's main menu). It makes sure that the threads involved are not in
*  menu mode already, finds the owner/notification window, initializes
*  pMenuState and sends the WM_ENTERMENULOOP message.
* It successful, it returns a pointer to a pMenuState. If so, the caller
*  must call MNEndMenuState when done.
*
* History:
* 4-25-91 Mikehar       Port for 3.1 merge
* 5-20-96 GerardoB      Renamed and changed (Old name: xxxMNGetPopup)
\***************************************************************************/
PMENUSTATE xxxMNStartMenuState(PWND pwnd)
{
    PPOPUPMENU ppopupmenu;
    PTHREADINFO ptiCurrent, ptiNotify;
    PMENUSTATE pMenuState;
    TL tlpwnd;

    CheckLock(pwnd);

    /*
     * Bail if the current thread is already in menu mode
     */
    ptiCurrent = PtiCurrent();
    if (ptiCurrent->pMenuState != NULL) {
        return NULL;
    }

    /*
     * If the window doesn't have any children, return pwndActive.
     */
    if (!TestwndChild(pwnd)) {
        pwnd = GETPTI(pwnd)->pq->spwndActive;
    } else {

        /*
         * Search up the parents for a window with a System Menu.
         */
        while (TestwndChild(pwnd)) {
            if (TestWF(pwnd, WFSYSMENU))
                break;
            pwnd = pwnd->spwndParent;
        }
    }

    if (pwnd == NULL) {
        return NULL;
    }

    if (!TestwndChild(pwnd) && (pwnd->spmenu != NULL)) {
        goto hasmenu;
    }

    if (!TestWF(pwnd, WFSYSMENU)) {
        return NULL;
    }

hasmenu:
    /*
     * If the owner/notification window was created by another thread,
     *  make sure that it's not in menu mode already
     * This can happen if PtiCurrent() is attached to other threads, one of
     *  which created pwnd.
     */
    ptiNotify = GETPTI(pwnd);
    if (ptiNotify->pMenuState != NULL) {
        return NULL;
    }

    /*
     * Allocate ppoupmenu and pMenuState
     */
    ppopupmenu = MNAllocPopup(FALSE);
    if (ppopupmenu == NULL) {
        return NULL;
    }

    pMenuState = MNAllocMenuState(ptiCurrent, ptiNotify, ppopupmenu);
    if (pMenuState == NULL) {
        MNFreePopup(ppopupmenu);
        return NULL;
    }

    ppopupmenu->fIsMenuBar = TRUE;
    ppopupmenu->fHasMenuBar = TRUE;
    Lock(&(ppopupmenu->spwndNotify), pwnd);
    ppopupmenu->posSelectedItem = MFMWFP_NOITEM;
    Lock(&(ppopupmenu->spwndPopupMenu), pwnd);
    ppopupmenu->ppopupmenuRoot = ppopupmenu;

    /*
     * Notify the app we are entering menu mode.  wParam is always 0 since this
     * procedure will only be called for menu bar menus not TrackPopupMenu
     * menus.
     */
    ThreadLockAlways(pwnd, &tlpwnd);
    xxxSendMessage(pwnd, WM_ENTERMENULOOP, 0, 0L);
    ThreadUnlock(&tlpwnd);

    return pMenuState;
}