elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: (TUTORIAL) Aprende a emular Sentinel Dongle By Yapis


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Cambio el cursor y se ve en blanco y negro
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Cambio el cursor y se ve en blanco y negro  (Leído 2,963 veces)
Lekim

Desconectado Desconectado

Mensajes: 268



Ver Perfil
Cambio el cursor y se ve en blanco y negro
« en: 7 Septiembre 2015, 18:40 pm »

Q tal

Mi problema es simple pero al mismo tiempo extraño.  Resulta que quiero hacer que al pasar el puntero por un control, digamos un Label, el puntero cambie.

Lo que hago es cargar en un archivo de recursos un cursor.  Y luego lo llamo del siguiente modo en el evento MouseMove de un Label:

Código
  1. Dim curPen As New System.IO.MemoryStream(My.Resources.Resource1.Lapiz)
  2. Cursor.Current = New Cursor(curPen)

Funciona, pero da igual si el cursor es de 8 bits o 24 bits, se ve de color negro o blanco y negro.

No entiendo porqué.

Gracias



En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.809



Ver Perfil
Re: Cambio el cursor y se ve en blanco y negro
« Respuesta #1 en: 7 Septiembre 2015, 22:23 pm »

Funciona, pero da igual si el cursor es de 8 bits o 24 bits, se ve de color negro o blanco y negro.

No entiendo porqué.

Cómo indica la documentación oficial de la class System.Windows.Forms.Cursor, no soporta cursores con colores distintos a blanco y negro.

The Cursor class does not support animated cursors (.ani files) or cursors with colors other than black and white.

Tienes que hechar mano de la WinAPI, particulármente la función LoadCursorFromFile, la cual aparte de solventar el problema de los colores también permite utilizar cursores animados:
LoadCursorFromFile function - MSDN



He desarrollado la siguiente class para simplificar la tarea y automatizar la carga del cursor.

