Autor
|
Tema: Cambio el cursor y se ve en blanco y negro (Leído 2,963 veces)
|
Lekim
Desconectado
Mensajes: 268
|
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: Dim curPen As New System.IO.MemoryStream(My.Resources.Resource1.Lapiz) 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
Mensajes: 9.809
|
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:' *********************************************************************** ' Author : Elektro ' Modified : 07-September-2015 ' *********************************************************************** ' <copyright file="CursorUtil.vb" company="Elektro Studios"> ' Copyright (c) Elektro Studios. All rights reserved. ' </copyright> ' *********************************************************************** #Region " Imports " Imports System Imports System.ComponentModel Imports System.IO Imports System.Runtime.InteropServices Imports System.Windows.Forms #End Region ''' ---------------------------------------------------------------------------------------------------- ''' <summary> ''' Contains related cursor utilities. ''' </summary> ''' ---------------------------------------------------------------------------------------------------- Public NotInheritable Class CursorUtil #Region " P/Invoking " ''' ---------------------------------------------------------------------------------------------------- ''' <summary> ''' Platform Invocation methods (P/Invoke), access unmanaged code. ''' This class does not suppress stack walks for unmanaged code permission. ''' <see cref="System.Security.SuppressUnmanagedCodeSecurityAttribute"/> must not be applied to this class. ''' This class is for methods that can be used anywhere because a stack walk will be performed. ''' </summary> ''' ---------------------------------------------------------------------------------------------------- ''' <remarks>http://msdn.microsoft.com/en-us/library/ms182161.aspx</remarks> ''' ---------------------------------------------------------------------------------------------------- Private NotInheritable Class NativeMethods #Region " Functions " ''' ---------------------------------------------------------------------------------------------------- ''' <summary> ''' Creates a cursor based on data contained in a file. ''' </summary> ''' ---------------------------------------------------------------------------------------------------- ''' <param name="filepath"> ''' The source of the file data to be used to create the cursor. ''' The data in the file must be in either .CUR or .ANI format. ''' </param> ''' ---------------------------------------------------------------------------------------------------- ''' <returns> ''' If the function is successful, the return value is an <see cref="IntPtr"/> to the new cursor. ''' If the function fails, the return value is <see cref="IntPtr.Zero"/>. ''' To get extended error information, call <see cref="Marshal.GetLastWin32Error"/>. ''' </returns> ''' ---------------------------------------------------------------------------------------------------- ''' <remarks> ''' <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms648392%28v=vs.85%29.aspx"/> ''' </remarks> ''' ---------------------------------------------------------------------------------------------------- <DllImport("User32.dll", CharSet:=CharSet.Ansi, BestFitMapping:=False, ThrowOnUnmappableChar:=True, SetLastError:=True)> Public Shared Function LoadCursorFromFile( ByVal filepath As String ) As IntPtr End Function #End Region End Class #End Region #Region " Constructors " ''' <summary> ''' Prevents a default instance of the <see cref="CursorUtil"/> class from being created. ''' </summary> Private Sub New() End Sub #End Region #Region " Public Methods " ''' ---------------------------------------------------------------------------------------------------- ''' <summary> ''' Creates a cursor based on data contained in a managed .Net resource. ''' </summary> ''' ---------------------------------------------------------------------------------------------------- ''' <param name="resource"> ''' The resource. ''' </param> ''' ---------------------------------------------------------------------------------------------------- ''' <returns> ''' <see cref="System.Windows.Forms.Cursor"/>. ''' </returns> ''' ---------------------------------------------------------------------------------------------------- <DebuggerStepThrough> <DebuggerHidden> Public Shared Function LoadCursorFromResource(ByVal resource As Byte(), Optional cleanTempFile As Boolean = True) As Cursor Dim tmpFilepath As String = String.Format("{0}.ani", Path.GetTempFileName) Try Using fs As New FileStream(tmpfilepath, FileMode.Create, FileAccess.Write, FileShare.Read) fs.Write(resource, 0, resource.Length) End Using Dim result As IntPtr = NativeMethods.LoadCursorFromFile(tmpFilepath) Dim win32Err As Integer = Marshal.GetLastWin32Error If result = IntPtr.Zero Then Throw New Win32Exception([error]:=win32Err) Else Return New Cursor(result) End If Catch ex As Exception Throw Finally If (cleanTempFile ) AndAlso (File. Exists(tmpFilepath )) Then End If End Try End Function #End Region End Class
Modo de empleo:Public NotInheritable Class Form1 : Inherits Form Private Sub Label1_MouseEnter(ByVal sender As Object, ByVal e As EventArgs) _ Handles Label1.MouseEnter Static cur As Cursor If cur Is Nothing Then cur = CursorUtil.LoadCursorFromResource(My.Resources.MyCursor) End If ' Asegurarse de liberar el objeto cuando sea necesario... DirectCast(sender, Label).Cursor = cur End Sub Private Sub Label1_MouseLeave(ByVal sender As Object, ByVal e As EventArgs) _ Handles Label1.MouseLeave DirectCast(sender, Label).Cursor = Cursors.Default End Sub End Class
Recursos usados para las pruebas:➢ Metro X Cursor Set - DeviantArtSaludos
|
|
« Última modificación: 8 Septiembre 2015, 05:14 am por Eleкtro »
|
En línea
|
|
|
|
Lekim
Desconectado
Mensajes: 268
|
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: 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. Imports System Imports System.ComponentModel Imports System.IO Imports System.Runtime.InteropServices Imports System.Windows.Forms Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load End Sub Private Sub Label1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseMove Static cur As Cursor If cur Is Nothing Then cur = CursorUtil.LoadCursorFromResource(My.Resources.Resource1.Cursor1) End If ' Asegurarse de liberar el objeto cuando sea necesario... DirectCast(sender, Label).Cursor = cur End Sub End Class Public NotInheritable Class CursorUtil <DllImport("User32.dll", CharSet:=CharSet.Ansi, BestFitMapping:=False, ThrowOnUnmappableChar:=True, SetLastError:=True)> Public Shared Function LoadCursorFromFile(ByVal filepath As String) As IntPtr End Function Public Shared Function LoadCursorFromResource(ByVal resource As Byte(), Optional ByVal cleanTempFile As Boolean = True) As Cursor Dim tmpFilepath As String = String.Format("{0}.cur", Path.GetTempFileName) Try Using fs As New FileStream(tmpFilepath, FileMode.Create, FileAccess.Write, FileShare.Read) fs.Write(resource, 0, resource.Length) End Using Dim result As IntPtr = LoadCursorFromFile(tmpFilepath) Dim win32Err As Integer = Marshal.GetLastWin32Error If result = IntPtr.Zero Then Throw New Win32Exception([error]:=win32Err) Else Return New Cursor(result) End If Catch ex As Exception Throw Finally If (cleanTempFile ) AndAlso (File. Exists(tmpFilepath )) Then End If End Try End Function 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
Mensajes: 9.809
|
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: 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.vbClass CursorUtil ... End lass Class Form1 ... 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
Mensajes: 268
|
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 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
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Efecto blanco y negro
Diseño Gráfico
|
Vassago
|
6
|
3,330
|
15 Marzo 2004, 20:09 pm
por Vassago
|
|
|
juego en blanco y negro??
Juegos y Consolas
|
Galagar
|
2
|
1,827
|
31 Agosto 2004, 23:36 pm
por Galagar
|
|
|
BLANCO Y NEGRO
Multimedia
|
circus2003
|
3
|
2,375
|
13 Junio 2005, 21:05 pm
por Songoku
|
|
|
Se me ve blanco y negro
Software
|
//rastaman//
|
0
|
1,663
|
24 Septiembre 2005, 03:41 am
por //rastaman//
|
|
|
Televisor en blanco y negro.
« 1 2 »
Multimedia
|
Hacker wifi
|
10
|
6,619
|
15 Junio 2008, 21:49 pm
por ni0x
|
|