Как я могу изменить цвета шрифта отдельных символов в подэлементе ListView? - PullRequest
5 голосов
/ 20 февраля 2011

Я писал приложение с использованием Windows API и хотел знать, как создать список с подпунктами, содержащими разноцветный текст.

Для пояснения, вот изображение того, как это реализовано в API Monitor:

Обратите внимание, что в столбце «API» текст имеет несколько цветов, например, форматированный текст или что-то в этом роде. Мне было интересно, как я это сделаю.

Кто-то сказал мне что-то сделать с нестандартным рисунком, но он не был уверен. Я посмотрел на это, и я обработал NM_CUSTOMDRAW. Вот результат моего теста:

А вот и код:

inline LRESULT HandleWM_NOTIFY(LPARAM lParam)
{
   switch (((LPNMHDR)lParam)->code)
   {
      case NM_CUSTOMDRAW:
      {
         switch (((LPNMHDR)lParam)->idFrom)
         {
            case ID_LISTVIEW1:
            {
               LPNMLVCUSTOMDRAW lpNMLVCD = (LPNMLVCUSTOMDRAW)lParam;
               if (lpNMLVCD->nmcd.dwDrawStage == CDDS_PREPAINT)
               {
                  return CDRF_NOTIFYITEMDRAW;
               }
               else if (lpNMLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
               {
                  COLORREF crText;
                  switch (lpNMLVCD->nmcd.dwItemSpec % 3)
                  {
                     case 0:
                        crText = RGB(255, 0, 0);
                        break;
                     case 1:
                        crText = RGB(0, 255, 0);
                        break;
                     case 2:
                        crText = RGB(0, 0, 255);
                        break;
                  }

                  lpNMLVCD->clrText = crText;
                  lpNMLVCD->
               }

               return CDRF_DODEFAULT;
            }
            default: break;
         }

         break;
      }

      default: break;
   }

   return 0;
}

Используя метод NM_CUSTOMDRAW, я не могу изменить цвета шрифта отдельных символов; Я могу только изменить цвет шрифта всего, что в подпункте, а это не то, что я хочу.

Как мне добиться того, что делает API-монитор? Я чувствую, что это будет очень сложно, но любые предложения приветствуются.

1 Ответ

7 голосов
/ 20 февраля 2011

NM_CUSTOMDRAW - это решение.Сожалею, что здесь нет простого решения.Вам просто нужно вывести владелец нужного текста разными цветами последовательно, а не коллективно, используйте API GetTextExtentPoint32, чтобы помочь при рисовании текста.Вы возвращаете CDRF_SKIPDEFAULT, чтобы сказать списку, чтобы не отображать текст, вы позаботились об этом.

if (lpNMHdr->code == NM_CUSTOMDRAW)
{
    LPNMLVCUSTOMDRAW lpCD = (LPNMLVCUSTOMDRAW)lpNMHdr;
    if (lpCD->nmcd.dwDrawStage == CDDS_PREPAINT)
    {
        return CDRF_NOTIFYITEMDRAW;
    }

    if (lpCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
    {
        return CDRF_NOTIFYSUBITEMDRAW;
    }

    if (lpCD->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT|CDDS_SUBITEM))
    {
        if (lpCD->iSubItem == 0) //detect which subitem is being drawn
        {
            LPCTSTR lpcszBuf1 = _T("example");
            LPCTSTR lpcszBuf2 = _T("text");

            RECT iR = { 0 };
            ListView_GetSubItemRect(lpCD->nmcd.hdr.hwndFrom, lpCD->nmcd.dwItemSpec, lpCD->iSubItem, LVIR_BOUNDS, &iR);

            SetBkMode(lpCD->nmcd.hdc, TRANSPARENT);

            SIZE sz = { 0 };
            GetTextExtentPoint32(lpCD->nmcd.hdc, lpcszBuf1, 7, &sz);

            SetTextColor(lpCD->nmcd.hdc, RGB(255, 0, 0));                   
            DrawText(lpCD->nmcd.hdc, lpcszBuf1, -1, &iR, DT_LEFT);

            iR.left += sz.cx;

            SetTextColor(lpCD->nmcd.hdc, RGB(0, 255, 0));                   
            DrawText(lpCD->nmcd.hdc, lpcszBuf2, -1, &iR, DT_LEFT);                  

            return CDRF_SKIPDEFAULT;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...