0

I try to achieve a little 'trick' in a WPF Window.

So I have a horizontal Window of 500 width and 30 height with a WindowStyle to None, so I add a button to move the window with the DragMove() function.

This part is working well.

My problem is that when I move the window near the border of the screen, I want to rotate my window to have a vertical one of 30x500 (it's work like the time doctor reduced bar).

To do so I listen to the LocationChanged event.

Here is the code :

XAML:

<Window x:Class="POCClient1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="Echino Time"
        Height="30" Width="500"
        Topmost="True"
        WindowStyle="None"
        ResizeMode="NoResize"
        WindowStartupLocation="CenterScreen">
    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Close"
                        Executed="CloseCmdExecuted"
                        CanExecute="CloseCmdCanExecute"/>
    </Window.CommandBindings>
    <Grid x:Name="ContainerGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="2*"/>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>

        <UniformGrid x:Name="ButtonUniformGrid2" Grid.Column="0" Columns="2" Rows="1" HorizontalAlignment="Stretch">
            <Button Grid.Column="0" x:Name="MoveButton" PreviewMouseLeftButtonDown="MoveWindow" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="3" Cursor="Hand">
                <Image Source="images/move.png" />
            </Button>
            <Button Grid.Column="0" x:Name="RotateButton" Click="RotateButton_Click" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="3">
                <Image Source="images/rotate.png" />
            </Button>
        </UniformGrid>

        <UniformGrid x:Name="ButtonUniformGrid" Grid.Column="1" Columns="2" Rows="1" HorizontalAlignment="Stretch">
            <Button Margin="3" Click="StartButton_Click">Start</Button>
            <Button Margin="3" Click="StopButton_Click">Stop</Button>
        </UniformGrid>

        <Label  Grid.Column="2" x:Name="TaskLabel" Content="POC 01" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="0" Margin="0,7" />
        <Label  Grid.Column="3" x:Name="TimeLabel" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="0" Content="Chrono" />
        <Button Grid.Column="4" x:Name="CloseButton" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="3" Command="ApplicationCommands.Close">
            <Image Source="images/close.png" />
        </Button>
    </Grid>
</Window>

C# :

public partial class MainWindow : Window
    {
        private DispatcherTimer _dispatcherTimer;
        private Stopwatch _stopwatch = new Stopwatch();
        private enum Orientation { Horizontal, Vertical };
        private Orientation _windowOrientation;

        public MainWindow()
        {
            InitializeComponent();

            _windowOrientation = Orientation.Horizontal;
            _dispatcherTimer = new DispatcherTimer
            {
                Interval = TimeSpan.FromMilliseconds(500)
            };
            _dispatcherTimer.Tick += DispatcherTimer_Tick;
            //LocationChanged += MainWindow_LocationChanged;
        }

        private void MainWindow_LocationChanged(object sender, EventArgs e)
        {
            // https://stackoverflow.com/questions/48399180/wpf-current-screen-dimensions
            System.Drawing.Rectangle workingArea = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(this).Handle).WorkingArea;

            if (_windowOrientation == Orientation.Horizontal && (Left < 0 || Left > (SystemParameters.VirtualScreenWidth - Width)))
            {
                RotateToVerticalWindow();
            }
            else if (_windowOrientation == Orientation.Vertical && (Top < 0 || Top < Height))
            {
                RotateToHorizontalWindow();
            }
        }

        private void CloseCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void CloseCmdExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            Close();
        }

        private void DispatcherTimer_Tick(object sender, EventArgs e)
        {
            if (_stopwatch.IsRunning)
            {
                TimeLabel.Content = $"{_stopwatch.Elapsed:hh':'mm':'ss}";
            }
        }

        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            _stopwatch.Start();
            _dispatcherTimer.Start();
        }

        private void StopButton_Click(object sender, RoutedEventArgs e)
        {
            _stopwatch.Stop();
            _dispatcherTimer.Stop();
        }

        private void RotateButton_Click(object sender, RoutedEventArgs e)
        {
            if (_windowOrientation == Orientation.Horizontal)
            {
                RotateToVerticalWindow();
            }
            else if (_windowOrientation == Orientation.Vertical)
            {
                RotateToHorizontalWindow();
            }
        }

        // Move the window with drag of the button. Ensure that we are not over the taskbar
        private void MoveWindow(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            DragMove();

            // https://stackoverflow.com/questions/48399180/wpf-current-screen-dimensions
            System.Drawing.Rectangle workingArea = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(this).Handle).WorkingArea;

            //The left property of the window is calculated on the width of all screens, so use VirtualScreenWidth to have the correct width
            if (Top > (workingArea.Height - Height))
            {
                Top = (workingArea.Height - Height);
            }
            else if (Left > (SystemParameters.VirtualScreenWidth - Width))
            {
                Left = (SystemParameters.VirtualScreenWidth - Width);
            }
            else if (Left < 0)
            {
                Left = 0;
            }
        }

        private void RotateToVerticalWindow()
        {
            // Set new Width and Height for the window
            Width = 30;
            Height = 500;

            RotateTransform myRotateTransform = new RotateTransform
            {
                Angle = 90
            };

            ContainerGrid.LayoutTransform = myRotateTransform;
            _windowOrientation = Orientation.Vertical;
        }

        private void RotateToHorizontalWindow()
        {
            // Set new Width and Height for the window
            Width = 500;
            Height = 30;

            RotateTransform myRotateTransform = new RotateTransform
            {
                Angle = 0
            };

            ContainerGrid.LayoutTransform = myRotateTransform;
            _windowOrientation = Orientation.Horizontal;
        }
    }

