2 CanvasGadgets with 2 BindGadgets

Windows specific forum
HanPBF
Enthusiast
Enthusiast
Posts: 570
Joined: Fri Feb 19, 2010 3:42 am

2 CanvasGadgets with 2 BindGadgets

Post by HanPBF »

Hello!

Using this code:

Code: Select all

EnableExplicit

Procedure onCallback_Canvas1()
	debug "onCallback_Canvas1"
EndProcedure

Procedure onCallback_Canvas2()
	debug "onCallback_Canvas2"
EndProcedure

if OpenWindow(0, 0, 0, 512, 512, "Test")
	CanvasGadget(1, 8, 8, 128, 64, #PB_Canvas_Border)	
	BindGadgetEvent(1, @onCallback_Canvas1())
	
	CanvasGadget(2, 32, 16, 64, 24, #PB_Canvas_Border)	
	BindGadgetEvent(2, @onCallback_Canvas2())
endif	

repeat 
	define E = WaitWindowEvent()
until E=#PB_Event_CloseWindow
How can I make event 2 being triggered?
Only debug output is "onCallback_Canvas1".
Overlapping of canvasGadget is by intention...



Thanks a lot!
HanPBF
Enthusiast
Enthusiast
Posts: 570
Joined: Fri Feb 19, 2010 3:42 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by HanPBF »

O.k. got another error in my original code.

The silly SetWindowLongPtr_-method to mimick z-index works as needed....
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by mestnyi »

Code: Select all

EnableExplicit

Procedure GadgetsClip( WindowID = #False ) ;
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    Protected Dim EnumerateList.I(0)
    If WindowID = #False : WindowID = UseGadgetList(0) : EndIf
    Protected GadgetID = FindWindowEx_( WindowID, 0,0,0 )
    
    While GadgetID
      If GadgetID
        If GetWindowLongPtr_( GadgetID, #GWL_STYLE ) & #WS_CLIPSIBLINGS = #False 
          Protected Gadget = GetProp_( GadgetID, "PB_ID" ) ; IDGadget( GadgetID )
          If ( IsGadget( Gadget ) And 
               GadgetID( Gadget ) = GadgetID )
            Protected Height = GadgetHeight( Gadget ) 
            SetWindowLongPtr_( GadgetID, #GWL_STYLE, GetWindowLongPtr_( GadgetID, #GWL_STYLE )|#WS_CLIPSIBLINGS )
            ResizeGadget( Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, Height )
          EndIf
        EndIf
        ReDim EnumerateList( ArraySize( EnumerateList() ) + (1) ) : EnumerateList( ArraySize( EnumerateList() ) ) = GadgetID
      EndIf
      GadgetID = GetWindow_( GadgetID, #GW_HWNDNEXT )  
    Wend
    
    While ArraySize( EnumerateList() ) 
      If ArraySize( EnumerateList() )
        GadgetID = EnumerateList( ArraySize( EnumerateList() ) ) : ReDim EnumerateList( ArraySize( EnumerateList() ) - (1) )
        SetWindowPos_( GadgetID, #GW_HWNDLAST, 0,0,0,0, #SWP_NOMOVE|#SWP_NOSIZE )
      EndIf 
    Wend
    
    FreeArray( EnumerateList() )
  CompilerEndIf
EndProcedure

Procedure onCallback_Canvas()
  Debug "onCallback_Canvas " + EventGadget()
EndProcedure

If OpenWindow(0, 0, 0, 200, 100, "Test")
  CanvasGadget(1, 8, 8, 128, 64, #PB_Canvas_Border)   
  BindGadgetEvent(1, @onCallback_Canvas())
  
  CanvasGadget(2, 32, 16, 64, 24, #PB_Canvas_Border)  
  If StartDrawing(CanvasOutput(2))
    Box(0,0,OutputWidth(),OutputHeight(),0)
    StopDrawing()
  EndIf
  BindGadgetEvent(2, @onCallback_Canvas())
  
  
  GadgetsClip( )
EndIf   

If OpenWindow(10, 350, 0, 200, 100, "Test")
  CanvasGadget(11, 8, 8, 128, 64, #PB_Canvas_Border)   
  BindGadgetEvent(11, @onCallback_Canvas())
  
  CanvasGadget(12, 32, 16, 64, 24, #PB_Canvas_Border)  
  If StartDrawing(CanvasOutput(12))
    Box(0,0,OutputWidth(),OutputHeight(),0)
    StopDrawing()
  EndIf
  BindGadgetEvent(12, @onCallback_Canvas())
  
  
  GadgetsClip( )
EndIf   

Repeat 
  Define E = WaitWindowEvent()
Until E=#PB_Event_CloseWindow
Last edited by mestnyi on Mon Feb 08, 2016 7:29 am, edited 1 time in total.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: 2 CanvasGadgets with 2 BindGadgets

Post by netmaestro »

PureBasic doesn't support overlapped gadgets, unfortunately. If you want to get a layout like that working, you have to separate the events received by the contained canvas from those for the canvas it's sitting on. How to do that?

The key is to ask the OS to treat the containing canvas as though the smaller canvas were not there. Or, more precisely, that the clipping region occupied by the smaller canvas were not there. A "clipping region" defines an area of screen real estate that a given window (in this case canvas gadget) must maintain for:

a) drawing upkeep
b) mouse/keyboard events processing

When a window is first created, it is assigned a clipping region that covers its full rectangle, including both client and frame areas of the window. In order to separate events from an overlapping window, the original region must be modified to remove from it the real estate occupied by the usurping smaller window.

Mestnyi shows one way, a good one, that uses window style modifications to specify clipping details. There is a second way: Create a region the size of canvas 1, punch a hole in it the size and position of canvas 2, then apply the region to the larger canvas. Now canvas 1 has been told that the area occupied by canvas 2 does not fall within its drawing region and so it is excluded from all event processing and drawing. The smaller area is now free to host a second gadget, a gadget whose events will flow freely and, more importantly, readably.

My guess is that Mestnyi's approach and the one I've just described are identical in the end because when Windows reads the style changes being applied to the canvas, it makes the same region modifications "under the hood".

Code: Select all

EnableExplicit

Define.i one, two

Procedure onCallback_Canvas1()
  Debug "onCallback_Canvas1"
EndProcedure

Procedure onCallback_Canvas2()
  Debug "onCallback_Canvas2"
EndProcedure

one = CreateRectRgn_(0,0,128,64)
two = CreateRectRgn_(24,8,88,32)
CombineRgn_(one, one, two, #RGN_XOR)

If OpenWindow(0, 0, 0, 512, 512, "Test")
  CanvasGadget(1, 8, 8, 128, 64, #PB_Canvas_Border)   
  SetWindowRgn_(GadgetID(1), one, #True)
  BindGadgetEvent(1, @onCallback_Canvas1())
  
  CanvasGadget(2, 32, 16, 64, 24, #PB_Canvas_Border)   
  BindGadgetEvent(2, @onCallback_Canvas2())
EndIf   

Repeat 
  Define E = WaitWindowEvent()
Until E=#PB_Event_CloseWindow
Last edited by netmaestro on Wed Nov 11, 2015 6:23 pm, edited 2 times in total.
BERESHEIT
HanPBF
Enthusiast
Enthusiast
Posts: 570
Joined: Fri Feb 19, 2010 3:42 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by HanPBF »

Well, at the moment I can see no disavantage in using combinergn_.

So, event is extinguished due to xor with top-more gadget, right?

This should work for many gadgets.
A general solution would be to set z-index for the gadgets storing them in their partner structure (setGadgetData) and lookup the overlapping regions and clip them away.

The way with setWindowLongPtr_/SetWindowPos_ does not mean one gadget is put in front of the other?
At the moment the setWindowLongPtr approach seems easier to handle.
The combinergn_ approach seems technical better/cleaner.

I had this problem first when I rebuilt a data grid (as MS Access like endless form) a few months ago.

I can remember that I needed to reset the setwindowlongptr_ after some events like mousewheel or click.
Will check this next week with combinergn_.


Anyway, great idea!
Thanks a lot!
Both of You!
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by RASHAD »

Hi NM
That is a new tech. added to my archive
Thanks
Any news about luis you can share ?

Another shot
# 1:

Code: Select all

EnableExplicit

Procedure onCallback_Canvas1()
   Debug "onCallback_Canvas1"
EndProcedure

Procedure onCallback_Canvas2()
   Debug "onCallback_Canvas2"
EndProcedure

If OpenWindow(0, 0, 0, 512, 512, "Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
   CanvasGadget(1, 8, 8, 128, 64, #PB_Canvas_Border)   
   CanvasGadget(2, 32, 16, 64, 24, #PB_Canvas_Border)
   SetWindowLongPtr_( GadgetID(2), #GWL_HWNDPARENT,GadgetID(1))
   BindGadgetEvent(1, @onCallback_Canvas1())   
   BindGadgetEvent(2, @onCallback_Canvas2())
EndIf   

Repeat 
   Define E = WaitWindowEvent()
Until E=#PB_Event_CloseWindow
#2 :

Code: Select all

EnableExplicit

Procedure onCallback_Canvas1()
   Debug "onCallback_Canvas1"
EndProcedure

Procedure onCallback_Canvas2()
   Debug "onCallback_Canvas2"
EndProcedure

If OpenWindow(0, 0, 0, 512, 512, "Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
   CanvasGadget(1, 8, 8, 128, 64, #PB_Canvas_Border)   
   CanvasGadget(2, 32, 16, 64, 24, #PB_Canvas_Border)
   SetParent_(GadgetID(2),GadgetID(1))
   BindGadgetEvent(1, @onCallback_Canvas1())   
   BindGadgetEvent(2, @onCallback_Canvas2())
EndIf   

Repeat 
   Define E = WaitWindowEvent()
Until E=#PB_Event_CloseWindow
Last edited by RASHAD on Wed Nov 11, 2015 6:39 pm, edited 1 time in total.
Egypt my love
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: 2 CanvasGadgets with 2 BindGadgets

Post by netmaestro »

Is there a reason to fear something has happend to luis? I haven't heard anything.
BERESHEIT
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by RASHAD »

No
Just I miss him for long
Egypt my love
HanPBF
Enthusiast
Enthusiast
Posts: 570
Joined: Fri Feb 19, 2010 3:42 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by HanPBF »

Hi Rashad!

"That is a new tech. added to my archive"

Where is that archive?
Partly private/public?
Online?


Thanks!
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by RASHAD »

Hi HanPBF
Sorry it is a private archive
Egypt my love
HanPBF
Enthusiast
Enthusiast
Posts: 570
Joined: Fri Feb 19, 2010 3:42 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by HanPBF »

Hello RASHAD,

after migration of some servers last year I am currently again dev'ing with PB.

So, Your little trick helped a lot!!!

The problem without z-index is always You have to draw the things site by site which works also.
But You need 4 additional border gadgets / 'background' gadgets for one gadget.

Had to do so with containergadget; no drawing directly in containergadget and no color of border can be set; annoying.
So, did put one containergadget into another which works seamless.

Thanks2all!
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: 2 CanvasGadgets with 2 BindGadgets

Post by davido »

Hi RASHAD,
Regarding luis; perhaps his last post (no pun intended) might give a clue:
http://www.purebasic.fr/english/viewtop ... 78#p465678
DE AA EB
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by RASHAD »

Hi davido
Thanks for the info
Loosing good programmers like Sparkie,Fluid Byte,srod,luis,Trond and ......
NM and Danilo abandoned to Mac environment
It is a big loss to Windows forum
Egypt my love
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: 2 CanvasGadgets with 2 BindGadgets

Post by davido »

Hi RASHAD,
I, too will miss luis, like you he has helped me on many occasions.

Regarding srod, he has been posting recently. He provided me with some very useful information.
DE AA EB
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: 2 CanvasGadgets with 2 BindGadgets

Post by mestnyi »

PureBasic doesn't support overlapped gadgets

Is not it?
http://www.purebasic.fr/english/viewtop ... 15#p475798
Last edited by mestnyi on Thu Feb 18, 2016 8:48 pm, edited 1 time in total.
Post Reply