PWND xxxSetCapture( PWND pwnd) { PQ pq; PWND pwndCaptureOld; HWND hwndCaptureOld; pq = (PQ)PtiCurrent()->pq; /* * Don't allow the app to set capture to a window * from another queue. */ if ((pwnd != NULL) && GETPTI(pwnd)->pq != pq) return NULL; /* * If full screen capture don't allow any other capture */ if (gspwndScreenCapture) return NULL; pwndCaptureOld = pq->spwndCapture; hwndCaptureOld = HW(pwndCaptureOld); xxxCapture(PtiCurrent(), pwnd, CLIENT_CAPTURE); if (hwndCaptureOld != NULL) { if (RevalidateHwnd(hwndCaptureOld)) return pwndCaptureOld; } return NULL; }
HANDLE xxxLoadHmodIndex( int iatom, BOOL bWx86KnownDll) { WCHAR pszLibName[MAX_PATH]; HANDLE hmod; UNICODE_STRING strLibrary; PTHREADINFO ptiCurrent = PtiCurrent(); UserAssert((!gptiRit || gptiRit->ppi != PtiCurrent()->ppi) && "Shouldn't load global hooks on system process - gptiRit->ppi is the system process"); if (iatom >= catomSysTableEntries) { RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Index out of range"); return NULL; } UserGetAtomName(aatomSysLoaded[iatom], pszLibName, sizeof(pszLibName)/sizeof(WCHAR)); /* * Call back the client to load the library. */ RtlInitUnicodeString(&strLibrary, pszLibName); hmod = ClientLoadLibrary(&strLibrary, bWx86KnownDll); if (hmod != NULL) { /* * Check to make sure another thread hasn't loaded this library * while we were outside the critical section. */ if (!TESTHMODLOADED(ptiCurrent, iatom)) { /* * Go ahead and bump the reference count. */ acatomSysUse[iatom]++; SETHMODLOADED(ptiCurrent, iatom, hmod); } else { /* * Another thread loaded it while we were outside the * critical section. Unload it so the system's * reference count is correct. */ ClientFreeLibrary(ptiCurrent->ppi->ahmodLibLoaded[iatom]); } } return hmod; }
void xxxShowTooltip(PTOOLTIPWND pttwnd) { SIZE size; POINT pt; DWORD dwFlags; CheckLock(pttwnd); if (pttwnd->pstr == NULL) return; if (pttwnd->pstr == gszCAPTIONTOOLTIP) { PWND pwnd = PtiCurrent()->rpdesk->spwndTrack; /* * The window text might have changed in callbacks, retrieve it now */ if (TestWF(pwnd, WEFTRUNCATEDCAPTION) && pwnd->strName.Length) { wcsncpycch(gszCAPTIONTOOLTIP, pwnd->strName.Buffer, CAPTIONTOOLTIPLEN-1); gszCAPTIONTOOLTIP[CAPTIONTOOLTIPLEN-1] = 0; } else { return; } } TooltipGetSize(pttwnd, &size); TooltipGetPosition(pttwnd, &size, &pt); dwFlags = SWP_CREATESPB | SWP_SHOWWINDOW | SWP_NOACTIVATE; if (TestEffectUP(TOOLTIPANIMATION)) { dwFlags |= SWP_NOREDRAW; } xxxSetWindowPos((PWND)pttwnd, PWND_TOP, pt.x, pt.y, size.cx, size.cy, dwFlags); }
/***************************************************************************\ * xxxHotTrackMenu * * Hot-track a menu item in the menu bar. \***************************************************************************/ BOOL xxxHotTrackMenu(PWND pwnd, UINT nItem, BOOL fDraw) { PMENU pmenu = pwnd->spmenu; PITEM pItem; HDC hdc; UINT oldAlign; TL tlpmenu; CheckLock(pwnd); /* * The window may have lied about the hit-test code on * WM_NCHITTEST. Make sure it does indeed have a menu. */ if (!TestWF(pwnd, WFMPRESENT) || pmenu == NULL) return FALSE; if (nItem >= pmenu->cItems) { RIPMSG0(RIP_WARNING, "xxxHotTrackMenu: menu too large"); return FALSE; } pItem = &pmenu->rgItems[nItem]; /* * Make sure we draw on the right spot */ ThreadLock(pmenu, &tlpmenu); xxxMNRecomputeBarIfNeeded(pwnd, pmenu); ValidateThreadLocks(NULL, PtiCurrent()->ptl, (ULONG_PTR)&tlpmenu, TRUE); if (fDraw) { if (TestMFS(pItem, MF_GRAYED)) { ThreadUnlock(&tlpmenu); return FALSE; } SetMFS(pItem, MFS_HOTTRACK); } else { ClearMFS(pItem, MFS_HOTTRACK); } hdc = _GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_USESTYLE | DCX_CACHE); GreSelectBrush(hdc, SYSHBR(MENUTEXT)); GreSelectFont(hdc, ghMenuFont); oldAlign = GreGetTextAlign(hdc); if (pmenu->rgItems && TestMFT(pmenu->rgItems, MFT_RIGHTORDER)) GreSetTextAlign(hdc, oldAlign | TA_RTLREADING); /* * When the item is not owner draw, xxxDrawMenuItem does not * call back and does not leave the critical section. */ xxxDrawMenuItem(hdc, pmenu, pItem, 0); GreSetTextAlign(hdc, oldAlign); ThreadUnlock(&tlpmenu); _ReleaseDC(hdc); return TRUE; }
VOID ZapActiveAndFocus(VOID) { PQ pq = PtiCurrent()->pq; Unlock(&pq->spwndActive); Unlock(&pq->spwndFocus); }
BOOL xxxReleaseCapture(VOID) { PTHREADINFO ptiCurrent = PtiCurrent(); /* * If we're releasing the capture from a window during tracking, * cancel tracking first. */ if (ptiCurrent->pmsd != NULL) { /* * Only remove the tracking rectangle if it's * been made visible. */ if (ptiCurrent->TIF_flags & TIF_TRACKRECTVISIBLE) { bSetDevDragRect(gpDispInfo->hDev, NULL, NULL); if (!(ptiCurrent->pmsd->fDragFullWindows)) xxxDrawDragRect(ptiCurrent->pmsd, NULL, DDR_ENDCANCEL); ptiCurrent->TIF_flags &= ~(TIF_TRACKRECTVISIBLE | TIF_MOVESIZETRACKING); } } xxxCapture(ptiCurrent, NULL, NO_CAP_CLIENT); return TRUE; }
VOID xxxDoSyncPaint( PWND pwnd, DWORD flags) { CheckLock(pwnd); /* * If any of our non-clipchildren parents have an update region, don't * do anything. This way we won't redraw our background or frame out * of order, only to have it get obliterated when our parent erases his * background. */ if (ParentNeedsPaint(pwnd)) return; /* * First of all if we are going to be queueing any WM_SYNCPAINT messages * to windows of another thread do it first while the window's update * regions are still in sync. This way there is no chance the update * region will be incorrect (through window movement during callbacks of * the WM_ERASEBKGND|WM_NCPAINT messages). */ DoQueuedSyncPaint(pwnd, flags, PtiCurrent()); xxxInternalDoSyncPaint(pwnd, flags); }
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); }
VOID DestroyThreadsHotKeys() { PHOTKEY *pphk; PHOTKEY phk; PTHREADINFO ptiCurrent = PtiCurrent(); pphk = &gphkFirst; while (*pphk) { if ((*pphk)->pti == ptiCurrent) { phk = *pphk; *pphk = (*pphk)->phkNext; /* * Unlock the object stored here. */ if ((phk->spwnd != PWND_FOCUS) && (phk->spwnd != PWND_INPUTOWNER)) { Unlock(&phk->spwnd); } UserFreePool(phk); } else { pphk = &((*pphk)->phkNext); } } }
/***************************************************************************\ * UpdatePerUserKeyboardIndicators * * Sets the initial keyboard indicators according to the user's profile. * * ASSUMPTIONS: * * 10-14-92 IanJa Created. \***************************************************************************/ VOID UpdatePerUserKeyboardIndicators(PUNICODE_STRING pProfileUserName) { DWORD dw; PQ pq; PTHREADINFO ptiCurrent = PtiCurrent(); pq = ptiCurrent->pq; /* * For terminal server, the client is responsible for synchronizing the * keyboard state. */ if (gbRemoteSession) { return; } /* * Initial Keyboard state (Num-Lock only) */ dw = FastGetProfileIntW(pProfileUserName, PMAP_KEYBOARD, wszInitialKeyboardIndicators, 2); dw &= 0x80000002; /* * The special value 0x80000000 in the registry indicates that the BIOS * settings are to be used as the initial LED state. (This is undocumented) */ if (dw == 0x80000000) { dw = gklpBootTime.LedFlags; } if (dw & 0x02) { SetKeyStateToggle(pq, VK_NUMLOCK); SetAsyncKeyStateToggle(VK_NUMLOCK); SetRawKeyToggle(VK_NUMLOCK); } else { ClearKeyStateToggle(pq, VK_NUMLOCK); ClearAsyncKeyStateToggle(VK_NUMLOCK); ClearRawKeyToggle(VK_NUMLOCK); } /* * Initialize KANA Toggle status */ gfKanaToggle = FALSE; ClearKeyStateToggle(pq, VK_KANA); ClearAsyncKeyStateToggle(VK_KANA); ClearRawKeyToggle(VK_KANA); UpdateKeyLights(FALSE); }
/***************************************************************************\ * PhkNextValid * * This helper routine walk the phkNext chain looking for the next valid * hook (i.e., not marked as destroyed). If the end of the local (or * thread specific) hook chain is reached, then it jumps to the global * (or desktop) chain. * * Once a hook is destroyed, we don't want anymore activity on it; however, * if the hook is locked at destroy time (= someone is calling it), then * we keep it in the list so CallNextHook will work properly * * History: * 03/24/96 GerardoB Moved to rtl and added *Valid stuff. * 01-30-91 DavidPe Created. \***************************************************************************/ PHOOK PhkNextValid(PHOOK phk) { #if DBG int iHook = phk->iHook; #ifdef _USERK_ CheckCritInShared(); #endif #endif do { /* * If this hook is marked as destroyed, it must be either * locked or we should be in the process of destroying it */ UserAssert(!(phk->flags & HF_DESTROYED) || (((PHEAD)phk)->cLockObj != 0) || (phk->flags & HF_INCHECKWHF)); /* * Get the next hook */ if (phk->phkNext != NULL) { phk = REBASEALWAYS(phk, phkNext); } else if (!(phk->flags & HF_GLOBAL)) { #ifdef _USERK_ phk = PtiCurrent()->pDeskInfo->aphkStart[phk->iHook + 1]; #else PCLIENTINFO pci = GetClientInfo(); phk = pci->pDeskInfo->aphkStart[phk->iHook + 1]; /* * If it found a pointer, rebase it. */ if (phk != NULL) { (KPBYTE)phk -= pci->ulClientDelta; } #endif UserAssert((phk == NULL) || (phk->flags & HF_GLOBAL)); } else { return NULL; } /* * If destroyed, keep looking. */ } while ((phk != NULL) && (phk->flags & HF_DESTROYED)); #ifdef _USERK_ DbgValidateHooks(phk, iHook); #endif return phk; }
BOOL _SetTaskmanWindow(PWND pwnd) { PDESKTOPINFO pdeskinfo = GETDESKINFO(PtiCurrent()); if (pwnd != NULL) { // Fail the call if another shell window exists if (pdeskinfo->spwndTaskman != NULL) return(FALSE); } Lock(&pdeskinfo->spwndTaskman, pwnd); return(TRUE); }
BOOL xxxPaintRect( PWND pwndBrush, PWND pwndPaint, HDC hdc, HBRUSH hbr, LPRECT lprc) { POINT ptOrg; CheckLock(pwndBrush); CheckLock(pwndPaint); if (pwndBrush == NULL) { pwndBrush = PtiCurrent()->rpdesk->pDeskInfo->spwnd; } if (pwndBrush == PWNDDESKTOP(pwndBrush)) { GreSetBrushOrg( hdc, 0, 0, &ptOrg); } else { GreSetBrushOrg( hdc, pwndBrush->rcClient.left - pwndPaint->rcClient.left, pwndBrush->rcClient.top - pwndPaint->rcClient.top, &ptOrg); } /* * If hbr < CTLCOLOR_MAX, it isn't really a brush but is one of our * special color values. Translate it to the appropriate WM_CTLCOLOR * message and send it off to get back a real brush. The translation * process assumes the CTLCOLOR*** and WM_CTLCOLOR*** values map directly. */ if (hbr < (HBRUSH)CTLCOLOR_MAX) { hbr = xxxGetControlColor(pwndBrush, pwndPaint, hdc, HandleToUlong(hbr) + WM_CTLCOLORMSGBOX); } FillRect(hdc, lprc, hbr); GreSetBrushOrg(hdc, ptOrg.x, ptOrg.y, NULL); return TRUE; }
HCURSOR _CreateEmptyCursorObject( BOOL fPublic) { PCURSOR pcurT; /* * Create the cursor object. */ pcurT = (PCURSOR)HMAllocObject(fPublic ? NULL : PtiCurrent(), NULL, TYPE_CURSOR, max(sizeof(CURSOR), sizeof(ACON))); return (HCURSOR)PtoH(pcurT); }
/***************************************************************************\ * xxxMessageEvent * * Description: Called when a hooked DDE message is sent or posted. flags * specifies the applicable MF_ flag. This is called in the server side * context of the sender or poster which may or may not be a DDEML process. * pdmhd contains DDE data extracted and copied from the client side. * * History: * 12-1-91 sanfords Created. \***************************************************************************/ VOID xxxMessageEvent( PWND pwndTo, UINT message, WPARAM wParam, LPARAM lParam, DWORD flag, PDDEML_MSG_HOOK_DATA pdmhd) { PEVENT_PACKET pep; PWND pwndFrom; TL tlpep; PTHREADINFO pti; CheckCritIn(); pep = (PEVENT_PACKET)UserAllocPoolWithQuota(sizeof(EVENT_PACKET) - sizeof(DWORD) + sizeof(MONMSGSTRUCT), TAG_DDE8); if (pep == NULL) { return; } pep->EventType = flag; pep->fSense = TRUE; pep->cbEventData = sizeof(MONMSGSTRUCT); #define pmsgs ((MONMSGSTRUCT *)&pep->Data) pmsgs->cb = sizeof(MONMSGSTRUCT); pmsgs->hwndTo = PtoH(pwndTo); pmsgs->dwTime = NtGetTickCount(); pwndFrom = RevalidateHwnd((HWND)wParam); if (pwndFrom != NULL) { pmsgs->hTask = GETPTI(pwndFrom)->pEThread->Cid.UniqueThread; } else { pmsgs->hTask = 0; } pmsgs->wMsg = message; pmsgs->wParam = wParam; pmsgs->lParam = lParam; if (pdmhd != NULL) { pmsgs->dmhd = *pdmhd; } #undef pmsgs pti = PtiCurrent(); ThreadLockPool(pti, pep, &tlpep); xxxCsEvent(pep, sizeof(MONMSGSTRUCT)); ThreadUnlockAndFreePool(pti, &tlpep); }
void xxxInvalidateDesktopOnPaletteChange(PWND pwnd) { PDESKTOP pdesk; PWND pwndShell; TL tlpwndShell; RECT rc; BOOL fRedrawDesktop; CheckLock(pwnd); /* * Invalidate the shell window. */ pdesk = PtiCurrent()->rpdesk; pwndShell = (pdesk) ? pdesk->pDeskInfo->spwndShell : NULL; if (!pwndShell) { fRedrawDesktop = TRUE; rc = gpsi->rcScreen; } else { ThreadLockAlways(pwndShell, &tlpwndShell); xxxRedrawWindow( pwndShell, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); /* * The shell window may not cover all of the desktop. * Invalidate the part of the desktop wallpaper it * doesn't sit over. */ fRedrawDesktop = SubtractRect(&rc, &pwnd->rcWindow, &pwndShell->rcWindow); ThreadUnlock(&tlpwndShell); } /* * Invalidate the desktop window. */ if (fRedrawDesktop) { xxxRedrawWindow( pwnd, &rc, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); } }
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; }
BOOL FCallerOk( PWND pwnd) { PTHREADINFO pti = PtiCurrent(); if ((GETPTI(pwnd)->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) && !(pti->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD))) { return FALSE; } if (GETPTI(pwnd)->pEThread->Cid.UniqueProcess == gpidLogon && pti->pEThread->Cid.UniqueProcess != gpidLogon) { return FALSE; } return TRUE; }
/***************************************************************************\ * xxxCancelMouseMoveTracking * * History * 12/07/96 GerardoB Created \***************************************************************************/ void xxxCancelMouseMoveTracking (DWORD dwDTFlags, PWND pwndTrack, int htEx, DWORD dwDTCancel) { CheckLock(pwndTrack); /* * Hottracking */ if ((dwDTFlags & DF_HOTTRACKING) && (dwDTCancel & DF_HOTTRACKING)) { /* * The current state must be owned by the current queue. * Otherwise, we're about to do an inter-queue cancelation. */ UserAssert(PtiCurrent()->pq == GETPTI(pwndTrack)->pq); xxxHotTrack(pwndTrack, htEx, FALSE); } /* * Tooltips */ if ((dwDTFlags & DF_TOOLTIPSHOWING) && (dwDTCancel & DF_TOOLTIP)) { PTOOLTIPWND pttwnd = (PTOOLTIPWND)PWNDTOOLTIP(pwndTrack); TL tlpwnd; ThreadLockAlways(pttwnd, &tlpwnd); xxxResetTooltip(pttwnd); ThreadUnlock(&tlpwnd); } /* * Mouse Leave */ if ((dwDTFlags & DF_TRACKMOUSELEAVE) && (dwDTCancel & DF_TRACKMOUSELEAVE)) { _PostMessage(pwndTrack, ((htEx == HTCLIENT) ? WM_MOUSELEAVE : WM_NCMOUSELEAVE), 0, 0); } /* * Mouse Hover */ if ((dwDTFlags & DF_TRACKMOUSEHOVER) && (dwDTCancel & DF_TRACKMOUSEHOVER)) { _KillSystemTimer(pwndTrack, IDSYS_MOUSEHOVER); } }
BOOL _UnregisterHotKey( PWND pwnd, int id) { PHOTKEY phk; BOOL fKeysExist; phk = FindHotKey(PtiCurrent(), pwnd, id, 0, 0, TRUE, &fKeysExist); /* * No hotkey to unregister, return FALSE. */ if (phk == NULL) { RIPERR0(ERROR_HOTKEY_NOT_REGISTERED, RIP_VERBOSE, ""); return FALSE; } return TRUE; }
/***************************************************************************\ * MNAllocMenuState * * Allocates and initializes a pMenuState * * 5-21-96 GerardoB Created \***************************************************************************/ PMENUSTATE MNAllocMenuState(PTHREADINFO ptiCurrent, PTHREADINFO ptiNotify, PPOPUPMENU ppopupmenuRoot) { PMENUSTATE pMenuState; UserAssert(PtiCurrent() == ptiCurrent); UserAssert(ptiCurrent->rpdesk == ptiNotify->rpdesk); /* * If gpMenuState is already taken, allocate one. */ if (gfMenuStateInUse) { pMenuState = (PMENUSTATE)UserAllocPoolWithQuota(sizeof(MENUSTATE), TAG_MENUSTATE); if (pMenuState == NULL) { return NULL; } } else { gfMenuStateInUse = TRUE; pMenuState = &gpMenuState; } /* * This is used by IsSomeOneInMenuMode and for debugging purposes */ guMenuStateCount++; /* * Initialize pMenuState. */ RtlZeroMemory(pMenuState, sizeof(*pMenuState)); pMenuState->pGlobalPopupMenu = ppopupmenuRoot; pMenuState->ptiMenuStateOwner = ptiCurrent; UserAssert(ptiCurrent->pMenuState == NULL); ptiCurrent->pMenuState = pMenuState; if (ptiNotify != ptiCurrent) { UserAssert(ptiNotify->pMenuState == NULL); ptiNotify->pMenuState = pMenuState; } return pMenuState; }
VOID UserRedrawDesktop(VOID) { TL tlpwnd; PWND pwndDesk; EnterCrit(); pwndDesk = PtiCurrent()->rpdesk->pDeskInfo->spwnd; ThreadLockAlways(pwndDesk, &tlpwnd); xxxInternalInvalidate(pwndDesk, HRGN_FULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); ThreadUnlock(&tlpwnd); LeaveCrit(); }
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); } } } }
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; }
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; }
VOID xxxInternalDoSyncPaint( PWND pwnd, DWORD flags) { CheckLock(pwnd); /* * Do the paint for this window. */ xxxSimpleDoSyncPaint(pwnd); /* * Normally we like to enumerate all of this window's children and have * them erase their backgrounds synchronously. However, this is a bad * thing to do if the window is NOT CLIPCHLIDREN. Here's the scenario * we want to to avoid: * * 1) Window 'A' is invalidated * 2) 'A' erases itself (or not, doesn't matter) * 3) 'A's children are enumerated and they erase themselves. * 4) 'A' paints over its children (remember, 'A' isn't CLIPCHILDREN) * 5) 'A's children paint but their backgrounds aren't their ERASEBKND * color (because 'A' painted over them) and everything looks like * dirt. */ if ((flags & DSP_ALLCHILDREN) || ((flags & DSP_ENUMCLIPPEDCHILDREN) && TestWF(pwnd, WFCLIPCHILDREN))) { TL tlpwnd; PBWL pbwl; HWND *phwnd; if (pbwl = BuildHwndList(pwnd->spwndChild, BWL_ENUMLIST, NULL)) { PTHREADINFO ptiCurrent = PtiCurrent(); HWND hwnd; /* * If the client dies during a callback, the hwnd list * will be freed in xxxDestroyThreadInfo. */ for (phwnd = pbwl->rghwnd; (hwnd = *phwnd) != (HWND)1; phwnd++) { if (hwnd == NULL) continue; if ((pwnd = (PWND)RevalidateHwnd(hwnd)) == NULL) continue; /* * Note: testing if a window is a child automatically * excludes the desktop window. */ if (TestWF(pwnd, WFCHILD) && (ptiCurrent != GETPTI(pwnd))) { /* * Don't cause any more intertask sendmessages cause it * does bad things to cbt's windowproc hooks. (Due to * SetParent allowing child windows in the topwindow * hierarchy. */ continue; } /* * Note that we pass only certain bits down as we recurse: * the other bits pertain to the current window only. */ ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd); xxxInternalDoSyncPaint(pwnd, flags); ThreadUnlock(&tlpwnd); } FreeHwndList(pbwl); } } }
void xxxEndMenu( PMENUSTATE pMenuState) { BOOL fMenuStateOwner; PPOPUPMENU ppopup; PTHREADINFO ptiCurrent; if ((ppopup = pMenuState->pGlobalPopupMenu) == NULL) { /* * We're not really in menu mode. This can happen * if we are forced out of menu loop too soon; i.e, from * inside xxxMNGetPopup or xxxTrackPopupMenuEx. */ UserAssert(!pMenuState->fInsideMenuLoop && !pMenuState->fMenuStarted); return; } pMenuState->fInsideMenuLoop = FALSE; pMenuState->fMenuStarted = FALSE; /* * Mark the popup as destroyed so people will not use it anymore. * This means that root popups can be marked as destroyed before * actually being destroyed (nice and confusing). */ ppopup->fDestroyed = TRUE; /* * Determine if this is the menu loop owner before calling back. * Only the owner can destroy the menu windows */ ptiCurrent = PtiCurrent(); fMenuStateOwner = (ptiCurrent == pMenuState->ptiMenuStateOwner); /* * Release mouse capture if we got it in xxxStartMenuState */ if (ptiCurrent->pq->spwndCapture == pMenuState->pGlobalPopupMenu->spwndNotify) { xxxMNReleaseCapture(); } /* * Bail if this is not the menu loop owner */ if (!fMenuStateOwner) { RIPMSG1(RIP_WARNING, "xxxEndMenu: Thread %#p doesn't own the menu loop", ptiCurrent); return; } /* * If the menu loop is running on a thread different than the thread * that owns spwndNotify, we can have two threads trying to end * this menu at the same time. */ if (pMenuState->fInEndMenu) { RIPMSG1(RIP_WARNING, "xxxEndMenu: already in EndMenu. pMenuState:%#p", pMenuState); return; } pMenuState->fInEndMenu = TRUE; if (pMenuState->pGlobalPopupMenu->spwndNotify != NULL) { if (!pMenuState->pGlobalPopupMenu->fInCancel) { xxxMNDismiss(pMenuState); } } else { BOOL fTrackedPopup = ppopup->fIsTrackPopup; /* * This should do the same stuff as MenuCancelMenus but not send any * messages... */ xxxMNCloseHierarchy(ppopup, pMenuState); if (fTrackedPopup) { xxxDestroyWindow(ppopup->spwndPopupMenu); } } }
BOOL _TranslateMessage( LPMSG pmsg, UINT flags) { PTHREADINFO pti; UINT wMsgType; WORD *pwParam; int cChar; BOOL fSysKey = FALSE; BOOL bBreak; LPARAM lParam; switch (pmsg->message) { default: return FALSE; case WM_SYSKEYDOWN: /* * HACK carried over from Win3 code: system messages * only get posted during KEYDOWN processing - so * set fSysKey only for WM_SYSKEYDOWN. */ fSysKey = TRUE; /* * Fall thru... */ case WM_SYSKEYUP: case WM_KEYDOWN: case WM_KEYUP: pti = PtiCurrent(); if ((pti->pMenuState != NULL) && (HW(pti->pMenuState->pGlobalPopupMenu->spwndPopupMenu) == pmsg->hwnd)) { flags |= 1; } else { flags &= ~1; } /* * Don't change the contents of the passed in structure. */ lParam = pmsg->lParam; cChar = InternalToUnicode(LOWORD(pmsg->wParam), // virtual key code HIWORD(lParam), // scan code, make/break bit pti->pq->afKeyState, pState, 16, // see init.c flags, &bBreak); /* * LATER 12/7/90 - GregoryW * Note: Win3.x TranslateMessage returns TRUE if ToAscii is called. * Proper behavior is to return TRUE if any translation is * performed by ToAscii. If we have to remain compatible * (even though apps clearly don't currently care about the * return value) then the following return should be changed * to TRUE. If we want the new 32-bit apps to have a meaningful * return value we should leave this as FALSE. * * If console is calling us with the TM_POSTCHARBREAKS flag then we * return FALSE if no char was actually posted * * !!! LATER get console to change so it does not need private API * TranslateMessageEx */ if (!cChar) { if (flags & TM_POSTCHARBREAKS) return FALSE; else return TRUE; } /* * Some translation performed. Figure out what type of * message to post. * */ if (cChar > 0) wMsgType = (fSysKey) ? (UINT)WM_SYSCHAR : (UINT)WM_CHAR; else { wMsgType = (fSysKey) ? (UINT)WM_SYSDEADCHAR : (UINT)WM_DEADCHAR; cChar = -cChar; // want positive value } if (bBreak) { lParam |= 0x80000000; } else { lParam &= ~0x80000000; } pwParam = (WORD *)pState; for ( ; cChar > 0; cChar--) { /* * If this is a multi-character posting, all but the last one * should be marked as fake keystrokes for Console/VDM. */ _PostMessage(PW(pmsg->hwnd), wMsgType, (DWORD)*pwParam, lParam | (cChar > 1 ? FAKE_KEYSTROKE : 0)); *pwParam = 0; // zero out old character pwParam += 1; } return TRUE; } }
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; }
BOOL xxxSendEraseBkgnd( PWND pwnd, HDC hdcBeginPaint, HRGN hrgnUpdate) { PTHREADINFO ptiCurrent; BOOL fErased; HDC hdc; CheckLock(pwnd); /* * For minimized dudes in win3.1, we would've sent an * WM_ICONERASEBKGND and cleared the erase bit. Now that min * windows in 4.0 are all nonclient, don't bother erasing at * all. Pretend like we did. * * NOTE: * For < 4.0 windows, we may have to send a fake WM_ICONERASEKBGND * to keep 'em happy. Saves time not to though. Getting a DC and * sending the message ain't speedy. */ if ((hrgnUpdate == NULL) || TestWF(pwnd, WFMINIMIZED)) return FALSE; /* * If a DC to use was not passed in, get one. * We want one clipped to this window's update region. */ if (hdcBeginPaint == NULL) { hdc = _GetDCEx(pwnd, hrgnUpdate, DCX_USESTYLE | DCX_INTERSECTRGN | DCX_NODELETERGN); } else { hdc = hdcBeginPaint; } /* * If we're send the WM_ERASEBKGND to another process * we need to change the DC owner. * * We'd like to change the owner to pwnd->pti->idProcess, but * GDI won't let us assign ownership back to ourselves later. */ ptiCurrent = PtiCurrent(); if (GETPTI(pwnd)->ppi != ptiCurrent->ppi) GreSetDCOwner(hdc, OBJECT_OWNER_PUBLIC); /* * Send the event to the window. This contains the DC clipped to * the update-region. */ fErased = (BOOL)xxxSendMessage(pwnd, WM_ERASEBKGND, (WPARAM)hdc, 0L); /* * If we've changed the DC owner, change it back to * the current process. */ if (GETPTI(pwnd)->ppi != ptiCurrent->ppi) GreSetDCOwner(hdc, OBJECT_OWNER_CURRENT); /* * If the WM_ERASEBKGND message did not erase the * background, then set this flag to let BeginPaint() * know to ask the caller to do it via the fErase * flag in the PAINTSTRUCT. */ if (!fErased) { SetWF(pwnd, WFERASEBKGND); if (!TestWF(pwnd, WFWIN31COMPAT)) SetWF(pwnd, WFSENDERASEBKGND); } /* * If we got a cache DC in this routine, release it. */ if (hdcBeginPaint == NULL) { ReleaseCacheDC(hdc, TRUE); } return fErased; }