Obtenga la posición del mouse en el lienzo con fondo transparente

estoy construyendo un sencillo WPF solicitud. tengo un transparente maximizado Window y Canvas (lienzo1).

Quiero obtener la posición del mouse. in canvas1 ó en MainWindow (en este caso es lo mismo).

Para hacer esto utilizo este código:

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

Este código funciona bien para un no transparente Canvas. El problema es que tengo un transparente Canvas, y este código no funciona... (No me da errores, pero las coordenadas son p.X = 0 y p.Y = 0).

¿Como puedo solucionar este problema?

preguntado el 31 de julio de 12 a las 11:07

Podrías dar tu lienzo Z-Index propiedad porque puede estar cerca de otras cosas que obtuvo en su aplicación. -

Índice Z = ? Tal vez pongas una respuesta. Si me ayuda haré +1 y lo marcaré. -

¿Has intentado usar opacidad en lugar de fondo transparente? -

No tengo una ventana/lienzo semitransparente porque MainWindow está en la parte superior (superior = verdadero). Y quiero hacer posible el clic. -

@ harry180, estoy aprendiendo. Si tienes una idea por favor publícala. :) -

2 Respuestas

Una posible solución es usar GetCursorPos Función Win32:

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

Tienes que convertir las coordenadas de píxeles a puntos si quieres usarlo en WPF.

Ejemplo de uso:

System.Drawing.Point point;
if(!GetCursorPos(out point))
    throw new InvalidOperationException("GetCursorPos failed");
// point contains cursor's position in screen coordinates.

Respondido 31 Jul 12, 12:07

@Juan, System.Drawing.Point point;GetCursorPos(out point);. point contendrá coordenadas de ratón. No olvide agregar la referencia System.Drawing.dll. - Dmitry

Solo un comentario. En última instancia, el argumento no tiene que ser un System.Drawing.Point. En Win32, es un drive estructura. También podría definir su propia estructura con dos miembros enteros y usar eso como tipo de argumento. Así te desharías de la System.Drawing.dll dependencia. - Clemens

@John Y una pregunta. ¿Cómo usará ahora esta función? ¿En un bucle sin fin actualizando constantemente la posición actual del mouse? Sigo pensando que necesitas el MouseHook. - Clemens

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>

¡Resuelto! Pero tarde :(

Respondido 31 Jul 12, 12:07

Oh gracias. Pero como dije en un comentario, no quiero un lienzo semitransparente: Opacity="0.01"... Porque quiero poder hacer clic en otra ventana (por ejemplo, la ventana de Firefox), la ventana WPF permanece en la parte superior. - Ionică Bizău

@John ¿Cómo espera obtener eventos del mouse en dos aplicaciones al mismo tiempo? ¿Movimiento del mouse en su ventana de superposición transparente y haga clic en alguna otra aplicación? ¡Eso no funcionará! - Clemens

@Clemens, creo que se puede hacer a través de Win32. Recuerdo haber leído algo sobre la piratería de mensajes win32 hace mucho tiempo, aunque no recuerdo los detalles. - Dmitry

@John o si solo quieres coordenadas, puedes usar GetCursorPos función. Aquí está la firma para pinvoke: pinvoke.net/default.aspx/user32.getcursorpos (aunque tendrás que convertir de píxeles a puntos) - Dmitry

¡Aceptar! O esto aquí - Alex

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.