Page 1 of 1

EnhanceGadgetCursor()

Posted: Mon Oct 27, 2008 1:54 am
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.

Posted: Mon Oct 27, 2008 3:12 am
by ts-soft
Image thanks for sharing

Posted: Mon Oct 27, 2008 3:25 am
by oldBear
Very nice.

Thanks.

Posted: Mon Oct 27, 2008 7:30 am
by Alireza
That's Great work by netmaestro. :)
you save me from API coding that is very hard for me.THX a lot.