Jump to content
Sign in to follow this  
Clark

ListViewItems and Tooltips

Recommended Posts

Clark

Hello all

I'm confused as to how to achieve a tooltip for listviewitems (not the listview as a whole; i.e. a tooltip for each listviewitem).

The help text seems to indicate (maybe) that it can be done, via _GuiCtrlListView_SetToolTips, but I can't figure out how to use it from the help file. The help is not very helpful to me. :)

I thought I might just get the cursor location and then use something like _GUICtrlListBox_GetItemFromPoint, but it seems there is no equivalent function (that I can find) which lets me get a listviewitem's handle using the cursor position.

Does anyone have any idea how this might be achieved?

TiA

Clark

Share this post


Link to post
Share on other sites
water

Search the forum and you will find a lot of hits like this


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-01-27 - Version 1.3.3.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
Clark

Thanks Water

The link you provided takes me to an explanation of how to get tooltips for Listboxes, not Listviews. I shall have a search once more in case I missed something elsewhere in the forums.

Share this post


Link to post
Share on other sites
PhoenixXL
Rough Example
#include <GUIConstantsEx.au3>
#include <Array.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

Opt('MustDeclareVars', 1)
Global $mylist, $hGUI
Example()

Func Example()
Local $MESSAGE = "The following buttons have been clicked"
Local $add, $clear, $close, $msg

$hGUI = GUICreate("My GUI list", 500, 400) ; will create a dialog box that when displayed is centered

Local $iListView = GUICtrlCreateListView("buttons|clicked", 10, 10, 400, 200)
$mylist = GUICtrlGetHandle(-1)

Local $id = GUICtrlCreateListViewItem("this is another|line which is larger than the list box", $iListView)
GUICtrlCreateListViewItem("Again another|Line", $iListView)

GUISetState()

$msg = 0
While $msg <> $GUI_EVENT_CLOSE
$msg = GUIGetMsg()
Switch $msg
Case $GUI_EVENT_MOUSEMOVE
TimerFunc()
EndSwitch
WEnd
EndFunc   ;==>Example

Func TimerFunc()
Local Static $iIndex_old = -1

Local $iIndex = _GUICtrlListView_HitTest($mylist)

If $iIndex[0] < 0 Then
$iIndex_old = -1
Return ToolTip('')
EndIf
If $iIndex[0] = $iIndex_old Then Return
ToolTip("ListView Row No." & $iIndex[0])
$iIndex_old = $iIndex[0]
EndFunc   ;==>TimerFunc
Edited by PhoenixXL
  • Like 1

My code:

PredictText: Predict Text of an Edit Control Like Scite. Remote Gmail: Execute your Scripts through Gmail. StringRegExp:Share and learn RegExp.

Run As System: A command line wrapper around PSEXEC.exe to execute your apps scripts as System (LSA). Database: An easier approach for _SQ_LITE beginners.

MathsEx: A UDF for Fractions and LCM, GCF/HCF. FloatingText: An UDF for make your text floating. Clipboard Extendor: A clipboard monitoring tool. 

Custom ScrollBar: Scroll Bar made with GDI+, user can use bitmaps instead. RestrictEdit_SRE: Restrict text in an Edit Control through a Regular Expression.

Share this post


Link to post
Share on other sites
PhoenixXL

Another Example so that The header is not counted as the Item 0

#include <GUIConstantsEx.au3>
#include <Array.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

Opt('MustDeclareVars', 1)
Global $mylist, $hGUI, $tPoint = DllStructCreate($tagPoint)
Example()

Func Example()
Local $MESSAGE = "The following buttons have been clicked"
Local $add, $clear, $close, $msg

$hGUI = GUICreate("My GUI list", 500, 400) ; will create a dialog box that when displayed is centered

Local $iListView = GUICtrlCreateListView("buttons|clicked", 10, 10, 400, 200)
$mylist = GUICtrlGetHandle(-1)

Local $id = GUICtrlCreateListViewItem("this is another|line which is larger than the list box", $iListView)
GUICtrlCreateListViewItem("Again another|Line", $iListView)

GUISetState()

