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.
Related
I'm trying to open another window from a menu control located on my main window and I want this window's startup position to be centered relative to the main window. I have achieved this by setting the Owner property of the secondary window to my main window and setting the WindowStartupLocation property in XAML to CenterOwner, like this:
PopupWindow about = new PopupWindow();
about.Owner = Application.Current.MainWindow;
about.Show();
about.Owner = null;
The problem with this is that a window with an Owner seems to always stay on top of the Owner and whenever the Owner window is minimized, the Owned window also minimizes. To fix this I remove the Owner after the window is shown. The code seems to work fine, but it also feels a little bit like a hack.
I know there is a way to do this by setting the startup location to manual and then calculating where the window should be positioned, but I'm starting the secondary window from a popup control and I couldn't find a way to reference a window other than main. I think I could loop through the Windows collection and check a property to see if it's the window I need, but that almost seems worse than what I'm doing here.
Is there a better or more standard way of doing this?
There is no "best" way per se to do this kind of thing. It actually doesn't have any built-in function. All of the methods for doing this are kind of "hacks", you might say. A standard way of doing this is getting the coordinates of the main window and based on the about window calculate where you want its location to be. Or you can do it your way too. Here is a simple example:
int width = mainwindow.getWidth() / 2;
int height = mainWindow.getHeight() / 2;
int locationWidth = width - about.getWidth() / 2;
int locationHeight = height - about.getHeight() / 2;
// Then set it
about.Location = new Cursor(locationWidth, locationHeight);
I don't remember exactly how to set the location, because I'm not on my normal computer. But you get the idea. Also, we do width - about.getWidth() / 2, because in C# the location is set not from the center but from the top left corner. Hope it helps.
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..
I want to draw a GUI Button on top of a GUI window that I have in my game, but no matter what I try the button always appears behind.
This is my Code:
GUI.depth = -30;
Rect navBackButton = new Rect(10, 10, 10, 10);
// DRAW NAVIGATION BUTTONS
if (GUI.Button(navBackButton, navBackButtonTexture))
{
// DO LOGIC HERE
}
GUI.depth = 10;
topScrollRect = new Rect(0, 0, Screen.width, topScrollHeight);
topScrollListSize = new Vector2(topScrollRect.width - 2*listMargin.x, topScrollRect.height - 2*listMargin.y);
GUI.skin.window = topStyle;
GUI.Window(0, topScrollRect, (GUI.WindowFunction)DoTopScrollWindow, "");
I have tried to draw the buttons before drawing the window, and the other way round, but both have the same result.
In this forum post (http://forum.unity3d.com/threads/setting-depth-of-a-window.12554/), it says that any GUI control with a depth of less than 1 will appear in front of GUI Windows, but I have set my depth to -30 and still the button appears behind the Window.
Any suggestions would be greatly appreciated!
The way to do this is to draw the button in DoTopScrollWindow().
You shouldn't try to place the buttons "on top" of the window, you should put them "in" the window, as the window is your navigation button's parent, conceptually. Additionally, drawing them in the window means that you can take advantage of relative positioning and window resizing without having to write a lot of extra code.
According to the docs, the parameter func in GUI.Window() is a function designed to display content inside the window.
In this case you want your buttons "inside" that window, so draw them in the function you pass in as func.
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 want to know the best way to design a full screen form, like positioning controls in a way that they won't get messed up if the user's resolution is different.
This is my fullscreen code:
int w = Screen.PrimaryScreen.Bounds.Width;
int h = Screen.PrimaryScreen.Bounds.Height;
this.Location = new Point(0, 0);
this.Size = new Size(w, h);
Anchors and Docks.
The Anchor will bind the control. The Dock property sets how it expands/shrinks.
So if you assign a button anchor to "Top, left" it's size and position stay locked on those sides. So if you dragged the Form window wider, the object would expand to towards the right and towards the bottom.