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; }
PWND GetTopLevelWindow( PWND pwnd) { if (pwnd != NULL) { while (TestwndChild(pwnd)) pwnd = REBASEPWND(pwnd, spwndParent); } return pwnd; }
BOOL _FChildVisible( PWND pwnd) { while (TestwndChild(pwnd)) { pwnd = REBASEPWND(pwnd, spwndParent); if (pwnd == NULL) break; if (!TestWF(pwnd, WFVISIBLE)) return FALSE; } return TRUE; }
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); }
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; }
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; }
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; }
// -------------------------------------------------------------------------- // // 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); } }
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; }
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); }
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); } } } }
/* * 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); } }
/***************************************************************************\ * * 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); }
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); }
/***************************************************************************\ * 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; }