Sign in to follow this  
Followers 0
Terenz

ListView color hover item

7 posts in this topic

#1 ·  Posted (edited)

Like title, this time is not an easy task :D

I want to color the item under the mouse in a ListView, after some research i have understand how to get the hover-id item but i don't have idea how to color it

The script:

#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>

$hGUI = GUICreate("Hover Test", 323, 184, 208, 168)
$cInput = GUICtrlCreateInput("", 8, 24, 305, 21)
$cListView = GUICtrlCreateListView("ListView", 8, 45, 305, 129)
$hListView = GUICtrlGetHandle($cListView)

GUICtrlSendMsg(-1, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_ONECLICKACTIVATE, $LVS_EX_TRACKSELECT)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)

For $i = 0 To 10
    GUICtrlCreateListViewItem("TEST_" & $i, $cListView)
Next

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $LVN_HOTTRACK ; Sent when the user moves the mouse over an item
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    ConsoleWrite(DllStructGetData($tInfo, "Item") & @LF)
                Case $NM_CUSTOMDRAW
                    ;???
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Thanks to all

Edited by Terenz

Nothing is so strong as gentleness. Nothing is so gentle as real strength

 

Share this post


Link to post
Share on other sites



A not so difficult way

#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>

$hGUI = GUICreate("Hover Test", 323, 184, 208, 168)
$cInput = GUICtrlCreateInput("", 8, 24, 305, 21)
$cListView = GUICtrlCreateListView("ListView", 8, 45, 305, 129)
$hListView = GUICtrlGetHandle($cListView)

GUICtrlSendMsg(-1, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_ONECLICKACTIVATE, $LVS_EX_TRACKSELECT)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)

Global $items[11], $hotitem = -1
For $i = 0 To 10
    $items[$i] = GUICtrlCreateListViewItem("TEST_" & $i, $cListView)
Next

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo, $hot_item
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $LVN_HOTTRACK ; Sent when the user moves the mouse over an item
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
               ;     ConsoleWrite(DllStructGetData($tInfo, "Item") & @LF)
                    $index = DllStructGetData($tInfo, "Item")
                    If $index <> $hotitem Then
                        For $i = 0 to 10
                           GuiCtrlSetColor($items[$i], 0x000000)
                        Next
                        If $index <> -1 Then GuiCtrlSetColor($items[$index], 0xff0000)
                        $hotitem = $index
                   EndIf
             EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Share this post


Link to post
Share on other sites

I want the difficult way :D

Jocking apart, i don't want to store all the list into an array and redim it everytime i'll add an item ( we are talk about many of that ) so i'll prefer to use WM_NOTIFY with $NM_CUSTOMDRAW

Thanks


Nothing is so strong as gentleness. Nothing is so gentle as real strength

 

Share this post


Link to post
Share on other sites

Here are the ideas for a solution based on custom drawn items:

#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>

$hGUI = GUICreate("Hover Test", 323, 184, 208, 168)
$cInput = GUICtrlCreateInput("", 8, 24, 305, 21)
$cListView = GUICtrlCreateListView("ListView", 8, 45, 305, 129)
$hListView = GUICtrlGetHandle($cListView)

GUICtrlSendMsg(-1, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_ONECLICKACTIVATE, $LVS_EX_TRACKSELECT)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)

For $i = 0 To 10
    GUICtrlCreateListViewItem("TEST_" & $i, $cListView)
