EnhanceGadgetCursor()

Share your advanced PureBasic knowledge/code with the community.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

EnhanceGadgetCursor()

Post by netmaestro »

Code: Select all

;======================================================
; Library:         EnhanceGadgetCursor
; Author:          Lloyd Gallant (netmaestro)
; Date:            October 26, 2008
; Target OS:       Microsoft Windows All
; Target Compiler: PureBasic 4.0 and later
; License:         Free, unrestricted, no warranty
;======================================================
;
; Library commands: EnhanceGadgetCursor( gadget [,cursor] )
;                   ResetGadgetCursor( gadget [,stopevents] )
;
; EnhanceGadgetCursor adds two event types to the gadget:
;
;   #Custom_EventType_MouseEnter, fires the first time the mouse enters the gadget
;   #Custom_EventType_MouseLeave, fires when the mouse is no longer inside the gadget
;
; These events are tested in the native fashion, using EventGadget() and EventType()
;
; If you load or create a custom cursor and pass its handle to EnhanceGadgetCursor
; it will be displayed whenever the mousepointer is inside the gadget.
; 
; ResetGadgetCursor removes the custom cursor from the gadget and optionally stops
; the enter-leave events from firing.
;
; Window properties are used to store the needed data, so you can enhance as many
; gadgets as you like in your project and there will be no conflicts. Globals are
; not used.
;
; A thread is used to monitor the mousepointer but there is nothing in it that
; would require the threadsafe switch if it's the only thread in your program.

Import "" 
  PB_Gadget_SendGadgetCommand(hWnd, EventType) 
EndImport 

#Custom_EventType_MouseEnter = 15000
#Custom_EventType_MouseLeave = 15001

Procedure gc_MonitorGadgetMouse(hwnd)

  Protected threadrunning = #True
  Protected mousewindow
  
  While threadrunning
    GetCursorPos_(cp.POINT)
    MapWindowPoints_(0,GetParent_(hwnd),cp,1)
    mousewindow = ChildWindowFromPoint_(GetParent_(hwnd), cp\x, cp\y)
    If mousewindow <> hwnd
      PB_Gadget_SendGadgetCommand(hwnd, #Custom_EventType_MouseLeave)
      threadrunning = #False
    EndIf
    Delay(1)
  Wend
  
  SetProp_(hwnd, "cursorstate", 0)
  
EndProcedure

Procedure gc_GadgetProc(hwnd, msg, wparam, lparam)

  Protected oldproc     = GetProp_(hwnd, "oldproc")
  Protected ctrlid      = GetProp_(hwnd, "PB_ID")
  Protected cursorstate = GetProp_(hwnd, "cursorstate")
  Protected cursor      = GetProp_(hwnd, "cursor")
    
  Select msg
    Case #WM_SETCURSOR
      If Not cursorstate
        cursorstate = #True
        SetProp_(hwnd, "cursorstate", #True)
        PB_Gadget_SendGadgetCommand(hwnd, #Custom_EventType_MouseEnter)
        CreateThread(@gc_MonitorGadgetMouse(), hwnd)
      EndIf
      If cursor
        SetCursor_(cursor)
        ProcedureReturn 0
      EndIf
    Case #WM_NCDESTROY
      RemoveProp_(hwnd, "oldproc")
      RemoveProp_(hwnd, "cursorstate")
      RemoveProp_(hwnd, "cursor")
  EndSelect
  
  ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
  
EndProcedure

ProcedureDLL EnhanceGadgetCursor(gadget, cursor=0)
  SetProp_(GadgetID(gadget), "oldproc", SetWindowLong_(GadgetID(gadget),#GWL_WNDPROC,@gc_GadgetProc()))
  SetProp_(GadgetID(gadget), "cursor", cursor)
EndProcedure

ProcedureDLL ResetGadgetCursor(gadget, stopevents=0)
   SetProp_(GadgetID(gadget), "cursor", 0)
   If stopevents
      SetWindowLong_(GadgetID(gadget),#GWL_WNDPROC, GetProp_(GadgetID(gadget), "oldproc"))
   EndIf
EndProcedure
Test program:

Code: Select all

IncludeFile "gadgetcursor.pbi"

CreateImage(0, 128,128)
StartDrawing(ImageOutput(0))
  Box(0,0,128,128,#Blue)
StopDrawing()
CreateImage(1, 128,128)
StartDrawing(ImageOutput(1))
  Box(0,0,128,128,#Red)
StopDrawing()

OpenWindow(0,0,0,640,480,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ImageGadget(1,100,100,128,128,ImageID(0))
ImageGadget(2,250,100,128,128,ImageID(1))

hand  = LoadCursor_(0, #IDC_HAND)
cross = LoadCursor_(0, #IDC_CROSS)

EnhanceGadgetCursor(1, cross)
EnhanceGadgetCursor(2, hand)

Repeat
  EventID = WaitWindowEvent()
  Select EventID
    Case #PB_Event_Gadget
      Select EventType() 
        Case  #Custom_EventType_MouseEnter
          Debug "Mouse enter gadget "+Str(EventGadget())
        Case #Custom_EventType_MouseLeave
          Debug "Mouse leave gadget "+Str(EventGadget())
      EndSelect
  EndSelect
Until EventID = #PB_Event_CloseWindow
Props to ts-soft for the import trick.
BERESHEIT
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

Image thanks for sharing
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
oldBear
Enthusiast
Enthusiast
Posts: 121
Joined: Tue Jul 05, 2005 2:42 pm
Location: berrypatch

Post by oldBear »

Very nice.

Thanks.
User avatar
Alireza
Enthusiast
Enthusiast
Posts: 143
Joined: Sat Aug 16, 2008 2:02 pm
Location: Iran

Post by Alireza »

That's Great work by netmaestro. :)
you save me from API coding that is very hard for me.THX a lot.
Post Reply