Listview Color of Selected Row

Started by Richard Kelly, April 15, 2014, 04:02:28 AM

Previous topic - Next topic

Richard Kelly

I've pulled enough out of examples that I can alternate rows in two different colors. Now, when a row is clicked, that row gets some default blue color (I have theme support checked) and I want to change that blue to match my applications color theme instead and can't seem to find any examples laying around. Does somebody have a "quickie" they can share?


Local lpNmh         As NMHDR Ptr
Local lpLvNm        As NM_LISTVIEW Ptr
Local lpLvCd        As NMLVCUSTOMDRAW Ptr

   Select Case wMsg

         
     Case %WM_NOTIFY
       
         lpNmh = lParam
         
         Select Case @lpNmh.idFrom
         
            Case IDC_SECURITYGROUPLIST_GROUPLIST
           
               lpLvNm = lParam
               
               Select Case @LpLvNm.hdr.Code
             
                  Case %NM_CUSTOMDRAW
               
                     lpLvCd = lParam
                   
                     Select Case @lplvcd.nmcd.dwDrawStage
                   
                        Case %CDDS_PREPAINT, %CDDS_ITEMPREPAINT
                     
                           Function = %CDRF_NOTIFYSUBITEMDRAW
                         
                        Case %CDDS_ITEMPREPAINT Or %CDDS_SUBITEM
                     
                           If (@lpLvCd.nmcd.dwItemSpec Mod 2) = 0 Then
                         
                              @lpLvCd.clrTextBk = %RGB_WHITE 
                              @lpLvCd.clrText = %Black
                           
                           Else
                         
                              @lpLvCd.clrTextBk = Rgb(251,225,218)     
                              @lpLvCd.clrText = %Black
                           
                           End If
                         
                           Function = %CDRF_NEWFONT
                         
                        Case Else
                     
                     End Select
                 
               End Select
                     
         End Select

   End Select


Rick Kelly

David Kenny

#1
Richard,

Were you able to test or implement Borje's solution?

Richard Kelly

Sorry it took a bit of time for me to get back. Life is life at times.

I did manage to test Borje's code from the PB forum thread:


http://www.powerbasic.com/support/pbforums/showthread.php?t=54744


The only change I made was to not draw the focus rectangle, the focused row color to another shade of orange and focused text color to white.

Works right out of the box although I'm not sure of the shade of orange I'm using for the focused row although orange is one of 6 colors in the color theme of my app.

Rick

David Kenny

Well done Rick!  I copied your screen shot and checked it in a paint program.  It looks to be the same shade of orange.  I used Corel Draw, both the selected line in the LV and the Status Bar had varying RGB values as if it is dithered.  But the range of each value was the same. My eyes can't tell the difference anyway.

Richard Kelly

I was just wondering if there was "too much" orange. The status bar and the focus row color are exactly the same RGB value.

The even row lighter shade of range is just the normal orange about 4 shades lighter.

My resident color "expert" is my wife and she approved of the 6 colors I selected for this app as I have no sense of color balancing.

RGB's

124,125,111 (some murky slate color)
227,73,25 (shade of red)
235,107,70 (orange/apricot)
218,219,204 (form background)
151,171,180 (things like buttons, etc)
55,55,42 (wherever I might want a black with less contrast)

Rick

David Kenny

I think it looks nice. Not too much orange in my opinion.

Richard Kelly

#6
Quote from: David Kenny on April 23, 2014, 05:18:29 AM
I think it looks nice. Not too much orange in my opinion.

Thank you.

Here is a more general purpose version of the code posted by Borje Hagstun I'm going to start using in my FF apps.


Sub DrawListviewRows (ByVal hwndListView As Dword, _
                      ByVal lParam As Long, _
                      ByVal nEvenColor As Long, _
                      ByVal nFocusColor As Long, _
                      ByVal nDrawFocusRectangle As Long)

' Ownerdraw ListView (Listview attribute set to LVS_OWNERDRAWFIXED)

' Derived from code provided by Borje Hagsten on the PowerBasic Forums April 2014.

' No support for images/icons

' Added to the CUSTOM handler for the form

'    Select Case wMsg
'      Case %WM_DRAWITEM
'         DrawListviewRows (hwndListView,lParam,nEvenColor,nFocusColor,nFocusTextColor,nDrawFocusRectangle)

