listWidgetPaint.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. #include "main.h"
  2. #include "./listWidgetInternal.h"
  3. #include <strsafe.h>
  4. static BOOL
  5. ListWidgetPaintSpacebar_Initialize(ListWidgetPaintSpacebar *self, ListWidget *widget,
  6. WidgetStyle *style, HWND hwnd, long width, long height)
  7. {
  8. if (NULL == self)
  9. return FALSE;
  10. self->bitmap = ListWidget_GetSpacebarBitmap(widget, style, hwnd, width, height);
  11. if (NULL == self->bitmap)
  12. {
  13. self->width = 0;
  14. self->height = 0;
  15. self->emptyBarOffset = 0;
  16. self->filledBarOffset = 0;
  17. return FALSE;
  18. }
  19. self->width = width;
  20. self->height = height;
  21. self->emptyBarOffset = 0;
  22. self->filledBarOffset = height;
  23. return TRUE;
  24. }
  25. static void
  26. ListWidgetPaintSpacebar_Uninitialize(ListWidgetPaintSpacebar *self)
  27. {
  28. if (NULL == self)
  29. return;
  30. }
  31. static BOOL
  32. ListWidgetPaintArrow_Initialize(ListWidgetPaintArrow *self, ListWidget *widget,
  33. WidgetStyle *style, HWND hwnd)
  34. {
  35. BITMAP bitmapInfo;
  36. if (NULL == self)
  37. return FALSE;
  38. self->bitmap = ListWidget_GetArrowsBitmap(widget, style, hwnd);
  39. if (NULL == self->bitmap ||
  40. sizeof(bitmapInfo) != GetObject(self->bitmap, sizeof(bitmapInfo), &bitmapInfo))
  41. {
  42. ZeroMemory(self, sizeof(ListWidgetPaintArrow));
  43. return FALSE;
  44. }
  45. self->width = bitmapInfo.bmWidth;
  46. self->height = bitmapInfo.bmHeight/2;
  47. if (self->height < 0)
  48. self->height = -self->height;
  49. self->collapsedOffset = 0;
  50. self->expandedOffset = self->height;
  51. return TRUE;
  52. }
  53. static void
  54. ListWidgetPaintArrow_Uninitialize(ListWidgetPaintArrow *self)
  55. {
  56. if (NULL == self)
  57. return;
  58. }
  59. BOOL
  60. ListWidgetPaint_Initialize(ListWidgetPaint *self, ListWidget *widget, WidgetStyle *style,
  61. HWND hwnd, HDC hdc, const RECT *paintRect, BOOL erase)
  62. {
  63. HDC windowDC;
  64. if (NULL == self)
  65. return FALSE;
  66. if (NULL == widget || NULL == style)
  67. return FALSE;
  68. self->widget = widget;
  69. self->style = style;
  70. self->hwnd = hwnd;
  71. self->hdc = hdc;
  72. self->erase = erase;
  73. self->paintRect = paintRect;
  74. windowDC = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
  75. if (NULL != windowDC)
  76. {
  77. self->sourceDC = CreateCompatibleDC(windowDC);
  78. ReleaseDC(hwnd, windowDC);
  79. }
  80. if (NULL == self->sourceDC)
  81. return FALSE;
  82. if (FALSE == ListWidget_GetItemMetrics(style, &self->itemMetrics))
  83. return FALSE;
  84. if (FALSE == ListWidget_GetCategoryMetrics(style, &self->categoryMetrics))
  85. return FALSE;
  86. if (FALSE == ListWidgetPaintSpacebar_Initialize(&self->spacebar, widget, style, hwnd,
  87. widget->itemWidth - (self->itemMetrics.offsetLeft + self->itemMetrics.offsetRight),
  88. self->itemMetrics.spacebarHeight))
  89. {
  90. // ListWidgetPaint_Uninitialize(self);
  91. // return FALSE;
  92. }
  93. if (FALSE == ListWidgetPaintArrow_Initialize(&self->arrow, widget, style, hwnd))
  94. {
  95. // ListWidgetPaint_Uninitialize(self);
  96. // return FALSE;
  97. }
  98. return TRUE;
  99. }
  100. void
  101. ListWidgetPaint_Uninitialize(ListWidgetPaint *self)
  102. {
  103. if (NULL == self)
  104. return;
  105. if (NULL != self->sourceDC)
  106. DeleteDC(self->sourceDC);
  107. ListWidgetPaintSpacebar_Uninitialize(&self->spacebar);
  108. ListWidgetPaintArrow_Uninitialize(&self->arrow);
  109. }
  110. static BOOL
  111. ListWidgetPaint_DrawSpacebar(ListWidgetPaint *self, HDC hdc, int x, int y,
  112. uint64_t totalSpace, uint64_t usedSpace)
  113. {
  114. RECT *partRect, sourceRect;
  115. BOOL succeeded;
  116. long usedWidth;
  117. ListWidgetPaintSpacebar *spacebar;
  118. if (NULL == self)
  119. return FALSE;
  120. partRect = &self->partRect;
  121. spacebar = &self->spacebar;
  122. if (NULL == spacebar->bitmap)
  123. return FALSE;
  124. succeeded = TRUE;
  125. if (usedSpace > totalSpace)
  126. usedSpace = totalSpace;
  127. if (0 == totalSpace)
  128. usedWidth = 0;
  129. else
  130. usedWidth = (long)(spacebar->width * (double)usedSpace/totalSpace);
  131. SetRect(partRect, x, y, x + spacebar->width, y + spacebar->height);
  132. SetRect(&sourceRect, 0, 0, spacebar->width, spacebar->height);
  133. OffsetRect(&sourceRect, 0, spacebar->emptyBarOffset);
  134. if (FALSE == Image_AlphaBlend(hdc, partRect, self->sourceDC, &sourceRect, 255,
  135. spacebar->bitmap, self->paintRect, AlphaBlend_Normal, NULL))
  136. {
  137. succeeded = FALSE;
  138. }
  139. if (0 != usedWidth)
  140. {
  141. SetRect(partRect, x, y, x + usedWidth, y + spacebar->height);
  142. SetRect(&sourceRect, 0, 0, usedWidth, spacebar->height);
  143. OffsetRect(&sourceRect, 0, spacebar->filledBarOffset);
  144. if (FALSE == Image_AlphaBlend(hdc, partRect, self->sourceDC, &sourceRect, 255,
  145. spacebar->bitmap, self->paintRect, AlphaBlend_Normal, NULL))
  146. {
  147. succeeded = FALSE;
  148. }
  149. }
  150. return succeeded;
  151. }
  152. void
  153. ListWidgetPaint_DrawItemAction(ListWidgetPaint *self, HDC hdc, ListWidgetItem *item, ListWidgetActivity *activity)
  154. {
  155. HDC sourceDC;
  156. WidgetStyle *style;
  157. ListWidget *widget;
  158. ListWidgetItemMetric *metrics;
  159. RECT *partRect, sourceRect;
  160. HBITMAP bitmap, prevSourceBitmap;
  161. COLORREF prevTextColor;
  162. HFONT prevFont;
  163. int stringLength;
  164. if (NULL == activity ||
  165. FALSE == ListWidget_GetItemActivityRect(self->widget, item, &self->itemMetrics, &self->partRect) ||
  166. FALSE == IntersectRect(&sourceRect, &self->partRect, self->paintRect))
  167. {
  168. return;
  169. }
  170. style = self->style;
  171. widget = self->widget;
  172. metrics = &self->itemMetrics;
  173. sourceDC = self->sourceDC;
  174. partRect = &self->partRect;
  175. prevSourceBitmap = GetCurrentBitmap(sourceDC);
  176. prevTextColor = GetTextColor(hdc);
  177. prevFont = GetCurrentFont(hdc);
  178. if (NULL != widget->activityFont)
  179. SelectFont(hdc, widget->activityFont);
  180. bitmap = ListWidget_GetActivityBadgeBitmap(widget, style, self->hwnd,
  181. RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
  182. if (NULL != bitmap)
  183. {
  184. Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, self->paintRect,
  185. AlphaBlend_Normal, NULL);
  186. }
  187. if (FALSE == IS_STRING_EMPTY(activity->title) &&
  188. FALSE != ListWidget_GetItemActivityTitleRect(widget, hdc, item, metrics, partRect) &&
  189. FALSE != IntersectRect(&sourceRect, partRect, self->paintRect))
  190. {
  191. stringLength = lstrlen(activity->title);
  192. OffsetRect(partRect, 0, 1);
  193. SetTextColor(hdc, 0x000000);
  194. DrawText(hdc, activity->title, stringLength, partRect,
  195. DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_EDITCONTROL | DT_WORD_ELLIPSIS);
  196. OffsetRect(partRect, 0, -1);
  197. SetTextColor(hdc, 0xFFFFFF);
  198. DrawText(hdc, activity->title, stringLength, partRect,
  199. DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_EDITCONTROL | DT_WORD_ELLIPSIS);
  200. }
  201. if (FALSE != ListWidget_GetItemActivityProgressRect(widget, hdc, item, metrics, partRect) &&
  202. FALSE != IntersectRect(&sourceRect, partRect, self->paintRect))
  203. {
  204. bitmap = ListWidget_GetActivityProgressBitmap(widget, style);
  205. if (NULL != bitmap)
  206. {
  207. SetRect(&sourceRect, 0, 0,
  208. widget->activityMetrics.progressWidth, widget->activityMetrics.progressHeight);
  209. OffsetRect(&sourceRect, 0, widget->activityMetrics.progressHeight * activity->step);
  210. Image_AlphaBlend(hdc, partRect, sourceDC, &sourceRect, 255, bitmap, self->paintRect,
  211. AlphaBlend_Normal, NULL);
  212. }
  213. }
  214. if ((unsigned int)-1 != activity->percent &&
  215. FALSE != ListWidget_GetItemActivityPercentRect(widget, hdc, item, metrics, partRect) &&
  216. FALSE != IntersectRect(&sourceRect, partRect, self->paintRect))
  217. {
  218. wchar_t buffer[6] = {0};
  219. if (FAILED(StringCchPrintf(buffer, ARRAYSIZE(buffer), L"%d%%", activity->percent)))
  220. stringLength = 0;
  221. else
  222. stringLength = lstrlen(buffer);
  223. OffsetRect(partRect, 0, 1);
  224. SetTextColor(hdc, 0x000000);
  225. DrawText(hdc, buffer, stringLength, partRect,
  226. DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE);
  227. OffsetRect(partRect, 0, -1);
  228. SetTextColor(hdc, 0xFFFFFF);
  229. DrawText(hdc, buffer, stringLength, partRect,
  230. DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE);
  231. }
  232. SetTextColor(hdc, prevTextColor);
  233. SelectFont(hdc, prevFont);
  234. }
  235. BOOL
  236. ListWidgetPaint_DrawItem(ListWidgetPaint *self, ListWidgetItem *item)
  237. {
  238. RECT frameRect;
  239. long frameHeight, frameWidth;
  240. HDC hdc, sourceDC, bufferDC, targetDC;
  241. WidgetStyle *style;
  242. ListWidget *widget;
  243. ListWidgetItemMetric *metrics;
  244. RECT *partRect, paintRect;
  245. HBITMAP bitmap, prevSourceBitmap;
  246. if (NULL == self || NULL == item)
  247. return FALSE;
  248. hdc = self->hdc;
  249. style = self->style;
  250. widget = self->widget;
  251. metrics = &self->itemMetrics;
  252. sourceDC = self->sourceDC;
  253. partRect = &self->partRect;
  254. prevSourceBitmap = GetCurrentBitmap(sourceDC);
  255. if (FALSE == ListWidget_GetItemFrameRect(widget, item, metrics, &frameRect))
  256. return FALSE;
  257. frameWidth = RECTWIDTH(frameRect);
  258. frameHeight = RECTHEIGHT(frameRect);
  259. if (FALSE == IntersectRect(&paintRect, &item->rect, self->paintRect))
  260. return TRUE;
  261. CopyRect(partRect, &paintRect);
  262. if (FALSE != BackBuffer_EnsureSizeEx(&widget->backBuffer,
  263. RECTWIDTH(paintRect), RECTHEIGHT(paintRect),
  264. RECTWIDTH(item->rect), RECTHEIGHT(item->rect)))
  265. {
  266. bufferDC = BackBuffer_GetDC(&widget->backBuffer);
  267. if (NULL != bufferDC)
  268. {
  269. SetViewportOrgEx(bufferDC, -paintRect.left, -paintRect.top, NULL);
  270. SetTextColor(bufferDC, GetTextColor(hdc));
  271. SetBkColor(bufferDC, GetBkColor(hdc));
  272. SetBkMode(bufferDC, GetBkMode(hdc));
  273. SelectFont(bufferDC, GetCurrentFont(hdc));
  274. targetDC = hdc;
  275. hdc = bufferDC;
  276. }
  277. }
  278. else
  279. bufferDC = NULL;
  280. if (FALSE != self->erase)
  281. {
  282. FillRect(hdc, partRect, style->backBrush);
  283. }
  284. if (FALSE != ListWidgetItem_IsHovered(item))
  285. {
  286. bitmap = ListWidget_GetHoverBitmap(widget, style, self->hwnd,
  287. frameWidth, frameHeight);
  288. Image_AlphaBlend(hdc, &frameRect, sourceDC, NULL, 255, bitmap, &paintRect,
  289. AlphaBlend_Normal, NULL);
  290. }
  291. if (FALSE != ListWidgetItem_IsSelected(item))
  292. {
  293. bitmap = (GetFocus() == self->hwnd) ?
  294. ListWidget_GetSelectBitmap(widget, style, self->hwnd, frameWidth, frameHeight) :
  295. ListWidget_GetInactiveSelectBitmap(widget, style, self->hwnd, frameWidth, frameHeight);
  296. Image_AlphaBlend(hdc, &frameRect, sourceDC, NULL, 255, bitmap, &paintRect,
  297. AlphaBlend_Normal, NULL);
  298. }
  299. bitmap = ListWidget_GetItemImage(widget, style, item);
  300. if (NULL != bitmap)
  301. {
  302. partRect->left = frameRect.left + metrics->offsetLeft + metrics->imageOffsetLeft;
  303. partRect->top = frameRect.top + metrics->offsetTop + metrics->imageOffsetTop;
  304. partRect->right = frameRect.right - (metrics->offsetRight + metrics->imageOffsetRight);
  305. partRect->bottom = frameRect.bottom - metrics->imageOffsetBottom;
  306. Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, &paintRect,
  307. AlphaBlend_ScaleSource | AlphaBlend_AlignBottom, NULL);
  308. }
  309. bitmap = ListWidget_GetConnectionImage(style, item->connection,
  310. widget->connectionSize.cx, widget->connectionSize.cy);
  311. if (NULL != bitmap &&
  312. FALSE != ListWidget_GetItemConnectionRect(widget, item, metrics, partRect))
  313. {
  314. Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, &paintRect,
  315. AlphaBlend_AlignCenter | AlphaBlend_AlignBottom, NULL);
  316. }
  317. ListWidgetPaint_DrawItemAction(self, hdc, item, item->activity);
  318. if (FALSE != ListWidgetItem_IsInteractive(item) && 0 != widget->commandsCount)
  319. {
  320. HBITMAP commandBitmap;
  321. size_t index;
  322. RECT commandPaintRect;
  323. bitmap = NULL;
  324. for(index = 0; index < widget->commandsCount; index++)
  325. {
  326. long offset;
  327. BYTE sourceAlpha;
  328. ListWidget_GetCommandRect(widget->commands[index], partRect);
  329. OffsetRect(partRect, frameRect.left, frameRect.top);
  330. if (FALSE == IntersectRect(&commandPaintRect, partRect, &paintRect))
  331. continue;
  332. if (FALSE != ListWidget_GetCommandPressed(widget->commands[index]))
  333. sourceAlpha = 200;
  334. else if (FALSE != ListWidget_GetCommandDisabled(widget->commands[index]))
  335. sourceAlpha = 32;
  336. else
  337. sourceAlpha = 255;
  338. if (NULL == item->activity &&
  339. FALSE != ListWidget_GetCommandPrimary(widget->commands[index]))
  340. {
  341. bitmap = ListWidget_GetLargeBadgeBitmap(widget, style, self->hwnd,
  342. RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
  343. Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, &commandPaintRect,
  344. AlphaBlend_AlignCenter, NULL);
  345. bitmap = NULL;
  346. offset = widget->primaryCommandSize.cy/6;
  347. if (offset < 3)
  348. offset = 3;
  349. InflateRect(partRect, -offset, -offset);
  350. commandBitmap = ListWidget_GetCommandLargeBitmap(style, widget->commands[index],
  351. RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
  352. if (NULL == commandBitmap)
  353. commandBitmap = ListWidget_GetUnknownCommandLargeBitmap(widget, style,
  354. RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
  355. }
  356. else
  357. {
  358. if (NULL == bitmap)
  359. {
  360. bitmap = ListWidget_GetSmallBadgeBitmap(widget, style, self->hwnd,
  361. RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
  362. }
  363. Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, &commandPaintRect,
  364. AlphaBlend_AlignCenter, NULL);
  365. offset = widget->secondaryCommandSize.cy/6;
  366. if (offset < 3)
  367. offset = 3;
  368. InflateRect(partRect, -offset, -offset);
  369. commandBitmap = ListWidget_GetCommandSmallBitmap(style, widget->commands[index],
  370. RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
  371. if (NULL == commandBitmap)
  372. commandBitmap = ListWidget_GetUnknownCommandSmallBitmap(widget, style,
  373. RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
  374. }
  375. if (NULL != commandBitmap)
  376. {
  377. Image_AlphaBlend(hdc, partRect, sourceDC, NULL, sourceAlpha, commandBitmap, &commandPaintRect,
  378. AlphaBlend_Normal, NULL);
  379. }
  380. }
  381. }
  382. if (FALSE != ListWidget_GetItemSpacebarRect(widget, item, metrics, partRect))
  383. {
  384. ListWidgetPaint_DrawSpacebar(self, hdc,
  385. partRect->left,
  386. partRect->top,
  387. item->spaceTotal, item->spaceUsed);
  388. }
  389. if (FALSE == ListWidgetItem_IsTextEdited(item) &&
  390. FALSE == IS_STRING_EMPTY(item->title) &&
  391. FALSE != ListWidget_GetItemTitleRect(widget, item, metrics, TRUE, partRect))
  392. {
  393. DrawText(hdc, item->title, -1, partRect,
  394. DT_CENTER | DT_NOPREFIX | DT_WORDBREAK | DT_EDITCONTROL | DT_END_ELLIPSIS);
  395. }
  396. SelectBitmap(sourceDC, prevSourceBitmap);
  397. if (NULL != bufferDC)
  398. {
  399. hdc = targetDC;
  400. SetViewportOrgEx(bufferDC, 0, 0, NULL);
  401. BackBuffer_Copy(&widget->backBuffer, hdc,
  402. paintRect.left, paintRect.top, RECTWIDTH(paintRect), RECTHEIGHT(paintRect));
  403. }
  404. return TRUE;
  405. }
  406. BOOL
  407. ListWidgetPaint_DrawCategory(ListWidgetPaint *self, ListWidgetCategory *category)
  408. {
  409. HDC hdc;
  410. RECT elementRect, *partRect;
  411. WidgetStyle *style;
  412. ListWidgetCategoryMetric *metrics;
  413. if (NULL == self || NULL == category)
  414. return FALSE;
  415. hdc = self->hdc;
  416. style = self->style;
  417. partRect = &self->partRect;
  418. metrics = &self->categoryMetrics;
  419. if (FALSE == IntersectRect(partRect, &category->rect, self->paintRect))
  420. return TRUE;
  421. CopyRect(partRect, &category->rect);
  422. partRect->right -= metrics->offsetRight;
  423. if (FALSE != IntersectRect(partRect, partRect, self->paintRect))
  424. FillRect(hdc, partRect, WIDGETSTYLE_CATEGORY_BRUSH(style));
  425. partRect->left = category->rect.right - metrics->offsetRight;
  426. partRect->right = category->rect.right;
  427. if (FALSE != IntersectRect(partRect, partRect, self->paintRect))
  428. FillRect(hdc, partRect, WIDGETSTYLE_BACK_BRUSH(style));
  429. if (NULL != self->arrow.bitmap)
  430. {
  431. long limit;
  432. SetRect(&elementRect, 0, 0, self->arrow.width, self->arrow.height);
  433. OffsetRect(&elementRect,
  434. 0,
  435. (FALSE == category->collapsed) ?
  436. self->arrow.expandedOffset :
  437. self->arrow.collapsedOffset);
  438. CopyRect(partRect, &category->rect);
  439. partRect->left += metrics->offsetLeft;
  440. partRect->right = partRect->left + self->arrow.width;
  441. limit = (RECTHEIGHT(category->rect) - self->arrow.height - metrics->offsetTop);
  442. partRect->top += metrics->offsetTop + limit/2 + limit%2;
  443. partRect->bottom = partRect->top + self->arrow.height;
  444. limit = category->rect.bottom - metrics->offsetBottom - metrics->lineHeight;
  445. if (partRect->bottom > limit)
  446. OffsetRect(partRect, 0, (limit - partRect->bottom));
  447. limit = category->rect.top + metrics->offsetTop;
  448. if (partRect->top < limit)
  449. OffsetRect(partRect, 0, (limit - partRect->top));
  450. Image_AlphaBlend(hdc, partRect, self->sourceDC, &elementRect,
  451. 255, self->arrow.bitmap, self->paintRect,
  452. AlphaBlend_Normal, NULL);
  453. }
  454. CopyRect(&elementRect, &category->rect);
  455. elementRect.left += metrics->offsetLeft + metrics->iconWidth + metrics->titleOffsetLeft;
  456. elementRect.top += metrics->offsetTop;
  457. elementRect.right -= metrics->offsetRight;
  458. elementRect.bottom -= (metrics->offsetBottom + metrics->lineHeight + metrics->lineOffsetTop);
  459. if (FALSE != IntersectRect(partRect, &elementRect, self->paintRect))
  460. {
  461. COLORREF prevTextColor = SetTextColor(hdc, WIDGETSTYLE_CATEGORY_TEXT_COLOR(style));
  462. HFONT prevFont = SelectFont(hdc, WIDGETSTYLE_CATEGORY_FONT(style));
  463. if (NULL == category->countString)
  464. {
  465. size_t count, index;
  466. wchar_t buffer[64] = {0};
  467. count = 0;
  468. index = category->groups.size();
  469. while(index--)
  470. {
  471. count += category->groups[index]->items.size();
  472. }
  473. if (SUCCEEDED(StringCchPrintf(buffer, ARRAYSIZE(buffer), L" (%u)", count)))
  474. category->countString = String_Duplicate(buffer);
  475. }
  476. if (-1 == category->titleWidth)
  477. {
  478. category->titleWidth = 0;
  479. if (FALSE == IS_STRING_EMPTY(category->title))
  480. {
  481. SetRect(partRect, 0, 0, 0, RECTHEIGHT(elementRect));
  482. if (FALSE != DrawText(hdc, category->title, -1, partRect,
  483. DT_CALCRECT | DT_LEFT | DT_TOP | DT_NOPREFIX | DT_SINGLELINE))
  484. {
  485. category->titleWidth = RECTWIDTH(*partRect);
  486. }
  487. }
  488. }
  489. if (-1 == category->countWidth)
  490. {
  491. category->countWidth = 0;
  492. if (FALSE == IS_STRING_EMPTY(category->countString))
  493. {
  494. SetRect(partRect, 0, 0, 0, RECTHEIGHT(elementRect));
  495. if (FALSE != DrawText(hdc, category->countString, -1, partRect,
  496. DT_CALCRECT | DT_LEFT | DT_TOP | DT_NOPREFIX | DT_SINGLELINE))
  497. {
  498. category->countWidth = RECTWIDTH(*partRect);
  499. }
  500. }
  501. }
  502. if (0 != category->titleWidth)
  503. {
  504. CopyRect(partRect, &elementRect);
  505. if (partRect->right < (partRect->left + category->titleWidth + category->countWidth))
  506. partRect->right = partRect->right - category->countWidth;
  507. if (partRect->right > partRect->left)
  508. {
  509. DrawText(hdc, category->title, -1, partRect,
  510. DT_LEFT | DT_BOTTOM | DT_NOPREFIX | DT_SINGLELINE | DT_END_ELLIPSIS);
  511. }
  512. }
  513. if (0 != category->countWidth)
  514. {
  515. CopyRect(partRect, &elementRect);
  516. partRect->left += category->titleWidth;
  517. if (partRect->left > (partRect->right - category->countWidth))
  518. {
  519. partRect->left = partRect->right - category->countWidth;
  520. if (partRect->left < elementRect.left)
  521. partRect->left = elementRect.left;
  522. }
  523. if (partRect->right > partRect->left)
  524. {
  525. DrawText(hdc, category->countString, -1, partRect,
  526. DT_LEFT | DT_BOTTOM | DT_NOPREFIX | DT_SINGLELINE);
  527. }
  528. }
  529. SetTextColor(hdc, prevTextColor);
  530. SelectFont(hdc, prevFont);
  531. }
  532. if (0 != metrics->lineHeight)
  533. {
  534. CopyRect(partRect, &category->rect);
  535. partRect->right -= metrics->offsetRight;
  536. partRect->bottom -= metrics->offsetBottom;
  537. partRect->top = partRect->bottom - metrics->lineHeight;
  538. if (FALSE != IntersectRect(partRect, partRect, self->paintRect))
  539. {
  540. COLORREF prevBackColor;
  541. prevBackColor = SetBkColor(hdc, WIDGETSTYLE_CATEGORY_LINE_COLOR(style));
  542. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, partRect, NULL, 0, NULL);
  543. SetBkColor(hdc, prevBackColor);
  544. }
  545. }
  546. return TRUE;
  547. }
  548. BOOL
  549. ListWidgetPaint_DrawEmptyCategoryText(ListWidgetPaint *self, ListWidgetCategory *category)
  550. {
  551. HDC hdc;
  552. WidgetStyle *style;
  553. RECT *partRect;
  554. BOOL result;
  555. COLORREF prevTextColor;
  556. if (NULL == self || NULL == category)
  557. return FALSE;
  558. hdc = self->hdc;
  559. style = self->style;
  560. partRect = &self->partRect;
  561. if (FALSE == IntersectRect(partRect, self->paintRect, &category->emptyTextRect))
  562. return TRUE;
  563. if (FALSE != self->erase)
  564. {
  565. FillRect(hdc, partRect, style->backBrush);
  566. }
  567. if (FALSE != IS_STRING_EMPTY(category->emptyText))
  568. return TRUE;
  569. prevTextColor = SetTextColor(hdc, WIDGETSTYLE_CATEGORY_EMPTY_TEXT_COLOR(style));
  570. result = DrawText(hdc, category->emptyText, -1, &category->emptyTextRect,
  571. DT_CENTER | DT_TOP | DT_NOPREFIX | DT_WORDBREAK | DT_EDITCONTROL);
  572. SetTextColor(hdc, prevTextColor);
  573. return result;
  574. }