Código fuente:
Código
  1. ' ***********************************************************************
  2. ' Author   : Elektro
  3. ' Modified : 07-September-2015
  4. ' ***********************************************************************
  5. ' <copyright file="CursorUtil.vb" company="Elektro Studios">
  6. '     Copyright (c) Elektro Studios. All rights reserved.
  7. ' </copyright>
  8. ' ***********************************************************************
  9.  
  10. #Region " Imports "
  11.  
  12. Imports System
  13. Imports System.ComponentModel
  14. Imports System.IO
  15. Imports System.Runtime.InteropServices
  16. Imports System.Windows.Forms
  17.  
  18. #End Region
  19.  
  20. ''' ----------------------------------------------------------------------------------------------------
  21. ''' <summary>
  22. ''' Contains related cursor utilities.
  23. ''' </summary>
  24. ''' ----------------------------------------------------------------------------------------------------
  25. Public NotInheritable Class CursorUtil
  26.  
  27. #Region " P/Invoking "
  28.  
  29.    ''' ----------------------------------------------------------------------------------------------------
  30.    ''' <summary>
  31.    ''' Platform Invocation methods (P/Invoke), access unmanaged code.
  32.    ''' This class does not suppress stack walks for unmanaged code permission.
  33.    ''' <see cref="System.Security.SuppressUnmanagedCodeSecurityAttribute"/> must not be applied to this class.
  34.    ''' This class is for methods that can be used anywhere because a stack walk will be performed.
  35.    ''' </summary>
  36.    ''' ----------------------------------------------------------------------------------------------------
  37.    ''' <remarks>http://msdn.microsoft.com/en-us/library/ms182161.aspx</remarks>
  38.    ''' ----------------------------------------------------------------------------------------------------
  39.    Private NotInheritable Class NativeMethods
  40.  
  41. #Region " Functions "
  42.  
  43.        ''' ----------------------------------------------------------------------------------------------------
  44.        ''' <summary>
  45.        ''' Creates a cursor based on data contained in a file.
  46.        ''' </summary>
  47.        ''' ----------------------------------------------------------------------------------------------------
  48.        ''' <param name="filepath">
  49.        ''' The source of the file data to be used to create the cursor.
  50.        ''' The data in the file must be in either .CUR or .ANI format.
  51.        ''' </param>
  52.        ''' ----------------------------------------------------------------------------------------------------
  53.        ''' <returns>
  54.        ''' If the function is successful, the return value is an <see cref="IntPtr"/> to the new cursor.
  55.        ''' If the function fails, the return value is <see cref="IntPtr.Zero"/>.
  56.        ''' To get extended error information, call <see cref="Marshal.GetLastWin32Error"/>.
  57.        ''' </returns>
  58.        ''' ----------------------------------------------------------------------------------------------------    
  59.        ''' <remarks>
  60.        ''' <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms648392%28v=vs.85%29.aspx"/>
  61.        ''' </remarks>
  62.        ''' ----------------------------------------------------------------------------------------------------
  63.        <DllImport("User32.dll", CharSet:=CharSet.Ansi, BestFitMapping:=False, ThrowOnUnmappableChar:=True, SetLastError:=True)>
  64.        Public Shared Function LoadCursorFromFile(
  65.                ByVal filepath As String
  66.        ) As IntPtr
  67.        End Function
  68.  
  69. #End Region
  70.  
  71.    End Class
  72.  
  73. #End Region
  74.  
  75. #Region " Constructors "
  76.  
  77.    ''' <summary>
  78.    ''' Prevents a default instance of the <see cref="CursorUtil"/> class from being created.
  79.    ''' </summary>
  80.    Private Sub New()
  81.    End Sub
  82.  
  83. #End Region
  84.  
  85. #Region " Public Methods "
  86.  
  87.    ''' ----------------------------------------------------------------------------------------------------
  88.    ''' <summary>
  89.    ''' Creates a cursor based on data contained in a managed .Net resource.
  90.    ''' </summary>
  91.    ''' ----------------------------------------------------------------------------------------------------
  92.    ''' <param name="resource">
  93.    ''' The resource.
  94.    ''' </param>
  95.    ''' ----------------------------------------------------------------------------------------------------
  96.    ''' <returns>
  97.    ''' <see cref="System.Windows.Forms.Cursor"/>.
  98.    ''' </returns>
  99.    ''' ----------------------------------------------------------------------------------------------------
  100.    <DebuggerStepThrough>
  101.    <DebuggerHidden>
  102.    Public Shared Function LoadCursorFromResource(ByVal resource As Byte(),
  103.                                                  Optional cleanTempFile As Boolean = True) As Cursor
  104.  
  105.        Dim tmpFilepath As String = String.Format("{0}.ani", Path.GetTempFileName)
  106.  
  107.        Try
  108.            Using fs As New FileStream(tmpfilepath, FileMode.Create, FileAccess.Write, FileShare.Read)
  109.                fs.Write(resource, 0, resource.Length)
  110.            End Using
  111.  
  112.            Dim result As IntPtr = NativeMethods.LoadCursorFromFile(tmpFilepath)
  113.            Dim win32Err As Integer = Marshal.GetLastWin32Error
  114.  
  115.            If result = IntPtr.Zero Then
  116.                Throw New Win32Exception([error]:=win32Err)
  117.            Else
  118.                Return New Cursor(result)
  119.            End If
  120.  
  121.        Catch ex As Exception
  122.            Throw
  123.  
  124.        Finally
  125.            If (cleanTempFile) AndAlso (File.Exists(tmpFilepath)) Then
  126.                File.Delete(tmpFilepath)
  127.            End If
  128.  
  129.        End Try
  130.  
  131.    End Function
  132.  
  133. #End Region
  134.  
  135. End Class

Modo de empleo:
Código
  1. Public NotInheritable Class Form1 : Inherits Form
  2.  
  3.    Private Sub Label1_MouseEnter(ByVal sender As Object, ByVal e As EventArgs) _
  4.    Handles Label1.MouseEnter
  5.  
  6.        Static cur As Cursor
  7.  
  8.        If cur Is Nothing Then
  9.            cur = CursorUtil.LoadCursorFromResource(My.Resources.MyCursor)
  10.        End If
  11.  
  12.        ' Asegurarse de liberar el objeto cuando sea necesario...
  13.  
  14.        DirectCast(sender, Label).Cursor = cur
  15.  
  16.    End Sub
  17.  
  18.    Private Sub Label1_MouseLeave(ByVal sender As Object, ByVal e As EventArgs) _
  19.    Handles Label1.MouseLeave
  20.  
  21.        DirectCast(sender, Label).Cursor = Cursors.Default
  22.  
  23.    End Sub
  24.  
  25. End Class

Recursos usados para las pruebas:


Metro X Cursor Set - DeviantArt

Saludos


« Última modificación: 8 Septiembre 2015, 05:14 am por Eleкtro » En línea

Lekim

Desconectado Desconectado

Mensajes: 268



Ver Perfil
Re: Cambio el cursor y se ve en blanco y negro
« Respuesta #2 en: 8 Septiembre 2015, 16:51 pm »

Gracias, el código va perfecto.

Tan sólo un problema me ha dado y es el siguiente. He usado un Form simple en VisualBasic.Net 2010 y tras copiar y pegar tu código ocurría el siguiente error:

Código:
La clase Form1 se puede diseñar, per no es la primera clase de archivo.
Visual Studio requiere que los diseñadores utilicen la primera clase del archivo.
Mueva el código de clase para convertirla en la primera clase del archivo y vuelva a intetar cargar el diseñador de nuevo.

No se podía ver el diseño del form.

Por ello,si me lo permites, he reducido y cambiado el orden de tu código. También he usado el evento MouseMove en lugar de Label1_MouseEnter y Label1_MouseLeave, ya que el Label que uso en mi programa se crea en tiempo real y es una matriz de control. Creo el evento mediante código y prefiero crear sólo un evento en lugar de dos. Funciona igual. También he cambiado "{0}.ani" por "{0}.cur" ya que mi cursor no es animado. Espero que no te importe.



Código
  1. Imports System
  2. Imports System.ComponentModel
  3. Imports System.IO
  4. Imports System.Runtime.InteropServices
  5. Imports System.Windows.Forms
  6.  
  7. Public Class Form1
  8.  
  9.    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  10.  
  11.    End Sub
  12.  
  13.    Private Sub Label1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseMove
  14.        Static cur As Cursor
  15.  
  16.        If cur Is Nothing Then
  17.            cur = CursorUtil.LoadCursorFromResource(My.Resources.Resource1.Cursor1)
  18.        End If
  19.  
  20.        ' Asegurarse de liberar el objeto cuando sea necesario...
  21.  
  22.        DirectCast(sender, Label).Cursor = cur
  23.    End Sub
  24. End Class
  25.  
  26.  
  27. Public NotInheritable Class CursorUtil
  28.    <DllImport("User32.dll", CharSet:=CharSet.Ansi, BestFitMapping:=False, ThrowOnUnmappableChar:=True, SetLastError:=True)>
  29.    Public Shared Function LoadCursorFromFile(ByVal filepath As String) As IntPtr
  30.    End Function
  31.  
  32.    Public Shared Function LoadCursorFromResource(ByVal resource As Byte(), Optional ByVal cleanTempFile As Boolean = True) As Cursor
  33.  
  34.        Dim tmpFilepath As String = String.Format("{0}.cur", Path.GetTempFileName)
  35.  
  36.        Try
  37.            Using fs As New FileStream(tmpFilepath, FileMode.Create, FileAccess.Write, FileShare.Read)
  38.                fs.Write(resource, 0, resource.Length)
  39.            End Using
  40.  
  41.            Dim result As IntPtr = LoadCursorFromFile(tmpFilepath)
  42.            Dim win32Err As Integer = Marshal.GetLastWin32Error
  43.  
  44.            If result = IntPtr.Zero Then
  45.                Throw New Win32Exception([error]:=win32Err)
  46.            Else
  47.                Return New Cursor(result)
  48.            End If
  49.  
  50.        Catch ex As Exception
  51.            Throw
  52.  
  53.        Finally
  54.            If (cleanTempFile) AndAlso (File.Exists(tmpFilepath)) Then
  55.                File.Delete(tmpFilepath)
  56.            End If
  57.  
  58.        End Try
  59.  
  60.    End Function
  61.  
  62. End Class


Esperaba no tener que usar una función API. No entiendo como no se permite usar cursores en color, la verdad.

« Última modificación: 8 Septiembre 2015, 16:53 pm por Lekim » En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.809



Ver Perfil
Re: Cambio el cursor y se ve en blanco y negro
« Respuesta #3 en: 9 Septiembre 2015, 00:05 am »

Tan sólo un problema me ha dado y es el siguiente. He usado un Form simple en VisualBasic.Net 2010 y tras copiar y pegar tu código ocurría el siguiente error:

Código:
La clase Form1 se puede diseñar, per no es la primera clase de archivo.
Visual Studio requiere que los diseñadores utilicen la primera clase del archivo.
Mueva el código de clase para convertirla en la primera clase del archivo y vuelva a intetar cargar el diseñador de nuevo.

No se podía ver el diseño del form.

Por ello,si me lo permites, he reducido y cambiado el orden de tu código.

Corrígeme si me equivoco al hacer suposiciones, pero deduzco que lo que hiciste fue simplemente copiar y pegar en la class principal el código de ambas classes, de esta forma:

Form1.vb
Código
  1. Class CursorUtil
  2. ...
  3. End lass
  4.  
  5. Class Form1
  6. ...
  7. End Class

Por supuesto eso no te podría haber funcionado y el modo en el que lo corregiste fue modificando el orden de las definiciones de esas classes, pero lo que realmente debes hacer es crear una nueva class, me refiero a un nuevo archivo class.vb donde debes definir la class CursorUtil.



Esperaba no tener que usar una función API. No entiendo como no se permite usar cursores en color, la verdad.

Si, deja bastante que desear la ausencia de compatibilidad con cursores regulares, pero así es la realidad, lo cierto es que la tecnología WindowsForms se puede considerar casi-deprecada ya que es primitiva en muchos otros aspectos gráficos y hay que estar hackeando constantemente la UI para realizar modificaciones estéticas comunes, ese es el gran inconveniente que conlleva utilizar WinForms.

Si realmente quieres evitar este tipo de problemas entonces la mejor opción sería migrar a la tecnología WPF (WindowsPresentationFoundation) ya que es la que actuálmente está en constante desarrollo y actualización por parte de Microsoft, en comparación con Windowsforms donde, en lo referente a la UI y las classes u otros miembros relacionados con la UI ya no veremos ninguna mejora/actualización cómo por ejemplo eso, la esencial compatibilidad de cursores.

En WPF el equivalente a la class System.Windows.Forms.Cursor sería la class System.Windows.Input.Cursor, la cual por supuesto soporta cursores estáticos y animados a 32-bit depth en full HD x'D.

Saludos!
« Última modificación: 9 Septiembre 2015, 00:42 am por Eleкtro » En línea

Lekim

Desconectado Desconectado

Mensajes: 268



Ver Perfil
Re: Cambio el cursor y se ve en blanco y negro
« Respuesta #4 en: 15 Septiembre 2015, 17:51 pm »

Corrígeme si me equivoco al hacer suposiciones, pero deduzco que lo que hiciste fue simplemente copiar y pegar en la class principal el código de ambas classes, de esta forma:
No te equivocas jeje, es verdad, tendría que haberlo metido en un módulo. Fallo de novatos  :xD

En cuanto a lo de WPF. Pues he hecho algunas pruebas y lo he usado.. muy poco no, nada en absoluto. Mi primeros intentos fue porque leí maravillas con respecto a su capacidad gráfica y que podías personalizar los controles. Eso es algo que a mí me gusta hacer. El problema es que no he conseguido personalizar los controles en general, es decir, no tener que estar estableciendo la configuración gráfica para cada control, y de este modo establecer una aspecto gráfico uniforme y cosntante en toda la aplicación. He encontrado ejemplos en la red pero no me han funcionado, supongo que no habré hecho algo bien.

Más adelante, un día de estos crearé un nuevo tema y preguntaré sobre esto en cuestion, poniendo el código y el método que he usado y haber si alguien me ayuda con este tema. Mientras tanto usaré el form clásico. Poco a poco se va llenando el bote.
 
Saludos


En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Efecto blanco y negro
Diseño Gráfico
Vassago 6 3,330 Último mensaje 15 Marzo 2004, 20:09 pm
por Vassago
juego en blanco y negro??
Juegos y Consolas
Galagar 2 1,827 Último mensaje 31 Agosto 2004, 23:36 pm
por Galagar
BLANCO Y NEGRO
Multimedia
circus2003 3 2,375 Último mensaje 13 Junio 2005, 21:05 pm
por Songoku
Se me ve blanco y negro
Software
//rastaman// 0 1,663 Último mensaje 24 Septiembre 2005, 03:41 am
por //rastaman//
Televisor en blanco y negro. « 1 2 »
Multimedia
Hacker wifi 10 6,619 Último mensaje 15 Junio 2008, 21:49 pm
por ni0x
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines