In my GUI, i need to change Parents of PictureBoxes to the background PictureBox so that the transparency works correctly.
However, changing the parent also changes the location of the pictureboxes. I have tried grabbing the absolute location of the picture box via the PointToClient, but it doesn't work. I put the coordinates in the comments, and they don't change after assigning the new parent even though the image visibly changes location. Furthermore, I don't expect that it could possibly work as it's being passed a point, not an object with more information about parents and whatnot that's needed to deduce the absolute position.
What is the correct way to deduce the absolute position of an element so that I can move the image to the correct location after its parent changes? Or is there a better way to do this?
Point oldRel = pictureBox4.Location; //258, 109
Point oldAbs = PointToClient(oldRel); //75, -96
//Commenting out this line fixes the image shift but ruins the transparency
pictureBox4.Parent = pictureBox2;
Point newRel = pictureBox4.Location; //258, 109
Point newAbs = PointToClient(pictureBox4.Location); //75, -96
This will move a Control child from one Parent to a new one, keeping the absolute screen position intact:
void MoveTo(Control child, Control newParent )
{
child.Location = newParent.PointToClient(child.PointToScreen(Point.Empty));
child.Parent = newParent;
}
The trick with PointToClient and PointToScreen is to use them from the right parent control; not setting the control will default to the Form, which will miss out on the actual position of the parent..
Related
I am using Xamarin native (not forms) and I have an ImageView inside a RelativeLayout.
Is there any way to get the absolute position of the view relative to the screen and not relative to the parent?
I saw some solutions for this problem on Xamarin.Forms that loop through the parent view and add its coordinates relative to its parent, but it doesn't seem to work here.
I tried using iv.GetX() but this is for getting the position in relative to the parent.
What is the way to get the absolute position?
Thanks in advance.
You could get the absolute coordinates across the entire screen with the GetLocationOnScreen method.
like:
int[] location = new int[2];
iv.GetLocationOnScreen(location);
int x = location[0];
int y = location[1];
Note:
This value is calculated from the top of the screen, which includes the height of the notification bar.If those parameters are printed in the Activity's OnCreate() method, they are all 0, and you won't get them until the UI controls are loaded.
It's better to get it in OnWindowFocusChanged method.
I'm making a WPF application using C# and I am in the stage of developing more UI for it. I have all my components such as TextBlocks and other Canvases inside of a main Canvas, but if I drag the left side of it to make more room, it expands on the right side, meaning I have to move everything over. The same thing happens when I try and extend the top; The bottom gets bigger. I have the RenderTransformOrigin of the Canvas set to 0,0 so I'm not quite sure what is going on. Any help is appreciated.
Thanks!
By default, a Canvas doesn't have a Width or Height, its actual size depends if you set those properties explicitly, or if you set HorizontalAlignment or VerticalAlignment to Stretch.
In either case, elements inside of a Canvas are aligned relative to its top-left corner, except if you explicitly set their Canvas.Top, Canvas.Left, Canvas.Right and/or Canvas.Bottom properties.
You could also position elements containing a Geometry (like derivatives of Shape, Path being a common example) by their absolute Geometry coordinates. Actually this already is the way they are rendered.
Regarding your comment in the question, usually you don't change where things align relative to the Canvas, since it is much easier (I think even recommended) to reposition the canvas itself, so that everything it contains would be repositioned too.
Common ways to do that would be adding elements to a Canvas, and then position that Canvas inside another "parent" Canvas, similar to "grouping" in vector design programs like CorelDraw/Inkscape/Illustrator.
Another way would be to use RenderTransform property of Canvas containing the elements you want to reposition.
After you get used to see Canvas as a "coordinate system", you can and should think of Canvas-inside-Canvas-inside-Canvas-... as a way of hierarchically grouping things that share the same cartesian space, as opposed to Panels and ContentControls, which are nested inside one another and cannot typically share space.
Like I said in my comment, all the controls inside the canvas are positioned relative to the canvas' top left point. If you want them to retain their "position" when the canvas is resized to the left or top, you will need to offset them yourself. You could do this with a utility method that you call whenever you want to resize the canvas:
public static void StretchWidthLeft(Canvas canvas, double newWidth)
{
double diff = newWidth - canvas.Width;
canvas.Width = newWidth;
foreach (UIElement child in canvas.Children)
{
Canvas.SetLeft(child, Canvas.GetLeft(child) + diff);
}
}
public static void StretchHeightTop(Canvas canvas, double newHeight)
{
double diff = newHeight - canvas.Height;
canvas.Height = newHeight;
foreach (UIElement child in canvas.Children)
{
Canvas.SetTop(child, Canvas.GetTop(child) + diff);
}
}
Note that these methods do not reposition the canvases themselves. How you would do that depends on how the canvas' parent is maintaining their position.
I'm trying to get points along a Shapes.Path object from a Silverlight MainWindow.xaml file. I use Expression Blend to create the path.
The following code works fine unless I try to move the path in expression blend, which only moves the margins. Apparently that doesn't get calculated in, and I get the points from where the path was originally created.
var pathGeometry = path.Data.GetFlattenedPathGeometry();
var currentPoint = new System.Windows.Point();
var tangentPoint = new System.Windows.Point();
var rList = new List<Point>();
var pointsCount = 10;
for (int i = 0; i < pointsCount; i++)
{
double fraction = (double)i / (double)(pointsCount - 1);
pathGeometry.GetPointAtFractionLength(fraction, out currentPoint, out tangentPoint);
rList.Add(currentPoint);
}
return rList;
Any suggestions on how to get the margin change to also calculate in?
Ah... I think I see the problem. PathGeometry does not inherit from UIElement, meaning that it does not have any sense of Margins. The Geometry is hosted within a control that does, and it is that control which actually draws the Geometry onto the screen. If you want to translate a point on the Geometry into screen coordinates, then you'll need to find the location of the host control and calculate the offset.
My guess is that your PathGeometry is hosted inside a Path control. (Confusing, no?) Getting the location in screen coordinates is relatively easy. You can call the PointToScreen method on Path and feed it the calculated point (perhaps adding any padding you may be applying). Getting a point relative to the window is more complicated. You could call PointToScreen (for point 0,0) on the window and then subtract the Path's point from the window's. Or, you could put the Path inside a Canvas (where the Canvas is directly inside the window) and simply get the Canvas.Top and Canvas.Left.
You don't say what your ultimate goal is, so it is difficult to recommend a particular solution for you.
I know this has been asked before (Get Absolute Position of element within the window in wpf) but I haven't been able to implement properly yet. I'm trying to have a child window open up relative to the control in the parent window. So far, I have this;
messageWindow = new Message(true);
Point relativePoint = btn1.TransformToAncestor(this).Transform(new Point(0, 0));
messageWindow.Left = relativePoint.X;
messageWindow.Top = relativePoint.Y;
messageWindow.Show();
Now although this does effect the position of the child window (messageWindow), it doesn't seem to place it on/beside the btn1 control in the parent. Another problem I have with it is that if I move the parent window, then recall this method having closed the original messageWindow the new instance of the window displays in the old position (even though btn1 is in a new position). I find this odd and was wondering if anyone could help me fix this.
UPDATE
Thanks to Charleh for explaining that I was only setting them relative to the control location in the window, not to the overall screen. So now it is a question of getting the parent window's location on the screen and adding it to the XY also. How would I get this? Just tried this code (although I'll be honest, I don't quite understand it) bus still doesn't seem to follow very closely. What's a good way of getting Window location on the screen?;
messageWindow= new Message(true);
Point relativePoint = btn1.TransformToAncestor(this).Transform(new Point(0, 0));
PresentationSource ScreenPos = PresentationSource.FromVisual(this);
messageWindow.Left = relativePoint.X + (96.0 * ScreenPos.CompositionTarget.TransformToDevice.M11);
messageWindow.Top = relativePoint.Y + (96.0 * ScreenPos.CompositionTarget.TransformToDevice.M22);
messageWindow.Show();
relativePoint is the position of the control relative to the Window, not the screen. When setting the Left and Right points of messageWindow (the child window), the points are relative to the screen, not the parent window.
In order to get the correct position, you'll need to find the position of the parent window and then do some math to find where the control is located relative to the screen, not the window which should give you the location of where you want to place the child window.
I have added an View List onto a Panel like this:
panelComponent.Controls.Add(viewListComponent);
Everything works just fine. Mouse events are handled, repainting works. But one problem: I can't move it around dynamically. If I change the control.Top variable, it just sits there without moving.
It's like the control is glued to the top left corner. Resizing the right and bottom properties works just fine! I did it without dynamically adding and then no problem.
What could be causing this, and how do I fix it?
Two possible explanations. First is the Dock property, docking it to the top keeps the control at the top of the container, no matter what you assign to the Top or Location properties.
The other one is value types, the Location property is Point, a struct. This code will not move the control:
var lbl = new Label();
panel1.Controls.Add(lbl);
var pos = lbl.Location;
pos.Y = 42; // No effect
Try using the Location property:
viewListComponent.Location = new Point(42, 42);