Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

classchg.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: class.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains RegisterClass and the related window class management 00007 * functions. 00008 * 00009 * History: 00010 * 12-20-94 FritzS 00011 * 00012 \***************************************************************************/ 00013 00014 #include "precomp.h" 00015 #pragma hdrstop 00016 00017 BOOL VisWindow(PWND,DWORD); 00018 00019 00020 /***************************************************************************\ 00021 * xxxSetClassIconEnum 00022 * 00023 * 00024 \***************************************************************************/ 00025 00026 BOOL xxxSetClassIconEnum( 00027 PWND pwnd, 00028 LPARAM lParam) 00029 { 00030 CheckLock(pwnd); 00031 00032 if (pwnd->pcls == (PCLS)lParam) { 00033 /* 00034 * If the window doesn't have a small icon or it comes from 00035 * WM_QUERYDRAGICON, redraw the title. In the WM_QUERYDRAGICON 00036 * case, get rid of the small icon so redrawing the title will 00037 * create it if necessary. 00038 */ 00039 if (TestWF(pwnd, WFSMQUERYDRAGICON)) 00040 DestroyWindowSmIcon(pwnd); 00041 00042 if (!_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp),PROPF_INTERNAL)) 00043 xxxRedrawTitle(pwnd, DC_ICON); 00044 } 00045 00046 return TRUE; 00047 } 00048 00049 /***************************************************************************\ 00050 * SetClassIcon 00051 * 00052 * Changes the big/small icon of a class. Called from SetClassWord(). 00053 * 00054 \***************************************************************************/ 00055 00056 PCURSOR xxxSetClassIcon( 00057 PWND pwnd, 00058 PCLS pcls, 00059 PCURSOR pCursor, 00060 int gcw) 00061 { 00062 PTHREADINFO pti = PtiCurrent(); 00063 PCURSOR pCursorOld; 00064 HCURSOR hCursorOld; 00065 TL tlpwndChild; 00066 BOOL fRedraw; 00067 00068 CheckLock(pwnd); 00069 00070 /* 00071 * Save old icon 00072 */ 00073 pCursorOld = ((gcw == GCLP_HICON) ? pcls->spicn : pcls->spicnSm); 00074 00075 if (pCursorOld != pCursor) { 00076 00077 fRedraw = TRUE; 00078 00079 hCursorOld = PtoH(pCursorOld); 00080 00081 /* 00082 * Set new icon 00083 */ 00084 if (gcw == GCLP_HICON) { 00085 00086 /* 00087 * Destroy private cached small icon first. 00088 */ 00089 if (pcls->spicnSm && !DestroyClassSmIcon(pcls)) 00090 fRedraw = FALSE; 00091 00092 Lock(&(pcls->spicn), pCursor); 00093 00094 } else { 00095 00096 /* 00097 * We don't allow apps to see the small icons we create from 00098 * their big icons. They can see their own. Saves memory 00099 * leak problems and is easier. 00100 */ 00101 if (pcls->CSF_flags & CSF_CACHEDSMICON) { 00102 DestroyClassSmIcon(pcls); 00103 hCursorOld = NULL; 00104 } 00105 00106 Lock(&(pcls->spicnSm), pCursor); 00107 } 00108 00109 if (pcls->spicn && !pcls->spicnSm) 00110 xxxCreateClassSmIcon(pcls); 00111 00112 if (fRedraw) { 00113 00114 if (pcls->cWndReferenceCount > 1) { 00115 ThreadLock(pti->rpdesk->pDeskInfo->spwnd->spwndChild, &tlpwndChild); 00116 xxxInternalEnumWindow(pti->rpdesk->pDeskInfo->spwnd->spwndChild, 00117 xxxSetClassIconEnum, 00118 (LPARAM)pcls, 00119 BWL_ENUMLIST); 00120 ThreadUnlock(&tlpwndChild); 00121 } else { 00122 xxxSetClassIconEnum(pwnd, (LPARAM)pcls); 00123 } 00124 } 00125 00126 /* 00127 * Revalidate the old cursor 00128 */ 00129 if (hCursorOld != NULL) { 00130 pCursorOld = HMRevalidateHandleNoRip(hCursorOld); 00131 } else { 00132 pCursorOld = NULL; 00133 } 00134 } 00135 00136 return(pCursorOld); 00137 } 00138 00139 /***************************************************************************\ 00140 * DestroyClassSmIcon() 00141 * 00142 * Destroys the small icon of a class if we've created a cached one. 00143 * 00144 \***************************************************************************/ 00145 00146 BOOL DestroyClassSmIcon( 00147 PCLS pcls) 00148 { 00149 00150 /* 00151 * If we don't have a cached icon, then no work. 00152 */ 00153 if (pcls->CSF_flags & CSF_CACHEDSMICON) { 00154 if (pcls->spicnSm) { 00155 _DestroyCursor(pcls->spicnSm, CURSOR_ALWAYSDESTROY); 00156 Unlock(&pcls->spicnSm); 00157 } 00158 pcls->CSF_flags &= ~CSF_CACHEDSMICON; 00159 return TRUE; 00160 } 00161 00162 return FALSE; 00163 } 00164 00165 /***************************************************************************\ 00166 * xxxCreateClassSmIcon 00167 * 00168 * Creates a cached class small icon from a class big icon. 00169 * 00170 \***************************************************************************/ 00171 00172 VOID xxxCreateClassSmIcon( 00173 PCLS pcls) 00174 { 00175 PCURSOR pcur; 00176 00177 UserAssert(pcls->cWndReferenceCount > 0); 00178 UserAssert(pcls->spicn); 00179 UserAssert(!pcls->spicnSm); 00180 00181 pcur = xxxClientCopyImage(PtoH(pcls->spicn), 00182 pcls->spicn->rt == PTR_TO_ID(RT_ICON) ? IMAGE_ICON : IMAGE_CURSOR, 00183 SYSMET(CXSMICON), 00184 SYSMET(CYSMICON), 00185 LR_DEFAULTCOLOR | LR_COPYFROMRESOURCE); 00186 00187 Lock(&pcls->spicnSm, pcur); 00188 if (pcls->spicnSm) 00189 pcls->CSF_flags |= CSF_CACHEDSMICON; 00190 } 00191 00192 /***************************************************************************\ 00193 * SetWindowStyle 00194 * 00195 * Changes the style bits of a window. Called from SetWindowLong(). This 00196 * sends two messages, a changing and a changed. Upon receipt of a 00197 * WM_STYLECHANGING message, a window can muck with the style bits for 00198 * validation purposes. The WM_STYLECHANGED message is simply after the 00199 * fact. 00200 * 00201 \***************************************************************************/ 00202 00203 LONG xxxSetWindowStyle( 00204 PWND pwnd, 00205 int gwl, 00206 DWORD styleNew) 00207 { 00208 STYLESTRUCT sty; 00209 BOOL fWasChild; 00210 BOOL fIsChild; 00211 00212 CheckLock(pwnd); 00213 UserAssert(IsWinEventNotifyDeferredOK()); 00214 00215 /* 00216 * HACK-O-RAMA 00217 * A STYLESTRUCT currently has just one field: a DWORD for the style. 00218 * Therefore, conveniently, we can pass a pointer into the stack for 00219 * LPARAM. But, if we add stuff, we'll have to change this. 00220 */ 00221 sty.styleOld = ((gwl == GWL_STYLE) ? pwnd->style : pwnd->ExStyle); 00222 sty.styleNew = styleNew; 00223 00224 /* 00225 * Note that we don't do validation before _and_ after. It is sufficient 00226 * to do our stuff at the end. 00227 */ 00228 00229 /* 00230 * We break Quicken 2.0 if we send the messages. That's why we version 00231 * switch them. 00232 */ 00233 00234 /* 00235 * Send a WM_STYLECHANGING message to the window, so it can muck with 00236 * the style bits. Like validate some stuff. 00237 */ 00238 if (TestWF(pwnd, WFWIN40COMPAT)) { 00239 xxxSendMessage(pwnd, WM_STYLECHANGING, gwl, (LPARAM)(LPSTYLESTRUCT)&sty); 00240 } 00241 00242 /* 00243 * Now do our own validation. 00244 */ 00245 if (gwl == GWL_STYLE) { 00246 00247 BOOL fWasVisWindow; 00248 00249 /* 00250 * If this is an edit control that has ES_PASSWORD set and 00251 * the caller does not own it and is trying to reset it, 00252 * fail the call. 00253 */ 00254 if ((PpiCurrent() != GETPTI(pwnd)->ppi) && 00255 (GETFNID(pwnd) == FNID_EDIT) && 00256 (sty.styleOld & ES_PASSWORD) && 00257 !(sty.styleNew & ES_PASSWORD)) { 00258 RIPERR0(ERROR_ACCESS_DENIED, 00259 RIP_WARNING, 00260 "Access denied in xxxSetWindowStyle"); 00261 00262 return 0; 00263 } 00264 00265 /* Listbox ownerdraw style check was moved to the client side (client\ntstubs.c) */ 00266 00267 /* 00268 * Do proper validation on style bits 00269 */ 00270 if (pwnd->spwndParent == PWNDDESKTOP(pwnd)) 00271 sty.styleNew |= WS_CLIPSIBLINGS; 00272 00273 /* 00274 * If the clipping-ness is changing, invalidate the dc cache. 00275 */ 00276 if ((sty.styleNew & (WS_CLIPCHILDREN | WS_CLIPSIBLINGS)) != 00277 (sty.styleOld & (WS_CLIPCHILDREN | WS_CLIPSIBLINGS))) { 00278 00279 /* 00280 * No need to DeferWinEventNotify() - pwnd is locked 00281 */ 00282 zzzInvalidateDCCache(pwnd, IDC_DEFAULT); 00283 } 00284 00285 /* 00286 * This breaks all Paradox dialogs 1.0-5.0 that have combos. They 00287 * enumerate all child windows, add on minimized, then sit in a peek 00288 * loop. After that they enumerate all child windows and remove 00289 * WS_MINIMIZE--except the code below won't let them. 00290 * 00291 * Result is weird painting and an inability to use the dialog any 00292 * more short of dismissing it 00293 * 00294 * Temp fix: Check for child window first. 00295 */ 00296 00297 /* 00298 * if this window is REALLY minimized (minimized bit is set and caption 00299 * present bit is removed), then don't allow app to remove the minimize 00300 * bit -- this fixes FoxBlow's attempt at being the OS -- jeffbog 00301 */ 00302 if (!TestWF(pwnd, WFCHILD) && 00303 TestWF(pwnd, WFMINIMIZED) && 00304 !TestWF(pwnd, WFCPRESENT) && 00305 !(sty.styleNew & WS_MINIMIZE)) { 00306 00307 sty.styleNew |= WS_MINIMIZE; 00308 } 00309 00310 /* 00311 * If we're changing the child bit, deal with spmenu appropriately. 00312 * If we're turning into a child, change spmenu to an id. If we're 00313 * turning into a top level window, turn spmenu into a menu. 00314 */ 00315 fWasChild = TestwndChild(pwnd); 00316 00317 pwnd->style = sty.styleNew; 00318 00319 fIsChild = TestwndChild(pwnd); 00320 00321 /* 00322 * If we turned into a top level window, change spmenu to NULL. 00323 * If we turned into a child from a top level window, unlock spmenu. 00324 */ 00325 if (fWasChild && !fIsChild) 00326 pwnd->spmenu = NULL; 00327 00328 if (!fWasChild && fIsChild) { 00329 ClrWF(pwnd, WFMPRESENT); 00330 UnlockWndMenu(pwnd, &pwnd->spmenu); 00331 } 00332 00333 /* 00334 * If the visible, child, or minimized style is changing, 00335 * then update the cVisWindows count 00336 */ 00337 fWasVisWindow = VisWindow(pwnd, sty.styleOld); 00338 if (fWasVisWindow != VisWindow(pwnd, sty.styleNew)) 00339 { 00340 00341 #if DBG 00342 if (TestWF(pwnd, WFINDESTROY)) { 00343 RIPMSG1(RIP_ERROR, "xxxSetWindowStyle: window INDESTROY 0x%08X", pwnd); 00344 } 00345 #endif 00346 00347 // IncDecVisWindows(pwnd, !fWasVisWindow); 00348 if (fWasVisWindow) 00349 DecVisWindows(pwnd); 00350 else 00351 IncVisWindows(pwnd); 00352 } 00353 } else { 00354 /* 00355 * First, see if the app might be setting bits that it really 00356 * doesn't know about. If so, replace those bits with the 00357 * current values. 00358 */ 00359 if (GetAppCompatFlags2(VER40) & GACF2_NO50EXSTYLEBITS) { 00360 sty.styleNew &= WS_EX_VALID40; 00361 } else { 00362 /* 00363 * Don't let aplications set unused extended bits 00364 * Mcostea #237449 00365 */ 00366 #if DBG 00367 if (sty.styleNew & ~WS_EX_ALLVALID) { 00368 RIPMSG0(RIP_WARNING, "Trying to set reserved exStyle bits in SetWindowLong"); 00369 } 00370 #endif 00371 sty.styleNew &= WS_EX_ALLVALID; 00372 } 00373 /* 00374 * Is someone trying to toggle the WS_EX_TOPMOST style bit? 00375 */ 00376 if ((sty.styleOld & WS_EX_TOPMOST) != (sty.styleNew & WS_EX_TOPMOST)) { 00377 00378 #if DBG 00379 /* 00380 * Rip in debug about this 00381 */ 00382 RIPMSG0(RIP_WARNING, "Can't change WS_EX_TOPMOST with SetWindowLong"); 00383 #endif 00384 00385 /* 00386 * BACKWARDS COMPATIBILITY HACK 00387 * If stuff is getting stored in the high word, then it must be 00388 * Lotus 123-W sticking a FAR pointer in this field. So don't 00389 * modify it. 00390 */ 00391 if (TestWF(pwnd, WFWIN40COMPAT) || !HIWORD(sty.styleNew)) { 00392 00393 /* 00394 * Don't let the bit be flipped 00395 */ 00396 sty.styleNew &= ~WS_EX_TOPMOST; 00397 sty.styleNew |= (sty.styleOld & WS_EX_TOPMOST); 00398 } 00399 } 00400 00401 { 00402 /* 00403 * Check pwnd->ExStyle directly since sty.styleOld can now be 00404 * different from the real state of the window, because of the 00405 * callbacks in this function from the time sty.styleOld was 00406 * remembered and up to now. We must call the layering functions 00407 * based on the real state of the layering bit. 00408 */ 00409 BOOL fWasSprite = (pwnd->ExStyle & WS_EX_LAYERED); 00410 BOOL fSprite = (sty.styleNew & WS_EX_LAYERED); 00411 00412 if (fWasSprite && !fSprite) { 00413 if (!UnsetLayeredWindow(pwnd)) { 00414 return 0; 00415 } 00416 } else if (!fWasSprite && fSprite) { 00417 if (!xxxSetLayeredWindow(pwnd, TRUE)) { 00418 return 0; 00419 } 00420 } 00421 } 00422 00423 #ifdef REDIRECTION 00424 { 00425 BOOL fWasRedirected = (pwnd->ExStyle & WS_EX_REDIRECTED); 00426 BOOL fRedirected = (sty.styleNew & WS_EX_REDIRECTED); 00427 00428 if (fWasRedirected && !fRedirected) { 00429 if (!UnsetRedirectedWindow(pwnd)) { 00430 return 0; 00431 } 00432 } else if (!fWasRedirected && fRedirected) { 00433 if (!SetRedirectedWindow(pwnd)) { 00434 return 0; 00435 } 00436 } 00437 } 00438 #endif // REDIRECTION 00439 00440 /* 00441 * The bits we use internally should be preserved 00442 */ 00443 pwnd->ExStyle = sty.styleNew | (sty.styleOld & ~WS_EX_ALLVALID); 00444 if ((sty.styleOld ^ sty.styleNew) 00445 & (WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LAYOUTRTL)) { 00446 xxxRedrawFrame(pwnd); 00447 } 00448 } 00449 00450 /* 00451 * See if we still need the 3D edge since the window styles changed. 00452 */ 00453 if (NeedsWindowEdge(pwnd->style, pwnd->ExStyle, TestWF(pwnd, WFWIN40COMPAT))) 00454 SetWF(pwnd, WEFWINDOWEDGE); 00455 else 00456 ClrWF(pwnd, WEFWINDOWEDGE); 00457 00458 /* 00459 * Send a WM_STYLECHANGED message 00460 */ 00461 if (TestWF(pwnd, WFWIN40COMPAT)) 00462 xxxSendMessage(pwnd, WM_STYLECHANGED, gwl, (LPARAM)(LPSTYLESTRUCT)&sty); 00463 00464 return(sty.styleOld); 00465 } 00466 00467 /***************************************************************************\ 00468 * VisWindow 00469 * 00470 * Based on style, determines if this is considered to be "visible" by 00471 * queue foreground styles. 00472 * 00473 \***************************************************************************/ 00474 00475 BOOL VisWindow( 00476 PWND pwnd, 00477 DWORD style) 00478 { 00479 return(FTopLevel(pwnd) && 00480 !(style & WS_MINIMIZE) && 00481 (style & WS_VISIBLE)); 00482 }

Generated on Sat May 15 19:39:24 2004 for test by doxygen 1.3.7