$msg = 0
While $msg <> $GUI_EVENT_CLOSE
$msg = GUIGetMsg()
Switch $msg
Case $GUI_EVENT_MOUSEMOVE
SetMousePos()
TimerFunc()
EndSwitch
WEnd
EndFunc   ;==>Example

Func TimerFunc()
Local Static $iIndex_old = -1

Local $iIndex = _GUICtrlListView_HitTest($mylist)

If HoveringOnHeader() Or $iIndex[0] < 0 Then
$iIndex_old = -1
Return ToolTip('')
EndIf
If $iIndex[0] = $iIndex_old Then Return
ToolTip("ListView Row No." & $iIndex[0])
$iIndex_old = $iIndex[0]
EndFunc   ;==>TimerFunc

Func SetMousePos()
DllStructSetData($tPoint, 1, MouseGetPos(0))
DllStructSetData($tPoint, 2, MouseGetPos(1))
EndFunc   ;==>SetMousePos

Func HoveringOnHeader()
Local $tRect = DllStructCreate($tagRect)
Local $aPos = WinGetPos(_GUICtrlListView_GetHeader($mylist))
$aPos[2] = $aPos[0] + $aPos[2]
$aPos[3] = $aPos[1] + $aPos[3]

If @error Then Return SetError(1, 0, 0)
For $i = 1 To 4
DllStructSetData($tRect, $i, $aPos[$i - 1])
Next

Return _WinAPI_PtInRect($tRect, $tPoint)
EndFunc   ;==>HoveringOnHeader

Thumbs up if it helped. ;)

Regards

  • Like 1

My code:

PredictText: Predict Text of an Edit Control Like Scite. Remote Gmail: Execute your Scripts through Gmail. StringRegExp:Share and learn RegExp.

Run As System: A command line wrapper around PSEXEC.exe to execute your apps scripts as System (LSA). Database: An easier approach for _SQ_LITE beginners.

MathsEx: A UDF for Fractions and LCM, GCF/HCF. FloatingText: An UDF for make your text floating. Clipboard Extendor: A clipboard monitoring tool. 

Custom ScrollBar: Scroll Bar made with GDI+, user can use bitmaps instead. RestrictEdit_SRE: Restrict text in an Edit Control through a Regular Expression.

Share this post


Link to post
Share on other sites
AutoBert

An another solution with $WM_NOTIFY:

;Autor Bugfix http://www.autoit.de/index.php?page=Thread&postID=117453#post117453
#include <ListViewConstants.au3>
#include <StructureConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIListView.au3>

$gui = GUICreate('test')
$hListView = GUICtrlCreateListView('Spalte1|Spalte2', 10, 10, 300, 200)
_GUICtrlListView_SetColumnWidth($hListView, 0, 146)
_GUICtrlListView_SetColumnWidth($hListView, 1, $LVSCW_AUTOSIZE_USEHEADER)
For $i = 1 To 10
    GUICtrlCreateListViewItem('Zeile ' & $i & ' Spalte 1|Zeile ' & $i & ' Spalte 2', $hListView)
Next
GUISetState()

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

Do
    $msg = GUIGetMsg()
Until $msg = $GUI_EVENT_CLOSE

Func ListView_HOTTRACK($iSubItem)
    Local $HotItem = _GUICtrlListView_GetHotItem($hListView)
    If $HotItem <> -1 Then _ToolTipMouseExit("Überfahrenes Item: " & $HotItem & " SubItem: " & $iSubItem & @CRLF & _
                                'Inhalt: ' & _GUICtrlListView_GetItemText($hListView, $HotItem, $iSubItem), 500)
EndFunc   ;==>ListView_HOTTRACK

