Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1314 lines
37 KiB

  1. #include "ctlspriv.h"
  2. #pragma hdrstop
  3. #include "usrctl32.h"
  4. #include "static.h"
  5. #include "image.h"
  6. #define SS_TEXTMIN1 0x0000000BL
  7. #define SS_TEXTMAX1 0x0000000DL
  8. #define SS_EDITCONTROL 0x00002000L
  9. #define ISSSTEXTOROD(bType) \
  10. (((bType) <= SS_TEXTMAX0) \
  11. || (((bType) >= SS_TEXTMIN1) \
  12. && ((bType) <= SS_TEXTMAX1)))
  13. // Common macros for image handling.
  14. #define IsValidImage(imageType, realType, max) \
  15. ((imageType < max) && (rgbType[imageType] == realType))
  16. //---------------------------------------------------------------------------//
  17. //
  18. // Type table. This is used for validation of the
  19. // image-types. For the PPC release we won't support
  20. // the metafile format, but others are OK.
  21. #define IMAGE_STMMAX IMAGE_ENHMETAFILE+1
  22. static BYTE rgbType[IMAGE_STMMAX] =
  23. {
  24. SS_BITMAP, // IMAGE_BITMAP
  25. SS_ICON, // IMAGE_CURSOR
  26. SS_ICON, // IMAGE_ICON
  27. SS_ENHMETAFILE // IMAGE_ENHMETAFILE
  28. };
  29. //---------------------------------------------------------------------------//
  30. //
  31. // LOBYTE of SS_ style is index into this array
  32. #define STK_OWNER 0x00
  33. #define STK_IMAGE 0x01
  34. #define STK_TEXT 0x02
  35. #define STK_GRAPHIC 0x03
  36. #define STK_TYPE 0x03
  37. #define STK_ERASE 0x04
  38. #define STK_USEFONT 0x08
  39. #define STK_USETEXT 0x10
  40. BYTE rgstk[] =
  41. {
  42. STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_LEFT
  43. STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_CENTER
  44. STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_RIGHT
  45. STK_IMAGE | STK_ERASE, // SS_ICON
  46. STK_GRAPHIC, // SS_BLACKRECT
  47. STK_GRAPHIC, // SS_GRAYRECT
  48. STK_GRAPHIC, // SS_WHITERECT
  49. STK_GRAPHIC, // SS_BLACKFRAME
  50. STK_GRAPHIC, // SS_GRAYFRAME
  51. STK_GRAPHIC, // SS_WHITEFRAME
  52. STK_OWNER, // SS_USERITEM
  53. STK_TEXT | STK_USEFONT | STK_USETEXT, // SS_SIMPLE
  54. STK_TEXT | STK_ERASE | STK_USEFONT | STK_USETEXT, // SS_LEFTNOWORDWRAP
  55. STK_OWNER | STK_USEFONT | STK_USETEXT, // SS_OWNERDRAW
  56. STK_IMAGE | STK_ERASE, // SS_BITMAP
  57. STK_IMAGE | STK_ERASE, // SS_ENHMETAFILE
  58. STK_GRAPHIC, // SS_ETCHEDHORZ
  59. STK_GRAPHIC, // SS_ETCHEDVERT
  60. STK_GRAPHIC // SS_ETCHEDFRAME
  61. };
  62. //---------------------------------------------------------------------------//
  63. //
  64. // InitStaticClass() - Registers the control's window class
  65. //
  66. BOOL InitStaticClass(HINSTANCE hInstance)
  67. {
  68. WNDCLASS wc;
  69. wc.lpfnWndProc = Static_WndProc;
  70. wc.lpszClassName = WC_STATIC;
  71. wc.style = CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS;
  72. wc.cbClsExtra = 0;
  73. wc.cbWndExtra = sizeof(PSTAT);
  74. wc.hInstance = hInstance;
  75. wc.hIcon = NULL;
  76. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  77. wc.hbrBackground = NULL;
  78. wc.lpszMenuName = NULL;
  79. return (RegisterClass(&wc) || (GetLastError() == ERROR_CLASS_ALREADY_EXISTS));
  80. }
  81. //---------------------------------------------------------------------------//
  82. void GetRectInParent(HWND hwnd, PRECT prc)
  83. {
  84. HWND hwndParent = GetParent(hwnd);
  85. GetWindowRect(hwnd, prc);
  86. ScreenToClient(hwndParent, (PPOINT)prc);
  87. ScreenToClient(hwndParent, (PPOINT)&prc->right);
  88. }
  89. //---------------------------------------------------------------------------//
  90. VOID GetIconSize(HICON hIcon, PSIZE pSize)
  91. {
  92. ICONINFO iconInfo;
  93. BITMAP bmp;
  94. pSize->cx = pSize->cy = 32;
  95. if (GetIconInfo(hIcon, &iconInfo))
  96. {
  97. if (GetObject(iconInfo.hbmColor, sizeof(bmp), &bmp))
  98. {
  99. pSize->cx = bmp.bmWidth;
  100. pSize->cy = bmp.bmHeight;
  101. }
  102. DeleteObject(iconInfo.hbmMask);
  103. DeleteObject(iconInfo.hbmColor);
  104. }
  105. }
  106. //---------------------------------------------------------------------------//
  107. //
  108. // SetStaticImage()
  109. //
  110. // Sets bitmap/icon of static guy, either in response to a STM_SETxxxx
  111. // message, or at create time.
  112. //
  113. HANDLE Static_SetImage(PSTAT pstat, HANDLE hImage, BOOL fDeleteIt)
  114. {
  115. UINT bType;
  116. RECT rc;
  117. RECT rcWindow;
  118. RECT rcClient;
  119. HANDLE hImageOld;
  120. DWORD dwRate;
  121. UINT cicur;
  122. BOOL fAnimated = FALSE;
  123. HWND hwnd = pstat->hwnd;
  124. LONG dwStyle = GET_STYLE(pstat);
  125. bType = dwStyle & SS_TYPEMASK;
  126. GetClientRect(hwnd, &rcClient);
  127. //
  128. // If this is an old-ani-icon, then delete its timer.
  129. //
  130. if ((bType == SS_ICON) && pstat->cicur > 1)
  131. {
  132. //
  133. // Old cursor was an animated cursor, so kill
  134. // the timer that is used to animate it.
  135. //
  136. KillTimer(hwnd, IDSYS_STANIMATE);
  137. }
  138. //
  139. // Initialize the old-image return value.
  140. //
  141. hImageOld = pstat->hImage;
  142. rc.right = rc.bottom = 0;
  143. if (hImage != NULL)
  144. {
  145. switch (bType)
  146. {
  147. case SS_ENHMETAFILE:
  148. {
  149. //
  150. // We do NOT resize the window.
  151. //
  152. rc.right = rcClient.right - rcClient.left;
  153. rc.bottom = rcClient.bottom - rcClient.top;
  154. break;
  155. }
  156. case SS_BITMAP:
  157. {
  158. BITMAP bmp;
  159. pstat->fAlphaImage = FALSE;
  160. if (GetObject(hImage, sizeof(BITMAP), &bmp))
  161. {
  162. rc.right = bmp.bmWidth;
  163. rc.bottom = bmp.bmHeight;
  164. if (bmp.bmBitsPixel == 32)
  165. {
  166. HDC hdc = CreateCompatibleDC(NULL);
  167. if (hdc)
  168. {
  169. RGBQUAD* prgb;
  170. HBITMAP hbmpImage32 = CreateDIB(hdc, bmp.bmWidth, bmp.bmHeight, &prgb);
  171. if (hbmpImage32)
  172. {
  173. HDC hdc32 = CreateCompatibleDC(hdc);
  174. if (hdc32)
  175. {
  176. HBITMAP hbmpOld = (HBITMAP)SelectObject(hdc32, hbmpImage32);
  177. HBITMAP hbmpTemp = (HBITMAP)SelectObject(hdc, hImage);
  178. BitBlt(hdc32, 0, 0, bmp.bmWidth, bmp.bmHeight, hdc, 0, 0, SRCCOPY);
  179. SelectObject(hdc, hbmpTemp);
  180. SelectObject(hdc32, hbmpOld);
  181. DeleteDC(hdc32);
  182. if (DIBHasAlpha(bmp.bmWidth, bmp.bmHeight, prgb))
  183. {
  184. PreProcessDIB(bmp.bmWidth, bmp.bmHeight, prgb);
  185. if (fDeleteIt)
  186. DeleteObject(hImage);
  187. pstat->fAlphaImage = TRUE;
  188. hImage = hbmpImage32;
  189. hbmpImage32 = NULL;
  190. fDeleteIt = TRUE;
  191. }
  192. }
  193. if (hbmpImage32)
  194. DeleteObject(hbmpImage32);
  195. }
  196. DeleteDC(hdc);
  197. }
  198. }
  199. }
  200. break;
  201. }
  202. case SS_ICON:
  203. {
  204. SIZE size;
  205. GetIconSize((HICON)hImage, &size);
  206. rc.right = size.cx;
  207. rc.bottom = size.cy;
  208. pstat->cicur = 0;
  209. pstat->iicur = 0;
  210. //
  211. // Perhaps we can do something like shell\cpl\main\mouseptr.c
  212. // here, and make GetCursorFrameInfo obsolete.
  213. //
  214. if (GetCursorFrameInfo(hImage, NULL, 0, &dwRate, &cicur))
  215. {
  216. fAnimated = (cicur > 1);
  217. pstat->cicur = cicur;
  218. }
  219. break;
  220. }
  221. }
  222. }
  223. pstat->hImage = hImage;
  224. pstat->fDeleteIt = fDeleteIt;
  225. //
  226. // Resize static to fit.
  227. // Do NOT do this for SS_CENTERIMAGE or SS_REALSIZECONTROL
  228. //
  229. if (!(dwStyle & SS_CENTERIMAGE) && !(dwStyle & SS_REALSIZECONTROL))
  230. {
  231. //
  232. // Get current window rect in parent's client coordinates.
  233. //
  234. GetRectInParent(hwnd, &rcWindow);
  235. //
  236. // Get new window dimensions
  237. //
  238. rc.left = 0;
  239. rc.top = 0;
  240. if (rc.right && rc.bottom)
  241. {
  242. AdjustWindowRectEx(&rc, dwStyle, FALSE, GET_EXSTYLE(pstat));
  243. rc.right -= rc.left;
  244. rc.bottom -= rc.top;
  245. }
  246. SetWindowPos(hwnd, HWND_TOP,
  247. 0, 0, rc.right, rc.bottom,
  248. SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
  249. }
  250. if (IsWindowVisible(hwnd))
  251. {
  252. InvalidateRect(hwnd, NULL, TRUE);
  253. UpdateWindow(hwnd);
  254. }
  255. //
  256. // If this is an aimated-icon, then start the timer for
  257. // the animation sequence.
  258. //
  259. if(fAnimated)
  260. {
  261. //
  262. // Perhaps we can do something like shell\cpl\main\mouseptr.c
  263. // here, and make GetCursorFrameInfo obsolete.
  264. //
  265. GetCursorFrameInfo(pstat->hImage, NULL, pstat->iicur, &dwRate, &cicur);
  266. dwRate = max(200, dwRate * 100 / 6);
  267. SetTimer(hwnd, IDSYS_STANIMATE, dwRate, NULL);
  268. }
  269. return hImageOld;
  270. }
  271. //---------------------------------------------------------------------------//
  272. //
  273. // Static_LoadImage()
  274. //
  275. // Loads the icon or bitmap from the app's resource file if a name was
  276. // specified in the dialog template. We assume that the name is the name
  277. // of the resource to load.
  278. //
  279. VOID Static_LoadImage(PSTAT pstat, LPTSTR lpszName)
  280. {
  281. HANDLE hImage = NULL;
  282. HWND hwnd = pstat->hwnd;
  283. ULONG ulStyle = GET_STYLE(pstat);
  284. HINSTANCE hInstance = (HINSTANCE) GetWindowInstance(hwnd);
  285. if (lpszName && *lpszName)
  286. {
  287. //
  288. // Only try to load the icon/bitmap if the string is non null.
  289. //
  290. if (*(BYTE *)lpszName == 0xFF)
  291. {
  292. lpszName = (TCHAR*)MAKEINTRESOURCE(((LPWORD)lpszName)[1]);
  293. }
  294. //
  295. // Load the image. If it can't be found in the app, try the
  296. // display driver.
  297. //
  298. if (lpszName)
  299. {
  300. switch ((ulStyle & SS_TYPEMASK))
  301. {
  302. case SS_BITMAP:
  303. hImage = LoadBitmap(hInstance, lpszName);
  304. //
  305. // If the above didn't load it, try loading it from the
  306. // display driver (hmod == NULL).
  307. //
  308. if (hImage == NULL)
  309. {
  310. hImage = LoadBitmap(NULL, lpszName);
  311. }
  312. break;
  313. case SS_ICON:
  314. if ((ulStyle & SS_REALSIZEIMAGE))
  315. {
  316. hImage = LoadImage(hInstance, lpszName, IMAGE_ICON, 0, 0, 0);
  317. }
  318. else
  319. {
  320. hImage = LoadIcon(hInstance, lpszName);
  321. //
  322. // We will also try to load a cursor-format if the
  323. // window is a 4.0 compatible. Icons/Cursors are really
  324. // the same. We don't do this for 3.x apps for the
  325. // usual compatibility reasons.
  326. //
  327. if ((hImage == NULL))
  328. {
  329. hImage = LoadCursor(hInstance, lpszName);
  330. }
  331. //
  332. // If the above didn't load it, try loading it from the
  333. // display driver (hmod == NULL).
  334. //
  335. if (hImage == NULL)
  336. {
  337. hImage = LoadIcon(NULL, lpszName);
  338. }
  339. }
  340. break;
  341. }
  342. //
  343. // Set the image if it was loaded.
  344. //
  345. if (hImage)
  346. {
  347. Static_SetImage(pstat, hImage, TRUE);
  348. }
  349. }
  350. }
  351. }
  352. //---------------------------------------------------------------------------//
  353. //
  354. // Static_DrawStateCB()
  355. //
  356. // Draws text statics, called by DrawState.
  357. //
  358. BOOL CALLBACK Static_DrawStateCB(HDC hdc, LPARAM lParam, WPARAM wParam, int cx, int cy)
  359. {
  360. BOOL fRet = FALSE;
  361. PSTAT pstat = (PSTAT)lParam;
  362. if (pstat)
  363. {
  364. INT cchName = GetWindowTextLength(pstat->hwnd);
  365. if (cchName > 0)
  366. {
  367. LPTSTR pszName = (LPTSTR)UserLocalAlloc(HEAP_ZERO_MEMORY, (cchName+1)*SIZEOF(TCHAR));
  368. if (pszName)
  369. {
  370. UINT uDTFlags = DT_NOCLIP|DT_EXPANDTABS;
  371. ULONG ulStyle = GET_STYLE(pstat);
  372. BYTE bType = (BYTE)(ulStyle & SS_TYPEMASK);
  373. RECT rc;
  374. SetRect(&rc, 0, 0, cx, cy);
  375. GetWindowText(pstat->hwnd, pszName, cchName+1);
  376. if (bType != LOBYTE(SS_LEFTNOWORDWRAP))
  377. {
  378. uDTFlags |= DT_WORDBREAK;
  379. uDTFlags |= (UINT)(bType - LOBYTE(SS_LEFT));
  380. if (TESTFLAG(ulStyle, SS_EDITCONTROL))
  381. {
  382. uDTFlags |= DT_EDITCONTROL;
  383. }
  384. }
  385. switch (ulStyle & SS_ELLIPSISMASK)
  386. {
  387. case SS_WORDELLIPSIS:
  388. uDTFlags |= DT_WORD_ELLIPSIS | DT_SINGLELINE;
  389. break;
  390. case SS_PATHELLIPSIS:
  391. uDTFlags |= DT_PATH_ELLIPSIS | DT_SINGLELINE;
  392. break;
  393. case SS_ENDELLIPSIS:
  394. uDTFlags |= DT_END_ELLIPSIS | DT_SINGLELINE;
  395. break;
  396. }
  397. if (TESTFLAG(ulStyle, SS_NOPREFIX))
  398. {
  399. uDTFlags |= DT_NOPREFIX;
  400. }
  401. if (TESTFLAG(ulStyle, SS_CENTERIMAGE))
  402. {
  403. uDTFlags |= DT_VCENTER | DT_SINGLELINE;
  404. }
  405. if (TESTFLAG(GET_EXSTYLE(pstat), WS_EXP_UIACCELHIDDEN))
  406. {
  407. uDTFlags |= DT_HIDEPREFIX;
  408. }
  409. else if (pstat->fPaintKbdCuesOnly)
  410. {
  411. uDTFlags |= DT_PREFIXONLY;
  412. }
  413. if (!pstat->hTheme)
  414. {
  415. DrawText(hdc, pszName, cchName, &rc, uDTFlags);
  416. }
  417. else
  418. {
  419. DrawThemeText(pstat->hTheme,
  420. hdc,
  421. 0,
  422. 0,
  423. pszName,
  424. cchName,
  425. uDTFlags,
  426. 0,
  427. &rc);
  428. }
  429. UserLocalFree(pszName);
  430. }
  431. }
  432. fRet = TRUE;
  433. }
  434. return fRet;
  435. }
  436. //---------------------------------------------------------------------------//
  437. void Static_Paint(PSTAT pstat, HDC hdc, BOOL fClip)
  438. {
  439. HWND hwndParent;
  440. RECT rc;
  441. UINT cmd;
  442. BYTE bType;
  443. BOOL fFont;
  444. HBRUSH hbrControl;
  445. UINT oldAlign;
  446. DWORD dwOldLayout=0;
  447. HANDLE hfontOld = NULL;
  448. HWND hwnd = pstat->hwnd;
  449. ULONG ulStyle = GET_STYLE(pstat);
  450. ULONG ulExStyle = GET_EXSTYLE(pstat);
  451. if (ulExStyle & WS_EX_RTLREADING)
  452. {
  453. oldAlign = GetTextAlign(hdc);
  454. SetTextAlign(hdc, oldAlign | TA_RTLREADING);
  455. }
  456. bType = (BYTE)(ulStyle & SS_TYPEMASK);
  457. GetClientRect(hwnd, &rc);
  458. if (fClip)
  459. {
  460. IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
  461. }
  462. fFont = (rgstk[bType] & STK_USEFONT) && (pstat->hFont != NULL);
  463. if (fFont)
  464. {
  465. hfontOld = SelectObject(hdc, pstat->hFont);
  466. }
  467. //
  468. // Send WM_CTLCOLORSTATIC to all statics (even frames) for 1.03
  469. // compatibility.
  470. //
  471. SetBkMode(hdc, OPAQUE);
  472. hbrControl = (HBRUSH)SendMessage(GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd);
  473. //
  474. // Do we erase the background? We don't for SS_OWNERDRAW
  475. // and STK_GRAPHIC kind of things.
  476. //
  477. hwndParent = GetParent(hwnd);
  478. if ((rgstk[bType] & STK_ERASE) &&
  479. !pstat->fPaintKbdCuesOnly &&
  480. !pstat->hTheme)
  481. {
  482. FillRect(hdc, &rc, hbrControl);
  483. }
  484. switch (LOBYTE(bType))
  485. {
  486. case SS_ICON:
  487. if (pstat->hImage)
  488. {
  489. int cx;
  490. int cy;
  491. if (ulExStyle & WS_EX_LAYOUTRTL)
  492. {
  493. dwOldLayout = SetLayoutWidth(hdc, -1, 0);
  494. }
  495. //
  496. // Perform the correct rect-setup.
  497. //
  498. if (ulStyle & SS_CENTERIMAGE)
  499. {
  500. SIZE size;
  501. GetIconSize((HICON)pstat->hImage, &size);
  502. cx = size.cx;
  503. cy = size.cy;
  504. rc.left = (rc.right - cx) / 2;
  505. rc.right = (rc.left + cx);
  506. rc.top = (rc.bottom - cy) / 2;
  507. rc.bottom = (rc.top + cy);
  508. }
  509. else
  510. {
  511. cx = rc.right - rc.left;
  512. cy = rc.bottom - rc.top;
  513. }
  514. DrawIconEx(hdc, rc.left, rc.top, (HICON)pstat->hImage, cx, cy,
  515. pstat->iicur, pstat->hTheme ? NULL : hbrControl, DI_NORMAL);
  516. if (ulExStyle & WS_EX_LAYOUTRTL)
  517. {
  518. SetLayoutWidth(hdc, -1, dwOldLayout);
  519. }
  520. }
  521. else
  522. {
  523. // Empty! Need to erase.
  524. FillRect(hdc, &rc, hbrControl);
  525. }
  526. break;
  527. case SS_BITMAP:
  528. if (pstat->hImage)
  529. {
  530. BITMAP bmp;
  531. //
  532. // Get the bitmap information. If this fails, then we
  533. // can assume somethings wrong with its format...don't
  534. // draw in this case.
  535. //
  536. if (GetObject(pstat->hImage, sizeof(BITMAP), &bmp))
  537. {
  538. HDC hdcT;
  539. if (ulStyle & SS_CENTERIMAGE)
  540. {
  541. rc.left = (rc.right - bmp.bmWidth) >> 1;
  542. rc.right = (rc.left + bmp.bmWidth);
  543. rc.top = (rc.bottom - bmp.bmHeight) >> 1;
  544. rc.bottom = (rc.top + bmp.bmHeight);
  545. }
  546. //
  547. // Select in the bitmap and blt it to the client-surface.
  548. //
  549. hdcT = CreateCompatibleDC(hdc);
  550. if (hdcT)
  551. {
  552. HBITMAP hbmpT = (HBITMAP)SelectObject(hdcT, pstat->hImage);
  553. if (pstat->fAlphaImage)
  554. {
  555. BLENDFUNCTION bf = {0};
  556. bf.BlendOp = AC_SRC_OVER;
  557. bf.SourceConstantAlpha = 255;
  558. bf.AlphaFormat = AC_SRC_ALPHA;
  559. bf.BlendFlags = 0;
  560. GdiAlphaBlend(hdc, rc.left, rc.top, rc.right-rc.left,
  561. rc.bottom-rc.top, hdcT, 0, 0, bmp.bmWidth, bmp.bmHeight, bf);
  562. }
  563. else
  564. {
  565. // I'm assuming people try to match the color to the dialog
  566. GdiTransparentBlt(hdc, rc.left, rc.top, rc.right-rc.left,
  567. rc.bottom-rc.top, hdcT, 0, 0, bmp.bmWidth,
  568. bmp.bmHeight, GetSysColor(COLOR_BTNFACE));
  569. }
  570. if (hbmpT)
  571. {
  572. SelectObject(hdcT, hbmpT);
  573. }
  574. DeleteDC(hdcT);
  575. }
  576. }
  577. }
  578. break;
  579. case SS_ENHMETAFILE:
  580. if (pstat->hImage)
  581. {
  582. RECT rcl;
  583. rcl.left = rc.left;
  584. rcl.top = rc.top;
  585. rcl.right = rc.right;
  586. rcl.bottom = rc.bottom;
  587. PlayEnhMetaFile(hdc, (HENHMETAFILE)pstat->hImage, &rcl);
  588. }
  589. break;
  590. case SS_OWNERDRAW:
  591. {
  592. DRAWITEMSTRUCT dis;
  593. dis.CtlType = ODT_STATIC;
  594. dis.CtlID = GetDlgCtrlID(hwnd);
  595. dis.itemAction = ODA_DRAWENTIRE;
  596. dis.itemState = IsWindowVisible(hwnd) ? ODS_DISABLED : 0;
  597. dis.hwndItem = hwnd;
  598. dis.hDC = hdc;
  599. dis.itemData = 0L;
  600. dis.rcItem = rc;
  601. if (TESTFLAG(GET_EXSTYLE(pstat), WS_EXP_UIACCELHIDDEN))
  602. {
  603. dis.itemState |= ODS_NOACCEL;
  604. }
  605. //
  606. // Send a WM_DRAWITEM message to the parent.
  607. //
  608. SendMessage(hwndParent, WM_DRAWITEM, (WPARAM)dis.CtlID, (LPARAM)&dis);
  609. break;
  610. }
  611. case SS_LEFT:
  612. case SS_CENTER:
  613. case SS_RIGHT:
  614. case SS_LEFTNOWORDWRAP:
  615. if (GetWindowTextLength(hwnd))
  616. {
  617. UINT dstFlags;
  618. dstFlags = DST_COMPLEX;
  619. if (!IsWindowEnabled(hwnd))
  620. {
  621. dstFlags |= DSS_DISABLED;
  622. }
  623. DrawState(hdc, GetSysColorBrush(COLOR_WINDOWTEXT),
  624. (DRAWSTATEPROC)Static_DrawStateCB,(LPARAM)pstat, (WPARAM)TRUE,
  625. rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
  626. dstFlags);
  627. }
  628. break;
  629. case SS_SIMPLE:
  630. {
  631. LPWSTR pszText = NULL;
  632. INT cchText;
  633. //
  634. // The "Simple" bType assumes everything, including the following:
  635. // 1. The Text exists and fits on one line.
  636. // 2. The Static item is always enabled.
  637. // 3. The Static item is never changed to be a shorter string.
  638. // 4. The Parent never responds to the CTLCOLOR message
  639. //
  640. cchText = max(GetWindowTextLength(hwnd), 0);
  641. pszText = (LPTSTR)UserLocalAlloc(HEAP_ZERO_MEMORY, (cchText+1)*SIZEOF(WCHAR));
  642. if (pszText)
  643. {
  644. if (cchText > 0)
  645. {
  646. cchText = GetWindowText(hwnd, pszText, cchText+1);
  647. }
  648. else
  649. {
  650. *pszText = 0;
  651. }
  652. if (ulStyle & SS_NOPREFIX && !pstat->hTheme)
  653. {
  654. ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE | ETO_CLIPPED, &rc, pszText, cchText, 0L);
  655. }
  656. else
  657. {
  658. //
  659. // Use OPAQUE for speed.
  660. //
  661. DWORD dwFlags;
  662. if (TESTFLAG(GET_EXSTYLE(pstat), WS_EXP_UIACCELHIDDEN))
  663. {
  664. dwFlags = DT_HIDEPREFIX;
  665. }
  666. else if (pstat->fPaintKbdCuesOnly)
  667. {
  668. dwFlags = DT_PREFIXONLY;
  669. }
  670. else if (ulStyle & SS_NOPREFIX)
  671. {
  672. dwFlags = DT_NOPREFIX;
  673. }
  674. else
  675. {
  676. dwFlags = 0;
  677. }
  678. if (!pstat->hTheme)
  679. {
  680. TextOut(hdc, rc.left, rc.top, pszText, cchText);
  681. }
  682. else
  683. {
  684. DrawThemeText(pstat->hTheme, hdc, 0, 0, pszText, cchText, dwFlags, 0, &rc);
  685. }
  686. }
  687. UserLocalFree(pszText);
  688. }
  689. break;
  690. }
  691. case SS_BLACKFRAME:
  692. cmd = (COLOR_3DDKSHADOW << 3);
  693. goto StatFrame;
  694. case SS_GRAYFRAME:
  695. cmd = (COLOR_3DSHADOW << 3);
  696. goto StatFrame;
  697. case SS_WHITEFRAME:
  698. cmd = (COLOR_3DHILIGHT << 3);
  699. StatFrame:
  700. DrawFrame(hdc, &rc, 1, cmd);
  701. break;
  702. case SS_BLACKRECT:
  703. hbrControl = GetSysColorBrush(COLOR_3DDKSHADOW);
  704. goto StatRect;
  705. case SS_GRAYRECT:
  706. hbrControl = GetSysColorBrush(COLOR_3DSHADOW);
  707. goto StatRect;
  708. case SS_WHITERECT:
  709. hbrControl = GetSysColorBrush(COLOR_3DHILIGHT);
  710. StatRect:
  711. FillRect(hdc, &rc, hbrControl);
  712. break;
  713. case SS_ETCHEDFRAME:
  714. DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT);
  715. break;
  716. }
  717. if (hfontOld)
  718. {
  719. SelectObject(hdc, hfontOld);
  720. }
  721. if (ulExStyle & WS_EX_RTLREADING)
  722. {
  723. SetTextAlign(hdc, oldAlign);
  724. }
  725. }
  726. //---------------------------------------------------------------------------//
  727. void Static_Repaint(PSTAT pstat)
  728. {
  729. HWND hwnd = pstat->hwnd;
  730. if (IsWindowVisible(hwnd))
  731. {
  732. HDC hdc;
  733. if (hdc = GetDC(hwnd))
  734. {
  735. Static_Paint(pstat, hdc, TRUE);
  736. ReleaseDC(hwnd, hdc);
  737. }
  738. }
  739. }
  740. //---------------------------------------------------------------------------//
  741. //
  742. // Static_NotifyParent()
  743. //
  744. // Sends WM_COMMAND notification messages.
  745. //
  746. LRESULT Static_NotifyParent(HWND hwnd, HWND hwndParent, int nCode)
  747. {
  748. LRESULT lret;
  749. if (!hwndParent)
  750. {
  751. hwndParent = GetParent(hwnd);
  752. }
  753. lret = SendMessage(hwndParent, WM_COMMAND,
  754. MAKELONG(GetDlgCtrlID(hwnd), nCode), (LPARAM)hwnd);
  755. return lret;
  756. }
  757. //---------------------------------------------------------------------------//
  758. //
  759. // Static_AniIconStep
  760. //
  761. // Advances to the next step in an animaged icon.
  762. //
  763. VOID Static_AniIconStep(PSTAT pstat)
  764. {
  765. DWORD dwRate;
  766. HWND hwnd = pstat->hwnd;
  767. dwRate = 0;
  768. //
  769. // Stop the timer for the next animation step.
  770. //
  771. KillTimer(hwnd, IDSYS_STANIMATE);
  772. if (++(pstat->iicur) >= pstat->cicur)
  773. {
  774. pstat->iicur = 0;
  775. }
  776. //
  777. // Perhaps we can do something like shell\cpl\main\mouseptr.c
  778. // here, and make GetCursorFrameInfo obsolete.
  779. //
  780. GetCursorFrameInfo(pstat->hImage, NULL, pstat->iicur, &dwRate, &pstat->cicur);
  781. dwRate = max(200, dwRate * 100 / 6);
  782. InvalidateRect(hwnd, NULL, FALSE);
  783. UpdateWindow(hwnd);
  784. SetTimer(hwnd, IDSYS_STANIMATE, dwRate, NULL);
  785. }
  786. //---------------------------------------------------------------------------//
  787. //
  788. // Static_WndProc
  789. //
  790. // WndProc for Static controls
  791. //
  792. LRESULT APIENTRY Static_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  793. {
  794. PSTAT pstat;
  795. LRESULT lReturn = FALSE;
  796. //
  797. // Get the instance data for this static control
  798. //
  799. pstat = Static_GetPtr(hwnd);
  800. if (!pstat && uMsg != WM_NCCREATE)
  801. {
  802. goto CallDWP;
  803. }
  804. switch (uMsg)
  805. {
  806. case STM_GETICON:
  807. wParam = IMAGE_ICON;
  808. case STM_GETIMAGE:
  809. if (IsValidImage(wParam, (GET_STYLE(pstat) & SS_TYPEMASK), IMAGE_STMMAX))
  810. {
  811. return (LRESULT)pstat->hImage;
  812. }
  813. break;
  814. case STM_SETICON:
  815. lParam = (LPARAM)wParam;
  816. wParam = IMAGE_ICON;
  817. case STM_SETIMAGE:
  818. if (IsValidImage(wParam, (GET_STYLE(pstat) & SS_TYPEMASK), IMAGE_STMMAX))
  819. {
  820. return (LRESULT)Static_SetImage(pstat, (HANDLE)lParam, FALSE);
  821. }
  822. break;
  823. case WM_ERASEBKGND:
  824. //
  825. // The control will be erased in Static_Paint().
  826. //
  827. return TRUE;
  828. case WM_PRINTCLIENT:
  829. Static_Paint(pstat, (HDC)wParam, FALSE);
  830. break;
  831. case WM_PAINT:
  832. {
  833. HDC hdc;
  834. PAINTSTRUCT ps;
  835. hdc = (HDC)wParam;
  836. if (hdc == NULL)
  837. {
  838. hdc = BeginPaint(hwnd, &ps);
  839. }
  840. if (IsWindowVisible(hwnd))
  841. {
  842. Static_Paint(pstat, hdc, !wParam);
  843. }
  844. //
  845. // If hwnd was destroyed, BeginPaint was automatically undone.
  846. //
  847. if (!wParam)
  848. {
  849. EndPaint(hwnd, &ps);
  850. }
  851. break;
  852. }
  853. case WM_CREATE:
  854. {
  855. BYTE bType = (BYTE)(GET_STYLE(pstat) & SS_TYPEMASK);
  856. pstat->hTheme = OpenThemeData(pstat->hwnd, L"Static");
  857. EnableThemeDialogTexture(GetParent(pstat->hwnd), ETDT_ENABLE);
  858. if ((rgstk[bType] & STK_TYPE) == STK_IMAGE)
  859. {
  860. LPTSTR lpszName;
  861. lpszName = (LPTSTR)(((LPCREATESTRUCT)lParam)->lpszName);
  862. //
  863. // Load the image
  864. //
  865. Static_LoadImage(pstat, lpszName);
  866. }
  867. else if (bType == SS_ETCHEDHORZ || bType == SS_ETCHEDVERT)
  868. {
  869. //
  870. // Resize static window to fit edge. Horizontal dudes
  871. // make bottom one edge from top, vertical dudes make
  872. // right edge one edge from left.
  873. //
  874. RECT rcClient;
  875. GetClientRect(hwnd, &rcClient);
  876. if (bType == SS_ETCHEDHORZ)
  877. {
  878. rcClient.bottom = GetSystemMetrics(SM_CYEDGE);
  879. }
  880. else
  881. {
  882. rcClient.right = GetSystemMetrics(SM_CXEDGE);
  883. }
  884. SetWindowPos(hwnd, HWND_TOP, 0, 0, rcClient.right,
  885. rcClient.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  886. }
  887. break;
  888. }
  889. case WM_DESTROY:
  890. {
  891. BYTE bType = (BYTE)(GET_STYLE(pstat) & SS_TYPEMASK);
  892. if (((rgstk[bType] & STK_TYPE) == STK_IMAGE) &&
  893. (pstat->hImage != NULL) &&
  894. (pstat->fDeleteIt))
  895. {
  896. if (bType == SS_BITMAP)
  897. {
  898. DeleteObject(pstat->hImage);
  899. }
  900. else if (bType == SS_ICON)
  901. {
  902. if (pstat->cicur > 1)
  903. {
  904. // Kill the animated cursor timer
  905. KillTimer(hwnd, IDSYS_STANIMATE);
  906. }
  907. DestroyIcon((HICON)(pstat->hImage));
  908. }
  909. }
  910. break;
  911. }
  912. case WM_NCCREATE:
  913. //
  914. // Allocate the static instance stucture
  915. //
  916. pstat = (PSTAT)UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(STAT));
  917. if (pstat)
  918. {
  919. DWORD dwStyle;
  920. DWORD dwExStyle;
  921. BYTE bType;
  922. //
  923. // Success... store the instance pointer.
  924. //
  925. TraceMsg(TF_STANDARD, "STATIC: Setting static instance pointer.");
  926. Static_SetPtr(hwnd, pstat);
  927. pstat->hwnd = hwnd;
  928. pstat->pww = (PWW)GetWindowLongPtr(hwnd, GWLP_WOWWORDS);
  929. dwStyle = GET_STYLE(pstat);
  930. dwExStyle = GET_EXSTYLE(pstat);
  931. bType = (BYTE)(dwStyle & SS_TYPEMASK);
  932. if ((dwExStyle & WS_EX_RIGHT) != 0)
  933. {
  934. AlterWindowStyle(hwnd, SS_TYPEMASK, SS_RIGHT);
  935. }
  936. if (dwStyle & SS_SUNKEN ||
  937. ((bType == LOBYTE(SS_ETCHEDHORZ)) || (bType == LOBYTE(SS_ETCHEDVERT))))
  938. {
  939. dwExStyle |= WS_EX_STATICEDGE;
  940. SetWindowLong(hwnd, GWL_EXSTYLE, dwExStyle);
  941. }
  942. goto CallDWP;
  943. }
  944. else
  945. {
  946. //
  947. // Failed... return FALSE.
  948. //
  949. // From a WM_NCCREATE msg, this will cause the
  950. // CreateWindow call to fail.
  951. //
  952. TraceMsg(TF_STANDARD, "STATIC: Unable to allocate static instance structure.");
  953. lReturn = FALSE;
  954. }
  955. break;
  956. case WM_NCDESTROY:
  957. if ( pstat->hTheme )
  958. {
  959. CloseThemeData(pstat->hTheme);
  960. }
  961. UserLocalFree(pstat);
  962. TraceMsg(TF_STANDARD, "STATIC: Clearing static instance pointer.");
  963. Static_SetPtr(hwnd, NULL);
  964. break;
  965. case WM_NCHITTEST:
  966. return (GET_STYLE(pstat) & SS_NOTIFY) ? HTCLIENT : HTTRANSPARENT;
  967. case WM_LBUTTONDOWN:
  968. case WM_NCLBUTTONDOWN:
  969. if (GET_STYLE(pstat) & SS_NOTIFY)
  970. {
  971. //
  972. // It is acceptable for an app to destroy a static label
  973. // in response to a STN_CLICKED notification.
  974. //
  975. Static_NotifyParent(hwnd, NULL, STN_CLICKED);
  976. }
  977. break;
  978. case WM_LBUTTONDBLCLK:
  979. case WM_NCLBUTTONDBLCLK:
  980. if (GET_STYLE(pstat) & SS_NOTIFY)
  981. {
  982. //
  983. // It is acceptable for an app to destroy a static label in
  984. // response to a STN_DBLCLK notification.
  985. //
  986. Static_NotifyParent(hwnd, NULL, STN_DBLCLK);
  987. }
  988. break;
  989. case WM_SETTEXT:
  990. {
  991. BYTE bType = (BYTE)(GET_STYLE(pstat) & SS_TYPEMASK);
  992. //
  993. // No more hack to set icon/bitmap via WM_SETTEXT!
  994. //
  995. if (rgstk[bType] & STK_USETEXT)
  996. {
  997. if (DefWindowProc(hwnd, WM_SETTEXT, wParam, lParam))
  998. {
  999. Static_Repaint(pstat);
  1000. return TRUE;
  1001. }
  1002. }
  1003. break;
  1004. }
  1005. case WM_ENABLE:
  1006. Static_Repaint(pstat);
  1007. if (GET_STYLE(pstat) & SS_NOTIFY)
  1008. {
  1009. Static_NotifyParent(hwnd, NULL, (wParam ? STN_ENABLE : STN_DISABLE));
  1010. }
  1011. break;
  1012. case WM_GETDLGCODE:
  1013. return (LONG)DLGC_STATIC;
  1014. case WM_SETFONT:
  1015. {
  1016. BYTE bType = (BYTE)(GET_STYLE(pstat) & SS_TYPEMASK);
  1017. //
  1018. // wParam - handle to the font
  1019. // lParam - if true, redraw else don't
  1020. //
  1021. if (rgstk[bType] & STK_USEFONT)
  1022. {
  1023. pstat->hFont = (HANDLE)wParam;
  1024. if (lParam && IsWindowVisible(hwnd))
  1025. {
  1026. InvalidateRect(hwnd, NULL, TRUE);
  1027. UpdateWindow(hwnd);
  1028. }
  1029. }
  1030. break;
  1031. }
  1032. case WM_GETFONT:
  1033. {
  1034. BYTE bType = (BYTE)(GET_STYLE(pstat) & SS_TYPEMASK);
  1035. if (rgstk[bType] & STK_USEFONT)
  1036. {
  1037. return (LRESULT)pstat->hFont;
  1038. }
  1039. break;
  1040. }
  1041. case WM_TIMER:
  1042. if (wParam == IDSYS_STANIMATE)
  1043. {
  1044. Static_AniIconStep(pstat);
  1045. }
  1046. break;
  1047. case WM_UPDATEUISTATE:
  1048. {
  1049. DefWindowProc(hwnd, uMsg, wParam, lParam);
  1050. if (HIWORD(wParam) & UISF_HIDEACCEL)
  1051. {
  1052. BYTE bType = (BYTE)(GET_STYLE(pstat) & SS_TYPEMASK);
  1053. if (ISSSTEXTOROD(bType))
  1054. {
  1055. pstat->fPaintKbdCuesOnly = TRUE;
  1056. Static_Repaint(pstat);
  1057. pstat->fPaintKbdCuesOnly = FALSE;
  1058. }
  1059. }
  1060. }
  1061. break;
  1062. case WM_GETOBJECT:
  1063. if(lParam == OBJID_QUERYCLASSNAMEIDX)
  1064. {
  1065. lReturn = MSAA_CLASSNAMEIDX_STATIC;
  1066. }
  1067. else
  1068. {
  1069. lReturn = FALSE;
  1070. }
  1071. break;
  1072. case WM_THEMECHANGED:
  1073. if ( pstat->hTheme )
  1074. {
  1075. CloseThemeData(pstat->hTheme);
  1076. }
  1077. pstat->hTheme = OpenThemeData(pstat->hwnd, L"Static");
  1078. InvalidateRect(pstat->hwnd, NULL, TRUE);
  1079. lReturn = TRUE;
  1080. break;
  1081. default:
  1082. CallDWP:
  1083. lReturn = DefWindowProc(hwnd, uMsg, wParam, lParam);
  1084. }
  1085. return lReturn;
  1086. }