Help! Mouse control outside of canvas..

BlitzPlus Forums/BlitzPlus Programming/Help! Mouse control outside of canvas..

MOUSE CONTROL OUTSIDE OF CANVAS

Please run the code below.
When the mouse pointer exits the canvas, the rectangle doesn't follow the pointer anymore.
This is because player\x# and player\y# gets its coordinates from MouseX(canvas)/MouseY(canvas).
What I'm after, is when the pointer exits, for example, on the right side, the rectangle stops at the canvas' right edge, no matter how far the pointer goes beyond the canvas, but you'll still be able to control the Y axis, player\y#...

I've just started messing with the GUI side of B+, and this problem's been bugging me since sunday!

Anyone got the answer to this? Cheers :)

winw=320:winh=240
Global window=CreateWindow( "test...",200,ClientHeight(Desktop() )/2-winh/2,winw,winh,Desktop(),3+32 )
Global canvas=CreateCanvas( 0,0,320,240,window )

SetGadgetLayout canvas,1,1,1,1;set canvas attributes to stretch
SetGadgetShape window,ClientWidth( Desktop() )/2-400/2,ClientHeight( Desktop() )/2-480/2,400,480;resize canvas, 320x240 to 400x480
ActivateGadget canvas
SetBuffer CanvasBuffer( canvas )

Type player1
	Field x#
	Field y#
End Type

player.player1=New player1
player\x#=160
player\y#=180

MoveMouse 160,120,canvas

;----------------------------------------------------------------------------------------------------
While Not KeyHit( 1 )
	Cls
	id=PeekEvent()
	If id<>0 Then
		If id=$803 Then Exit
		FlushEvents()
	EndIf
	Gosub updateplayer
	FlipCanvas canvas
Wend
End
;----------------------------------------------------------------------------------------------------

.updateplayer
For player.player1=Each player1
		player\x# =  MouseX(canvas)
		player\y# =  MouseY(canvas)
	Rect player\x#-8,player\y#-8,16,16
Next
Return


try inserting desktop() into it, never tried it, but might work

MouseXY( desktop ) won't work, since I'm drawing to canvas,
and I'd be getting the X/Y coordinates from the desktop.
The canvas size is stretched to 400x480, and the desktop size might be 1024x768. Also take GadgetXY( window ) into account.

uh, I think uh, just clip your mouse coord-values to the size of your canvas *when drawing*

Anyway, I'd use EventX() and EventY() anyway..

Hmm what do you mean CS_TBL?
Using MouseX/Y(desktop) and just drawing the player on the canvas at EventX, EventY when
WaitEvent(0)=$203 occurs?

The coordinates would be way off, since the desktop could be 800x600, 1024x768 or whatever, and the canvas is really 320x240 scaled to 400x480...

Also, when outside of the canvas, how would I go about updating the X Y coords? Because I need to be able to, for example, update the player's Y coord if MouseX() isn't inside the canvas..

you will have to similuate mouse x and y when outside canvas area, best bet might be to use x,y coords that doesnt take into consideration of canvas, just mousex() and mousey()

norki: Uhm, uh, is this what you want to establish?
(hold down the mousebutton and drag the mouse in the canvas)
app=CreateWindow("bla",0,0,640,480)

canvas=CreateCanvas(32,32,128,128,app)


Repeat
	WaitEvent()
	If EventID()=$803 quit=True

	If EventSource()=canvas
		If EventID()=$201
			lmd=True
		EndIf
		If EventID()=$202
			lmd=True
		EndIf
		If lmd
			SetBuffer CanvasBuffer(canvas)
				x=EventX()
				y=EventY()
				cx=x
				cy=y

				If cx<0 cx=0
				If cy<0 cy=0
				If cx>127 cx=127
				If cy>127 cy=127

				Cls
				
				Color 255,255,255
				Rect cx-4,cy-4,9,9,False

				Text 32,32,"x: "+x
				Text 32,48,"y: "+y

				
			FlipCanvas canvas
		EndIf
	EndIf
	
Until quit
End


CS_TBL:
Yes, I've done something much the same as that,
but it seems it can't be done without holding down the left
mouse button.. :\

Nicoust:
I've tried using MouseXY(desktop), but then I have to use
GadgetXY(window) and that includes the window borders, which can vary in size..

ok, I give up :)

Hey thanks for the effort CS_TBL, I appreciate it :)

Here...

http://www.blitzbasic.com/codearcs/codearcs.php?code=1290

Thanks BlitzSupport! Perfect! :D

I kind of think I've solved this using the B+ commands, but this userlib seems more
robust, so I'll use it. Though, is it safe to use this user32.dll hackery?

Below I've posted my solution (doesn't use user32.dll).. hope it's useful to someone.
If you make improvements, corrections etc. to the code, please email me.

;CANVAS X/Y by norki.