Next

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local Static $iHot = -1, $iHotPrev = -1
    Local $hWndFrom, $iCode, $tNMHDR, $tInfo
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $LVN_HOTTRACK ; Sent when the user moves the mouse over an item
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    $iHot = DllStructGetData($tInfo, "Item")
                    If $iHot <> $iHotPrev Then
                        ;ConsoleWrite($iHot & @LF)
                        If $iHot <> -1 Then _GUICtrlListView_RedrawItems( $hListView, $iHot, $iHot )
                        If $iHotPrev <> -1 Then _GUICtrlListView_RedrawItems( $hListView, $iHotPrev, $iHotPrev )
                        If $iHot <> $iHotPrev And $iHot <> -1 Then $iHotPrev = $iHot
                    EndIf

                Case $NM_CUSTOMDRAW
                  Local $tNMLVCUSTOMDRAW = DllStructCreate( $tagNMLVCUSTOMDRAW, $ilParam )
                  Local $dwDrawStage = DllStructGetData( $tNMLVCUSTOMDRAW, "dwDrawStage" )

                  Switch $dwDrawStage                               ; Holds a value that specifies the drawing stage

                    Case $CDDS_PREPAINT                             ; Before the paint cycle begins
                      Return $CDRF_NOTIFYITEMDRAW                   ; Notify the parent window of any ITEM-related drawing operations

                    Case $CDDS_ITEMPREPAINT                         ; Before painting an item
                      Return $CDRF_NOTIFYSUBITEMDRAW                ; Notify the parent window of any SUBITEM-related drawing operations

                    Case BitOR( $CDDS_ITEMPREPAINT, $CDDS_SUBITEM ) ; Before painting a subitem
                      Local $dwItemSpec = DllStructGetData( $tNMLVCUSTOMDRAW, "dwItemSpec" )  ; Item index
                      ;Local $iSubItem   = DllStructGetData( $tNMLVCUSTOMDRAW, "iSubItem"   ) ; Subitem index
                      ;Local $uItemState = DllStructGetData( $tNMLVCUSTOMDRAW, "uItemState" ) ; Item state
                      If $dwItemSpec = $iHot Then ; Hot row
                        DllStructSetData( $tNMLVCUSTOMDRAW, "ClrText",   0x000000 )
                        DllStructSetData( $tNMLVCUSTOMDRAW, "ClrTextBk", 0x00FF00 )
                      Else ; Other rows
                        DllStructSetData( $tNMLVCUSTOMDRAW, "ClrText",   0x000000 )
                        DllStructSetData( $tNMLVCUSTOMDRAW, "ClrTextBk", 0xFFFFFF )
                      EndIf
                      Return $CDRF_NEWFONT                          ; $CDRF_NEWFONT must be returned after changing font or colors
                  EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
It's not a complete solution.
1 person likes this

Share this post


Link to post
Share on other sites

Cool LarsJ  :thumbsup:

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Nice LarsJ ;)


Nothing is so strong as gentleness. Nothing is so gentle as real strength

 

Share this post


Link to post
Share on other sites

Thank you. The example below is better.

  • Handles multiple columns. Takes care of horizontal movement of the cursor in the same row through different columns.
  • The hot state is item specific. Subitems doesn't matter. Custom draw is handled in the item case. The subitem case is deleted.
  • Hot state is properly set. Even if you leave and enter the listview through the same item (e.g. on the left side).
  • Hot state is reset when the cursor is moved out of the listview.
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>

Opt( "MustDeclareVars", 1 )

Global $hGUI, $iGUIw = 350, $iGUIh = 400, $fCursorInListView = False
Global $hLV, $iLVx = 2, $iLVy = 2, $iLVw = $iGUIw - 4, $iLVh = $iGUIh - 4
Global $iHot = -1, $iHotPrev = -1

Example()

Func Example()

  $hGUI = GUICreate( "Hot item", $iGUIw, $iGUIh )

  Local $idLV = GUICtrlCreateListView( "Column 0|Column 1|Column 2|Column 3", $iLVx, $iLVy, $iLVw, $iLVh )
  GUICtrlSendMsg( $idLV, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_ONECLICKACTIVATE, $LVS_EX_TRACKSELECT )
  $hLV = GUICtrlGetHandle( $idLV )
  For $i = 0 To 99
    GUICtrlCreateListViewItem( "Cell " & $i & ".0" & "|Cell " & $i & ".1" & "|Cell " & $i & ".2" & "|Cell " & $i & ".3", $idLV )
  Next

  Local $hHeader = _GUICtrlListView_GetHeader( $hLV )
  Local $aPos = WinGetPos( $hHeader )
  $iLVy += $aPos[3]
  $iLVh -= $aPos[3]

  GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )

  GUISetState()

  Local $aInfo, $aTest
  While 1
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        Exit
    EndSwitch
  WEnd

