#922 – Mouse Shortcuts Available in a TextBox Control

There are several ways that you can interact with the text in a TextBox control using a mouse.  The most common are:

  • Left-click:  Set the cursor to the current position of the mouse pointer
  • Right-click:  Display Cut/Copy/Paste menu
  • Dbl-click:  Select an entire word
  • Left-click and drag:  Select text by dragging mouse pointer
  • Shift+Left-click:  Select text from cursor to current mouse position
Advertisement

#879 – Positioning a Popup Relative to the Mouse

You can use the Placement property of a Popup to indicate how the popup should be positioned relative to the current mouse pointer.  You can use one of the values listed below for the Placement property.

Note that there are other possible values for the Placement property.  The subset listed below are the ones used to position the popup relative to the mouse pointer.

  • Mouse – Top left corner of popup lines up with the bottom left corner of the rectangle surrounding the mouse pointer

879-001

  • MousePoint – Top left corner of popup lines up with the actual mouse pointing position (the upper left corner of the pointer)

879-002

 

#729 – Mouse.GetPosition Doesn’t Work While Dragging

If you are handling the DragOver event during a drag-and-drop operation and you want to find the current mouse position, you need to use DragEventArgs.GetPosition, rather than the static Mouse.GetPosition method.

In the example below, we initiate a drag-and-drop operation in a window and then try reporting the mouse’s position in the window’s DragOver handler.  We try using both methods to get the mouse position, but only the DragEventArgs.GetPosition method works.

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Application 2" Height="350" Width="325"
        MouseDown="Window_MouseDown"
        AllowDrop="True" DragOver="Window_DragOver">
    <StackPanel>
        <Label Name="lblInfo1" Content="Info 1"/>
        <Label Name="lblInfo2" Content="Info 2"/>
    </StackPanel>
</Window>

 

        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            DragDrop.DoDragDrop((DependencyObject)e.Source, "Sample", DragDropEffects.Copy);
        }

        private void Window_DragOver(object sender, DragEventArgs e)
        {
            System.Windows.Point p1 = Mouse.GetPosition(this);
            lblInfo1.Content = string.Format("Mouse.GetPosition: {0}, {1}", p1.X, p1.Y);

            System.Windows.Point p2 = e.GetPosition(this);
            lblInfo2.Content = string.Format("DragEventArgs.GetPosition: {0}, {1}", p2.X, p2.Y);
        }

729-001

#693 – TextBox Control Supports Drag-and-Drop

The TextBox control in WPF automatically supports drag-and-drop, in several different scenarios.

You can select text in one TextBox and drag it into another.  If you just click the left mouse button on some selected text and drag, the text will be cut from the first TextBox and pasted into the second.

 

If you hold the Ctrl key down while clicking and dragging, you can do a copy operation.

 

You can also drag text from another application (e.g. a web browser) into a TextBox in your application.

 

And you can drag text from a TextBox out of your application, into an application that accepts text as the result of a drag operation.

 

#692 – Common Controls Typically Do Not Capture the Mouse

It’s a convention within Windows that controls typically do not capture the mouse after they intercept a mouse down event.  For example, you click on a Button by pressing and releasing the left mouse button.  But if you press the left mouse button, and then move the mouse pointer off the button before releasing, the mouse will not get clicked.

Avoiding a mouse capture in this case allows the user to avoid a click action after inadvertently pressing the left mouse button down over the wrong user interface element.

#691 – IsMouseCaptured Indicates Whether Mouse Is Currently Captured

You can use the CaptureMouse and ReleaseMouseCapture methods to capture/release the mouse pointer, so that a user interface element will get all future mouse events.

You can also check the IsMouseCaptured property of a UIElement object at any time, to see whether this element has currently captured the mouse.  In the example below, IsMouseCaptured is true while we’re moving the mouse pointer across the label only while we have a mouse button pressed.

        private void Feast_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Console.WriteLine("Feast_MouseDown");
            Label l = e.Source as Label;
            l.CaptureMouse();
        }

        private void Feast_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Console.WriteLine("Feast_MouseUp");
            Label l = e.Source as Label;
            l.ReleaseMouseCapture();
        }

        private void Feast_MouseMove(object sender, MouseEventArgs e)
        {
            Label l = e.Source as Label;
            Console.WriteLine(string.Format("IsMouseCaptured={0}", l.IsMouseCaptured));
        }

#689 – An Application Can Lose Its Mouse Capture

You can capture the mouse on one mouse button event and then release it on another, with your application in some state while the mouse is captured.

