Page 1 of 1

Detect row and column when hovering over ListIconGadget

Posted: Tue May 16, 2006 10:14 am
by Fangbeast
I'd like to detect the row and column when hovering over ListIconGadget. The idea is to popup a window containing a small thumbnail of the item on the line (It's for my library book manager for occasions when a book has a cover page) and I think I can do this when I click on a line but not when I hover on a line and hover detection is what I need to do.

Posted: Tue May 16, 2006 11:55 am
by Trond
This is for row detection:

Code: Select all

OpenWindow(0, 0, 0, 512, 384, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CreateGadgetList(WindowID(0))
ListIconGadget(0, 10, 10, 492, 344, "Column 1", 100, #PB_ListIcon_FullRowSelect)
TextGadget(1, 10, 362, 100, 20, "")
For I = 0 To 100
  AddGadgetItem(0, I, "Item " + Str(I))
Next


Repeat
  Select WaitWindowEvent()
    Case 512
      GetWindowRect_(GadgetID(0), @Rect.RECT)
      ScreenToClient_(WindowID(0), @Rect)
      ScreenToClient_(WindowID(0), @Rect+8)
      With Rect
        If WindowMouseX(0) > \Left And WindowMouseX(0) < \Right
          If WindowMouseY(0) > \Top And WindowMouseY(0) < \Bottom
            HitTestInfo.LV_HITTESTINFO
            HitTestInfo\pt\x = WindowMouseX(0)
            HitTestInfo\pt\y = WindowMouseY(0)
            ClientToScreen_(WindowID(0), @HitTestInfo\pt)
            ScreenToClient_(GadgetID(0), @HitTestInfo\pt)
            ItemIndex = SendMessage_(GadgetID(0), #LVM_HITTEST, 0, @HitTestInfo)
            SetGadgetText(1, GetGadgetItemText(0, ItemIndex, 0))
          EndIf
        EndIf
      EndWith
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver

Posted: Tue May 16, 2006 12:01 pm
by Fangbeast
Great Trond, thanks. That will be more than enough. The rest I can do!!

Woohoo!!

Posted: Tue May 16, 2006 12:03 pm
by srod
Use the #LVM_SUBITEMHITTEST message to determine row and column at the same time. It should slot straight into Trond's code.

Posted: Tue May 16, 2006 1:37 pm
by Fangbeast
srod wrote:Use the #LVM_SUBITEMHITTEST message to determine row and column at the same time. It should slot straight into Trond's code.
If I could speak your language, I would. But it's all Greek to me. (grin). based on what Trond showed me, this is what I have got so far. Eventually, I will want an imagegadget to follow the cursor and show the cover for a book in the library if the record on that row has one.

1. I hit a row, get the co-ordinates
2. I get the record number which is in row 4
3. I query the record in the sqlite database
4. If record has an image, it is shown in the poup window following the cursor.

I can do 1 to 4 now. It's just a matter of fine tuning where the window shows up, making sure it's hidden if the cursor steps out of the boundaries of the window, hiding the window if there is no image etc. That will be fun.

By the way, is there a Windows constant for event 512?

P.S. Thanks for EasyVent Srod, it will come in handy for a future project and is a great work.

**EDIT** Got the cursor hiding and positioning almost right. Now to experiment on my main program (MWUAHAHAHA). Of course; if I knew where to stick the #LVM_SUBITEMHITTEST, I probably wouldn't have to do the crude repositioning of the floating window that I do now but, at least it works!!

Code: Select all

Enumeration 1
  #Window_hovertest
  #Window_info
EndEnumeration

#WindowIndex = #PB_Compiler_EnumerationValue

Enumeration 1
  #Gadget_hovertest_fmain
  #Gadget_hovertest_items
  #Gadget_info_sinfo
EndEnumeration

#GadgetIndex = #PB_Compiler_EnumerationValue

Enumeration 1
  #StatusBar_hovertest
EndEnumeration

#StatusBarIndex = #PB_Compiler_EnumerationValue

#StatusBar_hovertest_messages = 0

Procedure.l Window_hovertest()
  If OpenWindow(#Window_hovertest,80,80,500,400,"ListIconGadget hover co-ordinate test",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible)
    If CreateGadgetList(WindowID(#Window_hovertest))
      Frame3DGadget(#Gadget_hovertest_fmain,5,0,490,375,"")
      ListIconGadget(#Gadget_hovertest_items,15,15,470,350,"Col1",146,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
        AddGadgetColumn(#Gadget_hovertest_items,1,"Col2",146)
        AddGadgetColumn(#Gadget_hovertest_items,2,"Col3",146)
      CreateStatusBar(#StatusBar_hovertest,WindowID(#Window_hovertest))
        AddStatusBarField(500)
      HideWindow(#Window_hovertest,0)
      ProcedureReturn WindowID(#Window_hovertest)
    EndIf
  EndIf
EndProcedure

Procedure.l Window_info()
  If OpenWindow(#Window_info,0,0,400,20,"",#PB_Window_BorderLess|#PB_Window_Invisible)
    If CreateGadgetList(WindowID(#Window_info))
      StringGadget(#Gadget_info_sinfo,0,0,400,20,"")
        PVDynamic_AddColorGadget(#Gadget_info_sinfo,0,16744703)
        SetGadgetFont(#Gadget_info_sinfo,LoadFont(#Gadget_info_sinfo,"Arial",12,0))
      HideWindow(#Window_info,1)
      ProcedureReturn WindowID(#Window_info)
    EndIf
  EndIf
EndProcedure

Procedure WindowCallback(WindowID, Message, wParam, lParam)
  ReturnValue = #PB_ProcessPureBasicEvents
  If Message = #WM_CTLCOLORSTATIC Or Message = #WM_CTLCOLOREDIT Or Message = #WM_CTLCOLORLISTBOX
    ReturnValue = PVDynamic_ColorGadget(lParam, wParam)
  EndIf
  ProcedureReturn ReturnValue
EndProcedure

If Window_hovertest()
  Window_info()
  ;SetWindowCallback(@WindowCallback()) ; Visual designer callback for gadget colours and other things
  quithovertest = 0
  For I = 0 To 20
    AddGadgetItem(#Gadget_hovertest_items, -1, "Item " + Str(I) + Chr(10) + "Phlegm " + Str(I + 1) + Chr(10) + "Smeg " + Str(I + 2))
  Next
  Repeat
    Select WaitWindowEvent()
      Case 512
        GetWindowRect_(GadgetID(#Gadget_hovertest_items), @Rect.RECT)
        ScreenToClient_(WindowID(#Window_hovertest), @Rect)
        ScreenToClient_(WindowID(#Window_hovertest), @Rect + 8)
        With Rect
          If WindowMouseX(#Window_hovertest) > \Left And WindowMouseX(#Window_hovertest) < \Right
            If WindowMouseY(#Window_hovertest) > \Top And WindowMouseY(#Window_hovertest) < \Bottom
              HideWindow(#Window_info, 0)
              HitTestInfo.LV_HITTESTINFO
              HitTestInfo\pt\x = WindowMouseX(#Window_hovertest)
              HitTestInfo\pt\y = WindowMouseY(#Window_hovertest)
              ClientToScreen_(WindowID(#Window_hovertest), @HitTestInfo\pt)
              ScreenToClient_(GadgetID(#Gadget_hovertest_items), @HitTestInfo\pt)
              ItemIndex = SendMessage_(GadgetID(#Gadget_hovertest_items), #LVM_HITTEST, 0, @HitTestInfo)
              ResizeWindow(#Window_info, HitTestInfo\pt\x + 290, HitTestInfo\pt\y + 200, #PB_Ignore , #PB_Ignore )
              SetGadgetText(#Gadget_info_sinfo, GetGadgetItemText(#Gadget_hovertest_items, ItemIndex, 2))
            Else
              HideWindow(#Window_info, 1)
            EndIf
          Else
            HideWindow(#Window_info, 1)
          EndIf
        EndWith
      Case #PB_Event_CloseWindow
        If EventWindow() = #Window_hovertest
          quithovertest = 1
        EndIf
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Gadget_hovertest_items
            Select EventType()
              Case #PB_EventType_LeftDoubleClick
              Case #PB_EventType_RightDoubleClick
              Case #PB_EventType_RightClick
              Default
            EndSelect
        EndSelect
    EndSelect
  Until quithovertest
  CloseWindow(#Window_hovertest)
EndIf
End


Posted: Tue May 16, 2006 3:17 pm
by netmaestro
The windows message number 512 = #WM_MOUSEMOVE, which seems apropos to how it's being used in your very cool little program. Nice work!

Posted: Wed May 17, 2006 1:22 am
by Fangbeast
That's strange as if I replace the 512 with #WM_MOUSEMOVE, the program no longer works. Maybe it's one of those undeclared constants not yet added but then again, the compiler would have complained I suppose.

Anyway, I can't take credit here, Trond came up with the code. I just don't have this sort of experience with the API to think like that.

Finally added the above logic to my main "booky" program and it works fine. An imagegadget on a borderless window follows the mouse and displays the book cover if there is one. If there is no cover, the image hides. If the cursor leaves the boundaries of the app window, the image hides.

Only problem now is the amount of flickering on the ListIconGadget as the constant redrawing happens but I can live with that.

Posted: Wed May 17, 2006 1:35 am
by netmaestro
See if it will detect it as #WM_MOUSEFIRST as that is another constant that has the value $200 or 512. It's odd though that PB didn't recognize it as both of those are present in the PureBasic residents.

Posted: Wed May 17, 2006 2:20 am
by Fangbeast
Didn't do it that time either. Must be some sort of special case.

@Trond do you know what windows event constant 512 stands for?

Posted: Wed May 17, 2006 7:16 am
by Trond
512 is #WM_MOUSEMOVE.

Let me guess three times: You forgot the #.
Edit: That was only one guess I guess.

Posted: Wed May 17, 2006 7:45 am
by Dare2
I guess you could say two, if you count the edit.
:)

Posted: Wed May 17, 2006 8:43 am
by Fangbeast
No, I didn't forget the "#". I may be shortsighted and make mistakes all day long but I am not quite blind yet :D :D :D :D :D :D (except when I see a naked woman)

Posted: Wed May 17, 2006 8:45 am
by Fangbeast
#EDIT#

I've added specific window detection to my code and that seems to have done the trick.