-->

在窗口拖动动态保证金(Dynamic Margin on Window Drag)

2019-09-19 02:15发布

这个问题由于缺乏回复的好了,所以完全重写。 我想一个窗口,是拖能,但因为它是被拖累,改变利润率为窗口的老位置一直延伸。 IE窗口向右移动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 ,因为我将窗口移动)往往会左右移动,以及因此不再受我的点击。 希望这是明确的,作进一步评论的问题。

OLD -只读明白我想做

所以我想创建一个具有一个弹出窗口的指针/线路从子窗口即将在父窗口的特定位置的应用程序。 我实现了这个像这样;

<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 COORDS为新值。 所有这些值进行计算,就像我说的,通过打开的窗口中COORDS比较当前COORDS。

我的问题是,这是不对的。 会很感动看到有人能想出解决办法。

Answer 1:

IM惊讶没有代码,从窗口坐标到屏幕坐标切换。 在我的项目,我不得不把一个窗口权限的控制之下。 我用这个在控制中间得到该点的屏幕坐标:

    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));

如果我不这样做,就不会有在放置错误,越到右侧的更多的错误。



Answer 2:

确定一个小应用程序我所做的:
有主窗口,非常简单的内容,线路和一个Button主窗口:

<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没有内容或后面的代码。

背后主窗口的代码:

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 );
    }


}

它的作用是,只要窗口中的一个被移动或调整大小,这将画一条线到主窗口是“链接”按钮,将TestWindow的中间。

OK OK我知道这是不是你想要的:=),因为该行不能走主窗口之外。 但这个想法是有一个透明的弹出覆盖在你做同样的事情的整个屏幕。



Answer 3:

居然发现这样做的一个很好的方式。 我所做的是我设置子窗口的WindowState="Maximized" ,然后放置以外的所有LineCanvas并按照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;

如果你想有一个线连接两个让你的窗口非常简单的方式来显示相对于父窗口。 它给移动窗口的外观,但实际上你走动最大化的透明窗控制。



文章来源: Dynamic Margin on Window Drag