Func _ToolTipMouseExit($TEXT, $TIME=-1, $x=-1, $y=-1, $TITLE='', $ICON=0, $OPT='')
    If $TIME = -1 Then $TIME = 3000
    Local $start = TimerInit(), $pos0 = MouseGetPos()
    If ($x = -1) Or ($y = -1) Then
        ToolTip($TEXT, $pos0[0], $pos0[1], $TITLE, $ICON, $OPT)
    Else
        ToolTip($TEXT, $x, $y, $TITLE, $ICON, $OPT)
    EndIf
    Do
        Sleep(50)
        $pos = MouseGetPos()
    Until (TimerDiff($start) > $TIME) Or _
        (Abs($pos[0] - $pos0[0]) > 10 Or _
         Abs($pos[1] - $pos0[1]) > 10)
    ToolTip('')
EndFunc ;_ToolTipMouseExit

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView
    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_HOTTRACK ; Sent by a list-view control when the user moves the mouse over an item
                    Local $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    ListView_HOTTRACK(DllStructGetData($tInfo, "SubItem"))
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

  • Like 2

Share this post


Link to post
Share on other sites
Clark

Thanks Guys

I shall give both of these a try today and let you know how they go.

I wrestled with this all day yesterday experimenting with gethovertime and settooltips but got nowhere.

edit: They both work a treat. The key is in _GUICtrlListView_HitTest, which I did not stumble across in the help files. Thanks for both your help.

Edited by Clark

Share this post


Link to post
Share on other sites
Zedna

Another Example so that The header is not counted as the Item 0

...

 

Thanks for this example.

I use it in my project but in accomodated way and with _GUICtrlListView_SubItemHitTest() instead of _GUICtrlListView_HitTest().

 

Here is simplified original example using _GUICtrlHeader_HitTest() to test if mouse is over the header:

Also $iIndex_old is declared as global instead of local static to be working also with older AutoIt's versions:

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

Opt('MustDeclareVars', 1)
Global $mylist, $header, $hGUI
Global $iIndex_old = -1

Example()

Func Example()
    Local $MESSAGE = "The following buttons have been clicked"
    Local $add, $clear, $close, $msg

    $hGUI = GUICreate("My GUI list", 500, 400) ; will create a dialog box that when displayed is centered

    Local $iListView = GUICtrlCreateListView("buttons|clicked", 10, 10, 400, 200)
    $mylist = GUICtrlGetHandle(-1)
    $header = _GUICtrlListView_GetHeader($mylist)

    Local $id = GUICtrlCreateListViewItem("this is another|line which is larger than the list box", $iListView)
    GUICtrlCreateListViewItem("Again another|Line", $iListView)

    GUISetState()

    $msg = 0
    While $msg <> $GUI_EVENT_CLOSE
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_MOUSEMOVE
                TimerFunc()
        EndSwitch
    WEnd
EndFunc   ;==>Example

Func TimerFunc()
    Local $iIndex = _GUICtrlListView_HitTest($mylist)

    If $iIndex[0] < 0 Or HoveringOnHeader() Then
        If $iIndex_old = -1 Then Return ; avoid calling ToolTip('') when not needed
        $iIndex_old = -1
        Return ToolTip('')
    EndIf
    If $iIndex[0] = $iIndex_old Then Return
    ToolTip("ListView Row No." & $iIndex[0])
    $iIndex_old = $iIndex[0]
EndFunc   ;==>TimerFunc

Func HoveringOnHeader()
    Local $iX = _WinAPI_GetMousePosX(True, $header)
    Local $iY = _WinAPI_GetMousePosY(True, $header)
    Local $aHT = _GUICtrlHeader_HitTest ($header, $iX, $iY)
;~     Return $aHT[1] + $aHT[2] + $aHT[3] > 0 ; returns true also over last unused column/header
    Return $aHT[0] >= 0 ; returns false over last unused column/header (we have to test also Item/SubItem = -1 in ListView)
EndFunc
EDIT: Added code to avoid calling ToolTip('') when not needed. Edited by Zedna

Share this post


Link to post
Share on other sites
Zedna

Here is example not only testing items but also testing subitems of ListView.
Also added StatusBar showing results of Item/SubItem from _GUICtrlListView_SubItemHitTest() and result of HoveringOnHeader() during MouseMove event.
Also added code to avoid calling ToolTip('') when not needed.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiStatusBar.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

Opt('MustDeclareVars', 1)
Global $mylist, $header, $hGUI, $StatusBar
Global $iItem_old = -1, $iSubItem_old = -1