;The reason I made this is because when you use MouseX/Y(canvas) and the pointer
;leaves the canvas, you lose control of the player in a most horrible way, say if you
;move the mouse really fast to the right, the sprite's last X/Y position might be in the
;middle of the playfield, helpless, and you won't gain control until the pointer reenters
;the canvas. Therefore, I use MouseX/Y(desktop) and CanvasX/Y as an offset to where
;on the canvas to draw the player.

;Formula to find Canvas X and Y below..
;CanvasX=GadgetX(window)+(GadgetWidth(window)-GadgetWidth(canvas))/2
;CanvasY=GadgetY(window)+(GadgetHeight(window)-GadgetHeight(canvas))-((GadgetWidth(window)-GadgetWidth(canvas))/2)

;I've tested this on WinXP and Win98SE using various border widths and resolutions.
;I don't know how it would fare against a desktop that uses skinning applications though..
;Let me know if it craps on you..
;Don't worry about seeing GadgetWidth() in the CanvasY calculation, it's only there
;because it's easier to use to find the border size, which is the same on all four sides.
;Of course, the titlebar height is added on the top side.

;NOTE: These calculations won't work if the window's got a status bar, if the window shape isn't
;set to be in client coordinates (32), and if the window is set to be a tool window.
;All other flags are working though.
;Also note that this example was made to work with a stretched canvas, but this can easily be changed.

Const winw=320		;Original game resolution width
Const winh=240		;Original game resolution height
Const str_winw=400	;Stretched width
Const str_winh=480	;Stretched height

Global window=CreateWindow("Canvas X/Y by norki",ClientWidth(Desktop())/2-winw,ClientHeight(Desktop())/2-winh/2,winw,winh,Desktop(),3+32)
Global canvas=CreateCanvas(0,0,winw,winh,window)
SetGadgetLayout canvas,1,1,1,1;Set canvas attributes to stretch
SetGadgetShape window,ClientWidth(Desktop())/2-str_winw/2,ClientHeight(Desktop())/2-str_winh/2,str_winw,str_winh;
ActivateGadget canvas
SetBuffer CanvasBuffer(canvas)

Type player1
	Field x#
	Field y#
End Type

player.player1=New player1
player\x#=winw/2
player\y#=winh/2

CanvasX=GadgetX(window)+(GadgetWidth(window)-GadgetWidth(canvas))/2
CanvasY=GadgetY(window)+(GadgetHeight(window)-GadgetHeight(canvas))-((GadgetWidth(window)-GadgetWidth(canvas))/2)

MoveMouse winw/2,winh/2,canvas
;----------------------------------------------------------------------------------------------------
While Not KeyHit(1)
	Select WaitEvent(0)
	Case $803;Window close
		Exit
	Case $801;Window move, update CanvasX and CanvasY
		CanvasX=GadgetX(window)+(GadgetWidth(window)-GadgetWidth(canvas))/2
		CanvasY=GadgetY(window)+(GadgetHeight(window)-GadgetHeight(canvas))-((GadgetWidth(window)-GadgetWidth(canvas))/2)
	Case $802;Window size, update CanvasX and CanvasY
		CanvasX=GadgetX(window)+(GadgetWidth(window)-GadgetWidth(canvas))/2
		CanvasY=GadgetY(window)+(GadgetHeight(window)-GadgetHeight(canvas))-((GadgetWidth(window)-GadgetWidth(canvas))/2)
	End Select
	Cls
	Gosub updateplayer
	FlipCanvas canvas
Wend
;Clean up and end
For player.player1=Each player1:Delete player:Next
FreeGadget canvas:FreeGadget window
End
;----------------------------------------------------------------------------------------------------
.updateplayer
For player.player1=Each player1
	;Correct the stretched coordinates, and make it the player's coords
	player\x#=((MouseX(Desktop)-CanvasX)/(Float(GadgetWidth(canvas))/Float(winw)))
	player\y#=((MouseY(Desktop)-CanvasY)/(Float(GadgetHeight(canvas))/Float(winh)))
	If player\x#<0 player\x#=0;Bounds checking
	If player\x#>winw-1 player\x#=winw-1
	If player\y#<0 player\y#=0
	If player\y#>winh-1 player\y#=winh-1
	Color 255,0,255:Rect player\x#-3, player\y#-3,6,6
	Color 255,255,255:Text 1,40,"PlayerX/Y in "+winw+"x"+winh+" coords:"+Int(player\x#)+","+Int(player\y#)
	Text 1,20,"CanvasX/Y relative to screen:"+(GadgetX(window)+(GadgetWidth(window)-GadgetWidth(canvas))/2)+","+(GadgetY(window)+((GadgetHeight(window)-GadgetHeight(canvas))/2)+(((GadgetHeight(window)-GadgetHeight(canvas))/2)/2)+(GadgetWidth(window)-GadgetWidth(canvas))/2)
	Text 1,30,"MouseX/Y relative to canvas:"+(MouseX(Desktop)-CanvasX)+","+(MouseY(Desktop)-CanvasY)
Next
Return