Help! Mouse control outside of canvas..

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

norki(Posted 2005) [#1]
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



Nicstt(Posted 2005) [#2]
try inserting desktop() into it, never tried it, but might work


norki(Posted 2005) [#3]
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.


CS_TBL(Posted 2005) [#4]
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..


norki(Posted 2005) [#5]
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..


Nicstt(Posted 2005) [#6]
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()


CS_TBL(Posted 2005) [#7]
norki: Uhm, uh, is this what you want to establish?
(hold down the mousebutton and drag the mouse in the canvas)



norki(Posted 2005) [#8]
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..


CS_TBL(Posted 2005) [#9]
ok, I give up :)


norki(Posted 2005) [#10]
Hey thanks for the effort CS_TBL, I appreciate it :)


BlitzSupport(Posted 2005) [#11]
Here...

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


norki(Posted 2005) [#12]
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