' hwndListView - Window handle to the listview control
' lParam - Passed from the FF CUSTOM handler for the FF form
' nEvenColor - color to use for even numbered rows
' nFocusColor - color to use for row with focus
' nFocusTextColor - color to use for the text on row with focus
' nDrawFocusRectangle - 1=Draw focus rectangle for focus row

Local nTotalColumns     As Long
Local nColumn           As Long
Local hBrush            As Dword
Local lpdis             As DRAWITEMSTRUCT Ptr
Local pt                As PointApi
Local rc                As Rect
Static szText           As Asciiz * 100


  lpdis = lParam

  Select Case @lpdis.itemAction

    Case %ODA_DRAWENTIRE, %ODA_SELECT

'Clear Background

      If (@lpdis.itemState And %ODS_SELECTED) Then

          hBrush = CreateSolidBrush (nFocusColor)
          FillRect @lpdis.hDC, @lpdis.rcItem, hBrush
          DeleteObject hBrush
          SetBkColor @lpdis.hDC, nFocusColor
          SetTextColor @lpdis.hDC, %White         

      Else

          If @lpdis.itemID Mod 2 = 0 Then

              FillRect @lpdis.hDC, @lpdis.rcItem, GetSysColorBrush(%COLOR_WINDOW)
              SetBkColor @lpdis.hDC, GetSysColor(%COLOR_WINDOW)
              SetTextColor @lpdis.hDC, GetSysColor(%COLOR_WINDOWTEXT)

          Else

              hBrush = CreateSolidBrush (nEvenColor)
              FillRect @lpdis.hDC, @lpdis.rcItem, hBrush
              DeleteObject hBrush
              SetBkColor @lpdis.hDC, nEvenColor
              SetTextColor @lpdis.hDC, GetSysColor(%COLOR_WINDOWTEXT)

          End If

      End If
     
' Get row coordinates

      ListView_GetItemPosition(hwndListView, 0, pt)

' Get the total number of columns

      nTotalColumns = FF_ListView_GetColumnCount (hwndListView)
      Decr nTotalColumns
      rc  = @lpdis.rcItem
     
      For nColumn = 0 To nTotalColumns

        rc.nLeft = IIF(nColumn > 0, rc.nRight, pt.x)     
        rc.nRight = rc.nLeft + ListView_GetColumnWidth (hwndListView, nColumn)
        ListView_GetItemText hwndListView, @lpdis.itemID, nColumn, szText, SizeOf(szText)
        DrawText @lpdis.hDC, szText, Len(szText), rc, %DT_LEFT Or %DT_SINGLELINE Or %DT_VCENTER
     
      Next
     
      If nDrawFocusRectangle = 1 Then
     
         If GetFocus() = hwndListView And (@lpdis.itemState And %ODS_SELECTED) Then
         
            DrawFocusRect(@lpdis.hDC, @lpdis.rcItem)
           
         End If     
     
      End If

  End Select
 
End Sub


Of course now, I have to figure out how to support showing an icon from as associated imagelist. This will be really useful over and over again when it gets ironed out.

Rick

Richard Kelly

I occasionally have a listview where I want an icon in the first column of certain rows. Taking what I had just started using, I added a column on the left and when inserting the row, I determined if I wanted an icon shown and which one from an attached imagelist. Additionally, I also adjusted the background fill to skip over that newly added first column as I liked that appearance. So, although now the code is not perfectly an all around general purpose routine, it does just what I want with the app I'm working on.


Sub DrawListviewRows (ByVal hwndListView As Dword, _I occasionally have a listview where I want an icon in the first column of certain rows. Taking what I had just started using, I added a column on the left and when inserting the row, I determined if I wanted an icon shown and which one from an attached imagelist. Additionally, I also adjusted the background fill to skip over that newly added first column as I liked that appearance. So, although now the code is not perfectly an all around general purpose routine, it does just what I want with the app I'm working on.
                      ByVal lParam As Long, _
                      ByVal nEvenColor As Long, _
                      ByVal nFocusColor As Long, _
                      ByVal nDrawFocusRectangle As Long, _
                      Optional ByVal nDrawImage As Long)

' Ownerdraw ListView (Listview attribute set to LVS_OWNERDRAWFIXED)

' Derived from code provided by Borje Hagsten on the PowerBasic Forums April 2014.

' No support for images/icons

' Added to the CUSTOM handler for the form