For example, changing the background color of a label while the left mouse button is down.

        private Brush savedBrush;

        private void Feast_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Console.WriteLine("Feast_MouseDown");
            Label l = e.Source as Label;
            l.CaptureMouse();
            savedBrush = l.Background;
            l.Background = Brushes.Cyan;
        }

        private void Feast_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Console.WriteLine("Feast_MouseUp");
            Label l = e.Source as Label;
            l.ReleaseMouseCapture();
            l.Background = savedBrush;
        }

Although your code normally releases the mouse capture, it’s also possible that some system event causes the mouse capture to be lost.  (E.g. A system dialog pops up).  In this case, you won’t get the expected event, so your event handler never gets a chance to release the mouse capture.  Your application then ends up in an unacceptable state.  (E.g. Label’s background color wrong).

#688 – Moving an Element with the Mouse

Here’s a short example that uses the MouseDown, MouseMove and MouseUp events to move a user interface element around on the screen.  We place a Label in a Canvas and then bind its position to a couple of properties that keep track of the desired X and Y position of the label.  The properties derive from a base position for the label, plus the current mouse position.

Here’s the XAML:

    <Canvas>
        <Label Content="Feast" Background="ForestGreen" Padding="12,7"
               Canvas.Left="{Binding XPosition}" Canvas.Top="{Binding YPosition}"
               MouseDown="Feast_MouseDown"  MouseUp="Feast_MouseUp" MouseMove="Feast_MouseMove"/>
    </Canvas>

And the code:

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        private Point BasePoint = new Point(0.0, 0.0);
        private double DeltaX = 0.0;
        private double DeltaY = 0.0;
        private bool moving = false;
        private Point PositionInLabel;

        public double XPosition
        {
            get { return BasePoint.X + DeltaX; }
        }

        public double YPosition
        {
            get { return BasePoint.Y + DeltaY; }
        }

        private void Feast_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Label l = e.Source as Label;
            if (l != null)
            {
                l.CaptureMouse();
                moving = true;
                PositionInLabel = e.GetPosition(l);
            }
        }

        private void Feast_MouseMove(object sender, MouseEventArgs e)
        {
            if (moving)
            {
                Point p = e.GetPosition(null);
                DeltaX = p.X - BasePoint.X - PositionInLabel.X;
                DeltaY = p.Y - BasePoint.Y - PositionInLabel.Y;
                RaisePropertyChanged("XPosition");
                RaisePropertyChanged("YPosition");
            }
        }

        private void Feast_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Label l = e.Source as Label;
            if (l != null)
            {
                l.ReleaseMouseCapture();
                BasePoint.X += DeltaX;
                BasePoint.Y += DeltaY;
                DeltaX = 0.0;
                DeltaY = 0.0;
                moving = false;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string prop)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

The end result looks something like this:

#687 – What Happens If You Forget to Release The Mouse

A user interface element can capture the mouse, asking to receive all future mouse events, no matter where the mouse cursor is located.  You’ll typically capture the mouse in a mouse down or related event and then release the mouse in the corresponding mouse up event so that things go back to normal.

But what happens if something goes wrong and you forget to release the mouse?  At that point, the element that captured the mouse will continue to receive mouse input.  This means that other elements in your application that use the mouse will no longer function.

In the example below, the Raphael label captures the mouse on mouse down, but does not release it on mouse up.  Then when I click on the Button, the Raphael label is still getting the mouse events.

#684 – Mouse Events Occur for the Element That the Mouse Is Over

Mouse events normally fire for the element that mouse is current positioned over.  In the example below, notice that the Source property for the event handler always refers to the Label that the mouse is currently positioned over.

    <StackPanel MouseDown="Label_MouseDown" MouseUp="Label_MouseUp" MouseMove="Label_MouseMove">
        <Label Content="Sistine" Background="ForestGreen" Padding="10,20"/>
        <Label Content="Buonarroti" Background="Peru" Padding="10,20"/>
    </StackPanel>

 

        private void Label_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Label l = e.Source as Label;
            if (l != null)
                Console.WriteLine(string.Format("MouseDown on {0}", l.Content));
        }

        private void Label_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Label l = e.Source as Label;
            if (l != null)
                Console.WriteLine(string.Format("MouseUp on {0}", l.Content));
        }

        private void Label_MouseMove(object sender, MouseEventArgs e)
        {
            Label l = e.Source as Label;
            if (l != null)
            {
                Point p = e.GetPosition(null);
                Console.WriteLine(string.Format("MouseMove on {0} at ({1},{2})", l.Content, p.X, p.Y));
            }
        }

If we press the mouse button while over one Label, move to the other Label and release the button, we get: