locked
Making a selection rectangle follow the mouse. RRS feed

  • Question

  • I am trying to make a selection rectangle following the mouse.

    This works fine for Top and Left, but not Bottom and Right. Always off by a little.

    It doesn't seem to come from window border size as it's the same in full screen
    and it's the same even when cursor is Cursor.None.

    Mouse position is really the center of the rectangle ...

    Do you have any idea ?

    Thank you,

    Code
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace WpfApplication2
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                // Insert code required on object creation below this point.
                MouseMove += MainWindow_MouseMove;
                MouseWheel += MainWindow_MouseWheel;
                KeyDown += MainWindow_KeyDown;
                Cursor = Cursors.None;
            }
    
            private void MainWindow_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.Escape)
                {
                    Application.Current.Shutdown();
                }
            }
    
            private void MainWindow_MouseMove(object sender, MouseEventArgs e)
            {
                Point position = Mouse.GetPosition(this);
    
                double w = rectangle.ActualWidth/2;
                double h = rectangle.ActualHeight/2;
    
                if (position.X < w)
                {
                    position.X = w;
                }
    
                if (position.Y < h)
                {
                    position.Y = h;
                }
    
                if (position.X > ActualWidth - w)
                {
                    position.X = ActualWidth - w;
                }
    
                if (position.Y > ActualHeight - h)
                {
                    position.Y = ActualHeight - h;
                }
    
                rectangle.RenderTransform = new TranslateTransform(position.X - w, position.Y - h);
            }
    
            private void MainWindow_MouseWheel(object sender, MouseWheelEventArgs e)
            {
                bool shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
                int mul;
                mul = shift ? 10 : 1;
                mul = e.Delta > 0 ? mul : -mul;
                rectangle.Width += mul;
                rectangle.Height += mul;
                MainWindow_MouseMove(sender, e);
            }
        }
    }


    XAML

    <Window
    	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    	x:Class="WpfApplication2.MainWindow"
    	x:Name="Window"
    	Title="MainWindow" Background="BlanchedAlmond" WindowStyle="None" WindowStartupLocation="CenterScreen"   HorizontalAlignment="Left" VerticalAlignment="Top" Height="480" Width="640">
        <Grid x:Name="LayoutRoot">
            <Rectangle x:Name="rectangle" Stroke="Red" VerticalAlignment="Top" Height="200" HorizontalAlignment="Left" Width="200" RenderTransformOrigin="0.5,0.5">
    
            </Rectangle>
            <Label x:Name="label" Foreground="Red" Height="23" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="159"></Label>
        </Grid>
    </Window>

    Thursday, January 14, 2010 1:49 AM

Answers

  • Hi.

    It actually is because of window border.

    You can see it when you try window with no border like:
    WindowStyle="None" AllowsTransparency="True"

    So what you need to do is not to use window ActualWidth and ActualHeight but your client area dimensions (which are smaller).

    In this example you could use:
    LayoutRoot dimensions

                if (position.X > LayoutRoot.ActualWidth - w)
                {
                    position.X = LayoutRoot.ActualWidth - w;
                }
    
                if (position.Y > LayoutRoot.ActualHeight - h)
                {
                    position.Y = LayoutRoot.ActualHeight - h;
                }
    
    • Marked as answer by Aybe One Thursday, January 14, 2010 4:13 AM
    Thursday, January 14, 2010 4:05 AM

All replies

  • Hi.

    It actually is because of window border.

    You can see it when you try window with no border like:
    WindowStyle="None" AllowsTransparency="True"

    So what you need to do is not to use window ActualWidth and ActualHeight but your client area dimensions (which are smaller).

    In this example you could use:
    LayoutRoot dimensions

                if (position.X > LayoutRoot.ActualWidth - w)
                {
                    position.X = LayoutRoot.ActualWidth - w;
                }
    
                if (position.Y > LayoutRoot.ActualHeight - h)
                {
                    position.Y = LayoutRoot.ActualHeight - h;
                }
    
    • Marked as answer by Aybe One Thursday, January 14, 2010 4:13 AM
    Thursday, January 14, 2010 4:05 AM
  • Actually AllowTransparency fixes it, thanks !

    What was strange is that ActualHeight was still 640 which was correct ...
    Thursday, January 14, 2010 4:13 AM
  • It is not strange, 640 is dimension of your whole window including border.

    Dimension of your client area (where you move with rectangle) is smaller like 625 x 465
    Thursday, January 14, 2010 4:19 AM