Personalizing highlight colors through custom draw

WEBINAR:
Live

Full Text Search: The Key to Better Natural Language Queries for NoSQL in Node.js


Date: 1/31/2018 @ 2 p.m. ET

The listview control enables a coder to set its normal background color and normal foreground color, but uses the system colors when highlighting. These system colors are only settable through the display properties dialog (yuk!) Ownerdrawing items will do the trick, but requires that the entire row be drawn by the user. Using the following method through custom draw, no additional drawing code need be implemented.

In a desperate attempt at avoiding ownerdraw, I initially tried row bitmap manipulation through device contexts at certain stages of the custom draw process, but this was WAY TOO SLOW. The following steps are simple and FAST! The process is as follows:

  • 1. Intercept the listview draw routine just before it is about to draw a highlighted row (item).
  • 2. Turn off the row highlight.
  • 3. Set the row colors to whatever you want.
  • 4. Let the listview draw the row.
  • 5. Intercept the listview draw routine after it has drawn the row (post-draw item).
  • 6. Turn this row's highlighting back on.
  • This still enables the row related processing, such as single-click highlighting, to be handled by the listview control.

    Code snippets: The working version of this was originally based on CListView, I removed references to it to generalize the code outside of MFC, so you'll have to forgive typos:

    
    COLORREF g_MyClrFgHi; // My foreground hilite color
    COLORREF g_MyClrBgHi; // My background hilite color
    
    HWND     g_hListView; // Window handle of listview control
    
    
    void  EnableHighlighting(HWND hWnd, int row, bool bHighlight)
    {
      ListView_SetItemState(hWnd, row, bHighlight? 0xff: 0, LVIS_SELECTED);
    }
    
    bool  IsRowSelected(HWND hWnd, int row)
    {
      return ListView_GetItemState(hWnd, row, LVIS_SELECTED) != 0;
    }
    
    
    bool  IsRowHighlighted(HWND hWnd, int row)
    {
      // We check if row is selected.
      // We also check if window has focus. This was because the original listview
      //  control I created did not have style LVS_SHOWSELALWAYS. So if the listview
      //  does not have focus, then there is no highlighting.
    
      return IsRowSelected(hWnd, row) && (::GetFocus(hWnd) == hWnd);
    }
    
    
    BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
    {
      static bool bIsHighlighted = false;
    
      *pResult = 0;
    
      NMHDR *p = (NMHDR *)lParam;
    
      switch (p->code)
      { 
      ... 
      case NM_CUSTOMDRAW:
    
        NMLVCUSTOMDRAW *lvcd = (NMLVCUSTOMDRAW *)p;
        NMCUSTOMDRAW   &nmcd = lvcd->nmcd;
    
        switch (nmcd.dwDrawStage)
        {
        case CDDS_PREPAINT:
    
          // We want item prepaint notifications, so...
          *pResult = CDRF_NOTIFYITEMDRAW;
          break;
    
        case CDDS_ITEMPREPAINT:
        {
          int iRow = (int)nmcd.dwItemSpec;
    
          bHighlighted = IsRowHighlighted(g_hListView, iRow);
          if (bHighlighted)
          {
            lvcd->clrText   = g_MyClrFgHi; // Use my foreground hilite color
            lvcd->clrTextBk = g_MyClrBgHi; // Use my background hilite color
    
            // Turn off listview highlight otherwise it uses the system colors!
            EnableHighlighting(g_hListView, iRow, false);
          }
    
          // We want item post-paint notifications, so...
          *pResult = CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT;
          break;
        }
    
        case CDDS_ITEMPOSTPAINT:
        {
          if (bHighlighted)
          {
            int  iRow = (int)nmcd.dwItemSpec;
    
            // Turn listview control's highlighting back on now that we have
            // drawn the row in the colors we want.
            EnableHighlighting(g_hListView, iRow, true);
          }
    
          *pResult = CDRF_DODEFAULT;
          break;
        }
    
        default:
          *pResult = CDRF_DODEFAULT;
          break;
        }
        break;
      ...
      }
    
    }
    


    Comments

    • Mr

      Posted by Anon on 02/03/2016 07:06am

      Awesome, thanks

      Reply
    Leave a Comment
    • Your email address will not be published. All fields are required.

    Top White Papers and Webcasts

    • For the first time in decades, IT leaders now consider all-flash storage as a strategic IT asset.  IT has become a new operating model that enables self-service with high performance, density and resiliency. It also offers the self-service agility of the public cloud combined with the security, performance, and cost-effectiveness of a private cloud.  Download this MIT Technology Review paper to learn more about how all-flash storage is transforming the data center.

    • Microsoft Azure® is a leading choice for businesses looking to take advantage of the cloud. Azure is particularly appealing to businesses that have already invested in Microsoft on-premises and are now considering running these applications and other workloads in the cloud. To understand how to make this move to Azure, many businesses are turning to managed service providers (MSPs) with specific Azure expertise. Read this white paper to learn the eight key areas to focus on when considering an MSP for an …

    Most Popular Programming Stories

    More for Developers

    RSS Feeds

    Thanks for your registration, follow us on our social networks to keep up-to-date