/****************************** Module Header ******************************\ * Module Name: class.c * * Copyright (c) 1985-91, 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(DWORD); /***************************************************************************\ * xxxSetClassIconEnum * * \***************************************************************************/ BOOL xxxSetClassIconEnum( PWND pwnd, LPARAM lParam) { 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; TL tlpwndChild; BOOL fRedraw; /* * Save old icon */ pCursorOld = ((gcw == GCL_HICON) ? pcls->spicn : pcls->spicnSm); if (pCursorOld != pCursor) { fRedraw = TRUE; /* * Set new icon */ if (gcw == GCL_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 (TestCF2(pcls, CFCACHEDSMICON)) { DestroyClassSmIcon(pcls); pCursorOld = 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, (WNDENUMPROC_PWND)xxxSetClassIconEnum, (LONG)pcls, BWL_ENUMLIST); ThreadUnlock(&tlpwndChild); } else { xxxSetClassIconEnum(pwnd, (LONG)pcls); } } } 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 (TestCF2(pcls, CFCACHEDSMICON)) { if (pcls->spicnSm) { _DestroyCursor(pcls->spicnSm, CURSOR_ALWAYSDESTROY); Unlock(&pcls->spicnSm); } ClrCF2(pcls, CFCACHEDSMICON); 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 == (WORD)RT_ICON ? IMAGE_ICON : IMAGE_CURSOR, SYSMET(CXSMICON), SYSMET(CYSMICON), LR_DEFAULTCOLOR | LR_COPYFROMRESOURCE); Lock(&pcls->spicnSm, pcur); if (pcls->spicnSm) SetCF2(pcls, CFCACHEDSMICON); } /***************************************************************************\ * SetWindowStyle * * 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; BOOL fIsChild; /* * HACK-O-RAMA * A STYLESTRUCT currently has just one field: a DWORD for the style. * Therefore, conveniently, we can pass a pointer into the stack for * LPARAM. But, if we add stuff, we'll have to change this. */ 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) && (GETFNID(pwnd) == FNID_EDIT) && (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))) { InvalidateDCCache(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); Unlock(&pwnd->spmenu); } /* * If the visible, child, or minimized style is changing, * then update the cVisWindows count */ fWasVisWindow = VisWindow(sty.styleOld); if (fWasVisWindow != VisWindow(sty.styleNew)) { // IncDecVisWindows(pwnd, !fWasVisWindow); if (fWasVisWindow) DecVisWindows(pwnd); else IncVisWindows(pwnd); } } else { /* * Is someone trying to toggle the WS_EX_TOPMOST style bit? */ if ((sty.styleOld & WS_EX_TOPMOST) != (sty.styleNew & WS_EX_TOPMOST)) { #ifdef DEBUG /* * Rip in debug about this */ RIPMSG0(RIP_WARNING, "Can't change WS_EX_TOPMOST with SetWindowLong"); #endif /* * 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); } } pwnd->ExStyle = sty.styleNew; } /* * 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( DWORD style) { return(((style & (WS_POPUP | WS_CHILD)) != WS_CHILD) && !(style & WS_MINIMIZE) && (style & WS_VISIBLE)); }