I have an app with a game board and can pick up and move tiles around with panning using mr.gestures, that's working well.
My game board is a MR.Gestures.AbsoluteLayout and that's where I capture the panning gesture.
If I add that game board as a child to another MR.Gestures.AbsoluteLayout then it seems the gestures are blocked by the parent and it no longer works.
Is there a way to pass gestures though to children or ignore gestures on a parent in some way?
Is there a way to pass gestures though to children or ignore gestures
on a parent in some way?
For me this problem appeared only on Android.. The answer is Yes:
When parent receives gesture event it must check if finger x,y is within specific childs views. If yes, parent just ignores the gesture.
Regarding the code, ill just past one event handler to get the idea. In my case i have 2 childs (like and bookmark) over a parent frame:
//-------------------------------------------------------------------
private void OnTapped_MainFrame(object sender, TapEventArgs e)
//-------------------------------------------------------------------
{
//Get parent screen abs pos in pixels
//We are using native code get absolute screen position
var ptFrame = DependencyService.Get<INiftyHelpers>().GetViewAbsolutePosition((View)sender);
//Gets childs (hotspots) screen abs position in pixels
var ptFav = DependencyService.Get<INiftyHelpers>().GetViewAbsolutePosition((View)hsFav);
var ptLike = DependencyService.Get<INiftyHelpers>().GetViewAbsolutePosition((View)hsLike);
//Gets childs (hotspots) rectangles, everything in pixels using screen density
var rectFav = new Rectangle(ptFav, new Size(hsFav.Width * AppHelper.DisplayDensity, hsFav.Height * AppHelper.DisplayDensity));
var rectLike = new Rectangle(ptLike, new Size(hsLike.Width * AppHelper.DisplayDensity, hsLike.Height * AppHelper.DisplayDensity));
//Convert the finger XY to screen pos in pixels
var ptTouch = new Point(ptFrame.X + e.Center.X * AppHelper.DisplayDensity, ptFrame.Y + e.Center.Y * AppHelper.DisplayDensity); //absolute relative to screen
//check if withing childs
if (rectFav.Contains(ptTouch) || rectLike.Contains(ptTouch))
return; //Ignore input and let childs process their gestures!
//Process input
//..
}
I'm working on an application to display DICOM Files and now I'm getting into MPR. Is there a control that will allow you to have like a line in a picturebox or panel like this:
http://www.vcreatelogic.com/docs/gcf-2.6.0/html/MPRView.jpg
The intention is to move that line and perform some stuff while is moving, so I basically need some sort of control or custom control (or maybe a custom icon) that will allow the user to see where he's moving in the picturebox as he moves the mouse.
Thank you!
UPDATE:
Here's the code I'm using:
In the Mouse Down of the Picturebox:
if (e.Clicks == 2)
{
horizontalstart = new Point(0, e.Y);//Start point of Horizontal line.
horizontalend = new Point(picbox_mpr.Width, e.Y);//End point of Horizontal line.
verticalstart = new Point(e.X, 0);//Start point of Vertical line
verticalend = new Point(e.X, picbox_mpr.Height);//End point of Vertical line.
}
Then in the MouseMove (where I can Pan the picture) I want those lines to remain fixed in the spot that were drawn..
UPDATE:
The whole idea is to draw the lines if the user double click in the image, then if the image is moved, move those lines along with the image..
First things first,the method I am giving does not require a custom control in order to work,it makes use of two of the events provided by PictureBox to run the logic,but if still you need a custom control you should be able to do that by porting these methods to that control with a little coding.
The following are two fields that will hold most of the values in our logic,
private Point horizontalstart, horizontalend;
private Point verticalstart, verticalend;
private bool drawlines;//Specifies a value whether PictureBox should redraw itself.
Let me explain what are these points for;
The first Point statement holds starting and end point of Horizontal line,and
the second Point statement holds starting and end point of Vertical line.
When you'r done with it write this code in MouseMoveEvent of your PictureBox;
private void SourcePictureBox_MouseMove(object sender, MouseEventArgs e)
{
if(drawlines==true)//If the lines should move.
{
horizontalstart = new Point(0, e.Y);//Start point of Horizontal line.
horizontalend = new Point(SourcePictureBox.Width, e.Y);//End point of Horizontal line.
verticalstart = new Point(e.X, 0);//Start point of Vertical line
verticalend = new Point(e.X, SourcePictureBox.Height);//End point of Vertical line.
SourcePictureBox.Invalidate();//Force PictureBox to repaint.
}
else if(drawlines==false)//To lock the lines at current coordinates.
{
//Add any code if needed.
}
}
where SourcePictureBox is the PictureBox that we are operating upon.As soon as the MouseMoveEvent is raised new coordinates for both lines are calculated and a repaint message is sent to PictureBox,which draws the lines using the coordinates declared and calculated above.
Ok so now write the code below in the Paint event of your PictureBox;
private void SourcePictureBox_Paint(object sender, PaintEventArgs e)
{
if (SourcePictureBox.Image != null)
{
e.Graphics.DrawLine(SystemPens.WindowText, horizontalstart, horizontalend);//Draw Horizontal line.
e.Graphics.DrawLine(SystemPens.WindowText, verticalstart, verticalend);//Draw Vertical line.
}
}
One more thing that i noticed in your image,the guidelines the image is showing are a little small than the image,if this is the case,then replace both the statements in MouseMoveEvent event excluding the Invalidate() one with the following;
horizontalstart = new Point(0+10, e.Y);//Start point of Horizontal line.
horizontalend = new Point(SourcePictureBox.Width-10, e.Y);//End point of Horizontal line.
verticalstart = new Point(e.X, 0+10);//Start point of Vertical line
verticalend = new Point(e.X, SourcePictureBox.Height-10);//End point of Vertical line.
But what's new in these statements,nothing except they increase the start point of both lines by value 10(int) and decrease the end points with value 10,thus giving you some space between the edges of PictureBox and the guiding lines.Please note if you want to increase or decrease the space replace value 10 with a value you would like but keep in mind the value must not be bigger than half of the size of your PictureBox.
The other thing i would like to address is if you want to change the colour of guiding lines,replace the first argument of both statements in Paint Event with any of values offered by class SystemPens.If there is nothing in the class that satisfies you,you are always free to create on for yourself.If you know how to do it,then its the best choice,incase if you need some help,take a look here.Creating a new pen gives you the option of defining a width for the guilding lines.
Update
`At anytime,to stop the lines from moving,set drawlines(declared above) to false,to resume their functionality set it to true.
It's not a foolproof method but I Hope it's enough to get your job done,and don't forget to rename the PictureBox and associated events with the name of your PictureBox.
Solved it!
here's the code:
//Variable declaration:
private Point horizontalstart, horizontalend, verticalstart, verticalend, horizontalstart_initialpoint, horizontalend_initialpoint, verticalstart_initialpoint, verticalend_initialpoint;
System.Drawing.Pen redline= new System.Drawing.Pen(System.Drawing.Color.Red);
private Point redlinemovedpoints = Point.Empty;
private Point redline_panstart = Point.Empty;
void picbox_mpr_MouseDown(object sender, MouseEventArgs e)
{
redline_panstart = new Point(e.X, e.Y); //saves the point from where you pan the picture
if (e.Clicks == 2) //if the user double clicks, then the red line is drawn in the PictureBox
{
horizontalstart = new Point(0, e.Y);//Start point of Horizontal line.
horizontalend = new Point(picbox_mpr.Width, e.Y);//End point of Horizontal line.
verticalstart = new Point(e.X, 0);//Start point of Vertical line
verticalend = new Point(e.X, picbox_mpr.Height);//End point of Vertical line.
//fixed reference points, this is used to store where the line was drawn initially.
horizontalstart_initialpoint= horizontalstart;
horizontalend_initialpoint = horizontalend;
verticalstart_initialpoint = verticalstart;
verticalend_initialpoint = verticalend;
picbox_mpr.Invalidate(); // Draw the lines (see paint event at the bottom)
}
void picbox_mpr_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left & pan) // don't worry about pan, is a variable I use to determine if the user is dragging the mouse.
{
redlinemovedpoints = new Point(e.Location.X - redline_panstart.X,
e.Location.Y - redline_panstart.Y); // this is the X and Y points move
horizontalstart = new Point(horizontalstart_initialpoint.X + redlinemovedpoints.X, horizontalstart_initialpoint.Y+redlinemovedpoints.Y);
horizontalend = new Point(picbox_mpr.Width, horizontalend_initialpoint.Y + redlinemovedpoints.Y);
verticalstart = new Point(verticalstart_initialpoint.X + redlinemovedpoints.X, verticalstart_initialpoint.Y + redlinemovedpoints.Y);
verticalend = new Point(verticalstart_initialpoint.X + redlinemovedpoints.X, picbox_mpr.Height);
picbox_mpr.Invalidate(); //re draws the lines, this time moved X or Y depending the pan.
}
}
void picbox_mpr_MouseUp(object sender, MouseEventArgs e)
{
//save the line points positions where after panning the image
horizontalstart_initialpoint = horizontalstart;
horizontalend_initialpoint = horizontalend;
verticalstart_initialpoint = verticalstart;
verticalend_initialpoint = verticalend;
}
private void picbox_mpr_Paint(object sender, PaintEventArgs e)
{
Image tmp = (Image)img.RenderImage(0);
e.Graphics.Clear(System.Drawing.Color.Black);
e.Graphics.DrawImage(tmp, movingPoint);
tmp.Dispose();
e.Graphics.DrawLine(redline, horizontalstart, horizontalend);//Draw Horizontal line.
e.Graphics.DrawLine(redline, verticalstart, verticalend);//Draw Horizontal line.
}
I am presently learning C# and have chosen as a project to write a simple colour picker control ; however things have changed substantially since I last looked at writing code and I have struck this problem.
I am using the Mousedown event in my control to get the mouse coordinates as a Point - this is working fine and returns exactly what I would expect - the mouse coordinates relative to my control; however when I try and do a check against the control location I am returned a value as a Point showing the position of my control relative to the form which in certain cases the mouse coordinates will be outside the bounds of because their values will be less than the relative start position of the control I.E I click at pixel 1,1 in the control - the mouse position is 1,1 but because the control is located at 9,9 relative to the form the location of the mouse is less than the bounds of the control - I have absolutely no idea how to fix this, I have been attempting to sort it out with PointToClient and PointToScreen to no avail as they seem to come up with outlandish values can someone please help me out it's driving me insane.
I've managed to sort this out myself so thought I'd post the answer and it can hopefully help someone else. I was having problems getting Point values that were relative to the same pixel origin : this sorted it.
private void ColourPicker_MouseDown(object sender, MouseEventArgs e)
{ // Probably being paranoid but I am worried about scaling issues, this.Location
// would return the same result as this mess but may not handle
// scaling <I haven't checked>
Point ControlCoord = this.PointToClient(this.PointToScreen(this.Location));
int ControlXStartPosition = ControlCoord.X;
int ControlYStartPosition = ControlCoord.Y;
int ControlXCalculatedWidth = ((RectangleColumnsCount + 1) * WidthPerBlock ) + ControlXStartPosition;
int ControlYCalculatedHeight = ((RectangleRowsCount + 1) * HeightPerBlock) + ControlYStartPosition;
// Ensure that the mouse coordinates are comparible to the control coordinates for boundry checks.
Point ControlRelitiveMouseCoord = this.ParentForm.PointToClient(this.PointToScreen(e.Location));
int ControlRelitiveMouseXcoord = ControlRelitiveMouseCoord.X;
int ControlRelitiveMouseYcoord = ControlRelitiveMouseCoord.Y;
// Zero Relitive coordinates are used for caluculating the selected block location
int ZeroRelitiveXMouseCoord = e.X;
int ZeroRelitiveYMouseCoord = e.Y;
// Ensure we are in the CALCULATED boundries of the control as the control maybe bigger than the painted area on
// the design time form and we don't want to use unpaited area in our calculations.
if((ControlRelitiveMouseXcoord > ControlXStartPosition) && (ControlRelitiveMouseXcoord < ControlXCalculatedWidth))
{
if((ControlRelitiveMouseYcoord > ControlYStartPosition) && (ControlRelitiveMouseYcoord < ControlYCalculatedHeight))
{
SetEvaluatedColourFromPosition(ZeroRelitiveXMouseCoord, ZeroRelitiveYMouseCoord);
}
}
}
I have some images/sprites/buttons (i tried them all :)) scrolling/moving on the stage. The user has to tap them to remove them.
The problem is that the touchevent does not match the position of the image.
The faster the touchable sprites move, the further the distance between the touch and the actual image. i.e.:
a image is moving across the screen with 20px/frame:
Touching the image triggers nothing, touching 20 before it triggers a touch on the image.
when image is not moving, this doesn't happen. It seems that the image is already moved internally, but not yet drawn to the screen, but thats just a wild guess. The example below uses a button, but the same goes for an image. I"ll provide a short example of the code, but i guess its pretty straightforward what i'm trying to do.
private var _image:Button;
protected function init():void {
//create pickup image
_image = new Button(assets.getTexture("button"));
_image.scaleWhenDown = 1;
_image.addEventListener(Event.TRIGGERED, onClick_image);
addChild(_image);
//listen to touch event (not used, but example for touch on image instead of button
//touchable = true;
//addEventListener(TouchEvent.TOUCH, onTouch_image);
}
private function onEnter_frame(e:Event):void {
_image.x -= 20;
}
I've written a home-brew view_port class for a 2D strategy game. The panning (with arrow keys) and zooming (with mouse wheel) work fine, but I'd like the view to also home towards wherever the cursor is placed, as in Google Maps or Supreme Commander
I'll spare you the specifics of how the zoom is implemented and even what language I'm using: this is all irrelevant. What's important is the zoom function, which modifies the rectangle structure (x,y,w,h) that represents the view. So far the code looks like this:
void zoom(float delta, float mouse_x, float mouse_y)
{
zoom += delta;
view.w = window.w/zoom;
view.h = window.h/zoom;
// view.x = ???
// view.y = ???
}
Before somebody suggests it, the following will not work:
view.x = mouse_x - view.w/2;
view.y = mouse_y - view.h/2;
This picture illustrates why, as I attempt to zoom towards the smiley face:
As you can see when the object underneath the mouse is placed in the centre of the screen it stops being under the mouse, so we stop zooming towards it!
If you've got a head for maths (you'll need one) any help on this would be most appreciated!
I managed to figure out the solution, thanks to a lot of head-scratching a lot of little picture: I'll post the algorithm here in case anybody else needs it.
Vect2f mouse_true(mouse_position.x/zoom + view.x, mouse_position.y/zoom + view.y);
Vect2f mouse_relative(window_size.x/mouse_pos.x, window_size.y/mouse_pos.y);
view.x = mouse_true.x - view.w/mouse_relative.x;
view.y = mouse_true.y - view.h/mouse_relative.y;
This ensures that objects placed under the mouse stay under the mouse. You can check out the code over on github, and I also made a showcase demo for youtube.
In my concept there is a camera and a screen.
The camera is the moving part. The screen is the scalable part.
I made an example script including a live demo.
The problem is reduced to only one dimension in order to keep it simple.
https://www.khanacademy.org/cs/cam-positioning/4772921545326592
var a = (mouse.x + camera.x) / zoom;
// now increase the zoom e.g.: like that:
zoom = zoom + 1;
var newPosition = a * zoom - mouse.x;
camera.setX(newPosition);
screen.setWidth(originalWidth * zoom);
For a 2D example you can simply add the same code for the height and y positions.