none
como cambiar la imagen del cursor en wpf

    Question

  • hola a todos estado desarrollando una pequeña aplicación calculadora en la cual interviene el kinect sdk beta2.... 
    en la cual tengo una imagen cursor que se puede mover con la mano derecha algo parecido a la interfaz del Xbox 360 con el kinect incorporado, al inicializar la aplicación dicha imagen la podemos mover con la mano derecha, lo que deseo hacer es que el mouse pueda también
    mover esta imagen y trabajar como si fuera el cursor normar.

    en pocas palabras que al iniciar la aplicación
    la imagen que se mueve con el kinect sea el nuevo cursor remplazando la flecha tradicional.

    agradesco cualquier colaboracion

    aqui les dejo una imagen de la aplicacion..

    http://s2.subirimagenes.com/imagen/previo/thump_7426230captura.png


    Saturday, February 11, 2012 5:24 PM

Answers

  • Hola jhonk.

    El link de Nestor, es una de las formas de hacerlo (la parte que hablan de ocultar el icono y mostrar una imagen), sobretodo si se quiere realizar en silverlight sin elevar permisos.

    yo voy a exponer otra forma, que se puede implementar en WPF y silverlight con permisos elevados, ya que se hace uso del WINAPI, a la vieja usanza.

    He modificado una clase que tenia para simplificarla lo maximo que he podido para tener una base funcional de donde partir.

    La clase hace uso de las funciones WINAPI mediante interoperabilidad para establecer el cursor. Como esta muy bien comentada no creo que hayan problemas para entender lo que hace:

    /// <summary>
    /// Clase para implementar un cursor personalizado mediante WINAPI
    /// </summary>
    class CustomCursor
    {
    
        #region [SafeCursorHandle]
    
        /// <summary>
        /// Clase para crear un contenedor seguro para usar con manejadores de WINAPI de cursores, esto evita que sean
        /// recolectados por el GC los manejadores ademas de poder ser liberados de forma personalizada.
        /// </summary>
        private class SafeCursorHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
        {
            /// <summary>
            /// Constructor por defecto de la clase
            /// </summary>
            /// <param name="hCursor" />handle del cursor a encapsular
            public SafeCursorHandle(IntPtr hCursor) : base(true)
            {
                // guardar el handle
                this.SetHandle(hCursor);
            }
    
            /// <summary>
            /// Funcion sobreescrita para liberar el handle al cursor correctamente
            /// </summary>
            /// <returns>True si se libera correctamente, false en caso contrario</returns>
            protected override bool ReleaseHandle()
            {
                // eliminar el cursor mediante WINAPI
                return DestroyIcon(this.handle);
            }
        }
    
        #endregion [SafeCursorHandle]
    
    
        /// <summary>
        /// Funcion para crear un cursor personalizado
        /// </summary>
        public static Cursor createCustomCursor(System.Drawing.Bitmap _bitmap)
        {
            // handle al icono a usar en el cursor
            IntPtr hIcon = IntPtr.Zero;
                
            try
            {
                // estructura con la informacion del cursor
                ICONINFO iconInfo = new ICONINFO();
                // obtener el puntero al icono que representa el bitmap
                hIcon = _bitmap.GetHicon();
                // rellenar la estructura con la informacion del icono
                GetIconInfo(hIcon, out iconInfo);
                // establecer el offset del puntero del cursor en la esquina del bitmap (por defecto es el centro)
                iconInfo.xHotspot = 0;
                iconInfo.yHotspot = 0;
                // la estructura es para un cursor
                iconInfo.fIcon = false;
    
                // crear el cursor mediante la estructura con la informacion
                IntPtr hCursor = CreateIconIndirect(ref iconInfo);
    
                // encapsular el handle al cursor en un objeto administrado seguro para liberarse correctamente
                SafeCursorHandle hCursorFile = new SafeCursorHandle(hCursor);
                // crear el cursor
                return System.Windows.Interop.CursorInteropHelper.Create(hCursorFile);
            }
            finally
            {
                // liberar el manejador a la imagen usada para el cursor
                // NOTA: el cursor es eliminado automaticamente mediante el objeto 'SafeCursorHandle', pero 
                // el manejador de la imagen usada no es eliminada y es recomendable liberar el recurso.
                DestroyIcon(hIcon);
            }
        }
    
    
        #region [WINAPI]
    
        /// <summary>
        /// Estructura con informacion del icono de WINAPI
        /// </summary>
        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        private struct ICONINFO
        {
            /// <summary>
            /// especifica cuando esta estructura define un icono o un cursor
            /// TRUE especifica un icono, FALSE especifica cursor
            /// </summary>
            public bool fIcon;
            /// <summary>
            /// la coordenada x del punto del cursor            
            /// </summary>
            public Int32 xHotspot;
            /// <summary>
            /// la coordenada y del punto del cursor
            /// </summary>
            public Int32 yHotspot;
            /// <summary>
            /// la mascara de bits para el bitmap del icono
            /// </summary>
            public IntPtr hbmMask;
            /// <summary>
            /// Handle al bitmap con el color del icono
            /// </summary>
            public IntPtr hbmColor;
        }
    
        /// <summary>
        /// Funcion winapi para la creacion del cursor
        /// </summary>
        /// <param name="_iconInfo" />estructura <see cref="ICONINFO"></see> con la informacion del cursor
        /// <returns>manejador al cursor</returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr CreateIconIndirect(ref ICONINFO _iconInfo);
    
        /// <summary>
        /// Funcion winapi para obtener la informacion de un icono/cursor
        /// </summary>
        /// <param name="_hIcon" />manejador al icono
        /// <param name="_iconInfo" />estructura <see cref="ICONINFO"></see> donde sera guardada la informacion del icono/cursor
        /// <returns>true si tiene exito, false en caso contrario</returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool GetIconInfo(IntPtr _hIcon, out ICONINFO _iconInfo);
    
        /// <summary>
        /// Funcion winapi para eliminar la memoria usada por un icono mediante su manejador
        /// </summary>
        /// <param name="handle" />manejador al icono a liberar
        /// <returns>true si tiene exito, false en caso contrario</returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        extern static bool DestroyIcon(IntPtr handle);
    
        #endregion [WINAPI]
    
    }

    Como se hace uso de WINAPI, se deben liberar todos los recursos obligadamente (al estilo c++).

    Para usar la clase tan solo tienes que hacer algo asi:

            /// <summary>
            /// Constructor por defecto de la clase
            /// </summary>
            public MainWindow()
            {
                InitializeComponent();
    
                // crear el cursor personalizado
                this.Cursor = CustomCursor.createCustomCursor(new System.Drawing.Bitmap(@"audio-keyboard.png"));
            }

    Y se pondra la imagen en el control que se especifique.

    Como el WINAPI de windows, hace uso del GDI para los bitmaps, se utiliza la clase System.Drawing.Bitmap para simplificar el proceso, no obstante, es posible que dispongas de un Windows.Controls.Image de WPF, de modo que te pongo un link de un post donde explico como pasar de uno a otro:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/67c25a23-33bd-4b4b-bd12-43ebce77dc8d

    Si tienes algun problema para implementarlo, comentalo.


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/



    • Edited by David_González Monday, February 20, 2012 12:43 PM
    • Marked as answer by jhonK Sunday, March 04, 2012 7:47 PM
    Monday, February 20, 2012 12:38 PM

