|
|
/****************************** Module Header ******************************\
* Module Name: class.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * This module contains RegisterClass and the related window class management * functions. * * History: * 12-20-94 FritzS * \***************************************************************************/
#include "precomp.h"
#pragma hdrstop
BOOL VisWindow(PWND,DWORD);
/***************************************************************************\
* xxxSetClassIconEnum \***************************************************************************/ BOOL xxxSetClassIconEnum( PWND pwnd, LPARAM lParam) { CheckLock(pwnd);
if (pwnd->pcls == (PCLS)lParam) { /*
* If the window doesn't have a small icon or it comes from * WM_QUERYDRAGICON, redraw the title. In the WM_QUERYDRAGICON * case, get rid of the small icon so redrawing the title will * create it if necessary. */ if (TestWF(pwnd, WFSMQUERYDRAGICON)) { DestroyWindowSmIcon(pwnd); }
if (!_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp),PROPF_INTERNAL)) { xxxRedrawTitle(pwnd, DC_ICON); } }
return TRUE; }
/***************************************************************************\
* SetClassIcon * * Changes the big/small icon of a class. Called from SetClassWord(). \***************************************************************************/ PCURSOR xxxSetClassIcon( PWND pwnd, PCLS pcls, PCURSOR pCursor, int gcw) { PTHREADINFO pti = PtiCurrent(); PCURSOR pCursorOld; HCURSOR hCursorOld; TL tlpwndChild; BOOL fRedraw;
CheckLock(pwnd);
/*
* Save old icon. */ pCursorOld = ((gcw == GCLP_HICON) ? pcls->spicn : pcls->spicnSm); if (pCursorOld != pCursor) { fRedraw = TRUE;
hCursorOld = PtoH(pCursorOld);
/*
* Set new icon. */ if (gcw == GCLP_HICON) { /*
* Destroy private cached small icon first. */ if (pcls->spicnSm && !DestroyClassSmIcon(pcls)) { fRedraw = FALSE; }
Lock(&(pcls->spicn), pCursor);
} else {
/*
* We don't allow apps to see the small icons we create from * their big icons. They can see their own. Saves memory * leak problems and is easier. */ if (pcls->CSF_flags & CSF_CACHEDSMICON) { DestroyClassSmIcon(pcls); hCursorOld = NULL; }
Lock(&(pcls->spicnSm), pCursor); }
if (pcls->spicn && !pcls->spicnSm) { xxxCreateClassSmIcon(pcls); }
if (fRedraw) { if (pcls->cWndReferenceCount > 1) { ThreadLock(pti->rpdesk->pDeskInfo->spwnd->spwndChild, &tlpwndChild); xxxInternalEnumWindow(pti->rpdesk->pDeskInfo->spwnd->spwndChild, xxxSetClassIconEnum, (LPARAM)pcls, BWL_ENUMLIST); ThreadUnlock(&tlpwndChild); } else { xxxSetClassIconEnum(pwnd, (LPARAM)pcls); } }
/*
* Revalidate the old cursor */ if (hCursorOld != NULL) { pCursorOld = HMRevalidateHandleNoRip(hCursorOld); } else { pCursorOld = NULL; } }
return pCursorOld; }
/***************************************************************************\
* DestroyClassSmIcon * * Destroys the small icon of a class if we've created a cached one. \***************************************************************************/ BOOL DestroyClassSmIcon( PCLS pcls) { /*
* If we don't have a cached icon, then no work. */ if (pcls->CSF_flags & CSF_CACHEDSMICON) { if (pcls->spicnSm) { _DestroyCursor(pcls->spicnSm, CURSOR_ALWAYSDESTROY); Unlock(&pcls->spicnSm); } pcls->CSF_flags &= ~CSF_CACHEDSMICON; return TRUE; }
return FALSE; }
/***************************************************************************\
* xxxCreateClassSmIcon * * Creates a cached class small icon from a class big icon. \***************************************************************************/ VOID xxxCreateClassSmIcon( PCLS pcls) { PCURSOR pcur;
UserAssert(pcls->cWndReferenceCount > 0); UserAssert(pcls->spicn); UserAssert(!pcls->spicnSm);
pcur = xxxClientCopyImage(PtoH(pcls->spicn), pcls->spicn->rt == PTR_TO_ID(RT_ICON) ? IMAGE_ICON : IMAGE_CURSOR, SYSMET(CXSMICON), SYSMET(CYSMICON), LR_DEFAULTCOLOR | LR_COPYFROMRESOURCE);
Lock(&pcls->spicnSm, pcur); if (pcls->spicnSm) { pcls->CSF_flags |= CSF_CACHEDSMICON; } }
/***************************************************************************\
* xxxSetWindowStyle * * Changes the style bits of a window. Called from SetWindowLong(). This * sends two messages, a changing and a changed. Upon receipt of a * WM_STYLECHANGING message, a window can muck with the style bits for * validation purposes. The WM_STYLECHANGED message is simply after the * fact. \***************************************************************************/ LONG xxxSetWindowStyle( PWND pwnd, int gwl, DWORD styleNew) { STYLESTRUCT sty; BOOL fWasChild, fIsChild, fBefore, fAfter;
CheckLock(pwnd); UserAssert(IsWinEventNotifyDeferredOK());
sty.styleOld = ((gwl == GWL_STYLE) ? pwnd->style : pwnd->ExStyle); sty.styleNew = styleNew;
/*
* Note that we don't do validation before _and_ after. It is sufficient * to do our stuff at the end. */
/*
* We break Quicken 2.0 if we send the messages. That's why we version * switch them. * * Send a WM_STYLECHANGING message to the window, so it can muck with * the style bits. Like validate some stuff. */ if (TestWF(pwnd, WFWIN40COMPAT)) { xxxSendMessage(pwnd, WM_STYLECHANGING, gwl, (LPARAM)(LPSTYLESTRUCT)&sty); }
/*
* Now do our own validation. */ if (gwl == GWL_STYLE) { BOOL fWasVisWindow;
/*
* If this is an edit control that has ES_PASSWORD set and * the caller does not own it and is trying to reset it, * fail the call. */ if (PpiCurrent() != GETPTI(pwnd)->ppi && IS_EDIT(pwnd) && (sty.styleOld & ES_PASSWORD) && !(sty.styleNew & ES_PASSWORD)) { RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, "Access denied in xxxSetWindowStyle"); return 0; }
/* Listbox ownerdraw style check was moved to the client side (client\ntstubs.c) */
/*
* Do proper validation on style bits. */ if (pwnd->spwndParent == PWNDDESKTOP(pwnd)) { sty.styleNew |= WS_CLIPSIBLINGS; }
/*
* If the clipping-ness is changing, invalidate the dc cache. */ if ((sty.styleNew & (WS_CLIPCHILDREN | WS_CLIPSIBLINGS)) != (sty.styleOld & (WS_CLIPCHILDREN | WS_CLIPSIBLINGS))) {
/*
* No need to DeferWinEventNotify() - pwnd is locked */ zzzInvalidateDCCache(pwnd, IDC_DEFAULT); }
/*
* This breaks all Paradox dialogs 1.0-5.0 that have combos. They * enumerate all child windows, add on minimized, then sit in a peek * loop. After that they enumerate all child windows and remove * WS_MINIMIZE--except the code below won't let them. * * Result is weird painting and an inability to use the dialog any * more short of dismissing it * * Temp fix: Check for child window first. */
/*
* if this window is REALLY minimized (minimized bit is set and caption * present bit is removed), then don't allow app to remove the minimize * bit -- this fixes FoxBlow's attempt at being the OS -- jeffbog */ if (!TestWF(pwnd, WFCHILD) && TestWF(pwnd, WFMINIMIZED) && !TestWF(pwnd, WFCPRESENT) && !(sty.styleNew & WS_MINIMIZE)) {
sty.styleNew |= WS_MINIMIZE; }
/*
* If we're changing the child bit, deal with spmenu appropriately. * If we're turning into a child, change spmenu to an id. If we're * turning into a top level window, turn spmenu into a menu. */ fWasChild = TestwndChild(pwnd);
pwnd->style = sty.styleNew;
fIsChild = TestwndChild(pwnd);
/*
* If we turned into a top level window, change spmenu to NULL. * If we turned into a child from a top level window, unlock spmenu. */ if (fWasChild && !fIsChild) { pwnd->spmenu = NULL; }
if (!fWasChild && fIsChild) { ClrWF(pwnd, WFMPRESENT); UnlockWndMenu(pwnd, &pwnd->spmenu); }
/*
* If the visible, child, or minimized style is changing, * then update the cVisWindows count */ fWasVisWindow = VisWindow(pwnd, sty.styleOld); if (fWasVisWindow != VisWindow(pwnd, sty.styleNew)) {
if (fWasVisWindow) { DecVisWindows(pwnd); } else { IncVisWindows(pwnd); } } } else { /*
* First, see if the app might be setting bits that it really * doesn't know about. If so, replace those bits with the * current values. */ if (GetAppCompatFlags2(VER40) & GACF2_NO50EXSTYLEBITS) { sty.styleNew &= WS_EX_VALID40; } else { /*
* Don't let aplications set unused extended bits. */ if (sty.styleNew & ~WS_EX_ALLVALID) { RIPMSGF1(RIP_WARNING, "Trying to set reserved exStyle bits 0x%x", sty.styleNew); }
sty.styleNew &= WS_EX_ALLVALID; }
/*
* Is someone trying to toggle the WS_EX_TOPMOST style bit? */ if ((sty.styleOld & WS_EX_TOPMOST) != (sty.styleNew & WS_EX_TOPMOST)) { RIPMSG0(RIP_WARNING, "Can't change WS_EX_TOPMOST with SetWindowLong");
/*
* BACKWARDS COMPATIBILITY HACK * If stuff is getting stored in the high word, then it must be * Lotus 123-W sticking a FAR pointer in this field. So don't * modify it. */ if (TestWF(pwnd, WFWIN40COMPAT) || !HIWORD(sty.styleNew)) { /*
* Don't let the bit be flipped. */ sty.styleNew &= ~WS_EX_TOPMOST; sty.styleNew |= (sty.styleOld & WS_EX_TOPMOST); } }
/*
* Check pwnd->ExStyle directly since sty.styleOld can now be * different from the real state of the window, because of the * callbacks in this function from the time sty.styleOld was * remembered and up to now. We must call the layering functions * based on the real state of the layering bit. */ fBefore = (pwnd->ExStyle & WS_EX_LAYERED); fAfter = (sty.styleNew & WS_EX_LAYERED);
if (fBefore && !fAfter) { UnsetLayeredWindow(pwnd); } else if (!fBefore && fAfter) { if (!xxxSetLayeredWindow(pwnd, TRUE)) { return 0; } }
fBefore = (pwnd->ExStyle & WS_EX_COMPOSITED); fAfter = (sty.styleNew & WS_EX_COMPOSITED);
if (!fBefore && fAfter) { /*
* If we are turning WS_EX_COMPOSITED on, none of our parents * should already have WS_EX_COMPOSITED turned on. If any do, * since we were explicitely trying to turn this style on, fail * the call. */
if (GetStyleWindow(pwnd->spwndParent, WEFCOMPOSITED) != NULL) { return 0; } }
if (fBefore && !fAfter) { UnsetRedirectedWindow(pwnd, REDIRECT_COMPOSITED); } else if (!fBefore && fAfter) { if (!SetRedirectedWindow(pwnd, REDIRECT_COMPOSITED)) { return 0; }
/*
* We have successfully turned WS_EX_COMPOSITED on for ourself, so * need to ensure that none of our child have WS_EX_COMPOSITED also * turned on. */
xxxTurnOffCompositing(pwnd, TRUE); }
#ifdef REDIRECTION
{
BOOL fVisrgnChange = FALSE; fBefore = (pwnd->ExStyle & WS_EX_EXTREDIRECTED); fAfter = (sty.styleNew & WS_EX_EXTREDIRECTED);
if (fBefore && !fAfter) { UnsetRedirectedWindow(pwnd, REDIRECT_EXTREDIRECTED); fVisrgnChange = TRUE; } else if (!fBefore && fAfter) { if (!SetRedirectedWindow(pwnd, REDIRECT_EXTREDIRECTED)) { return 0; } fVisrgnChange = TRUE; }
if (fVisrgnChange) { BEGINATOMICCHECK(); zzzInvalidateDCCache(pwnd, IDC_DEFAULT | IDC_NOMOUSE); ENDATOMICCHECK(); } } #endif
/*
* The bits we use internally should be preserved */ pwnd->ExStyle = sty.styleNew | (pwnd->ExStyle & ~WS_EX_ALLVALID); if ((sty.styleOld ^ sty.styleNew) & (WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LAYOUTRTL)) { xxxRedrawFrame(pwnd); } }
/*
* See if we still need the 3D edge since the window styles changed. */ if (NeedsWindowEdge(pwnd->style, pwnd->ExStyle, TestWF(pwnd, WFWIN40COMPAT))) { SetWF(pwnd, WEFWINDOWEDGE); } else { ClrWF(pwnd, WEFWINDOWEDGE); }
/*
* Send a WM_STYLECHANGED message. */ if (TestWF(pwnd, WFWIN40COMPAT)) { xxxSendMessage(pwnd, WM_STYLECHANGED, gwl, (LPARAM)(LPSTYLESTRUCT)&sty); }
return sty.styleOld; }
/***************************************************************************\
* VisWindow * * Based on style, determines if this is considered to be "visible" by * queue foreground styles. \***************************************************************************/ BOOL VisWindow( PWND pwnd, DWORD style) { return (FTopLevel(pwnd) && !(style & WS_MINIMIZE) && (style & WS_VISIBLE)); }
|