2

I am building a simple WPF application. I have a transparent maximized Window and a Canvas (canvas1).

I want to get the mouse position in canvas1 or in MainWindow (in this case is same thing).

For doing this I use this code:

Point p = Mouse.GetPosition(canvas1); //and then I have p.X and p.Y

This code works fine for a non-transparent Canvas. The problem is that I have a transparent Canvas, and this code doesn't work... (It doesn't give me errors, but the coordinates are p.X = 0 and p.Y = 0).

How can I fix this problem?

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474

2 Answers2

1

C#

    using System.Windows;
    using System.Windows.Input;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System;
    using System.Windows.Threading;
    namespace Test
    {
        public partial class MainWindow : Window
        {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool GetCursorPos(ref Win32Point pt);

            [StructLayout(LayoutKind.Sequential)]
            internal struct Win32Point
            {
                public Int32 X;
                public Int32 Y;
            };
            public static Point GetMousePosition()
            {
                Win32Point w32Mouse = new Win32Point();
                GetCursorPos(ref w32Mouse);
                return new Point(w32Mouse.X, w32Mouse.Y);
            }

            private double screenWidth;
            private double screenHeight;

            public MainWindow()
            {
                InitializeComponent();
            }

            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
                screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight;

                this.Width = screenWidth;
                this.Height = screenHeight;
                this.Top = 0;
                this.Left = 0;
                DispatcherTimer timer = new DispatcherTimer();
                timer.Tick += new EventHandler(timer_Tick);
                timer.Start();
            }

            void timer_Tick(object sender, EventArgs e)
            {
                var mouseLocation = GetMousePosition();
                elipse1.Margin = new Thickness(mouseLocation.X, mouseLocation.Y, screenWidth - mouseLocation.X - elipse1.Width, screenHeight - mouseLocation.Y- elipse1.Height);
            }
        }
    }

XAML

    <Window x:Class="Test.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" 
            Height="350" Width="525" 
            WindowStyle="None" 
            Topmost="True" 
            AllowsTransparency="True" 
            Background="Transparent"
            ShowInTaskbar="False"
            Loaded="Window_Loaded">
        <Grid>
                <Ellipse Width="20" Height="20" Fill="Red" Name="elipse1"/>
        </Grid>
    </Window>

Solved! But to late :(

Alex
  • 897
  • 10
  • 17
  • 1
    Oh, thank you. But like I said in a comment I don't want a semitransparent canvas: Opacity="0.01"... Because I want to can click on another windows (for example Firefox window), the WPF window remaining on top. – Ionică Bizău Jul 31 '12 at 10:51
  • 1
    @John How do you expect to get mouse events in two applications at the same time? Mouse move in your transparent overlay window and click in some other application? That won't work! – Clemens Jul 31 '12 at 10:54
  • @Clemens I beleive it can be done via Win32. I remember reading something about win32 message hackery ages ago, though I don't remember details. – Dmitry Jul 31 '12 at 11:03
  • @John or if you just want coordinates, you can use `GetCursorPos` function. Here's the signature for pinvoke: http://www.pinvoke.net/default.aspx/user32.getcursorpos (you'll need to convert from pixels to points though) – Dmitry Jul 31 '12 at 11:09
  • Agree! Or this [link](http://stackoverflow.com/questions/10132804/c-sharp-tooltip-reporting-mouse-coordinates-on-3d-party-window) – Alex Jul 31 '12 at 11:11
  • @John Not all people are that greedy for reputation as you seem to be :-) – Clemens Jul 31 '12 at 11:15
  • @Clemens Answers should be posted as answers. I often search SO for workarounds and known solutions and I look only on answers. (And yes, I'm reputation-hungry. :-D) – Dmitry Jul 31 '12 at 11:23
  • I think problem is somewhere else.The behavior you said in question is when the background is {x:Null} or when it is not setted explicitly.This behavior is same for all Panel controls.But when you explicitly specify background=Transparent then it works. so I think problem is somewhere else.Where(method/event) exactly you getting these cursor coordinate. – yo chauhan Jul 31 '12 at 11:25
1

One possible workaround is to use GetCursorPos Win32 function:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetCursorPos(out System.Drawing.Point lpPoint); 

You have to convert the coordinates from pixels to points if you want to use it in WPF.

Usage example:

System.Drawing.Point point;
if(!GetCursorPos(out point))
    throw new InvalidOperationException("GetCursorPos failed");
// point contains cursor's position in screen coordinates.
Dmitry
  • 3,069
  • 1
  • 17
  • 26
  • @John, `System.Drawing.Point point;GetCursorPos(out point);`. `point` will contain mouse coords. Don't forget to add System.Drawing.dll reference. – Dmitry Jul 31 '12 at 11:24
  • 1
    Just a remark. The argument doesn't ultimately have to be a `System.Drawing.Point`. In Win32, it is a [POINT](http://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx) structure. You could as well define your own struct with two integer members and use that as argument type. Thus you would get rid of the `System.Drawing.dll` dependency. – Clemens Jul 31 '12 at 11:43
  • @John And a question. How will you now use this function? In an endless loop constantly updating the current mouse position? I still think you need the [MouseHook](http://stackoverflow.com/q/11607133/1136211). – Clemens Jul 31 '12 at 11:44