All replies

  • Monday, February 13, 2012 2:42 PM
  • Hola:

    Hace poco tuve que cambiar el cursor en mi aplicación.

    Es realmente sencillo, lo único que tienes que hacer es lo siguiente:

    Mouse.OverrideCursor = Cursors.Cross;

    En mi caso sustituyo el cursor por una cruz, pero tienes muchas opciones que podrás ver en Cursores.

    Saludos


    Atentamente José Luis Torre

    Monday, February 13, 2012 8:54 PM
  • hola primero que todo gracias por responder mi inquietudes...

    No sé si la pregunta que realice haya sido lo bastante puntual igual te explico a continuación que es  lo que quiero hacer.  yo se que podemos cambiar el cursor de esta manera en el .XAML

    Cursor="Cross"

    Cursor="Wait"

    hay una lista con una serie de opciones que podemos escoger.. pero lo que yo quiero hacer es cargar una imagen .JPG y a esta asignarle las acciones del mouse

    mira la aplicación que estoy desarrollando es una aplicación de kinect en la cual asigne una mano cursor con ella hago funcionar los botones de la calculadora hasta ahí no tengo ningún lio. "algo parecido a la interfaz del xbox 360"

    mira en el .XMAL cree un control asignándole la imagen la cual se llama "Mano" esta es la imagen que  a la hora de ejecutar la aplicación con la mano derecha es el cursor ahora deseo que "Mano" se pueda mover con el mouse remplazando el cursor en pocas palabra:

    Mano= cursor

    para que las personas que no tienen el kinect puedan hacer funcionar la aplicación como si lo tuvieran con el mouse.


    Tuesday, February 14, 2012 5:30 PM
  • Hola jhonk.

    El link de Nestor, es una de las formas de hacerlo (la parte que hablan de ocultar el icono y mostrar una imagen), sobretodo si se quiere realizar en silverlight sin elevar permisos.

    yo voy a exponer otra forma, que se puede implementar en WPF y silverlight con permisos elevados, ya que se hace uso del WINAPI, a la vieja usanza.

    He modificado una clase que tenia para simplificarla lo maximo que he podido para tener una base funcional de donde partir.

    La clase hace uso de las funciones WINAPI mediante interoperabilidad para establecer el cursor. Como esta muy bien comentada no creo que hayan problemas para entender lo que hace:

    /// <summary>
    /// Clase para implementar un cursor personalizado mediante WINAPI
    /// </summary>
    class CustomCursor
    {
    
        #region [SafeCursorHandle]
    
        /// <summary>
        /// Clase para crear un contenedor seguro para usar con manejadores de WINAPI de cursores, esto evita que sean
        /// recolectados por el GC los manejadores ademas de poder ser liberados de forma personalizada.
        /// </summary>
        private class SafeCursorHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
        {
            /// <summary>
            /// Constructor por defecto de la clase
            /// </summary>
            /// <param name="hCursor" />handle del cursor a encapsular
            public SafeCursorHandle(IntPtr hCursor) : base(true)
            {
                // guardar el handle
                this.SetHandle(hCursor);
            }
    
            /// <summary>
            /// Funcion sobreescrita para liberar el handle al cursor correctamente
            /// </summary>
            /// <returns>True si se libera correctamente, false en caso contrario</returns>
            protected override bool ReleaseHandle()
            {
                // eliminar el cursor mediante WINAPI
                return DestroyIcon(this.handle);
            }
        }
    
        #endregion [SafeCursorHandle]
    
    
        /// <summary>
        /// Funcion para crear un cursor personalizado
        /// </summary>
        public static Cursor createCustomCursor(System.Drawing.Bitmap _bitmap)
        {
            // handle al icono a usar en el cursor
            IntPtr hIcon = IntPtr.Zero;
                
            try
            {
                // estructura con la informacion del cursor
                ICONINFO iconInfo = new ICONINFO();
                // obtener el puntero al icono que representa el bitmap
                hIcon = _bitmap.GetHicon();
                // rellenar la estructura con la informacion del icono
                GetIconInfo(hIcon, out iconInfo);
                // establecer el offset del puntero del cursor en la esquina del bitmap (por defecto es el centro)
                iconInfo.xHotspot = 0;
                iconInfo.yHotspot = 0;
                // la estructura es para un cursor
                iconInfo.fIcon = false;
    
                // crear el cursor mediante la estructura con la informacion
                IntPtr hCursor = CreateIconIndirect(ref iconInfo);
    
                // encapsular el handle al cursor en un objeto administrado seguro para liberarse correctamente
                SafeCursorHandle hCursorFile = new SafeCursorHandle(hCursor);
                // crear el cursor
                return System.Windows.Interop.CursorInteropHelper.Create(hCursorFile);
            }
            finally
            {
                // liberar el manejador a la imagen usada para el cursor
                // NOTA: el cursor es eliminado automaticamente mediante el objeto 'SafeCursorHandle', pero 
                // el manejador de la imagen usada no es eliminada y es recomendable liberar el recurso.
                DestroyIcon(hIcon);
            }
        }
    
    
        #region [WINAPI]
    
        /// <summary>
        /// Estructura con informacion del icono de WINAPI
        /// </summary>
        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        private struct ICONINFO
        {
            /// <summary>
            /// especifica cuando esta estructura define un icono o un cursor
            /// TRUE especifica un icono, FALSE especifica cursor
            /// </summary>
            public bool fIcon;
            /// <summary>
            /// la coordenada x del punto del cursor            
            /// </summary>
            public Int32 xHotspot;
            /// <summary>
            /// la coordenada y del punto del cursor
            /// </summary>
            public Int32 yHotspot;
            /// <summary>
            /// la mascara de bits para el bitmap del icono
            /// </summary>
            public IntPtr hbmMask;
            /// <summary>
            /// Handle al bitmap con el color del icono
            /// </summary>
            public IntPtr hbmColor;
        }
    
        /// <summary>
        /// Funcion winapi para la creacion del cursor
        /// </summary>
        /// <param name="_iconInfo" />estructura <see cref="ICONINFO"></see> con la informacion del cursor
        /// <returns>manejador al cursor</returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr CreateIconIndirect(ref ICONINFO _iconInfo);
    
        /// <summary>
        /// Funcion winapi para obtener la informacion de un icono/cursor
        /// </summary>
        /// <param name="_hIcon" />manejador al icono
        /// <param name="_iconInfo" />estructura <see cref="ICONINFO"></see> donde sera guardada la informacion del icono/cursor
        /// <returns>true si tiene exito, false en caso contrario</returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool GetIconInfo(IntPtr _hIcon, out ICONINFO _iconInfo);
    
        /// <summary>
        /// Funcion winapi para eliminar la memoria usada por un icono mediante su manejador
        /// </summary>
        /// <param name="handle" />manejador al icono a liberar
        /// <returns>true si tiene exito, false en caso contrario</returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        extern static bool DestroyIcon(IntPtr handle);
    
        #endregion [WINAPI]
    
    }

    Como se hace uso de WINAPI, se deben liberar todos los recursos obligadamente (al estilo c++).

    Para usar la clase tan solo tienes que hacer algo asi:

            /// <summary>
            /// Constructor por defecto de la clase
            /// </summary>
            public MainWindow()
            {
                InitializeComponent();
    
                // crear el cursor personalizado
                this.Cursor = CustomCursor.createCustomCursor(new System.Drawing.Bitmap(@"audio-keyboard.png"));
            }

    Y se pondra la imagen en el control que se especifique.

    Como el WINAPI de windows, hace uso del GDI para los bitmaps, se utiliza la clase System.Drawing.Bitmap para simplificar el proceso, no obstante, es posible que dispongas de un Windows.Controls.Image de WPF, de modo que te pongo un link de un post donde explico como pasar de uno a otro:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/67c25a23-33bd-4b4b-bd12-43ebce77dc8d

    Si tienes algun problema para implementarlo, comentalo.


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/



    • Edited by David_González Monday, February 20, 2012 12:43 PM
    • Marked as answer by jhonK Sunday, March 04, 2012 7:47 PM
    Monday, February 20, 2012 12:38 PM