好的,因为没有回复,完全重写了这个问题。我想要一个可拖动的窗口但是当它被拖动时,改变边距以延伸到窗口的旧位置。即窗口向右移动X,向左延伸边缘X.现在我遇到了一些障碍,例如窗口由于某种原因被切断了边缘。这是我的代码,请告诉我你是否能发现任何东西!
private void Window_LocationChanged(object sender, EventArgs e)
{
double TmpLeft = Math.Abs(this.Left - WinLeft);
double TmpTop = Math.Abs(this.Top - WinTop);
if (this.IsLoaded)
{//depending on whether the window is moved left, right
if (this.Left > WinLeft)
{//depending on whether the window is moved up, down
if (this.Top > WinTop)
bdr.Margin = new Thickness(TmpLeft, TmpTop, 0, 0);
else
bdr.Margin = new Thickness(TmpLeft, 0, 0, TmpTop);
}
else
{
if (this.Top > WinTop)
bdr.Margin = new Thickness(0, TmpTop, TmpLeft+ 40, 0);
else
bdr.Margin = new Thickness(0, 0, TmpLeft, TmpTop);
}
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WinLeft = this.Left;
WinTop = this.Top;
bdr.Height = this.ActualHeight;//I set these because they are auto
bdr.Width = this.ActualWidth; //before the window opens
}
此时整个窗口(将窗口背景设置为黄色以便我可以看到边距)正在移动,我希望边缘的左上角保持在原位。我也注意到我点击拖动窗口的区域(border
)也会移动,所以当我移动窗口时,不再是我的点击。希望清楚,再评论任何进一步的问题。
老 - 只读了解我在做什么
所以我正在尝试创建一个具有弹出窗口的应用程序,其中指针/行从子窗口到父窗口中的特定位置。我是这样做的;
<Border Name="brdr" Margin="40,0,0,0" >
//Content
</Border>
<Line
Name="Pointer"
X1="0"
X2="40"
Y1="55"
Y2="50"
StrokeThickness="2"
Stroke="Black"
></Line>
注意边框上的40 Margin
左侧使窗口大于显示的窗口,以便Polygon
向左伸出并指向父窗口(如果有更好/更冷/这样做的更优雅的方式,我都是耳朵)。
所以这很好但现在我希望指针是动态的。如同,如果拖动子窗口,指针必须相对于父窗口的位置缩放。即它必须看起来好像是通过线路连接两个窗口。现在我的计划是记录子窗口打开的点(因为它相对于父窗口打开,初始化时它是正确的)然后使用它与新位置点之间的差异(拖动后)来查找新点这条线应该去。我的代码可能说它比我以前更好......
private void Window_LocationChanged(object sender, EventArgs e)
{
if (this.IsLoaded)
{
brdr.Margin = new Thickness(Math.Abs(this.Left - WinLeft) + 40, Math.Abs(this.Top - WinTop), 0, 0);
Pointer.X1 = Math.Abs(this.Left - WinLeft);
Pointer.Y1 = Math.Abs(this.Top - WinTop) + 55;
Pointer.X2 = Math.Abs(this.Left - WinLeft) + 40;
Pointer.Y2 = Math.Abs(this.Top - WinTop) + 50;
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WinLeft = this.Left;
WinTop = this.Top;
}
正如你所看到的,我必须设置窗口边距,使其延伸到旧位置。然后我将Line
坐标重置为新值。正如我所说,所有这些值都是通过比较开口窗口坐标和当前坐标来计算的。
我的问题是,这不对。看到有人能够解决这个问题会非常深刻。
答案 0 :(得分:0)
我很惊讶没有代码可以从窗口内坐标转换到屏幕坐标。 在我的一个项目中,我不得不在Control下面放置一个窗口。我用它来获取控件中间点的屏幕坐标:
Point point = MyControl.PointToScreen(new Point((MyControl.ActualWidth / 2)
, MyControl.ActualHeight));
PresentationSource source = PresentationSource.FromVisual(MyControl);
double dpiX = (96 * source.CompositionTarget.TransformToDevice.M11);
double dpiY = (96 * source.CompositionTarget.TransformToDevice.M22);
XInScreenCoordinates = ((point.X * 96 / dpiX));
YInScreenCoordinates = ((point.Y * 96 / dpiY));
如果我没有这样做,则放置时会出错,右侧越多,错误就越多。
答案 1 :(得分:0)
确定我做的小应用程序:
还有MainWindow,主窗口内容非常简单,一行
和一个按钮:
<Grid>
<Line x:Name="MyLine" Stroke="Black" StrokeThickness="4" />
<Button Name="MyButton" Margin="248,101,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Content="Button" />
</Grid>
然后我做了另一个名为TestWindow的小尺寸(300 * 300)窗口。
TestWindow没有任何内容或代码。
MainWindow背后的代码:
public partial class MainWindow : Window
{
public TestWindow MyTestWindow;
public MainWindow()
{
InitializeComponent();
MyTestWindow = new TestWindow();
MyTestWindow.Show();
MyTestWindow.LocationChanged += new EventHandler(WinLocationChanged);
MyTestWindow.SizeChanged += new SizeChangedEventHandler ( WinSizeChanged);
this.LocationChanged += new EventHandler(WinLocationChanged);
this.SizeChanged += new SizeChangedEventHandler(WinSizeChanged);
}
void WinSizeChanged(object sender, SizeChangedEventArgs e) {
UpdateLine(); }
void WinLocationChanged(object sender, EventArgs e) {
UpdateLine(); }
void UpdateLine()
{
// 1. get Window's center in in this window coordinates
double CX_sc =0.0, CY_sc = 0.0;
GetWindowCoordinatesInCurrentWindow(MyTestWindow, ref CX_sc, ref CY_sc);
// 2. Get Center of target Control coordinates in this window coordinates
Point CenterButtonPoint = MyButton.TransformToAncestor(this).Transform(new Point(MyButton.ActualWidth / 2.0, MyButton.ActualHeight / 2.0));
//3. Change line's coord.
MyLine.X1 = CX_sc;
MyLine.Y1 = CY_sc;
MyLine.X2 = CenterButtonPoint.X;
MyLine.Y2 = CenterButtonPoint.Y;
}
void GetWindowCoordinatesInCurrentWindow(Window ChildWindow, ref double X, ref double Y)
{
Point CenterOfChildWindow = ChildWindow.PointToScreen(new Point((ChildWindow.ActualWidth / 2)
, ChildWindow.ActualHeight/2));
Point UpperLeftOfCurrentWindow = this.PointToScreen(new Point(0, 0));
PresentationSource source = PresentationSource.FromVisual(this);
double dpiX = ( source.CompositionTarget.TransformToDevice.M11);
double dpiY = (source.CompositionTarget.TransformToDevice.M22);
X = (( CenterOfChildWindow.X -UpperLeftOfCurrentWindow.X ) /dpiX);
Y = ( (CenterOfChildWindow.Y-UpperLeftOfCurrentWindow.Y ) / dpiY );
}
}
它的作用是,无论何时移动或调整其中一个窗口,它都将绘制一个 进入MainWindow,将Button“链接”到TestWindow的中间。
好的我知道这不是你想要的:=),因为该行不能超出MainWindow。但我们的想法是拥有一个透明的Popup,它覆盖整个屏幕,你可以在其中做同样的事情。
答案 2 :(得分:0)
实际上找到了一个很好的方法。我做的是我设置子窗口WindowState="Maximized"
,然后将除Line
之外的所有内容放在Canvas
中,然后按照http://denismorozov.blogspot.ie/2008/01/drag-controls-in-wpf-using.html(好文章)我可以做到这一点可以在我的窗户周围移动。我对该线进行了硬编码,以便在窗口打开时它处于正确的位置。由于Line
的其中一个点不应移动,因此只需更新Canvas_MouseMove
事件中的其他点就可以了;
Point p = border.TransformToAncestor(this).Transform(new Point(0, 0));
Line.X2 = p.X;
Line.Y2 = p.Y + 50;
如果您想要一条连接两者的线,让窗口相对于父窗口显示的非常简单的方法。它给出了移动窗口的外观,但实际上是围绕最大化的透明窗口移动控件。