The issue is that when I reach the border, the content of the window is rotated but the Window doesn't take his new size.

Whant I want to achieve is rotating the Window and it's content while keeping the drag active so we can continue to drag after the rotation.

For now I add a button to "manually" rotate the Window to see the effect and it's working fine.

Thanks in advance :)

S.Martignier
  • 383
  • 2
  • 4
  • 17
  • I believe this is happening because you are dragging the window and the drag animation is being taken over by the OS. Since you can see the effect with the button and it's not happening for drag.. However; regardless of the case I have an alternative suggestion. I suggest dragging the content outside of the window, too look like you are dragging the window. You will have control over the effects and when you let go or let the content snap into place you simply move the window to that new location with the new values. – Michael Puckett II Sep 26 '18 at 14:07
  • Thanks for the suggestion, can you give me some lead on how to drag the content? Maybe I wasn't clear enough, the content of the window is rotated with my current code, but the window doesn't take the new values for width and heigth (it is set but then reset to previous values) – S.Martignier Sep 27 '18 at 06:24
  • I thought you said when you push the button, to do it manually without dragging, the Window did work as expected. Is this not the case? – Michael Puckett II Sep 27 '18 at 13:54
  • Yes when it's with the button it's work. – S.Martignier Sep 28 '18 at 08:07
  • New comment while i can edit only in the 5 minutes following Yes when it's with the button it's work. I will try to explain myself better: When the user click on the button to move the window I call the DragMove() Then I listen to the LocationChanged event and I check the position of the TopLeft to see if the window reach the border, if so I rotate the window content and set new size for the window. – S.Martignier Sep 28 '18 at 08:14
  • If a log in console the width and eight of my window I see this process : 1) when I start the DragMove : 500x30 2) LocationChanged : 500x30, then it call rotate 3) rotate : 30x500 4) return to LocationChanged: 30x500 5) return to dragmove : reset to 500x30 So At the end I have a Window with the wrong size but the content is rotated – S.Martignier Sep 28 '18 at 08:14
  • Right. I haven't duplicated this, so I'm not certain, but it sounds like the OS is taking over a little bit of your window resizing. Sort of like how you can dock Windows to the edges already. So the OS is listening to the move also and probably doing something with it. You may need to send the OS a message to tell it you've taken over, which may be as simple as a flag e.Handled = true sorta thing OR you may find it easier to manipulate the visual. You would move the content of the window and simply reset the window based on where the content was moved. That's what I meant previously. – Michael Puckett II Sep 28 '18 at 13:20

0 Answers0