Example()

Func Example()
    Local $MESSAGE = "The following buttons have been clicked"
    Local $add, $clear, $close, $msg

    $hGUI = GUICreate("My GUI list", 500, 400) ; will create a dialog box that when displayed is centered

    Local $iListView = GUICtrlCreateListView("buttons|clicked", 10, 10, 400, 200)
    $mylist = GUICtrlGetHandle(-1)
    $header = _GUICtrlListView_GetHeader($mylist)

    Local $id = GUICtrlCreateListViewItem("this is another|line which is larger than the list box", $iListView)
    GUICtrlCreateListViewItem("Again another|Line", $iListView)
    $StatusBar = _GUICtrlStatusBar_Create($hGUI, -1, "")

    GUISetState()

    $msg = 0
    While $msg <> $GUI_EVENT_CLOSE
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_MOUSEMOVE
                TimerFunc()
        EndSwitch
    WEnd
EndFunc   ;==>Example

Func TimerFunc()
    Local $aHit = _GUICtrlListView_SubItemHitTest($mylist)
    _GUICtrlStatusBar_SetText($StatusBar, StringFormat("Item: %d SubItem: %d OnHeader: %d", $aHit[0], $aHit[1], HoveringOnHeader() ))

    If $aHit[0] < 0 Or $aHit[1] < 0 Or HoveringOnHeader() Then
        If $iItem_old = -1 Or $iSubItem_old = -1 Then Return ; avoid calling ToolTip('') when not needed
        $iItem_old = -1
        $iSubItem_old = -1
        Return ToolTip('')
    EndIf

    If $aHit[0] = $iItem_old And $aHit[1] = $iSubItem_old Then Return

    ToolTip("ListView Row " & $aHit[0] & " Col " & $aHit[1])
    $iItem_old = $aHit[0]
    $iSubItem_old  = $aHit[1]
EndFunc   ;==>TimerFunc

Func HoveringOnHeader()
    Local $iX = _WinAPI_GetMousePosX(True, $header)
    Local $iY = _WinAPI_GetMousePosY(True, $header)
    Local $aHT = _GUICtrlHeader_HitTest ($header, $iX, $iY)
;~    Return $aHT[1] + $aHT[2] + $aHT[3] > 0 ; returns true also over last unused column/header
    Return $aHT[0] >= 0 ; returns false over last unused column/header (we have to test also Item/SubItem = -1 in ListView)
EndFunc
Edited by Zedna

Share this post


Link to post
Share on other sites
jrsofsd

First, all credit goes to Zedna!

One of my projects has TWO Listviews, and I wanted to add ToolTips to both of them. I've modified Zedna's example to accommodate multiple Listviews with ToolTips with the function _ListView_ToolTips() in ListView_ToolTips.au3.

The function takes two parameters: a 0-based 1D or 2D ToolTip array and the ID of the Listview control. Create a 1D array of ToolTips if the Listview has one column, a 2D array if the Listview has multiple columns. Row zero is for header ToolTips.

The function is called in the GUIGetMsg() Loop; this code snippet handles ToolTips for 2 Listviews:

While $msg <> $GUI_EVENT_CLOSE
        $msg = GUIGetMsg()

        Switch $msg
            Case $GUI_EVENT_MOUSEMOVE
                If Not _ListView_ToolTips ( $aToolTips2D_Gems, $idListView_Gems ) Then
                    _GUICtrlStatusBar_SetText( $StatusBar, StringFormat("Gems _ListView_ToolTips error: %d", @error) )
                EndIf
                If Not _ListView_ToolTips ( $aToolTips2D_Cats, $idListView_Cats ) Then
                    _GUICtrlStatusBar_SetText( $StatusBar, StringFormat("Cats _ListView_ToolTips error: %d", @error) )
                EndIf
        EndSwitch

    WEnd

I've included 5 example scripts, of which the most interesting is: "2 X 2D Listview - Header Item Subitem ToolTips.au3".

This example GUI has two multi-column Listviews with ToolTips.

ListView_ToolTips.zip

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  

×