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

statctl.c

Go to the documentation of this file.
00001 /****************************************************************************\ 00002 * 00003 * STATIC.C 00004 * 00005 * Copyright (c) 1985 - 1999, Microsoft Corporation 00006 * 00007 * Static Dialog Controls Routines 00008 * 00009 * 13-Nov-1990 mikeke from win3 00010 * 29-Jan-1991 IanJa StaticPaint -> xxxStaticPaint; partial revalidation 00011 * 01-Nov-1994 ChrisWil merged in Daytona/Chicago w/Ani-Icons. 00012 * 00013 \****************************************************************************/ 00014 00015 #include "precomp.h" 00016 #pragma hdrstop 00017 00018 /* 00019 * Local Routines. 00020 */ 00021 VOID xxxNextAniIconStep(PSTAT); 00022 HANDLE xxxSetStaticImage(PSTAT,HANDLE,BOOL); 00023 VOID xxxStaticLoadImage(PSTAT,LPWSTR); 00024 00025 00026 /* 00027 * Type table. This is used for validation of the 00028 * image-types. For the PPC release we won't support 00029 * the metafile format, but others are OK. 00030 */ 00031 #define IMAGE_STMMAX IMAGE_ENHMETAFILE+1 00032 00033 static BYTE rgbType[IMAGE_STMMAX] = { 00034 SS_BITMAP, // IMAGE_BITMAP 00035 SS_ICON, // IMAGE_CURSOR 00036 SS_ICON, // IMAGE_ICON 00037 SS_ENHMETAFILE // IMAGE_ENHMETAFILE 00038 }; 00039 00040 00041 /* 00042 * LOBYTE of SS_ style is index into this array 00043 */ 00044 #define STK_OWNER 0x00 00045 #define STK_IMAGE 0x01 00046 #define STK_TEXT 0x02 00047 #define STK_GRAPHIC 0x03 00048 #define STK_TYPE 0x03 00049 00050 #define STK_ERASE 0x04 00051 #define STK_USEFONT 0x08 00052 #define STK_USETEXT 0x10 00053 00054 BYTE rgstk[] = { 00055 STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_LEFT 00056 STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_CENTER 00057 STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_RIGHT 00058 STK_IMAGE, // SS_ICON 00059 STK_GRAPHIC, // SS_BLACKRECT 00060 STK_GRAPHIC, // SS_GRAYRECT 00061 STK_GRAPHIC, // SS_WHITERECT 00062 STK_GRAPHIC, // SS_BLACKFRAME 00063 STK_GRAPHIC, // SS_GRAYFRAME 00064 STK_GRAPHIC, // SS_WHITEFRAME 00065 STK_OWNER, // SS_USERITEM 00066 STK_TEXT | STK_USEFONT | STK_USETEXT, // SS_SIMPLE 00067 STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_LEFTNOWORDWRAP 00068 STK_OWNER | STK_USEFONT | STK_USETEXT, // SS_OWNERDRAW 00069 STK_IMAGE, // SS_BITMAP 00070 STK_IMAGE | STK_ERASE, // SS_ENHMETAFILE 00071 STK_GRAPHIC, // SS_ETCHEDHORZ 00072 STK_GRAPHIC, // SS_ETCHEDVERT 00073 STK_GRAPHIC // SS_ETCHEDFRAME 00074 }; 00075 00076 LOOKASIDE StaticLookaside; 00077 00078 /* 00079 * Common macros for image handling. 00080 */ 00081 #define IsValidImage(imageType, realType, max) \ 00082 ((imageType < max) && (rgbType[imageType] == realType)) 00083 00084 00085 /***************************************************************************\ 00086 * 00087 * SetStaticImage() 00088 * 00089 * Sets bitmap/icon of static guy, either in response to a STM_SETxxxx 00090 * message, or at create time. 00091 * 00092 \***************************************************************************/ 00093 00094 HANDLE xxxSetStaticImage( 00095 PSTAT pstat, 00096 HANDLE hImage, 00097 BOOL fDeleteIt) 00098 { 00099 UINT bType; 00100 RECT rc; 00101 RECT rcWindow; 00102 HANDLE hImageOld; 00103 DWORD dwRate; 00104 UINT cicur; 00105 BOOL fAnimated = FALSE; 00106 PWND pwnd = pstat->spwnd; 00107 HWND hwnd = HWq(pwnd); 00108 00109 CheckLock(pwnd); 00110 00111 bType = TestWF(pwnd, SFTYPEMASK); 00112 00113 /* 00114 * If this is an old-ani-icon, then delete its timer. 00115 */ 00116 if ((bType == SS_ICON) && pstat->cicur > 1) { 00117 /* 00118 * Old cursor was an animated cursor, so kill 00119 * the timer that is used to animate it. 00120 */ 00121 NtUserKillTimer(hwnd, IDSYS_STANIMATE); 00122 } 00123 00124 /* 00125 * Initialize the old-image return value. 00126 */ 00127 hImageOld = pstat->hImage; 00128 00129 rc.right = rc.bottom = 0; 00130 00131 if (hImage != NULL) { 00132 00133 switch (bType) { 00134 00135 case SS_ENHMETAFILE: { 00136 /* 00137 * We do NOT resize the window. 00138 */ 00139 rc.right = pwnd->rcClient.right - pwnd->rcClient.left; 00140 rc.bottom = pwnd->rcClient.bottom - pwnd->rcClient.top; 00141 break; 00142 } 00143 00144 case SS_BITMAP: { 00145 00146 BITMAP bmp; 00147 00148 if (GetObject(hImage, sizeof(BITMAP), &bmp)) { 00149 rc.right = bmp.bmWidth; 00150 rc.bottom = bmp.bmHeight; 00151 } 00152 } 00153 break; 00154 00155 case SS_ICON: { 00156 00157 NtUserGetIconSize(hImage, 0, &rc.right, &rc.bottom); 00158 rc.bottom /= 2; 00159 00160 pstat->cicur = 0; 00161 pstat->iicur = 0; 00162 00163 // Perhaps we can do something like shell\cpl\main\mouseptr.c 00164 // here, and make GetCursorFrameInfo obsolete. 00165 if (GetCursorFrameInfo(hImage, NULL, 0, &dwRate, &cicur)) { 00166 fAnimated = (cicur > 1); 00167 pstat->cicur = cicur; 00168 } 00169 } 00170 break; 00171 } 00172 } 00173 00174 pstat->hImage = hImage; 00175 pstat->fDeleteIt = fDeleteIt; 00176 00177 00178 /* 00179 * Resize static to fit. 00180 * Do NOT do this for SS_CENTERIMAGE 00181 */ 00182 if (!TestWF(pwnd, SFCENTERIMAGE)) 00183 { 00184 /* 00185 * Get current window rect in parent's client coordinates. 00186 */ 00187 GetRect(pwnd, &rcWindow, GRECT_WINDOW | GRECT_PARENTCOORDS); 00188 00189 /* 00190 * Get new window dimensions 00191 */ 00192 rc.left = 0; 00193 rc.top = 0; 00194 00195 if (rc.right && rc.bottom) { 00196 _AdjustWindowRectEx(&rc, pwnd->style, FALSE, pwnd->ExStyle); 00197 rc.right -= rc.left; 00198 rc.bottom -= rc.top; 00199 } 00200 00201 rc.left = rcWindow.left; 00202 rc.top = rcWindow.top; 00203 00204 NtUserSetWindowPos( 00205 hwnd, 00206 HWND_TOP, 00207 0, 00208 0, 00209 rc.right, 00210 rc.bottom, 00211 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); 00212 } 00213 00214 if (TestWF(pwnd, WFVISIBLE)) { 00215 NtUserInvalidateRect(hwnd, NULL, TRUE); 00216 UpdateWindow(hwnd); 00217 } 00218 00219 00220 /* 00221 * If this is an aimated-icon, then start the timer for 00222 * the animation sequence. 00223 */ 00224 if(fAnimated) { 00225 // Perhaps we can do something like shell\cpl\main\mouseptr.c 00226 // here, and make GetCursorFrameInfo obsolete. 00227 GetCursorFrameInfo(pstat->hImage, NULL, pstat->iicur, &dwRate, &cicur); 00228 dwRate = max(200, dwRate * 100 / 6); 00229 NtUserSetTimer(hwnd, IDSYS_STANIMATE, dwRate, NULL); 00230 } 00231 00232 return hImageOld; 00233 } 00234 00235 00236 /***************************************************************************\ 00237 * 00238 * StaticLoadImage() 00239 * 00240 * Loads the icon or bitmap from the app's resource file if a name was 00241 * specified in the dialog template. We assume that the name is the name 00242 * of the resource to load. 00243 * 00244 \***************************************************************************/ 00245 00246 VOID xxxStaticLoadImage( 00247 PSTAT pstat, 00248 LPWSTR lpszName) 00249 { 00250 HANDLE hImage = NULL; 00251 PWND pwnd = pstat->spwnd; 00252 00253 CheckLock(pwnd); 00254 00255 if (lpszName && *lpszName) { 00256 00257 /* 00258 * Only try to load the icon/bitmap if the string is non null. 00259 */ 00260 if (*(BYTE FAR *)lpszName == 0xFF) 00261 lpszName = MAKEINTRESOURCE(((LPWORD)lpszName)[1]); 00262 00263 /* 00264 * Load the image. If it can't be found in the app, try the 00265 * display driver. 00266 */ 00267 if (lpszName) { 00268 00269 switch (TestWF(pwnd, SFTYPEMASK)) { 00270 case SS_BITMAP: 00271 00272 /* 00273 * If the window is not owned by the server, first call 00274 * back out to the client. 00275 */ 00276 if (!gfServerProcess && pwnd->hModule) 00277 hImage = LoadBitmap(pwnd->hModule, lpszName); 00278 00279 /* 00280 * If the above didn't load it, try loading it from the 00281 * display driver (hmod == NULL). 00282 */ 00283 if (hImage == NULL) 00284 hImage = LoadBitmap(NULL, lpszName); 00285 break; 00286 00287 case SS_ICON: 00288 if (TestWF(pwnd, SFREALSIZEIMAGE)) { 00289 if (!gfServerProcess && pwnd->hModule) { 00290 hImage = LoadImage(pwnd->hModule, lpszName, IMAGE_ICON, 0, 0, 0); 00291 } 00292 } else { 00293 /* 00294 * If the window is not owned by the server, first call 00295 * back out to the client. Try loading both icons/cursor 00296 * types. 00297 */ 00298 if (!gfServerProcess && pwnd->hModule) { 00299 00300 hImage = LoadIcon(pwnd->hModule, lpszName); 00301 00302 /* 00303 * We will also try to load a cursor-format if the 00304 * window is a 4.0 compatible. Icons/Cursors are really 00305 * the same. We don't do this for 3.x apps for the 00306 * usual compatibility reasons. 00307 */ 00308 if ((hImage == NULL) && TestWF(pwnd, WFWIN40COMPAT)) { 00309 hImage = LoadCursor(pwnd->hModule, lpszName); 00310 } 00311 } 00312 00313 /* 00314 * If the above didn't load it, try loading it from the 00315 * display driver (hmod == NULL). 00316 */ 00317 if (hImage == NULL) { 00318 hImage = LoadIcon(NULL, lpszName); 00319 } 00320 } 00321 00322 break; 00323 } 00324 00325 /* 00326 * Set the image if it was loaded. 00327 */ 00328 if (hImage) 00329 xxxSetStaticImage(pstat, hImage, TRUE); 00330 00331 } 00332 } 00333 } 00334 00335 00336 /***************************************************************************\ 00337 * StaticCallback() 00338 * 00339 * Draws text statics, called by DrawState. 00340 * 00341 * History: 00342 \***************************************************************************/ 00343 00344 BOOL CALLBACK StaticCallback( 00345 HDC hdc, 00346 PWND pwnd, 00347 BOOL fUnused, 00348 int cx, 00349 int cy) 00350 { 00351 UINT style; 00352 LPWSTR lpszName; 00353 RECT rc; 00354 BYTE bType; 00355 00356 UNREFERENCED_PARAMETER(fUnused); 00357 00358 bType = TestWF(pwnd, SFTYPEMASK); 00359 UserAssert(rgstk[bType] & STK_USETEXT); 00360 00361 if (pwnd->strName.Length) { 00362 lpszName = REBASE(pwnd, strName.Buffer); 00363 00364 style = DT_NOCLIP | DT_EXPANDTABS; 00365 00366 if (bType != LOBYTE(SS_LEFTNOWORDWRAP)) { 00367 style |= DT_WORDBREAK; 00368 style |= (UINT)(bType - LOBYTE(SS_LEFT)); 00369 00370 if (TestWF(pwnd, SFEDITCONTROL)) 00371 style |= DT_EDITCONTROL; 00372 } 00373 00374 switch (TestWF(pwnd, SFELLIPSISMASK)) { 00375 case HIBYTE(LOWORD(SS_ENDELLIPSIS)): 00376 style |= DT_END_ELLIPSIS | DT_SINGLELINE; 00377 break; 00378 00379 case HIBYTE(LOWORD(SS_PATHELLIPSIS)): 00380 style |= DT_PATH_ELLIPSIS | DT_SINGLELINE; 00381 break; 00382 00383 case HIBYTE(LOWORD(SS_WORDELLIPSIS)): 00384 style |= DT_WORD_ELLIPSIS | DT_SINGLELINE; 00385 break; 00386 } 00387 00388 if (TestWF(pwnd, SFNOPREFIX)) 00389 style |= DT_NOPREFIX; 00390 00391 if (TestWF(pwnd, SFCENTERIMAGE)) 00392 style |= DT_VCENTER | DT_SINGLELINE; 00393 00394 rc.left = 0; 00395 rc.top = 0; 00396 rc.right = cx; 00397 rc.bottom = cy; 00398 00399 if (TestWF(pwnd, WEFPUIACCELHIDDEN)) { 00400 style |= DT_HIDEPREFIX; 00401 } else if (((PSTATWND)pwnd)->pstat->fPaintKbdCuesOnly) { 00402 style |= DT_PREFIXONLY; 00403 } 00404 00405 DrawTextExW(hdc, lpszName, -1, &rc, (DWORD)style, NULL); 00406 00407 } 00408 00409 return(TRUE); 00410 } 00411 00412 00413 /***************************************************************************\ 00414 * xxxStaticPaint 00415 * 00416 * History: 00417 \***************************************************************************/ 00418 00419 void xxxStaticPaint( 00420 PSTAT pstat, 00421 HDC hdc, 00422 BOOL fClip) 00423 { 00424 PWND pwndParent; 00425 RECT rc; 00426 UINT cmd; 00427 BYTE bType; 00428 BOOL fFont; 00429 HBRUSH hbrControl; 00430 UINT oldAlign; 00431 #ifdef USE_MIRRORING 00432 DWORD dwOldLayout=0; 00433 #endif 00434 00435 HANDLE hfontOld = NULL; 00436 PWND pwnd = pstat->spwnd; 00437 HWND hwnd = HWq(pwnd); 00438 00439 CheckLock(pwnd); 00440 00441 if (TestWF(pwnd, WEFRTLREADING)) 00442 { 00443 oldAlign = GetTextAlign(hdc); 00444 SetTextAlign(hdc, oldAlign | TA_RTLREADING); 00445 } 00446 00447 bType = TestWF(pwnd, SFTYPEMASK); 00448 _GetClientRect(pwnd, &rc); 00449 00450 if (fClip) { 00451 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); 00452 } 00453 00454 fFont = (rgstk[bType] & STK_USEFONT) && (pstat->hFont != NULL); 00455 00456 if (fFont) { 00457 hfontOld = SelectObject(hdc, pstat->hFont); 00458 } 00459 00460 00461 /* 00462 * Send WM_CTLCOLORSTATIC to all statics (even frames) for 1.03 00463 * compatibility. 00464 */ 00465 SetBkMode(hdc, OPAQUE); 00466 hbrControl = GetControlBrush(hwnd, hdc, WM_CTLCOLORSTATIC); 00467 00468 00469 /* 00470 * Do we erase the background? We don't for SS_OWNERDRAW 00471 * and STK_GRAPHIC kind of things. 00472 */ 00473 pwndParent = REBASEPWND(pwnd, spwndParent); 00474 if ((rgstk[bType] & STK_ERASE) && !pstat->fPaintKbdCuesOnly) { 00475 PaintRect(HW(pwndParent), hwnd, hdc, hbrControl, &rc); 00476 } 00477 00478 switch (LOBYTE(bType)) { 00479 case SS_ICON: 00480 00481 if (pstat->hImage) { 00482 00483 int cx; 00484 int cy; 00485 POINT pt; 00486 00487 #ifdef USE_MIRRORING 00488 if (TestWF(pwnd,WEFLAYOUTRTL)) { 00489 dwOldLayout = SetLayoutWidth(hdc, -1, 0); 00490 } 00491 #endif 00492 /* 00493 * Perform the correct rect-setup. 00494 */ 00495 if (TestWF(pwnd,SFCENTERIMAGE)) { 00496 00497 NtUserGetIconSize(pstat->hImage, pstat->iicur, &cx, &cy); 00498 cy >>= 1; 00499 00500 rc.left = (rc.right - cx) / 2; 00501 rc.right = (rc.left + cx); 00502 rc.top = (rc.bottom - cy) / 2; 00503 rc.bottom = (rc.top + cy); 00504 00505 } else { 00506 00507 cx = rc.right - rc.left; 00508 cy = rc.bottom - rc.top; 00509 } 00510 00511 00512 /* 00513 * Output the icon. If it's animated, we indicate 00514 * the step-frame to output. 00515 */ 00516 if (GETFNID(pwndParent) == FNID_DESKTOP) { 00517 SetBrushOrgEx(hdc, 0, 0, &pt); 00518 } else { 00519 SetBrushOrgEx( 00520 hdc, 00521 pwndParent->rcClient.left - pwnd->rcClient.left, 00522 pwndParent->rcClient.top - pwnd->rcClient.top, 00523 &pt); 00524 } 00525 00526 DrawIconEx(hdc, rc.left, rc.top, pstat->hImage, cx, cy, 00527 pstat->iicur, hbrControl, DI_NORMAL); 00528 00529 SetBrushOrgEx(hdc, pt.x, pt.y, NULL); 00530 #ifdef USE_MIRRORING 00531 if (TestWF(pwnd,WEFLAYOUTRTL)) { 00532 SetLayoutWidth(hdc, -1, dwOldLayout); 00533 } 00534 #endif 00535 } else { 00536 00537 /* 00538 * Empty! Need to erase. 00539 */ 00540 PaintRect(HW(pwndParent), hwnd, hdc, hbrControl, &rc); 00541 } 00542 break; 00543 00544 case SS_BITMAP: 00545 00546 if (pstat->hImage) { 00547 00548 BITMAP bmp; 00549 HBITMAP hbmpT; 00550 RECT rcTmp; 00551 BOOL fErase; 00552 00553 00554 /* 00555 * Get the bitmap information. If this fails, then we 00556 * can assume somethings wrong with its format...don't 00557 * draw in this case. 00558 */ 00559 if (GetObject(pstat->hImage, sizeof(BITMAP), &bmp)) { 00560 00561 if (TestWF(pwnd, SFCENTERIMAGE)) { 00562 00563 fErase = ((bmp.bmWidth < rc.right) || 00564 (bmp.bmHeight < rc.bottom)); 00565 00566 rc.left = (rc.right - bmp.bmWidth) >> 1; 00567 rc.right = (rc.left + bmp.bmWidth); 00568 rc.top = (rc.bottom - bmp.bmHeight) >> 1; 00569 rc.bottom = (rc.top + bmp.bmHeight); 00570 00571 } else { 00572 00573 fErase = FALSE; 00574 } 00575 00576 /* 00577 * Select in the bitmap and blt it to the client-surface. 00578 */ 00579 RtlEnterCriticalSection(&gcsHdc); 00580 hbmpT = SelectObject(ghdcBits2, pstat->hImage); 00581 StretchBlt(hdc, rc.left, rc.top, rc.right-rc.left, 00582 rc.bottom-rc.top, ghdcBits2, 0, 0, bmp.bmWidth, 00583 bmp.bmHeight, SRCCOPY|NOMIRRORBITMAP); 00584 00585 /* 00586 * Only need to erase the background if the image is 00587 * centered and it's smaller than the client-area. 00588 */ 00589 if (fErase) { 00590 00591 HBRUSH hbr; 00592 00593 if (hbr = CreateSolidBrush(GetPixel(ghdcBits2, 0, 0))) { 00594 00595 POLYPATBLT PolyData; 00596 00597 ExcludeClipRect(hdc, rc.left, rc.top, 00598 rc.right, rc.bottom); 00599 00600 _GetClientRect(pwnd, &rcTmp); 00601 00602 PolyData.x = 0; 00603 PolyData.y = 0; 00604 PolyData.cx = rcTmp.right; 00605 PolyData.cy = rcTmp.bottom; 00606 PolyData.BrClr.hbr = hbr; 00607 00608 PolyPatBlt(hdc,PATCOPY,&PolyData,1,PPB_BRUSH); 00609 00610 DeleteObject(hbr); 00611 } 00612 } 00613 00614 if (hbmpT) { 00615 SelectObject(ghdcBits2, hbmpT); 00616 } 00617 RtlLeaveCriticalSection(&gcsHdc); 00618 } 00619 } 00620 break; 00621 00622 case SS_ENHMETAFILE: 00623 00624 if (pstat->hImage) { 00625 00626 RECT rcl; 00627 00628 rcl.left = rc.left; 00629 rcl.top = rc.top; 00630 rcl.right = rc.right; 00631 rcl.bottom = rc.bottom; 00632 00633 PlayEnhMetaFile(hdc, pstat->hImage, &rcl); 00634 } 00635 break; 00636 00637 case SS_OWNERDRAW: { 00638 00639 DRAWITEMSTRUCT dis; 00640 00641 dis.CtlType = ODT_STATIC; 00642 dis.CtlID = PtrToUlong(pwnd->spmenu); 00643 dis.itemAction = ODA_DRAWENTIRE; 00644 dis.itemState = (TestWF(pwnd, WFDISABLED) ? ODS_DISABLED : 0); 00645 dis.hwndItem = hwnd; 00646 dis.hDC = hdc; 00647 dis.itemData = 0L; 00648 dis.rcItem = rc; 00649 00650 if (TestWF(pwnd, WEFPUIACCELHIDDEN)) { 00651 dis.itemState |= ODS_NOACCEL; 00652 } 00653 00654 /* 00655 * Send a WM_DRAWITEM message to the parent. 00656 */ 00657 SendMessage(HW(pwndParent), WM_DRAWITEM, (WPARAM)dis.CtlID, (LPARAM)&dis); 00658 } 00659 break; 00660 00661 case SS_LEFT: 00662 case SS_CENTER: 00663 case SS_RIGHT: 00664 case SS_LEFTNOWORDWRAP: 00665 00666 if (pwnd->strName.Length) { 00667 00668 UINT dstFlags; 00669 00670 dstFlags = DST_COMPLEX; 00671 00672 if (TestWF(pwnd, WFDISABLED)) { 00673 #ifdef LATER 00674 if (SYSMET(SLOWMACHINE) && 00675 (GetBkColor(hdc) != SYSRGB(GRAYTEXT))) { 00676 00677 SetTextColor(hdc, SYSRGB(GRAYTEXT)); 00678 } 00679 else 00680 #endif 00681 dstFlags |= DSS_DISABLED; 00682 } 00683 00684 DrawState(hdc, SYSHBR(WINDOWTEXT), 00685 (DRAWSTATEPROC)StaticCallback,(LPARAM)pwnd, (WPARAM)TRUE, 00686 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 00687 dstFlags); 00688 } 00689 break; 00690 00691 case SS_SIMPLE: { 00692 00693 LPWSTR lpName; 00694 UINT cchName; 00695 00696 00697 /* 00698 * The "Simple" bType assumes everything, including the following: 00699 * 1. The Text exists and fits on one line. 00700 * 2. The Static item is always enabled. 00701 * 3. The Static item is never changed to be a shorter string. 00702 * 4. The Parent never responds to the CTLCOLOR message 00703 */ 00704 if (pwnd->strName.Length) { 00705 lpName = REBASE(pwnd, strName.Buffer); 00706 cchName = pwnd->strName.Length / sizeof(WCHAR); 00707 } else { 00708 lpName = (LPWSTR)szNull; 00709 cchName = 0; 00710 } 00711 00712 if (TestWF(pwnd,SFNOPREFIX)) { 00713 ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE | ETO_CLIPPED, 00714 &rc, lpName, cchName, 0L); 00715 } else { 00716 /* 00717 * Use OPAQUE for speed. 00718 */ 00719 DWORD dwFlags; 00720 if (TestWF(pwnd, WEFPUIACCELHIDDEN)) { 00721 dwFlags = DT_HIDEPREFIX; 00722 } else if (pstat->fPaintKbdCuesOnly) { 00723 dwFlags = DT_PREFIXONLY; 00724 } else { 00725 dwFlags = 0; 00726 } 00727 00728 PSMTextOut(hdc, rc.left, rc.top, 00729 lpName, cchName, dwFlags); 00730 } 00731 } 00732 break; 00733 00734 case SS_BLACKFRAME: 00735 cmd = (COLOR_3DDKSHADOW << 3); 00736 goto StatFrame; 00737 00738 case SS_GRAYFRAME: 00739 cmd = (COLOR_3DSHADOW << 3); 00740 goto StatFrame; 00741 00742 case SS_WHITEFRAME: 00743 cmd = (COLOR_3DHILIGHT << 3); 00744 StatFrame: 00745 DrawFrame(hdc, &rc, 1, cmd); 00746 break; 00747 00748 case SS_BLACKRECT: 00749 hbrControl = SYSHBR(3DDKSHADOW); 00750 goto StatRect; 00751 00752 case SS_GRAYRECT: 00753 hbrControl = SYSHBR(3DSHADOW); 00754 goto StatRect; 00755 00756 case SS_WHITERECT: 00757 hbrControl = SYSHBR(3DHILIGHT); 00758 StatRect: 00759 PaintRect(HW(pwndParent), hwnd, hdc, hbrControl, &rc); 00760 break; 00761 00762 case SS_ETCHEDFRAME: 00763 DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT); 00764 break; 00765 } 00766 00767 if (hfontOld) { 00768 SelectObject(hdc, hfontOld); 00769 } 00770 00771 if (TestWF(pwnd, WEFRTLREADING)) { 00772 SetTextAlign(hdc, oldAlign); 00773 } 00774 00775 } 00776 00777 00778 /***************************************************************************\ 00779 * 00780 * StaticRepaint() 00781 * 00782 \***************************************************************************/ 00783 00784 void StaticRepaint( 00785 PSTAT pstat) 00786 { 00787 PWND pwnd = pstat->spwnd; 00788 00789 if (IsVisible(pwnd)) { 00790 00791 HDC hdc; 00792 HWND hwnd = HWq(pwnd); 00793 00794 if (hdc = NtUserGetDC(hwnd)) { 00795 xxxStaticPaint(pstat, hdc, TRUE); 00796 NtUserReleaseDC(hwnd, hdc); 00797 } 00798 } 00799 } 00800 00801 00802 /***************************************************************************\ 00803 * 00804 * StaticNotifyParent() 00805 * 00806 * Sends WM_COMMAND notification messages. 00807 * 00808 \***************************************************************************/ 00809 00810 // LATER mikeke why do we have multiple versions of notifyparent? 00811 00812 LRESULT FAR PASCAL StaticNotifyParent( 00813 PWND pwnd, 00814 PWND pwndParent, 00815 int nCode) 00816 { 00817 LRESULT lret; 00818 TL tlpwndParent; 00819 00820 UserAssert(pwnd); 00821 00822 if (!pwndParent) { 00823 pwndParent = REBASEPWND(pwnd, spwndParent); 00824 } 00825 00826 ThreadLock(pwndParent, &tlpwndParent); 00827 lret = SendMessage(HW(pwndParent), WM_COMMAND, 00828 MAKELONG(PTR_TO_ID(pwnd->spmenu), nCode), (LPARAM)HWq(pwnd)); 00829 ThreadUnlock(&tlpwndParent); 00830 00831 return lret; 00832 } 00833 00834 /***************************************************************************\ 00835 * StaticWndProc 00836 * 00837 * History: 00838 \***************************************************************************/ 00839 00840 LRESULT APIENTRY StaticWndProcWorker( 00841 PWND pwnd, 00842 UINT message, 00843 WPARAM wParam, 00844 LPARAM lParam, 00845 DWORD fAnsi) 00846 { 00847 HWND hwnd = HWq(pwnd); 00848 BYTE bType; 00849 PSTAT pstat; 00850 static BOOL fInit = TRUE; 00851 00852 CheckLock(pwnd); 00853 00854 VALIDATECLASSANDSIZE(pwnd, FNID_STATIC); 00855 INITCONTROLLOOKASIDE(&StaticLookaside, STAT, spwnd, 8); 00856 00857 /* 00858 * If the control is not interested in this message, 00859 * pass it to DefWindowProc. 00860 */ 00861 if (!FWINDOWMSG(message, FNID_STATIC)) 00862 return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); 00863 00864 /* 00865 * Get the pstat for the given window now since we will use it a lot in 00866 * various handlers. This was stored using SetWindowLong(hwnd,0,pstat) when 00867 * we initially created the static control. 00868 */ 00869 pstat = ((PSTATWND)pwnd)->pstat; 00870 00871 /* 00872 * Get the control's type 00873 */ 00874 bType = TestWF(pwnd, SFTYPEMASK); 00875 00876 switch (message) { 00877 case STM_GETICON: 00878 wParam = IMAGE_ICON; 00879 00880 case STM_GETIMAGE: 00881 if (IsValidImage(wParam, bType, IMAGE_STMMAX)) { 00882 return (LRESULT)pstat->hImage; 00883 } 00884 break; 00885 00886 case STM_SETICON: 00887 lParam = (LPARAM)wParam; 00888 wParam = IMAGE_ICON; 00889 00890 case STM_SETIMAGE: 00891 if (IsValidImage(wParam, bType, IMAGE_STMMAX)) { 00892 return (LRESULT)xxxSetStaticImage(pstat, (HANDLE)lParam, FALSE); 00893 } 00894 break; 00895 00896 case WM_ERASEBKGND: 00897 00898 /* 00899 * The control will be erased in xxxStaticPaint(). 00900 */ 00901 return TRUE; 00902 00903 case WM_PRINTCLIENT: 00904 xxxStaticPaint(pstat, (HDC)wParam, FALSE); 00905 break; 00906 00907 case WM_PAINT: 00908 { 00909 HDC hdc; 00910 PAINTSTRUCT ps; 00911 00912 if ((hdc = (HDC)wParam) == NULL) { 00913 hdc = NtUserBeginPaint(hwnd, &ps); 00914 } 00915 00916 if (IsVisible(pwnd)) { 00917 xxxStaticPaint(pstat, hdc, !wParam); 00918 } 00919 00920 /* 00921 * If hwnd was destroyed, BeginPaint was automatically undone. 00922 */ 00923 if (!wParam) { 00924 NtUserEndPaint(hwnd, &ps); 00925 } 00926 } 00927 break; 00928 00929 case WM_CREATE: 00930 00931 if ((rgstk[bType] & STK_TYPE) == STK_IMAGE) { 00932 /* 00933 * Pull the name from LPCREATESTRUCT like Win95 does 00934 */ 00935 LPWSTR lpszName; 00936 LPSTR lpszAnsiName; 00937 struct { 00938 WORD tag; 00939 BYTE ordLo; 00940 BYTE ordHi; 00941 } dwUnicodeOrdinal; 00942 00943 if (fAnsi) { 00944 /* 00945 * Convert the ANSI string to unicode if it exists 00946 */ 00947 lpszAnsiName = (LPSTR)((LPCREATESTRUCT)lParam)->lpszName; 00948 if (lpszAnsiName) { 00949 if (lpszAnsiName[0] == (CHAR)0xff) { 00950 /* 00951 * Convert ANSI ordinal to UNICODE ordinal 00952 */ 00953 dwUnicodeOrdinal.tag = 0xFFFF; 00954 dwUnicodeOrdinal.ordLo = lpszAnsiName[1]; 00955 dwUnicodeOrdinal.ordHi = lpszAnsiName[2]; 00956 lpszName = (LPWSTR)&dwUnicodeOrdinal; 00957 } else { 00958 MBToWCSEx(0, lpszAnsiName, -1, &lpszName, -1, TRUE); 00959 } 00960 } else { 00961 lpszName = NULL; 00962 } 00963 } else { 00964 lpszName = (LPWSTR)(((LPCREATESTRUCT)lParam)->lpszName); 00965 } 00966 00967 /* 00968 * Load the image 00969 */ 00970 xxxStaticLoadImage(pstat, lpszName); 00971 00972 if (fAnsi && 00973 lpszName && 00974 lpszName != (LPWSTR)&dwUnicodeOrdinal) { 00975 /* 00976 * Free the converted ANSI string 00977 */ 00978 LocalFree(lpszName); 00979 } 00980 } else if (bType == SS_ETCHEDHORZ || bType == SS_ETCHEDVERT) { 00981 00982 /* 00983 * Resize static window to fit edge. Horizontal dudes 00984 * make bottom one edge from top, vertical dudes make 00985 * right edge one edge from left. 00986 */ 00987 00988 RECT rcClient; 00989 00990 _GetClientRect(pwnd, &rcClient); 00991 if (bType == SS_ETCHEDHORZ) 00992 rcClient.bottom = SYSMET(CYEDGE); 00993 else 00994 rcClient.right = SYSMET(CXEDGE); 00995 00996 NtUserSetWindowPos(hwnd, HWND_TOP, 0, 0, rcClient.right, 00997 rcClient.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 00998 } 00999 break; 01000 01001 case WM_DESTROY: 01002 if (((rgstk[bType] & STK_TYPE) == STK_IMAGE) && 01003 (pstat->hImage != NULL) && 01004 (pstat->fDeleteIt)) { 01005 01006 if (bType == SS_BITMAP) { 01007 DeleteObject(pstat->hImage); 01008 } else if (bType == SS_ICON) { 01009 if (pstat->cicur > 1) { 01010 /* 01011 * Kill the animated cursor timer 01012 */ 01013 NtUserKillTimer(hwnd, IDSYS_STANIMATE); 01014 } 01015 NtUserDestroyCursor((HCURSOR)(pstat->hImage), CURSOR_CALLFROMCLIENT); 01016 } 01017 } 01018 break; 01019 01020 case WM_NCCREATE: 01021 if (TestWF(pwnd,WEFRIGHT)) { 01022 NtUserAlterWindowStyle(hwnd, SS_TYPEMASK, SS_RIGHT); 01023 } 01024 01025 if (TestWF(pwnd, SFSUNKEN) || 01026 ((bType == LOBYTE(SS_ETCHEDHORZ)) || (bType == LOBYTE(SS_ETCHEDVERT)))) { 01027 SetWindowState(pwnd, WEFSTATICEDGE); 01028 } 01029 goto CallDWP; 01030 01031 case WM_NCDESTROY: 01032 case WM_FINALDESTROY: 01033 if (pstat) { 01034 Unlock(&pstat->spwnd); 01035 FreeLookasideEntry(&StaticLookaside, pstat); 01036 } 01037 NtUserSetWindowFNID(hwnd, FNID_CLEANEDUP_BIT); 01038 break; 01039 01040 case WM_NCHITTEST: 01041 return (TestWF(pwnd, SFNOTIFY) ? HTCLIENT : HTTRANSPARENT); 01042 01043 case WM_LBUTTONDOWN: 01044 case WM_NCLBUTTONDOWN: 01045 if (TestWF(pwnd, SFNOTIFY)) { 01046 01047 /* 01048 * It is acceptable for an app to destroy a static label 01049 * in response to a STN_CLICKED notification. 01050 */ 01051 StaticNotifyParent(pwnd, NULL, STN_CLICKED); 01052 } 01053 break; 01054 01055 case WM_LBUTTONDBLCLK: 01056 case WM_NCLBUTTONDBLCLK: 01057 if (TestWF(pwnd, SFNOTIFY)) { 01058 01059 /* 01060 * It is acceptable for an app to destroy a static label in 01061 * response to a STN_DBLCLK notification. 01062 */ 01063 StaticNotifyParent(pwnd, NULL, STN_DBLCLK); 01064 } 01065 break; 01066 01067 case WM_SETTEXT: 01068 /* 01069 * No more hack to set icon/bitmap via WM_SETTEXT! 01070 */ 01071 if (rgstk[bType] & STK_USETEXT) { 01072 if (_DefSetText(hwnd, (LPWSTR)lParam, fAnsi)) { 01073 StaticRepaint(pstat); 01074 return TRUE; 01075 } 01076 } 01077 break; 01078 01079 case WM_ENABLE: 01080 StaticRepaint(pstat); 01081 if (TestWF(pwnd, SFNOTIFY)) { 01082 StaticNotifyParent(pwnd, NULL, (wParam ? STN_ENABLE : STN_DISABLE)); 01083 } 01084 break; 01085 01086 case WM_GETDLGCODE: 01087 return (LONG)DLGC_STATIC; 01088 01089 case WM_SETFONT: 01090 01091 /* 01092 * wParam - handle to the font 01093 * lParam - if true, redraw else don't 01094 */ 01095 if (rgstk[bType] & STK_USEFONT) { 01096 01097 pstat->hFont = (HANDLE)wParam; 01098 01099 if (lParam && TestWF(pwnd, WFVISIBLE)) { 01100 NtUserInvalidateRect(hwnd, NULL, TRUE); 01101 UpdateWindow(hwnd); 01102 } 01103 } 01104 break; 01105 01106 case WM_GETFONT: 01107 if (rgstk[bType] & STK_USEFONT) { 01108 return (LRESULT)pstat->hFont; 01109 } 01110 break; 01111 01112 case WM_TIMER: 01113 if (wParam == IDSYS_STANIMATE) { 01114 xxxNextAniIconStep(pstat); 01115 } 01116 break; 01117 01118 /* 01119 * case WM_GETTEXT: 01120 * No more hack to get icon/bitmap via WM_GETTEXT! 01121 */ 01122 01123 case WM_INPUTLANGCHANGEREQUEST: 01124 if (IS_IME_ENABLED() || IS_MIDEAST_ENABLED()) { 01125 /* 01126 * #115190 01127 * If the window is one of controls on top of dialogbox, 01128 * let the parent dialog handle it. 01129 */ 01130 if (TestwndChild(pwnd) && pwnd->spwndParent) { 01131 PWND pwndParent = REBASEALWAYS(pwnd, spwndParent); 01132 if (pwndParent) { 01133 PCLS pclsParent = REBASEALWAYS(pwndParent, pcls); 01134 01135 UserAssert(pclsParent != NULL); 01136 if (pclsParent->atomClassName == gpsi->atomSysClass[ICLS_DIALOG]) { 01137 return SendMessageWorker(pwndParent, message, wParam, lParam, FALSE); 01138 } 01139 } 01140 } 01141 } 01142 goto CallDWP; 01143 01144 case WM_UPDATEUISTATE: 01145 { 01146 /* 01147 * DWP will change the UIState bits accordingly 01148 */ 01149 DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); 01150 01151 if (HIWORD(wParam) & UISF_HIDEACCEL) { 01152 /* 01153 * Change in AccelHidden state: need to repaint 01154 */ 01155 if (ISSSTEXTOROD(bType)) { 01156 pstat->fPaintKbdCuesOnly = TRUE; 01157 StaticRepaint(pstat); 01158 pstat->fPaintKbdCuesOnly = FALSE; 01159 } 01160 } 01161 } 01162 break; 01163 01164 default: 01165 CallDWP: 01166 return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); 01167 } 01168 01169 return 0L; 01170 } 01171 01172 01173 LRESULT WINAPI StaticWndProcA( 01174 HWND hwnd, 01175 UINT message, 01176 WPARAM wParam, 01177 LPARAM lParam) 01178 { 01179 PWND pwnd; 01180 01181 if ((pwnd = ValidateHwnd(hwnd)) == NULL) { 01182 return (0L); 01183 } 01184 01185 return StaticWndProcWorker(pwnd, message, wParam, lParam, TRUE); 01186 } 01187 01188 LRESULT WINAPI StaticWndProcW( 01189 HWND hwnd, 01190 UINT message, 01191 WPARAM wParam, 01192 LPARAM lParam) 01193 { 01194 PWND pwnd; 01195 01196 if ((pwnd = ValidateHwnd(hwnd)) == NULL) { 01197 return (0L); 01198 } 01199 01200 return StaticWndProcWorker(pwnd, message, wParam, lParam, FALSE); 01201 } 01202 01203 /***************************************************************************\ 01204 * Next Animated Icon Step 01205 * 01206 * Advances to the next step in an animaged icon. 01207 * 01208 * 01209 \***************************************************************************/ 01210 01211 VOID xxxNextAniIconStep( 01212 PSTAT pstat) 01213 { 01214 DWORD dwRate; 01215 PWND pwnd = pstat->spwnd; 01216 HWND hwnd = HWq(pwnd); 01217 01218 /* 01219 * Stop the timer for the next animation step. 01220 */ 01221 NtUserKillTimer(hwnd, IDSYS_STANIMATE); 01222 01223 if (++(pstat->iicur) >= pstat->cicur) { 01224 pstat->iicur = 0; 01225 } 01226 01227 // Perhaps we can do something like shell\cpl\main\mouseptr.c 01228 // here, and make GetCursorFrameInfo obsolete. 01229 GetCursorFrameInfo(pstat->hImage, NULL, pstat->iicur, &dwRate, &pstat->cicur); 01230 dwRate = max(200, dwRate * 100 / 6); 01231 01232 NtUserInvalidateRect(hwnd, NULL, FALSE); 01233 UpdateWindow(hwnd); 01234 01235 NtUserSetTimer(hwnd, IDSYS_STANIMATE, dwRate, NULL); 01236 } 01237

Generated on Sat May 15 19:41:52 2004 for test by doxygen 1.3.7