a Hotspot Control

Just starting out? Need help? Post your questions and find answers here.
User avatar
blueb
Addict
Addict
Posts: 1041
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

a Hotspot Control

Post by blueb »

In the past..
I used a tool that supplied a 'Hot-Spot' control, which was a
hidden button that I could place anywhere on the screen.

A hot spot is like a transparent button; when you click on it, an event is executed.
You might place a hot spot over an image and give it an OnClick event.
Or you could use a hot spot as a hidden control about which only you, the developer, knows.

------------

Quite handy actually.

So the question is:
How do I create an InvisibleGadgetButton() (NOTE: not a hidden gadget)
that:
- is invisible
- sits on top of other gadgets
- doesn't visibly display anything (borders, etc) until the mouse is over it
- remains clickable

So, I'd like to build a new control called a 'Hot-Spot'.
I'm thinking of using a CanvasGadget or an ImageGadget as a base, but another Gadget might be easier to start with.

Anyone have any experience in this area? :?:
- It was too lonely at the top.

System : PB 6.10 Beta 9 (x64) and Win Pro 11 (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: a Hotspot Control

Post by mk-soft »

Only for Window

Code: Select all

If OpenWindow(0, #PB_Ignore, #PB_Ignore, 800, 600, "Find the Button")
  ButtonGadget(0, Random(680, 20) , Random(480, 20), 100, 100, "", #BS_OWNERDRAW)
  ;ButtonGadget(0, 20, 20, 100, 100, "", #BS_OWNERDRAW)
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 0 : MessageRequester("Juhu", "founded!")
        EndSelect
    EndSelect
  ForEver
EndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: a Hotspot Control

Post by TI-994A »

blueb wrote:How do I create an InvisibleGadgetButton() (NOTE: not a hidden gadget)
that:
- is invisible
- sits on top of other gadgets
- doesn't visibly display anything (borders, etc) until the mouse is over it
- remains clickable
This would require comprehensive mouse handling, so a CanvasGadget() container would be ideal. The hot spot in this example:
1. is invisible (red box only for demo purposes, to indicate location)
2. remains invisible (mouse changes to hand cursor when hovered, optionally)
3. responds to all available mouse events
4. due to z-index restrictions, it's not able to effectively overlap other gadgets

Code: Select all

Enumeration
  #mainWindow
  #mainCanvas
  #textBox
  #button
EndEnumeration

Structure mousePoints
  x.i
  y.i
  width.i
  height.i
EndStructure

Define hotSpot.mousePoints

Procedure isHovering(*hotPoints.mousePoints)   
  inPoint = #False
  canvasX = GetGadgetAttribute(#mainCanvas, #PB_Canvas_MouseX)
  canvasY = GetGadgetAttribute(#mainCanvas, #PB_Canvas_MouseY)              
  With *hotPoints    
    If canvasX > \x And canvasX < \x + \width And 
       canvasY > \y And canvasY < \y + \height
      inPoint = #True
    EndIf
  EndWith
  ProcedureReturn inPoint
EndProcedure

Procedure drawHotSpot(*hotPoints.mousePoints) 
  With *hotPoints
    \x = Random(280, 0)
    \y = Random(200, 100)
    \width = 20
    \height = 20
    StartDrawing(CanvasOutput(#mainCanvas))
    Box(0, 0, 300, 300, #White)
    DrawingMode(#PB_2DDrawing_AlphaBlend)  
    Box(\x, \y, \width, \height, RGBA(255, 0, 0, 30))  
    StopDrawing()  
  EndWith
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#mainWindow, 0, 0, 300, 300, "HotSpot Mapping", wFlags)
CanvasGadget(#mainCanvas, 0, 0, 500, 300, #PB_Canvas_Container)
TextGadget(#textBox, 50, 50, 200, 50, "Find Hot Spot...", #PB_Text_Center)
SetGadgetColor(#textBox, #PB_Gadget_BackColor, #White)
ButtonGadget(#button, 50, 220, 200, 30, "Move HotSpot")
drawHotSpot(hotSpot)

Repeat
  event = WaitWindowEvent()
  Select event 
    Case #PB_Event_CloseWindow
      appQuit = 1
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #mainCanvas          
          Select EventType()
            Case #PB_EventType_MouseMove
              If isHovering(hotSpot)
                SetGadgetAttribute(#mainCanvas, #PB_Canvas_Cursor, #PB_Cursor_Hand)
                txt$ = "Hot Spot!"
              Else                   
                SetGadgetAttribute(#mainCanvas, #PB_Canvas_Cursor, #PB_Cursor_Default)
                txt$ = "Find Hot Spot..."                
              EndIf
              SetGadgetText(#textBox, txt$)
            Case #PB_EventType_LeftButtonDown
              If isHovering(hotSpot)
                MessageRequester("HotSpot Mapper", "Hello, Hot Spot!")
              EndIf              
          EndSelect          
        Case #button          
          drawHotSpot(hotSpot)
      EndSelect           
  EndSelect
  
  
Until appQuit
Tested and working with PureBasic v5.70 LTS b4 (x64) on Windows 10 and MacOS High Sierra.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: a Hotspot Control

Post by Dude »

mk-soft wrote:ButtonGadget(0, 20, 20, 100, 100, "", #BS_OWNERDRAW)
Nice! I may have a use for this in future. :)
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: a Hotspot Control

Post by RASHAD »

- is invisible
- sits on top of other gadgets
- doesn't visibly display anything (borders, etc) until the mouse is over it
- remains clickable

Code: Select all


OpenWindow(0,300,350,400,200,"Track Mouse Test",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)
ButtonGadget(0, 20, 20, 100, 100, "TEST")
ButtonGadget(10, 20, 20, 100, 100, "", #BS_OWNERDRAW)
SetWindowLongPtr_(GadgetID(10), #GWL_STYLE, GetWindowLongPtr_(GadgetID(10), #GWL_STYLE) | #WS_CLIPSIBLINGS)
SetWindowPos_(GadgetID(10), #HWND_TOP, 0, 0, 0, 0, #SWP_NOSIZE  | #SWP_NOMOVE)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
        Quit = 1

    Case #WM_MOUSEMOVE
          GetCursorPos_ (@p.POINT) 
          ScreenToClient_ (WindowID(0), @p)
          hWnd = ChildWindowFromPoint_ (WindowID(0), p\y<< 32 + p\x)
          
          TRACK.TRACKMOUSEEVENT
          TRACK\cbSize = SizeOf(TRACK)
          TRACK\dwFlags = #TME_HOVER|#TME_LEAVE
          TRACK\hwndTrack = hWnd
          TRACK\dwHoverTime = 10
          TrackMouseEvent_(@TRACK)
                   
    Case #WM_MOUSEHOVER
         Gad =  GetDlgCtrlID_(hWnd)
         If Gad = 10
           Debug "MOUSEHOVER Gadet : "  + Str(Gad)
         EndIf
         
    Case #WM_MOUSELEAVE
         If Gad = 10
           Debug "MOUSELEAVE Gadget : " + Str(Gad)
         EndIf
         
    Case #PB_Event_Gadget
        Select EventGadget()
          Case 10
            Debug "OK"
        EndSelect
  EndSelect
  
Until Quit = 1
Egypt my love
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: a Hotspot Control

Post by Kwai chang caine »

Dude wrote:
mk-soft wrote:ButtonGadget(0, 20, 20, 100, 100, "", #BS_OWNERDRAW)
Nice! I may have a use for this in future. :)
Yeeesss !!!! +100 :D
Really nice for simply hide admin button on GUI
Thanks MkSoft and Rashad 8)
ImageThe happiness is a road...
Not a destination
User avatar
blueb
Addict
Addict
Posts: 1041
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: a Hotspot Control

Post by blueb »

8)
Thanks guys,

Lots to digest, I'll give these a try... they all look viable.

I had also been thinking of a transparent image, but the Z-Order concerns me.

This can be worked around, but the perfect solution would be the ability to be placed on top of other controls.
- It was too lonely at the top.

System : PB 6.10 Beta 9 (x64) and Win Pro 11 (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: a Hotspot Control

Post by RASHAD »

Using CanvasGadget()
Zero Order seems OK

Code: Select all

#SC_DragMove      = $F012

Procedure WindowProc(hWnd,uMsg,wParam,lParam)
  Result = #PB_ProcessPureBasicEvents
  Select uMsg          
    Case #WM_NCACTIVATE
            Result = 1

  EndSelect
  ProcedureReturn Result
EndProcedure

If OpenWindow(0, 0, 0, 800, 600, "", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)  
SetWindowCallback(@WindowProc(),0)
OpenWindow(1,WindowX(0,#PB_Window_InnerCoordinate)+10, WindowY(0,#PB_Window_InnerCoordinate)+10,100,100,"", #PB_Window_BorderLess,WindowID(0))
SetWindowLongPtr_(WindowID(1), #GWL_EXSTYLE, #WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(1), RGBA(128,128,000,000), 0, #LWA_COLORKEY)
UseGadgetList(WindowID(1))  
CanvasGadget(0,  0, 0, 100, 100 )  
StartVectorDrawing(CanvasVectorOutput(0))  
  VectorSourceColor(RGBA(128,128,000,255))
  FillVectorOutput()
StopVectorDrawing()

UseGadgetList(WindowID(0))
ButtonGadget(1,10,10,100,100,"Test 1")
ButtonGadget(2,200,10,100,100,"Test 2")
ButtonGadget(3,105,120,100,100,"Test 3")
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
                     
    Case #PB_Event_Gadget
      Select EventGadget()
        Case  0
          Select EventType()
            Case #PB_EventType_MouseMove         
                 
            Case #PB_EventType_MouseEnter
                GetCursorPos_ (@p.POINT) 
                ScreenToClient_ (WindowID(0), @p)
                hWnd = ChildWindowFromPoint_ (WindowID(0), p\y<< 32 + p\x)
                Gad =  GetDlgCtrlID_(hWnd)
                Debug "Mouse Hover Gadget : "+ Str(Gad) 
                 
            Case #PB_EventType_MouseLeave
                Debug "Mouse Leave Gadget : "+ Str(Gad)
                                  
            Case #PB_EventType_LeftButtonDown
                SetCursor_(LoadCursor_(0, #IDC_SIZEALL))
                ReleaseCapture_()
                SendMessage_(GetForegroundWindow_(), #WM_SYSCOMMAND , #SC_DragMove,0) 
  ;                  
  ;             Case #PB_EventType_MouseMove 
  ;                  
            Case #PB_EventType_LeftButtonUp
              ReleaseCapture_()
  ;               
  ;             Case #PB_EventType_RightButtonDown 
          EndSelect
      EndSelect
  EndSelect
ForEver
EndIf
Egypt my love
User avatar
blueb
Addict
Addict
Posts: 1041
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: a Hotspot Control

Post by blueb »

Great example Rashad.

I was also thinking of creating a second Window, but like PureBasic's
StickyWindow() - the 'hotSpot' does not stay attached to the main form.

I made some visual changes to your code to see the effects...

Code: Select all

; =================================================================
;
; Author:     Rashad     
; Date:       February 13, 2019
; Explain:
;           
; Search tips:
;
; Typical Usage:   Hot Spot 3.pb       
; =================================================================

#SC_DragMove = $F012

Procedure WindowProc(hWnd,uMsg,wParam,lParam)
  Result = #PB_ProcessPureBasicEvents
  Select uMsg          
    Case #WM_NCACTIVATE
            Result = 1

  EndSelect
  ProcedureReturn Result
EndProcedure

If OpenWindow(0, 0, 0, 800, 600, "", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)  
SetWindowCallback(@WindowProc(),0)
OpenWindow(1,WindowX(0,#PB_Window_InnerCoordinate)+10, WindowY(0,#PB_Window_InnerCoordinate)+ 5, 20, 20,"", #PB_Window_BorderLess,WindowID(0)) ; changed size of 2nd window
SetWindowLongPtr_(WindowID(1), #GWL_EXSTYLE, #WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(1), RGBA(128,128,000,000), 0, #LWA_COLORKEY)
UseGadgetList(WindowID(1))  
CanvasGadget(0,  0, 0, 20, 20 )  ; made it smaller
StartVectorDrawing(CanvasVectorOutput(0))  
  VectorSourceColor(RGBA(255, 106, 106, 100)) ; changed color to see the effects
  FillVectorOutput()
StopVectorDrawing()

UseGadgetList(WindowID(0))
ButtonGadget(1,10,10,100,100,"Test 1")
ButtonGadget(2,200,10,100,100,"Test 2")
ButtonGadget(3,105,120,100,100,"Test 3")
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
                     
    Case #PB_Event_Gadget
      Select EventGadget()
        Case  0
          Select EventType()
            Case #PB_EventType_MouseMove         
                 
            Case #PB_EventType_MouseEnter
                GetCursorPos_ (@p.POINT) 
                ScreenToClient_ (WindowID(0), @p)
                hWnd = ChildWindowFromPoint_ (WindowID(0), p\y<< 32 + p\x)
                Gad =  GetDlgCtrlID_(hWnd)
                Debug "Mouse Hover Gadget : "+ Str(Gad) 
                 
            Case #PB_EventType_MouseLeave
                Debug "Mouse Leave Gadget : "+ Str(Gad)
                                  
            Case #PB_EventType_LeftButtonDown
                SetCursor_(LoadCursor_(0, #IDC_SIZEALL))
                ReleaseCapture_()
                SendMessage_(GetForegroundWindow_(), #WM_SYSCOMMAND , #SC_DragMove,0) 
  ;                  
  ;             Case #PB_EventType_MouseMove 
  ;                  
            Case #PB_EventType_LeftButtonUp
              ReleaseCapture_()
  ;               
  ;             Case #PB_EventType_RightButtonDown 
          EndSelect
      EndSelect
  EndSelect
ForEver
EndIf

- It was too lonely at the top.

System : PB 6.10 Beta 9 (x64) and Win Pro 11 (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
Post Reply