canvas transparency and/or image mouse movements
canvas transparency and/or image mouse movements
Ok, I have two questions... though based on my research I'm pretty sure I know the answers but maybe someone out there knows...
1. Is there a way to make the canvas gadget transparent in Windows? I can do it in OSX but would like a cross platform solution if possible.
Pretty sure this is a no.
OR
2. Is there a way to track mouse movements inside the image gadget (Windows and OSX) with the left mouse button down? Everything I tried has failed. Once you press the left button, it fires a drag event and you get nothing else until the drag ends.
Thanks!
Phil
1. Is there a way to make the canvas gadget transparent in Windows? I can do it in OSX but would like a cross platform solution if possible.
Pretty sure this is a no.
OR
2. Is there a way to track mouse movements inside the image gadget (Windows and OSX) with the left mouse button down? Everything I tried has failed. Once you press the left button, it fires a drag event and you get nothing else until the drag ends.
Thanks!
Phil
Re: canvas transparency and/or image mouse movements
1:
https://www.purebasic.fr/english/viewto ... 14#p624014
2.
Draw the image in a CanvasGadget, then you can follow the mouse (I think)
No code, no better help.
https://www.purebasic.fr/english/viewto ... 14#p624014
2.
Draw the image in a CanvasGadget, then you can follow the mouse (I think)
No code, no better help.
Re: canvas transparency and/or image mouse movements
I am aware of that, but the reason why I want to track mouse movements in the image gadget is because I cannot make the canvas gadget transparent. So either I make the canvas transparent or track mouse movements in the image gadget.infratec wrote: Sun Jul 28, 2024 7:35 pm 1:
https://www.purebasic.fr/english/viewto ... 14#p624014
2.
Draw the image in a CanvasGadget, then you can follow the mouse (I think)
No code, no better help.
Re: canvas transparency and/or image mouse movements
This makes the canvas gadget background transparent, only for Windows 8 and above. Is that what you are looking for?
Code: Select all
EnableExplicit
Procedure main()
Protected.l ev
Protected.i hwCanvas
Protected.l transparentColor
Protected.a opacity
OpenWindow(0, 10, 10, 600, 400, "Test", #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget)
CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0))
hwCanvas = GadgetID(0)
transparentColor = RGB(255, 255, 255) ;white transparent
opacity = 0
SetWindowLong_(hwCanvas, #GWL_EXSTYLE, GetWindowLong_(hwCanvas, #GWL_EXSTYLE) | #WS_EX_LAYERED)
SetLayeredWindowAttributes_(hwCanvas, transparentColor, opacity, #LWA_COLORKEY)
StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor(RGBA(255, 0, 0, 255))
AddPathCircle(DesktopScaledX(100), DesktopScaledX(100), DesktopScaledX(100))
FillPath()
StopVectorDrawing()
Repeat
ev = WaitWindowEvent()
Until ev = #PB_Event_CloseWindow
EndProcedure
main()
Re: canvas transparency and/or image mouse movements
Yes! That is *very* close to what I want. The only problem now is that any gadgets that are underneath the canvas still respond to events. Trying to have my cake and eat it, too. 
Thanks!
Phil

Thanks!
Phil
Re: canvas transparency and/or image mouse movements
PB does not handle 'layers' and z-order.
If you want that they not handle events... DisableGadget()
Or ... place your gadget in an own window without borders.
If you want that they not handle events... DisableGadget()
Or ... place your gadget in an own window without borders.
Re: canvas transparency and/or image mouse movements
Hmmm... that must be a windows thing because it doesn't do that on OSX.infratec wrote: Mon Jul 29, 2024 3:30 pm PB does not handle 'layers' and z-order.
If you want that they not handle events... DisableGadget()
Or ... place your gadget in an own window without borders.
If I overlap two gadgets on Windows and click on the gadget that is behind it, that gadget is brought to the front. To me that shouldn't happen. This happens with or without using the layer calls in that code snippet.
FYI - I'm a a mac person just trying to make some code cross platform.
Thanks for the info, though.
Phil
Re: canvas transparency and/or image mouse movements
This handles mouse events in the image gadget and probably others(not tested) in Mac and Windows, even when mouse is down.
But what are you trying to achieve?
But what are you trying to achieve?
Code: Select all
;gadgetEx.pb
;Justin 07/24
EnableExplicit
;- DECLARES
#GADGETEX_PROP_CALLBACK = "_pb_cb_"
#GADGETEX_PROP_OLD_PROC = "_pb_oldProc_"
#GADGETEX_PROP_TAREA = "_pb_tarea_"
Enumeration
#GADGETEX_EVENT_MOUSEMOVE
EndEnumeration
Procedure.w HIWORD2(Value.i)
ProcedureReturn (((Value) >> 16) & $FFFF)
EndProcedure
Procedure.w LOWORD2(Value.i)
ProcedureReturn ((Value) & $FFFF)
EndProcedure
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
#GADGETEX_MODIFIER_CONTROL = #MK_CONTROL
#GADGETEX_MODIFIER_SHIFT = #MK_SHIFT
#GADGETEX_MODIFIER_ALT = $80
#GADGETEX_MODIFIER_LEFTMOUSEBUTTON = #MK_LBUTTON
#GADGETEX_MODIFIER_RIGHTMOUSEBUTTON = #MK_RBUTTON
#GADGETEX_MODIFIER_MIDDLEMOUSEBUTTON = #MK_MBUTTON
CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS
#OBJC_ASSOCIATION_ASSIGN = 0
;NSTrackingAreaOptions
#NSTrackingMouseEnteredAndExited = $01
#NSTrackingMouseMoved = $02
#NSTrackingCursorUpdate = $04
#NSTrackingActiveWhenFirstResponder = $10
#NSTrackingActiveInKeyWindow = $20
#NSTrackingActiveInActiveApp = $40
#NSTrackingActiveAlways = $80
#NSTrackingAssumeInside = $100
#NSTrackingInVisibleRect = $200
#NSTrackingEnabledDuringMouseDrag = $400
#NSEventModifierFlagShift = 1 << 17
#NSEventModifierFlagControl = 1 << 18
#NSEventModifierFlagOption = 1 << 19
#NSEventModifierFlagCommand = 1 << 20
#GADGETEX_MODIFIER_CONTROL = #NSEventModifierFlagControl
#GADGETEX_MODIFIER_SHIFT = #NSEventModifierFlagShift
#GADGETEX_MODIFIER_ALT = #NSEventModifierFlagOption
#GADGETEX_MODIFIER_COMMAND = #NSEventModifierFlagCommand
#GADGETEX_MODIFIER_LEFTMOUSEBUTTON = 1 << 24
#GADGETEX_MODIFIER_RIGHTMOUSEBUTTON = 1 << 25
#GADGETEX_MODIFIER_MIDDLEMOUSEBUTTON = 1 << 26
PrototypeC gadgetEx_onMouseMovedProto(obj.i, sel.i, nsEv.i)
PrototypeC gadgetEx_onMouseDraggedProto(obj.i, sel.i, nsEv.i)
PrototypeC gadgetEx_onUpdateTrackingAreasProto(obj.i, sel.i)
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
#GADGETEX_MODIFIER_CONTROL = #GDK_CONTROL_MASK
#GADGETEX_MODIFIER_SHIFT = #GDK_SHIFT_MASK
#GADGETEX_MODIFIER_ALT = #GDK_MOD1_MASK
#GADGETEX_MODIFIER_LEFTMOUSEBUTTON = #GDK_BUTTON1_MASK
#GADGETEX_MODIFIER_RIGHTMOUSEBUTTON = #GDK_BUTTON3_MASK
#GADGETEX_MODIFIER_MIDDLEMOUSEBUTTON = #GDK_BUTTON2_MASK
Structure GdkEvent Align #PB_Structure_AlignC
StructureUnion
type.l
motion.GdkEventMotion
EndStructureUnion
EndStructure
CompilerEndIf
;- GADGETEX_GLOBAL
Structure GADGETEX_GLOBAL
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS
oldMouseMoved.gadgetEx_onMouseMovedProto
oldMouseDragged.gadgetEx_onMouseDraggedProto
oldRightMouseDragged.gadgetEx_onMouseDraggedProto
oldUpdateTrackingAreas.gadgetEx_onUpdateTrackingAreasProto
CompilerEndIf
EndStructure
;- GADGETEX_EVENT
Structure GADGETEX_EVENT
type.l
EndStructure
;- GADGETEX_EVENT_MOUSEMOVE
Structure GADGETEX_EVENT_MOUSEMOVE Extends GADGETEX_EVENT
x.l
y.l
modifiers.l ;biwise #GADGETEX_MODIFIER_
EndStructure
Prototype gadgetEx_callbackProto(gdt.i, *evt.GADGETEX_EVENT)
;-
;- PRIVATE
Procedure.i gadgetEx()
Static.GADGETEX_GLOBAL *gex
If *gex = 0
*gex = AllocateStructure(GADGETEX_GLOBAL)
EndIf
ProcedureReturn *gex
EndProcedure
;-
;- WINDOWS
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Procedure gadgetEx_onMouseMoveWin(hwnd.i, msg.l, wparam.i, lparam.i)
Protected.gadgetEx_callbackProto cb
Protected.GADGETEX_EVENT_MOUSEMOVE ev
cb = GetProp_(hwnd, #GADGETEX_PROP_CALLBACK)
If cb
ev\type = #GADGETEX_EVENT_MOUSEMOVE
ev\x = LOWORD2(lparam)
ev\y = HIWORD2(lparam)
ev\modifiers = wparam
If GetKeyState_(#VK_MENU) & $8000
ev\modifiers | #GADGETEX_MODIFIER_ALT
EndIf
cb(GetProp_(hwnd, "PB_ID"), @ev)
EndIf
EndProcedure
Procedure gadgetEx_onNcDestroyWin(hwnd.i, msg.l, wparam.i, lparam.i)
Protected.i oldProc
oldProc = GetProp_(hwnd, #GADGETEX_PROP_OLD_PROC)
RemoveProp_(hwnd, #GADGETEX_PROP_CALLBACK)
RemoveProp_(hwnd, #GADGETEX_PROP_OLD_PROC)
SetWindowLongPtr_(hwnd, #GWLP_WNDPROC, oldProc)
ProcedureReturn CallWindowProc_(oldProc, hwnd, msg, wparam, lparam)
EndProcedure
Procedure gadgetEx_procWin(hwnd.i, msg.l, wparam.i, lparam.i)
Select msg
Case #WM_MOUSEMOVE
gadgetEx_onMouseMoveWin(hwnd, msg, wparam, lparam)
Case #WM_NCDESTROY : ProcedureReturn gadgetEx_onNcDestroyWin(hwnd, msg, wparam, lparam)
EndSelect
ProcedureReturn CallWindowProc_(GetProp_(hwnd, #GADGETEX_PROP_OLD_PROC), hwnd, msg, wparam, lparam)
EndProcedure
;-
;- MAC
CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS
Procedure gadgetEx_onMouseMoveHandler(obj.i, sel.i, nsEv.i)
Protected.NSPoint pt
Protected.GADGETEX_EVENT_MOUSEMOVE ev
Protected.gadgetEx_callbackProto cb
Protected.i gdt
Protected.l btnMask, modifiers
cb = objc_getAssociatedObject_(obj, #GADGETEX_PROP_CALLBACK)
If cb
gdt = CocoaMessage(0, obj, "tag")
CocoaMessage(@pt, nsEv, "locationInWindow")
CocoaMessage(@pt, obj, "convertPoint:@", @pt, "fromView:", #nil)
ev\type = #GADGETEX_EVENT_MOUSEMOVE
ev\x = pt\x
ev\y = GadgetHeight(gdt) - pt\y
ev\modifiers = CocoaMessage(0, nsEv, "modifierFlags")
btnMask = CocoaMessage(0, 0, "NSEvent pressedMouseButtons")
If btnMask & 1 << 0
ev\modifiers | #GADGETEX_MODIFIER_LEFTMOUSEBUTTON
EndIf
If btnMask & 1 << 1
ev\modifiers | #GADGETEX_MODIFIER_RIGHTMOUSEBUTTON
EndIf
If btnMask & 1 << 2
ev\modifiers | #GADGETEX_MODIFIER_MIDDLEMOUSEBUTTON
EndIf
cb(gdt, @ev)
EndIf
EndProcedure
Procedure gadgetEx_onMouseMovedMac(obj.i, sel.i, nsEv.i)
Protected.GADGETEX_GLOBAL *gex = gadgetEx()
gadgetEx_onMouseMoveHandler(obj, sel, nsEv)
If *gex\oldMouseMoved
*gex\oldMouseMoved(obj, sel, nsEv)
EndIf
EndProcedure
Procedure gadgetEx_onMouseDraggedMac(obj.i, sel.i, nsEv.i)
Protected.GADGETEX_GLOBAL *gex = gadgetEx()
gadgetEx_onMouseMoveHandler(obj, sel, nsEv)
If *gex\oldMouseDragged
*gex\oldMouseDragged(obj, sel, nsEv)
EndIf
EndProcedure
Procedure gadgetEx_onRightMouseDraggedMac(obj.i, sel.i, nsEv.i)
Protected.GADGETEX_GLOBAL *gex = gadgetEx()
gadgetEx_onMouseMoveHandler(obj, sel, nsEv)
If *gex\oldRightMouseDragged
*gex\oldRightMouseDragged(obj, sel, nsEv)
EndIf
EndProcedure
ProcedureC gadgetEx_onUpdateTrackingAreas(obj.i, sel.i)
Protected.NSRect rc
Protected.i trackingArea
Protected.GADGETEX_GLOBAL *gex = gadgetEx()
trackingArea = objc_getAssociatedObject_(obj, #GADGETEX_PROP_TAREA)
If trackingArea
CocoaMessage(0, obj, "removeTrackingArea:", trackingArea)
CocoaMessage(0, trackingArea, "release")
EndIf
trackingArea = CocoaMessage(0, 0, "NSTrackingArea alloc")
objc_setAssociatedObject_(obj, #GADGETEX_PROP_TAREA, trackingArea, #OBJC_ASSOCIATION_ASSIGN)
CocoaMessage(0, trackingArea, "initWithRect:@", @rc,
"options:", #NSTrackingMouseEnteredAndExited | #NSTrackingActiveInActiveApp | #NSTrackingInVisibleRect | #NSTrackingMouseMoved | #NSTrackingEnabledDuringMouseDrag,
"owner:", obj, "userInfo:", #nil)
CocoaMessage(0, obj, "addTrackingArea:", trackingArea)
If *gex\oldUpdateTrackingAreas
*gex\oldUpdateTrackingAreas(obj, sel)
EndIf
EndProcedure
;-
;- LINUX
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
Procedure gadgetEx_onEventMotionNotifyLin(widget.i, *evt.GdkEventMotion, gdt.i)
Protected.GADGETEX_EVENT_MOUSEMOVE ev
Protected.gadgetEx_callbackProto cb
cb = g_object_get_data_(widget, #GADGETEX_PROP_CALLBACK)
If cb
ev\type = #GADGETEX_EVENT_MOUSEMOVE
ev\x = *evt\x
ev\y = *evt\y
ev\modifiers = *evt\state
cb(gdt, @ev)
EndIf
EndProcedure
Procedure gadgetEx_onEventLin(widget.i, *evt.GdkEvent, gdt.i)
Select *evt\type
Case #GDK_MOTION_NOTIFY : ProcedureReturn gadgetEx_onEventMotionNotifyLin(widget, *evt, gdt)
EndSelect
EndProcedure
CompilerEndIf
;-
;- PUBLIC
Procedure gadgetEx_setup(gdt.i, callback.i)
Protected.i osHandle
Protected.GADGETEX_GLOBAL *gex = gadgetEx()
osHandle = GadgetID(gdt)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
SetProp_(osHandle, #GADGETEX_PROP_CALLBACK, callback)
SetProp_(osHandle, #GADGETEX_PROP_OLD_PROC, SetWindowLongPtr_(osHandle, #GWLP_WNDPROC, @gadgetEx_procWin()))
ProcedureReturn #True
CompilerElseIf #PB_Compiler_OS = #PB_OS_MacOS
Protected.i viewClass
Protected.i selMouseMoved, selMouseDragged, selUpdateTrackingAreas, selRightMouseDragged
objc_setAssociatedObject_(osHandle, #GADGETEX_PROP_CALLBACK, callback, #OBJC_ASSOCIATION_ASSIGN)
viewClass = object_getClass_(osHandle)
selMouseMoved = sel_registerName_("mouseMoved:")
selMouseDragged = sel_registerName_("mouseDragged:")
selRightMouseDragged = sel_registerName_("rightMouseDragged:")
selUpdateTrackingAreas = sel_registerName_("updateTrackingAreas")
If class_getMethodImplementation_(viewClass, selMouseMoved) <> @gadgetEx_onMouseMovedMac()
*gex\oldMouseMoved = class_replaceMethod_(viewClass, selMouseMoved, @gadgetEx_onMouseMovedMac(), "v@:@")
EndIf
If class_getMethodImplementation_(viewClass, selMouseDragged) <> @gadgetEx_onMouseDraggedMac()
*gex\oldMouseDragged = class_replaceMethod_(viewClass, selMouseDragged, @gadgetEx_onMouseDraggedMac(), "v@:@")
EndIf
If class_getMethodImplementation_(viewClass, selUpdateTrackingAreas) <> @gadgetEx_onUpdateTrackingAreas()
*gex\oldUpdateTrackingAreas = class_replaceMethod_(viewClass, selUpdateTrackingAreas, @gadgetEx_onUpdateTrackingAreas(), "v@:@")
EndIf
If class_getMethodImplementation_(viewClass, selRightMouseDragged) <> @gadgetEx_onRightMouseDraggedMac()
*gex\oldRightMouseDragged = class_replaceMethod_(viewClass, selRightMouseDragged, @gadgetEx_onRightMouseDraggedMac(), "v@:@")
EndIf
ProcedureReturn #True
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
Select GadgetType(gdt)
Case #PB_GadgetType_Image
Protected.i evBox, wdName, parent
parent = gtk_widget_get_parent_(osHandle)
wdName = gtk_widget_get_name_(parent)
If wdName = 0 : ProcedureReturn #False: EndIf
If PeekS(wdName, -1, #PB_UTF8) = "GtkEventBox"
evBox = parent
ElseIf PeekS(wdName, -1, #PB_UTF8) = "GtkFrame"
parent = gtk_widget_get_parent_(parent)
wdName = gtk_widget_get_name_(parent)
If wdName = 0 : ProcedureReturn #False : EndIf
If PeekS(wdName, -1, #PB_UTF8) = "GtkEventBox"
evBox = parent
Else
ProcedureReturn #False
EndIf
Else
ProcedureReturn #False
EndIf
g_object_set_data_(evBox, #GADGETEX_PROP_CALLBACK, callback)
gtk_widget_add_events_(evBox, #GDK_POINTER_MOTION_MASK)
g_signal_connect_(evBox, "event", @gadgetEx_onEventLin(), gdt)
ProcedureReturn #True
;TODO Handle more gadget types
Default
ProcedureReturn #False
EndSelect
CompilerEndIf
EndProcedure
;-
;- --------------
;- TEST
;- --------------
Procedure.s getModifiersStr(mods.l)
Protected.s smods
If mods & #GADGETEX_MODIFIER_ALT = #GADGETEX_MODIFIER_ALT
smods + " " + "Alt"
EndIf
If mods & #GADGETEX_MODIFIER_CONTROL = #GADGETEX_MODIFIER_CONTROL
smods + " " + "Ctrl"
EndIf
If mods & #GADGETEX_MODIFIER_SHIFT = #GADGETEX_MODIFIER_SHIFT
smods + " " + "Shift"
EndIf
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
If mods & #GADGETEX_MODIFIER_COMMAND = #GADGETEX_MODIFIER_COMMAND
smods + " " + "Cmd"
EndIf
CompilerEndIf
If mods & #GADGETEX_MODIFIER_LEFTMOUSEBUTTON = #GADGETEX_MODIFIER_LEFTMOUSEBUTTON
smods + " " + "LButton"
EndIf
If mods & #GADGETEX_MODIFIER_RIGHTMOUSEBUTTON = #GADGETEX_MODIFIER_RIGHTMOUSEBUTTON
smods + " " + "RButton"
EndIf
If mods & #GADGETEX_MODIFIER_MIDDLEMOUSEBUTTON = #GADGETEX_MODIFIER_MIDDLEMOUSEBUTTON
smods + " " + "MButton"
EndIf
ProcedureReturn smods
EndProcedure
Procedure imgGdt1_Callback(gdt.i, *evt.GADGETEX_EVENT)
Select *evt\type
Case #GADGETEX_EVENT_MOUSEMOVE
Protected.GADGETEX_EVENT_MOUSEMOVE *evtMouseMove = *evt
Debug "img mouse move " + gdt + " " + *evtMouseMove\x + " " + *evtMouseMove\y
Debug "Modifiers " + getModifiersStr(*evtMouseMove\modifiers)
Debug ""
EndSelect
EndProcedure
Procedure main()
OpenWindow(0, 0, 0, 245, 105, "ImageGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
If LoadImage(0, #PB_Compiler_Home + "examples/sources/Data/Map.bmp")
ImageGadget(1, 10, 10, 100, 83, ImageID(0))
gadgetEx_setup(1, @imgGdt1_Callback())
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
EndProcedure
main()
Last edited by Justin on Wed Jul 31, 2024 7:30 pm, edited 3 times in total.
Re: canvas transparency and/or image mouse movements
Thank you! I might be able to work with this.Justin wrote: Mon Jul 29, 2024 11:50 pm This handles mouse events in the image gadget and probably others(not tested) in Mac and Windows, even when mouse is down.
But what are you trying to achieve?
Basically, I'm trying to create a simple runtime form designer. My idea was to use a transparent canvas or image gadget as an "overlay" that would sit on top of the gadget to intercept mouse movements and handle moving/resizing of the gadgets. That way I didn't have to disable the gadget in question or do custom drawing like the PB IDE does.
Re: canvas transparency and/or image mouse movements
I did some important changes on the Mac side, use the updated version on my previous post.
Re: canvas transparency and/or image mouse movements
Thank you!Justin wrote: Tue Jul 30, 2024 9:33 am I did some important changes on the Mac side, use the updated version on my previous post.
This is really useful.
Re: canvas transparency and/or image mouse movements
I had to finish this so i added Linux support and the key and button modifiers to the event.
In Mac and Linux the mouse is captured by default when draging the image, in windows doesn't. I could standarized but i leave it this way.
In Mac and Linux the mouse is captured by default when draging the image, in windows doesn't. I could standarized but i leave it this way.