EndFunc

Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam )
  Local $tNMHDR, $hWndFrom, $iCode
  $tNMHDR = DllStructCreate( $tagNMHDR, $lParam )
  $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) )
  $iCode = DllStructGetData( $tNMHDR, "Code" )

  Switch $hWndFrom

    Case $hLV

      Switch $iCode

        Case $LVN_HOTTRACK
            Local $tInfo = DllStructCreate( $tagNMLISTVIEW, $lParam )
            $iHot = DllStructGetData( $tInfo, "Item" )
            If $iHot <> $iHotPrev Then
              If Not $fCursorInListView Then
                AdlibRegister( "ResetHotRow", 100 )
                $fCursorInListView = True
              EndIf
              If $iHot <> -1 Then _GUICtrlListView_RedrawItems( $hLV, $iHot, $iHot )
              If $iHotPrev <> -1 Then _GUICtrlListView_RedrawItems( $hLV, $iHotPrev, $iHotPrev )
              If $iHot <> $iHotPrev Then
                If $iHot <> -1 Then
                  $iHotPrev = $iHot
                ElseIf $iHotPrev <> -1 Then
                  $iHot = $iHotPrev
                  _GUICtrlListView_RedrawItems( $hLV, $iHot, $iHot )
                EndIf
              EndIf
            EndIf

        Case $NM_CUSTOMDRAW
          Local $tNMLVCUSTOMDRAW = DllStructCreate( $tagNMLVCUSTOMDRAW, $lParam )
          Local $dwDrawStage = DllStructGetData( $tNMLVCUSTOMDRAW, "dwDrawStage" )

          Switch $dwDrawStage             ; Holds a value that specifies the drawing stage

            Case $CDDS_PREPAINT           ; Before the paint cycle begins
              Return $CDRF_NOTIFYITEMDRAW ; Notify the parent window of any ITEM-related drawing operations

            Case $CDDS_ITEMPREPAINT       ; Before painting an item
              Local $dwItemSpec = DllStructGetData( $tNMLVCUSTOMDRAW, "dwItemSpec" )  ; Item index
              If $dwItemSpec = $iHot Then ; Hot row
                DllStructSetData( $tNMLVCUSTOMDRAW, "ClrText",   0x000000 )
                DllStructSetData( $tNMLVCUSTOMDRAW, "ClrTextBk", 0xFFE8D8 ) ; Light blue, BGR
              Else ; Other rows
                DllStructSetData( $tNMLVCUSTOMDRAW, "ClrText",   0x000000 )
                DllStructSetData( $tNMLVCUSTOMDRAW, "ClrTextBk", 0xFFFFFF )
              EndIf
              Return $CDRF_NEWFONT        ; $CDRF_NEWFONT must be returned after changing font or colors

          EndSwitch

      EndSwitch

  EndSwitch

  Return $GUI_RUNDEFMSG
EndFunc

Func ResetHotRow()
  Local $aPos = GUIGetCursorInfo()
  If $aPos[0] < $iLVx Or $aPos[0] > $iLVx + $iLVw Or _
     $aPos[1] < $iLVy Or $aPos[1] > $iLVy + $iLVh Then
        $iHot = -1
        _GUICtrlListView_RedrawItems( $hLV, $iHotPrev, $iHotPrev )
        AdlibUnRegister( "ResetHotRow" )
        $fCursorInListView = False
        $iHotPrev = -1
  EndIf
EndFunc

One issue: There is a narrow area between first and second column, which is not hottrack enabled. The hot state is not updated when the cursor is moved vertically in this area. No problem between the other columns. The cause of this issue is probably, that the first column has a special role: It represents the items. All the other columns are alike. They represent the subitems.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0