/****************************************************************************\ * * STATIC.C * * Copyright (c) 1985 - 1999, Microsoft Corporation * * Static Dialog Controls Routines * * 13-Nov-1990 mikeke from win3 * 29-Jan-1991 IanJa StaticPaint -> xxxStaticPaint; partial revalidation * 01-Nov-1994 ChrisWil merged in Daytona/Chicago w/Ani-Icons. * \****************************************************************************/ #include "precomp.h" #pragma hdrstop /* * Local Routines. */ VOID xxxNextAniIconStep(PSTAT); HANDLE xxxSetStaticImage(PSTAT,HANDLE,BOOL); VOID xxxStaticLoadImage(PSTAT,LPWSTR); /* * Type table; this is used for validation of the image types. */ #define IMAGE_STMMAX IMAGE_ENHMETAFILE+1 static BYTE rgbType[IMAGE_STMMAX] = { SS_BITMAP, // IMAGE_BITMAP SS_ICON, // IMAGE_CURSOR SS_ICON, // IMAGE_ICON SS_ENHMETAFILE // IMAGE_ENHMETAFILE }; /* * LOBYTE of SS_ style is index into this array */ #define STK_OWNER 0x00 #define STK_IMAGE 0x01 #define STK_TEXT 0x02 #define STK_GRAPHIC 0x03 #define STK_TYPE 0x03 #define STK_ERASE 0x04 #define STK_USEFONT 0x08 #define STK_USETEXT 0x10 BYTE rgstk[] = { STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_LEFT STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_CENTER STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_RIGHT STK_IMAGE, // SS_ICON STK_GRAPHIC, // SS_BLACKRECT STK_GRAPHIC, // SS_GRAYRECT STK_GRAPHIC, // SS_WHITERECT STK_GRAPHIC, // SS_BLACKFRAME STK_GRAPHIC, // SS_GRAYFRAME STK_GRAPHIC, // SS_WHITEFRAME STK_OWNER, // SS_USERITEM STK_TEXT | STK_USEFONT | STK_USETEXT, // SS_SIMPLE STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_LEFTNOWORDWRAP STK_OWNER | STK_USEFONT | STK_USETEXT, // SS_OWNERDRAW STK_IMAGE, // SS_BITMAP STK_IMAGE | STK_ERASE, // SS_ENHMETAFILE STK_GRAPHIC, // SS_ETCHEDHORZ STK_GRAPHIC, // SS_ETCHEDVERT STK_GRAPHIC // SS_ETCHEDFRAME }; LOOKASIDE StaticLookaside; /* * Common macros for image handling. */ #define IsValidImage(imageType, realType, max) \ ((imageType < max) && (rgbType[imageType] == realType)) /***************************************************************************\ * xxxSetStaticImage * * Sets bitmap/icon of static guy, either in response to a STM_SETxxxx * message, or at create time. \***************************************************************************/ HANDLE xxxSetStaticImage( PSTAT pstat, HANDLE hImage, BOOL fDeleteIt) { UINT bType; RECT rc; RECT rcWindow; HANDLE hImageOld; DWORD dwRate; UINT cicur; BOOL fAnimated = FALSE; PWND pwnd = pstat->spwnd; HWND hwnd = HWq(pwnd); CheckLock(pwnd); bType = TestWF(pwnd, SFTYPEMASK); /* * If this is an old-ani-icon, then delete its timer. */ if (bType == SS_ICON && pstat->cicur > 1) { /* * Old cursor was an animated cursor, so kill the timer that is used * to animate it. */ NtUserKillTimer(hwnd, IDSYS_STANIMATE); } /* * Initialize the old-image return value. */ hImageOld = pstat->hImage; rc.right = rc.bottom = 0; if (hImage != NULL) { switch (bType) { case SS_ENHMETAFILE: { /* * We do NOT resize the window. */ rc.right = pwnd->rcClient.right - pwnd->rcClient.left; rc.bottom = pwnd->rcClient.bottom - pwnd->rcClient.top; break; } case SS_BITMAP: { BITMAP bmp; if (GetObject(hImage, sizeof(BITMAP), &bmp)) { rc.right = bmp.bmWidth; rc.bottom = bmp.bmHeight; } } break; case SS_ICON: { NtUserGetIconSize(hImage, 0, &rc.right, &rc.bottom); rc.bottom /= 2; pstat->cicur = 0; pstat->iicur = 0; if (GetCursorFrameInfo(hImage, NULL, 0, &dwRate, &cicur)) { fAnimated = (cicur > 1); pstat->cicur = cicur; } } break; } } pstat->hImage = hImage; pstat->fDeleteIt = fDeleteIt; /* * Resize static to fit. Do NOT do this for SS_CENTERIMAGE or * SS_REALSIZECONTROL. */ if (!TestWF(pwnd, SFCENTERIMAGE) && !TestWF(pwnd, SFREALSIZECONTROL)) { /* * Get current window rect in parent's client coordinates. */ GetRect(pwnd, &rcWindow, GRECT_WINDOW | GRECT_PARENTCOORDS); /* * Get new window dimensions. */ rc.left = 0; rc.top = 0; if (rc.right && rc.bottom) { _AdjustWindowRectEx(&rc, pwnd->style, FALSE, pwnd->ExStyle); rc.right -= rc.left; rc.bottom -= rc.top; } NtUserSetWindowPos(hwnd, HWND_TOP, 0, 0, rc.right, rc.bottom, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); } if (TestWF(pwnd, WFVISIBLE)) { NtUserInvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); } /* * If this is an aimated-icon, then start the timer for the animation * sequence. */ if(fAnimated) { GetCursorFrameInfo(pstat->hImage, NULL, pstat->iicur, &dwRate, &cicur); dwRate = max(200, dwRate * 100 / 6); NtUserSetTimer(hwnd, IDSYS_STANIMATE, dwRate, NULL); } return hImageOld; } /***************************************************************************\ * StaticLoadImage * * Loads the icon or bitmap from the app's resource file if a name was * specified in the dialog template. We assume that the name is the name of * the resource to load. \***************************************************************************/ VOID xxxStaticLoadImage( PSTAT pstat, LPWSTR lpszName) { HANDLE hImage = NULL; PWND pwnd = pstat->spwnd; CheckLock(pwnd); if (lpszName && *lpszName) { /* * Only try to load the icon/bitmap if the string is non null. */ if (*(BYTE FAR *)lpszName == 0xFF) lpszName = MAKEINTRESOURCE(((LPWORD)lpszName)[1]); /* * Load the image. If it can't be found in the app, try the * display driver. */ if (lpszName) { switch (TestWF(pwnd, SFTYPEMASK)) { case SS_BITMAP: /* * If the window is not owned by the server, first call * back out to the client. */ if (!gfServerProcess && pwnd->hModule) { hImage = LoadBitmap(KHANDLE_TO_HANDLE(pwnd->hModule), lpszName); } /* * If the above didn't load it, try loading it from the * display driver (hmod == NULL). */ if (hImage == NULL) { hImage = LoadBitmap(NULL, lpszName); } break; case SS_ICON: if (TestWF(pwnd, SFREALSIZEIMAGE)) { if (!gfServerProcess && pwnd->hModule) { hImage = LoadImage(KHANDLE_TO_HANDLE(pwnd->hModule), lpszName, IMAGE_ICON, 0, 0, 0); } } else { /* * If the window is not owned by the server, first call * back out to the client. Try loading both icons/cursor * types. */ if (!gfServerProcess && pwnd->hModule) { hImage = LoadIcon(KHANDLE_TO_HANDLE(pwnd->hModule), lpszName); /* * We will also try to load a cursor-format if the * window is 4.0 compatible. Icons/Cursors are really * the same. We don't do this for 3.x apps for the * usual compatibility reasons. */ if (hImage == NULL && TestWF(pwnd, WFWIN40COMPAT)) { hImage = LoadCursor(KHANDLE_TO_HANDLE(pwnd->hModule), lpszName); } } /* * If the above didn't load it, try loading it from the * display driver (hmod == NULL). */ if (hImage == NULL) { hImage = LoadIcon(NULL, lpszName); } } break; } /* * Set the image if it was loaded. */ if (hImage) { xxxSetStaticImage(pstat, hImage, TRUE); } } } } /***************************************************************************\ * StaticCallback * * Draws text statics, called by DrawState. \***************************************************************************/ BOOL CALLBACK StaticCallback( HDC hdc, LPARAM lData, WPARAM wData, int cx, int cy) { PWND pwnd = (PWND)lData; UINT style; LPWSTR lpszName; RECT rc; BYTE bType; UNREFERENCED_PARAMETER(wData); bType = TestWF(pwnd, SFTYPEMASK); UserAssert(rgstk[bType] & STK_USETEXT); if (pwnd->strName.Length) { lpszName = REBASE(pwnd, strName.Buffer); style = DT_NOCLIP | DT_EXPANDTABS; if (bType != LOBYTE(SS_LEFTNOWORDWRAP)) { style |= DT_WORDBREAK; style |= (UINT)(bType - LOBYTE(SS_LEFT)); if (TestWF(pwnd, SFEDITCONTROL)) { style |= DT_EDITCONTROL; } } switch (TestWF(pwnd, SFELLIPSISMASK)) { case HIBYTE(LOWORD(SS_ENDELLIPSIS)): style |= DT_END_ELLIPSIS | DT_SINGLELINE; break; case HIBYTE(LOWORD(SS_PATHELLIPSIS)): style |= DT_PATH_ELLIPSIS | DT_SINGLELINE; break; case HIBYTE(LOWORD(SS_WORDELLIPSIS)): style |= DT_WORD_ELLIPSIS | DT_SINGLELINE; break; } if (TestWF(pwnd, SFNOPREFIX)) { style |= DT_NOPREFIX; } if (TestWF(pwnd, SFCENTERIMAGE)) { style |= DT_VCENTER | DT_SINGLELINE; } rc.left = 0; rc.top = 0; rc.right = cx; rc.bottom = cy; if (TestWF(pwnd, WEFPUIACCELHIDDEN)) { style |= DT_HIDEPREFIX; } else if (((PSTATWND)pwnd)->pstat->fPaintKbdCuesOnly) { style |= DT_PREFIXONLY; } DrawTextExW(hdc, lpszName, -1, &rc, (DWORD)style, NULL); } return TRUE; } /***************************************************************************\ * xxxStaticPaint * * History: \***************************************************************************/ VOID xxxStaticPaint( PSTAT pstat, HDC hdc, BOOL fClip) { PWND pwndParent; RECT rc; UINT cmd; BYTE bType; BOOL fFont; HBRUSH hbrControl; UINT oldAlign; DWORD dwOldLayout = 0; HANDLE hfontOld = NULL; PWND pwnd = pstat->spwnd; HWND hwnd = HWq(pwnd); CheckLock(pwnd); if (TestWF(pwnd, WEFRTLREADING)) { oldAlign = GetTextAlign(hdc); SetTextAlign(hdc, oldAlign | TA_RTLREADING); } bType = TestWF(pwnd, SFTYPEMASK); _GetClientRect(pwnd, &rc); if (fClip) { IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); } fFont = (rgstk[bType] & STK_USEFONT) && (pstat->hFont != NULL); if (fFont) { hfontOld = SelectObject(hdc, pstat->hFont); } /* * Send WM_CTLCOLORSTATIC to all statics (even frames) for 1.03 * compatibility. */ SetBkMode(hdc, OPAQUE); hbrControl = GetControlBrush(hwnd, hdc, WM_CTLCOLORSTATIC); /* * Do we erase the background? We don't for SS_OWNERDRAW * and STK_GRAPHIC kind of things. */ pwndParent = REBASEPWND(pwnd, spwndParent); if ((rgstk[bType] & STK_ERASE) && !pstat->fPaintKbdCuesOnly) { PaintRect(HW(pwndParent), hwnd, hdc, hbrControl, &rc); } switch (LOBYTE(bType)) { case SS_ICON: if (pstat->hImage) { int cx; int cy; POINT pt; if (TestWF(pwnd,WEFLAYOUTRTL)) { dwOldLayout = SetLayoutWidth(hdc, -1, 0); } /* * Perform the correct rect-setup. */ if (TestWF(pwnd,SFCENTERIMAGE)) { NtUserGetIconSize(pstat->hImage, pstat->iicur, &cx, &cy); cy >>= 1; rc.left = (rc.right - cx) / 2; rc.right = (rc.left + cx); rc.top = (rc.bottom - cy) / 2; rc.bottom = (rc.top + cy); } else { cx = rc.right - rc.left; cy = rc.bottom - rc.top; } /* * Output the icon. If it's animated, we indicate * the step-frame to output. */ if (GETFNID(pwndParent) == FNID_DESKTOP) { SetBrushOrgEx(hdc, 0, 0, &pt); } else { SetBrushOrgEx( hdc, pwndParent->rcClient.left - pwnd->rcClient.left, pwndParent->rcClient.top - pwnd->rcClient.top, &pt); } DrawIconEx(hdc, rc.left, rc.top, pstat->hImage, cx, cy, pstat->iicur, hbrControl, DI_NORMAL); SetBrushOrgEx(hdc, pt.x, pt.y, NULL); if (TestWF(pwnd,WEFLAYOUTRTL)) { SetLayoutWidth(hdc, -1, dwOldLayout); } } else { /* * Empty! Need to erase. */ PaintRect(HW(pwndParent), hwnd, hdc, hbrControl, &rc); } break; case SS_BITMAP: if (pstat->hImage) { BITMAP bmp; HBITMAP hbmpT; RECT rcTmp; BOOL fErase; /* * Get the bitmap information. If this fails, then we * can assume somethings wrong with its format...don't * draw in this case. */ if (GetObject(pstat->hImage, sizeof(BITMAP), &bmp)) { if (TestWF(pwnd, SFCENTERIMAGE)) { fErase = ((bmp.bmWidth < rc.right) || (bmp.bmHeight < rc.bottom)); rc.left = (rc.right - bmp.bmWidth) >> 1; rc.right = (rc.left + bmp.bmWidth); rc.top = (rc.bottom - bmp.bmHeight) >> 1; rc.bottom = (rc.top + bmp.bmHeight); } else { fErase = FALSE; } /* * Select in the bitmap and blt it to the client-surface. */ RtlEnterCriticalSection(&gcsHdc); hbmpT = SelectObject(ghdcBits2, pstat->hImage); StretchBlt(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, ghdcBits2, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY|NOMIRRORBITMAP); /* * Only need to erase the background if the image is * centered and it's smaller than the client-area. */ if (fErase) { HBRUSH hbr; if (hbr = CreateSolidBrush(GetPixel(ghdcBits2, 0, 0))) { POLYPATBLT PolyData; ExcludeClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); _GetClientRect(pwnd, &rcTmp); PolyData.x = 0; PolyData.y = 0; PolyData.cx = rcTmp.right; PolyData.cy = rcTmp.bottom; PolyData.BrClr.hbr = hbr; PolyPatBlt(hdc,PATCOPY,&PolyData,1,PPB_BRUSH); DeleteObject(hbr); } } if (hbmpT) { SelectObject(ghdcBits2, hbmpT); } RtlLeaveCriticalSection(&gcsHdc); } } break; case SS_ENHMETAFILE: if (pstat->hImage) { RECT rcl; rcl.left = rc.left; rcl.top = rc.top; rcl.right = rc.right; rcl.bottom = rc.bottom; PlayEnhMetaFile(hdc, pstat->hImage, &rcl); } break; case SS_OWNERDRAW: { DRAWITEMSTRUCT dis; dis.CtlType = ODT_STATIC; dis.CtlID = PtrToUlong(pwnd->spmenu); dis.itemAction = ODA_DRAWENTIRE; dis.itemState = (TestWF(pwnd, WFDISABLED) ? ODS_DISABLED : 0); dis.hwndItem = hwnd; dis.hDC = hdc; dis.itemData = 0L; dis.rcItem = rc; if (TestWF(pwnd, WEFPUIACCELHIDDEN)) { dis.itemState |= ODS_NOACCEL; } /* * Send a WM_DRAWITEM message to the parent. */ SendMessage(HW(pwndParent), WM_DRAWITEM, (WPARAM)dis.CtlID, (LPARAM)&dis); } break; case SS_LEFT: case SS_CENTER: case SS_RIGHT: case SS_LEFTNOWORDWRAP: if (pwnd->strName.Length) { UINT dstFlags; dstFlags = DST_COMPLEX; if (TestWF(pwnd, WFDISABLED)) { dstFlags |= DSS_DISABLED; } DrawState(hdc, SYSHBR(WINDOWTEXT), StaticCallback, (LPARAM)pwnd, (WPARAM)TRUE, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, dstFlags); } break; case SS_SIMPLE: { LPWSTR lpName; UINT cchName; /* * The "Simple" bType assumes everything, including the following: * 1. The Text exists and fits on one line. * 2. The Static item is always enabled. * 3. The Static item is never changed to be a shorter string. * 4. The Parent never responds to the CTLCOLOR message */ if (pwnd->strName.Length) { lpName = REBASE(pwnd, strName.Buffer); cchName = pwnd->strName.Length / sizeof(WCHAR); } else { lpName = (LPWSTR)szNull; cchName = 0; } if (TestWF(pwnd,SFNOPREFIX)) { ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE | ETO_CLIPPED, &rc, lpName, cchName, 0L); } else { /* * Use OPAQUE for speed. */ DWORD dwFlags; if (TestWF(pwnd, WEFPUIACCELHIDDEN)) { dwFlags = DT_HIDEPREFIX; } else if (pstat->fPaintKbdCuesOnly) { dwFlags = DT_PREFIXONLY; } else { dwFlags = 0; } PSMTextOut(hdc, rc.left, rc.top, lpName, cchName, dwFlags); } } break; case SS_BLACKFRAME: cmd = (COLOR_3DDKSHADOW << 3); goto StatFrame; case SS_GRAYFRAME: cmd = (COLOR_3DSHADOW << 3); goto StatFrame; case SS_WHITEFRAME: cmd = (COLOR_3DHILIGHT << 3); StatFrame: DrawFrame(hdc, &rc, 1, cmd); break; case SS_BLACKRECT: hbrControl = SYSHBR(3DDKSHADOW); goto StatRect; case SS_GRAYRECT: hbrControl = SYSHBR(3DSHADOW); goto StatRect; case SS_WHITERECT: hbrControl = SYSHBR(3DHILIGHT); StatRect: PaintRect(HW(pwndParent), hwnd, hdc, hbrControl, &rc); break; case SS_ETCHEDFRAME: DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT); break; } if (hfontOld) { SelectObject(hdc, hfontOld); } if (TestWF(pwnd, WEFRTLREADING)) { SetTextAlign(hdc, oldAlign); } } /***************************************************************************\ * * StaticRepaint() * \***************************************************************************/ VOID StaticRepaint( PSTAT pstat) { PWND pwnd = pstat->spwnd; if (IsVisible(pwnd)) { HDC hdc; HWND hwnd = HWq(pwnd); if (hdc = NtUserGetDC(hwnd)) { xxxStaticPaint(pstat, hdc, TRUE); NtUserReleaseDC(hwnd, hdc); } } } /***************************************************************************\ * * StaticNotifyParent() * * Sends WM_COMMAND notification messages. * \***************************************************************************/ // LATER mikeke why do we have multiple versions of notifyparent? LRESULT FAR PASCAL StaticNotifyParent( PWND pwnd, PWND pwndParent, int nCode) { LRESULT lret; TL tlpwndParent; UserAssert(pwnd); if (!pwndParent) { pwndParent = REBASEPWND(pwnd, spwndParent); } ThreadLock(pwndParent, &tlpwndParent); lret = SendMessage(HW(pwndParent), WM_COMMAND, MAKELONG(PTR_TO_ID(pwnd->spmenu), nCode), (LPARAM)HWq(pwnd)); ThreadUnlock(&tlpwndParent); return lret; } /***************************************************************************\ * StaticWndProc * * History: \***************************************************************************/ LRESULT APIENTRY StaticWndProcWorker( PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, DWORD fAnsi) { HWND hwnd = HWq(pwnd); BYTE bType; PSTAT pstat; static BOOL fInit = TRUE; CheckLock(pwnd); VALIDATECLASSANDSIZE(pwnd, FNID_STATIC); INITCONTROLLOOKASIDE(&StaticLookaside, STAT, spwnd, 8); /* * If the control is not interested in this message, * pass it to DefWindowProc. */ if (!FWINDOWMSG(message, FNID_STATIC)) return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); /* * Get the pstat for the given window now since we will use it a lot in * various handlers. This was stored using SetWindowLong(hwnd,0,pstat) when * we initially created the static control. */ pstat = ((PSTATWND)pwnd)->pstat; /* * Get the control's type */ bType = TestWF(pwnd, SFTYPEMASK); switch (message) { case STM_GETICON: wParam = IMAGE_ICON; case STM_GETIMAGE: if (IsValidImage(wParam, bType, IMAGE_STMMAX)) { return (LRESULT)pstat->hImage; } break; case STM_SETICON: lParam = (LPARAM)wParam; wParam = IMAGE_ICON; case STM_SETIMAGE: if (IsValidImage(wParam, bType, IMAGE_STMMAX)) { return (LRESULT)xxxSetStaticImage(pstat, (HANDLE)lParam, FALSE); } break; case WM_ERASEBKGND: /* * The control will be erased in xxxStaticPaint(). */ return TRUE; case WM_PRINTCLIENT: xxxStaticPaint(pstat, (HDC)wParam, FALSE); break; case WM_PAINT: { HDC hdc; PAINTSTRUCT ps; if ((hdc = (HDC)wParam) == NULL) { hdc = NtUserBeginPaint(hwnd, &ps); } if (IsVisible(pwnd)) { xxxStaticPaint(pstat, hdc, !wParam); } /* * If hwnd was destroyed, BeginPaint was automatically undone. */ if (!wParam) { NtUserEndPaint(hwnd, &ps); } } break; case WM_CREATE: if ((rgstk[bType] & STK_TYPE) == STK_IMAGE) { /* * Pull the name from LPCREATESTRUCT like Win95 does */ LPWSTR lpszName; LPSTR lpszAnsiName; struct { WORD tag; BYTE ordLo; BYTE ordHi; } dwUnicodeOrdinal; if (fAnsi) { /* * Convert the ANSI string to unicode if it exists. */ lpszAnsiName = (LPSTR)((LPCREATESTRUCT)lParam)->lpszName; if (lpszAnsiName) { if (lpszAnsiName[0] == (CHAR)0xff) { /* * Convert ANSI ordinal to UNICODE ordinal */ dwUnicodeOrdinal.tag = 0xFFFF; dwUnicodeOrdinal.ordLo = lpszAnsiName[1]; dwUnicodeOrdinal.ordHi = lpszAnsiName[2]; lpszName = (LPWSTR)&dwUnicodeOrdinal; } else { MBToWCSEx(0, lpszAnsiName, -1, &lpszName, -1, TRUE); } } else { lpszName = NULL; } } else { lpszName = (LPWSTR)(((LPCREATESTRUCT)lParam)->lpszName); } /* * Load the image */ xxxStaticLoadImage(pstat, lpszName); if (fAnsi && lpszName && lpszName != (LPWSTR)&dwUnicodeOrdinal) { /* * Free the converted ANSI string. */ UserLocalFree(lpszName); } } else if (bType == SS_ETCHEDHORZ || bType == SS_ETCHEDVERT) { /* * Resize static window to fit edge. Horizontal dudes make * bottom one edge from top, vertical dudes make right edge one * edge from left. */ RECT rcClient; _GetClientRect(pwnd, &rcClient); if (bType == SS_ETCHEDHORZ) { rcClient.bottom = SYSMET(CYEDGE); } else { rcClient.right = SYSMET(CXEDGE); } NtUserSetWindowPos(hwnd, HWND_TOP, 0, 0, rcClient.right, rcClient.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); } break; case WM_DESTROY: if (((rgstk[bType] & STK_TYPE) == STK_IMAGE) && (pstat->hImage != NULL) && (pstat->fDeleteIt)) { if (bType == SS_BITMAP) { DeleteObject(pstat->hImage); } else if (bType == SS_ICON) { if (pstat->cicur > 1) { /* * Kill the animated cursor timer */ NtUserKillTimer(hwnd, IDSYS_STANIMATE); } NtUserDestroyCursor((HCURSOR)(pstat->hImage), CURSOR_CALLFROMCLIENT); } } break; case WM_NCCREATE: if (TestWF(pwnd,WEFRIGHT)) { NtUserAlterWindowStyle(hwnd, SS_TYPEMASK, SS_RIGHT); } if (TestWF(pwnd, SFSUNKEN) || ((bType == LOBYTE(SS_ETCHEDHORZ)) || (bType == LOBYTE(SS_ETCHEDVERT)))) { SetWindowState(pwnd, WEFSTATICEDGE); } goto CallDWP; case WM_NCDESTROY: case WM_FINALDESTROY: if (pstat) { Unlock(&pstat->spwnd); FreeLookasideEntry(&StaticLookaside, pstat); } NtUserSetWindowFNID(hwnd, FNID_CLEANEDUP_BIT); break; case WM_NCHITTEST: return (TestWF(pwnd, SFNOTIFY) ? HTCLIENT : HTTRANSPARENT); case WM_LBUTTONDOWN: case WM_NCLBUTTONDOWN: if (TestWF(pwnd, SFNOTIFY)) { /* * It is acceptable for an app to destroy a static label * in response to a STN_CLICKED notification. */ StaticNotifyParent(pwnd, NULL, STN_CLICKED); } break; case WM_LBUTTONDBLCLK: case WM_NCLBUTTONDBLCLK: if (TestWF(pwnd, SFNOTIFY)) { /* * It is acceptable for an app to destroy a static label in * response to a STN_DBLCLK notification. */ StaticNotifyParent(pwnd, NULL, STN_DBLCLK); } break; case WM_SETTEXT: /* * No more hack to set icon/bitmap via WM_SETTEXT! */ if (rgstk[bType] & STK_USETEXT) { if (_DefSetText(hwnd, (LPWSTR)lParam, fAnsi)) { StaticRepaint(pstat); return TRUE; } } break; case WM_ENABLE: StaticRepaint(pstat); if (TestWF(pwnd, SFNOTIFY)) { StaticNotifyParent(pwnd, NULL, (wParam ? STN_ENABLE : STN_DISABLE)); } break; case WM_GETDLGCODE: return (LONG)DLGC_STATIC; case WM_SETFONT: /* * wParam - handle to the font * lParam - if true, redraw else don't */ if (rgstk[bType] & STK_USEFONT) { pstat->hFont = (HANDLE)wParam; if (lParam && TestWF(pwnd, WFVISIBLE)) { NtUserInvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); } } break; case WM_GETFONT: if (rgstk[bType] & STK_USEFONT) { return (LRESULT)pstat->hFont; } break; case WM_TIMER: if (wParam == IDSYS_STANIMATE) { xxxNextAniIconStep(pstat); } break; /* * case WM_GETTEXT: * No more hack to get icon/bitmap via WM_GETTEXT! */ case WM_INPUTLANGCHANGEREQUEST: if (IS_IME_ENABLED() || IS_MIDEAST_ENABLED()) { /* * #115190 * If the window is one of controls on top of dialogbox, * let the parent dialog handle it. */ if (TestwndChild(pwnd) && pwnd->spwndParent) { PWND pwndParent = REBASEALWAYS(pwnd, spwndParent); if (pwndParent) { PCLS pclsParent = REBASEALWAYS(pwndParent, pcls); UserAssert(pclsParent != NULL); if (pclsParent->atomClassName == gpsi->atomSysClass[ICLS_DIALOG]) { return SendMessageWorker(pwndParent, message, wParam, lParam, FALSE); } } } } goto CallDWP; case WM_UPDATEUISTATE: { /* * DWP will change the UIState bits accordingly */ DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); if (HIWORD(wParam) & UISF_HIDEACCEL) { /* * Change in AccelHidden state: need to repaint */ if (ISSSTEXTOROD(bType)) { pstat->fPaintKbdCuesOnly = TRUE; StaticRepaint(pstat); pstat->fPaintKbdCuesOnly = FALSE; } } } break; default: CallDWP: return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); } return 0; } LRESULT WINAPI StaticWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PWND pwnd; if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return 0; } return StaticWndProcWorker(pwnd, message, wParam, lParam, TRUE); } LRESULT WINAPI StaticWndProcW( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PWND pwnd; if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return 0; } return StaticWndProcWorker(pwnd, message, wParam, lParam, FALSE); } /***************************************************************************\ * Next Animated Icon Step * * Advances to the next step in an animaged icon. \***************************************************************************/ VOID xxxNextAniIconStep( PSTAT pstat) { DWORD dwRate; PWND pwnd = pstat->spwnd; HWND hwnd = HWq(pwnd); /* * Stop the timer for the next animation step. */ NtUserKillTimer(hwnd, IDSYS_STANIMATE); if (++(pstat->iicur) >= pstat->cicur) { pstat->iicur = 0; } GetCursorFrameInfo(pstat->hImage, NULL, pstat->iicur, &dwRate, &pstat->cicur); dwRate = max(200, dwRate * 100 / 6); NtUserInvalidateRect(hwnd, NULL, FALSE); UpdateWindow(hwnd); NtUserSetTimer(hwnd, IDSYS_STANIMATE, dwRate, NULL); }