'    Select Case wMsg
'      Case %WM_DRAWITEM
'         DrawListviewRows (hwndListView,lParam,nEvenColor,nFocusColor,nFocusTextColor,nDrawFocusRectangle)

' hwndListView - Window handle to the listview control
' lParam - Passed from the FF CUSTOM handler for the FF form
' nEvenColor - color to use for even numbered rows
' nFocusColor - color to use for row with focus
' nFocusTextColor - color to use for the text on row with focus
' nDrawFocusRectangle - 1=Draw focus rectangle for focus row
' nDrawImage - 1=Use ImageList in first column

Local nTotalColumns     As Long
Local nColumn           As Long
Local nImageColumnSize  As Long
Local nImageIndex       As Long
Local hBrush            As Dword
Local lpdis             As DRAWITEMSTRUCT Ptr
Local pt                As PointApi
Local rc                As Rect
Static szText           As Asciiz * 100

  If nDrawImage = 1 Then
 
     nImageColumnSize = FF_ListView_GetColumnWidth (hwndListView, 0)
     
  Else
 
     nImageColumnSize = 0
     
  End If


  lpdis = lParam

  Select Case @lpdis.itemAction

    Case %ODA_DRAWENTIRE, %ODA_SELECT

'Clear Background

      rc = @lpdis.rcItem
      rc.nLeft = rc.nLeft + nImageColumnSize 

      If (@lpdis.itemState And %ODS_SELECTED) Then

          hBrush = CreateSolidBrush (nFocusColor)
          FillRect @lpdis.hDC, rc, hBrush 
          DeleteObject hBrush
          SetBkColor @lpdis.hDC, nFocusColor
          SetTextColor @lpdis.hDC, %White         

      Else

          If @lpdis.itemID Mod 2 = 0 Then

              FillRect @lpdis.hDC, rc, GetSysColorBrush(%COLOR_WINDOW)
              SetBkColor @lpdis.hDC, GetSysColor(%COLOR_WINDOW)
              SetTextColor @lpdis.hDC, GetSysColor(%COLOR_WINDOWTEXT)

          Else

              hBrush = CreateSolidBrush (nEvenColor)
              FillRect @lpdis.hDC, rc, hBrush 
              DeleteObject hBrush
              SetBkColor @lpdis.hDC, nEvenColor
              SetTextColor @lpdis.hDC, GetSysColor(%COLOR_WINDOWTEXT)

          End If

      End If
     
' Get row coordinates

      ListView_GetItemPosition(hwndListView, 0, pt)

' Get the total number of columns

      nTotalColumns = FF_ListView_GetColumnCount (hwndListView)
      Decr nTotalColumns
      rc  = @lpdis.rcItem
     
      For nColumn = 0 To nTotalColumns

        rc.nLeft = IIF(nColumn > 0, rc.nRight, pt.x)     
        rc.nRight = rc.nLeft + ListView_GetColumnWidth (hwndListView, nColumn)
       
        If nDrawImage = 1 Then
       
           If nColumn = 0 Then
           
              nImageIndex = FF_ListView_GetItemImage (hwndListView, @lpdis.itemID, 0)
             
              If nImageIndex >= 0 Then
           
                 ImageList_Draw (FF_ListView_GetImageList (hwndListView, %LVSIL_SMALL), nImageIndex, @lpdis.hDC, rc.nLeft, rc.nTop, %ILD_TRANSPARENT)

              End If
             
           Else
           
              ListView_GetItemText hwndListView, @lpdis.itemID, nColumn, szText, SizeOf(szText)
              DrawText @lpdis.hDC, szText, Len(szText), rc, %DT_LEFT Or %DT_SINGLELINE Or %DT_VCENTER                       
           
           End If
           
        Else
       
           ListView_GetItemText hwndListView, @lpdis.itemID, nColumn, szText, SizeOf(szText)
           DrawText @lpdis.hDC, szText, Len(szText), rc, %DT_LEFT Or %DT_SINGLELINE Or %DT_VCENTER
       
        End If
     
      Next
     
      If nDrawFocusRectangle = 1 Then
     
         If GetFocus() = hwndListView And (@lpdis.itemState And %ODS_SELECTED) Then
         
            DrawFocusRect(@lpdis.hDC, @lpdis.rcItem)
           
         End If     
     
      End If

  End Select
 
End Sub


Modify it for your FF projects and have some drawing fun!

Rick