ListView: Tooltip if text is too long for the list

Share your advanced PureBasic knowledge/code with the community.
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

ListView: Tooltip if text is too long for the list

Post by c4s »

Code: Select all

#Window = 1
#ListIcon = 2
#Text = 3
#ListView = 4
#LVS_EX_LABELTIP = $4000


If OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 200, 420, "ListView Tooltip", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(#Window))
   ListIconGadget(#ListIcon, 0, 0, 200, 200, "ListIconGadget:", 200)
    SendMessage_(GadgetID(#ListIcon), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, #LVS_EX_LABELTIP)
   TextGadget(#Text, 0, 200, 200, 20, "'ListViewGadget':")
   ListIconGadget(#ListView, 0, 220, 200, 200, "", 170, #LVS_NOCOLUMNHEADER)
    SendMessage_(GadgetID(#ListView), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, #LVS_EX_LABELTIP)
EndIf

For i = 1 To 100
   Text.s = RSet("", i, Chr(Random(95) + 32))
   AddGadgetItem(#ListIcon, -1, Text)
   AddGadgetItem(#ListView, -1, Text)
Next i

Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow: End
This doesn't work on a classic ListViewGadget. But we can easily build our
own with a ListIconGadget (see the example).

Hopefully someone finds it as usefull as I did...
c4s

P.S.
I think this should be available in PB with a flag option..!
That's also a reason why I post it here too (already did in the german forum ;))
UserOfPure
Enthusiast
Enthusiast
Posts: 469
Joined: Sun Mar 16, 2008 9:18 am

Re: ListView: Tooltip if text is too long for the list

Post by UserOfPure »

c4s wrote:I think this should be available in PB with a flag option..!
If the ListIconGadget has more than one column then it makes it impossible to use #PB_ListIcon_FullRowSelect to highlight the whole row. That's probably why it's not supported.

Code: Select all

#Window = 1
#ListIcon = 2
#Text = 3
#ListView = 4
#LVS_EX_LABELTIP = $4000

If OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 200, 420, "ListView Tooltip", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(#Window))

   ListIconGadget(#ListIcon, 0, 0, 200, 200, "ListIconGadget:", 200, #PB_ListIcon_FullRowSelect)
    AddGadgetColumn(#ListIcon, 1, "Second column", 100)
    SendMessage_(GadgetID(#ListIcon),#LVM_SETEXTENDEDLISTVIEWSTYLE,0,#LVS_EX_LABELTIP)
    TextGadget(#Text, 0, 200, 200, 20, "'ListViewGadget':")

   ListIconGadget(#ListView, 0, 220, 200, 200, "", 170)
    SendMessage_(GadgetID(#ListView),#LVM_SETEXTENDEDLISTVIEWSTYLE,0,#LVS_EX_LABELTIP)

EndIf

For i = 1 To 100
   Text.s = RSet("", i, Chr(Random(95) + 32))
   AddGadgetItem(#ListIcon, -1, Text + #LF$ + Text)
   AddGadgetItem(#ListView, -1, Text + #LF$ + Text)
Next i

SetActiveGadget(#ListIcon)

Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow: End
User avatar
Michael Vogel
Addict
Addict
Posts: 2806
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Does anyone know if there is a similar 'trick' for comboboxes?

Code: Select all

Code:
#Window = 1
#ListIcon = 2
#Text = 3
#ListView = 4
#LVS_EX_LABELTIP = $4000


If OpenWindow(#Window,#PB_Ignore,#PB_Ignore,200,420,"ListView Tooltip",#PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(#Window))
	ComboBoxGadget(#ListIcon,0,0,200,200,200)
	SendMessage_(GadgetID(#ListIcon), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, #LVS_EX_LABELTIP)
	TextGadget(#Text, 0, 200, 200, 20, "'ListViewGadget':")
	ListIconGadget(#ListView, 0, 220, 200, 200, "", 170, #LVS_NOCOLUMNHEADER)
	SendMessage_(GadgetID(#ListView), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, #LVS_EX_LABELTIP)
EndIf

For i = 1 To 100
	Text.s = RSet("", i, Chr(Random(95) + 32))
	AddGadgetItem(#ListIcon, -1, Text)
	AddGadgetItem(#ListView, -1, Text)
Next i

Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow: End
User avatar
Michael Vogel
Addict
Addict
Posts: 2806
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Just trying to refresh the former question, maybe it has been missed:

does anyone know if it is possible to get automatic info lines for long text entries of comboboxes (see example code in previous posting)?

Thank you for your lenity,
Michael
waldschrath
New User
New User
Posts: 8
Joined: Fri Nov 03, 2006 8:58 am

Post by waldschrath »

I dont think it is possible with just a Flag. You have to handle the Tooltips yourself.
waldschrath
New User
New User
Posts: 8
Joined: Fri Nov 03, 2006 8:58 am

Post by waldschrath »

Since my last Comment was probably not very helpful, I should probably add some sample Code to show what I mean.

Code: Select all

#TTF_TRACK = $20
#TTF_TRANSPARENT = $100

#SM_CXTHUMB = 10

#LB_ITEMFROMPOINT = $01A9


Structure CBINFOTIPINFO
  TipHandle.l
  ListboxHandle.l
  TipInfo.TOOLINFO
  CurrentItem.l
  TipTextLength.l
  *TipText
  *PrevWinProc
EndStructure


Procedure.l ComboBoxInfoTipInitTip ( WindowHandle.l, *Info.CBINFOTIPINFO )

  *Info\TipHandle = CreateWindowEx_(#WS_EX_TOPMOST, @"tooltips_class32", 0, #TTS_NOPREFIX + #TTS_ALWAYSTIP, #CW_USEDEFAULT, #CW_USEDEFAULT, #CW_USEDEFAULT,  #CW_USEDEFAULT, WindowHandle, 0, 0, 0)
  If #Null = *Info\TipHandle
    FreeMemory(*Info)
    ProcedureReturn #False
  EndIf
  
  *Info\TipInfo\cbSize = SizeOf(TOOLINFO)
  *Info\TipInfo\uFlags = #TTF_TRACK + #TTF_TRANSPARENT
  *Info\TipInfo\hwnd   = WindowHandle
  
  SendMessage_(*Info\TipHandle, #TTM_SETMAXTIPWIDTH, 0, 32767)
  SendMessage_(*Info\TipHandle, #TTM_ADDTOOL, 0, @*Info\TipInfo)
  SendMessage_(*Info\TipHandle, #TTM_SETTIPBKCOLOR, GetSysColor_(#COLOR_INFOBK), 0)
  SendMessage_(*Info\TipHandle, #TTM_SETTIPTEXTCOLOR, GetSysColor_(#COLOR_INFOTEXT), 0)
  
  Margins.RECT\left = 0
  Margins\top = -1
  Margins\right = 0
  Margins\bottom = -1
  SendMessage_(*Info\TipHandle, #TTM_SETMARGIN, 0, @Margins)
  
  SendMessage_(*Info\TipHandle, WM_SETFONT, SendMessage_(WindowHandle, #WM_GETFONT, 0, 0), 0)

  ProcedureReturn #True
  
EndProcedure  



Procedure.l ComboBoxInfoTipShowTip ( WindowHandle.l, *Info.CBINFOTIPINFO, TextLength.l, MaxWidth.l, XPos.l, YPos.l )

  dc.l = GetDC_(WindowHandle)
  OldFont.l = SelectObject_(dc, SendMessage_(WindowHandle, #WM_GETFONT, 0, 0))
  GetTextExtentPoint32_(dc, *Info\TipText, TextLength, @TextSize.SIZE)
  SelectObject_(dc, OldFont)
  ReleaseDC_(WindowHandle, dc)
  If TextSize\cx > MaxWidth 
    PokeW(@TipPoint.l, XPos & $ffff)
    PokeW(@TipPoint + 2, YPos & $ffff)
    SendMessage_(*Info\TipHandle, #TTM_UPDATETIPTEXT, 0, @*Info\TipInfo);
    SendMessage_(*Info\TipHandle, #TTM_TRACKPOSITION, 0, TipPoint);
    SendMessage_(*Info\TipHandle, #TTM_TRACKACTIVATE, 1, @*Info\TipInfo);
    ProcedureReturn #True
  EndIf
    
  ProcedureReturn #False
  
EndProcedure


Procedure.l ComboBoxInfoTipItemText ( WindowHandle.l, *Info.CBINFOTIPINFO, ItemIndex.l )

  TextLength.l = 0
  If ItemIndex < 0 
    TextLength = GetWindowTextLength_(WindowHandle)
  Else
    TextLength = SendMessage_(WindowHandle, #LB_GETTEXTLEN, ItemIndex, 0)
  EndIf
    
  If TextLength > 0
    If TextLength > (*Info\TipTextLength - 2)
      If #Null <> *Info\TipText
        FreeMemory(*Info\TipText)
      EndIf
      TextLength = TextLength + 128
      *Info\TipText = AllocateMemory(TextLength * SizeOf(Character))
      If #Null <> *Info\TipText 
        *Info\TipTextLength = TextLength
      Else
        *Info\TipTextLength = 0
      EndIf
    EndIf
    
    If #Null <> *Info\TipText
      If ItemIndex < 0 
        TextLength = GetWindowText_(WindowHandle, *Info\TipText, *Info\TipTextLength)
      Else
        TextLength = SendMessage_(WindowHandle, #LB_GETTEXT, ItemIndex, *Info\TipText)
      EndIf
  
      If TextLength >= 0      
        PokeW(*Info\TipText + (TextLength * SizeOf(Character)), 0)
      EndIf
    EndIf  
  EndIf
  
  ProcedureReturn TextLength
  
EndProcedure



Procedure.l ComboBoxInfoTipListBoxWinProc ( WindowHandle.l, Message.l, WParam.l, LParam.l )
  
  *Info.CBINFOTIPINFO = GetProp_(WindowHandle, @"cbinfotip")
  If #Null = *Info
    ProcedureReturn 0
  EndIf
  
  *WinProc = *Info\PrevWinProc
  If #Null = *WinProc
    ProcedureReturn 0
  EndIf

  Select Message
  
    Case #WM_NCDESTROY
      KillTimer_(WindowHandle, 1)
      SetWindowLong_(WindowHandle, #GWL_WNDPROC, *WinProc)
      RemoveProp_(WindowHandle, @"cbinfotip") 
      If #Null <> *Info\TipText
        FreeMemory(*Info\TipText)
      EndIf  
      FreeMemory(*Info)

    Case #WM_MOUSEWHEEL
      SendMessage_(*Info\TipHandle, #TTM_TRACKACTIVATE, 0, @*info\TipInfo)
      *Info\CurrentItem = -1
      KillTimer_(WindowHandle, 1)
      
    Case #WM_MOUSEMOVE
      GetClientRect_(WindowHandle, @ClientRect.RECT)
      If PtInRect_(@ClientRect, PeekW(@LParam), PeekW(@LParam + 2))
        SelectedItem.l = SendMessage_(WindowHandle, #LB_ITEMFROMPOINT, 0, LParam)
        If SelectedItem >= 0 
          If SelectedItem = *Info\CurrentItem
            ProcedureReturn CallWindowProc_(*WinProc, WindowHandle, Message, WParam, LParam)
          EndIf
          *Info\CurrentItem = SelectedItem
          SetWindowPos_(WindowHandle, #HWND_NOTOPMOST, 0, 0, 0, 0, #SWP_NOSIZE + #SWP_NOMOVE)
        
          TextLength.l = ComboBoxInfoTipItemText(WindowHandle, *Info, SelectedItem)
          If TextLength > 0
            *Info\TipInfo\lpszText = *info\TipText
            SendMessage_(WindowHandle, #LB_GETITEMRECT, SelectedItem, @ItemRect.RECT)
            ClientToScreen_(WindowHandle, @ItemRect)
            If ComboBoxInfoTipShowTip(WindowHandle, *Info, TextLength, ClientRect\right - ClientRect\left - 3, ItemRect\left, ItemRect\top)      
              SetTimer_(WindowHandle, 1, 50, 0)
              ProcedureReturn CallWindowProc_(*WinProc, WindowHandle, Message, WParam, LParam)
            EndIf
          EndIf    
        EndIf  
      EndIf
      SendMessage_(*Info\TipHandle, #TTM_TRACKACTIVATE, 0, @*info\TipInfo)
      *Info\CurrentItem = -1
      KillTimer_(WindowHandle, 1)
      
    Case #WM_TIMER
      If 1 = WParam 
        GetCursorPos_(@CurrentPoint.POINT)  
        ScreenToClient_(WindowHandle, @CurrentPoint)
        GetClientRect_(WindowHandle, @CurrentRect.RECT)
        ListBoxStyle.l = GetWindowLong_(WindowHandle, #GWL_STYLE)
        If (ListBoxStyle & #WS_VISIBLE) = 0 Or Not PtInRect_(@CurrentRect, CurrentPoint\x, CurrentPoint\y)
          SendMessage_(*Info\TipHandle, #TTM_TRACKACTIVATE, 0, @*info\TipInfo)
          KillTimer_(WindowHandle, 1)
        EndIf
      EndIf      

  EndSelect
          
  ProcedureReturn CallWindowProc_(*WinProc, WindowHandle, Message, WParam, LParam)
  
EndProcedure



Procedure.l ComboBoxInfoTipWinProc ( WindowHandle.l, Message.l, WParam.l, LParam.l )
  
  *Info.CBINFOTIPINFO = GetProp_(WindowHandle, @"cbinfotip")
  If #Null = *Info
    ProcedureReturn 0
  EndIf
  
  *WinProc = *Info\PrevWinProc
  If #Null = *WinProc
    ProcedureReturn 0
  EndIf
    
  Select Message
  
    Case #WM_NCDESTROY
      KillTimer_(WindowHandle, 1)
      SetWindowLong_(WindowHandle, #GWL_WNDPROC, *WinProc)
      RemoveProp_(WindowHandle, @"cbinfotip") 
      If #Null <> *Info\TipText
        FreeMemory(*Info\TipText)
      EndIf  
      FreeMemory(*Info)

    Case #WM_CTLCOLORLISTBOX 
      If *Info\ListBoxHandle = #Null
        *ListInfo.CBINFOTIPINFO = AllocateMemory(SizeOf(CBINFOTIPINFO))
        If #Null <> *ListInfo 
          If Not ComboBoxInfoTipInitTip(LParam, *ListInfo)
            FreeMemory(*ListInfo)
          Else
            *ListInfo\CurrentItem = -1 
            *ListInfo\PrevWinProc = GetWindowLong_(LParam, #GWL_WNDPROC)  
            SetProp_(LParam, @"cbinfotip", *ListInfo)
            SetWindowLong_(LParam, #GWL_WNDPROC, @ComboBoxInfoTipListBoxWinProc())
            *Info\ListBoxHandle = LParam 
          EndIf
        EndIf    
      EndIf          
    
    Case #WM_MOUSEMOVE
      GetClientRect_(WindowHandle, @ClientRect.RECT)
      ClientRect\right = ClientRect\right - GetSystemMetrics_(#SM_CXTHUMB) - 2
      If PtInRect_(@ClientRect, PeekW(@LParam), PeekW(@LParam + 2))
        ClientToScreen_(WindowHandle, @ClientRect)
        ClientToScreen_(WindowHandle, @ClientRect + 8)
        TextLength.l = ComboBoxInfoTipItemText(WindowHandle, *Info, -1)
        If TextLength > 0
          *Info\TipInfo\lpszText = *info\TipText
          If ComboBoxInfoTipShowTip(WindowHandle, *Info, TextLength, ClientRect\right - ClientRect\left, ClientRect\left, ClientRect\top)      
            SetTimer_(WindowHandle, 1, 50, 0)
            ProcedureReturn CallWindowProc_(*WinProc, WindowHandle, Message, WParam, LParam)
          EndIf
        EndIf  
      EndIf
      KillTimer_(WindowHandle, 1)
      SendMessage_(*Info\TipHandle, #TTM_TRACKACTIVATE, 0, @*info\TipInfo)

          
    Case #WM_TIMER
      If 1 = WParam 
        GetCursorPos_(@CurrentPoint.POINT)  
        ScreenToClient_(WindowHandle, @CurrentPoint)
        GetClientRect_(WindowHandle, @CurrentRect.RECT)
        CurrentRect\right = CurrentRect\right - GetSystemMetrics_(#SM_CXTHUMB) - 2
        If Not PtInRect_(@CurrentRect, CurrentPoint\x, CurrentPoint\y)
          SendMessage_(*Info\TipHandle, #TTM_TRACKACTIVATE, 0, @*info\TipInfo)
          KillTimer_(WindowHandle, 1)
        EndIf
      EndIf      
         
  EndSelect
          
  ProcedureReturn CallWindowProc_(*WinProc, WindowHandle, Message, WParam, LParam)
  
EndProcedure


Procedure.l ComboBoxInfoTip ( WindowHandle.l )

  *Info.CBINFOTIPINFO = AllocateMemory(SizeOf(CBINFOTIPINFO))
  If #Null = *Info 
    ProcedureReturn #False
  EndIf
    
  If Not ComboBoxInfoTipInitTip(WindowHandle, *Info)
    FreeMemory(*Info)
    ProcedureReturn #False
  EndIf
   
  *Info\PrevWinProc = GetWindowLong_(WindowHandle, #GWL_WNDPROC)  
  SetProp_(WindowHandle, @"cbinfotip", *Info)
  SetWindowLong_(WindowHandle, #GWL_WNDPROC, @ComboBoxInfoTipWinProc())
   
  ProcedureReturn #True   

EndProcedure
  





#Window = 1
#ListIcon = 2
#Text = 3
#ListView = 4
#LVS_EX_LABELTIP = $4000


If OpenWindow(#Window,#PB_Ignore,#PB_Ignore,200,420,"ListView Tooltip",#PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(#Window))
   ComboBoxGadget(#ListIcon,0,0,200,200,200)
   ComboBoxInfoTip(GadgetID(#ListIcon))
   TextGadget(#Text, 0, 200, 200, 20, "'ListViewGadget':")
   ListIconGadget(#ListView, 0, 220, 200, 200, "", 170, #LVS_NOCOLUMNHEADER)
   SendMessage_(GadgetID(#ListView), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, #LVS_EX_LABELTIP)
EndIf

For i = 1 To 100
   Text.s = RSet("", i, Chr(Random(95) + 32))
   AddGadgetItem(#ListIcon, -1, Text)
   AddGadgetItem(#ListView, -1, Text)
Next i


Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow: End 

User avatar
Michael Vogel
Addict
Addict
Posts: 2806
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Late response to waldschrath - THANKS!

Michael
Post Reply