Código:
Iconos Muy Grandes
Iconos Grandes
Iconos Medianos
Iconos Pequeños
Lista
Detalle
Mosaico
Contenido
Si eres de es@s que les gusta llenar el escritorio de iconos esto te vendrá de lujo, porque puedes ponerlo en modo Lista o detalle, permitiendo una forma ordenada y reduciendo notablemente el espacio y tamaño de los iconos. Esto es posible porque el lugar donde se encuentran los iconos del escritorio es en realidad el equivalente a un ListView cuyo nombre de clase es SHELLDLL_DefView.
El 'snippet' que permite esta acción es el siguiente:
Código
''' <summary> ''' Clase NativeMethods ''' </summary> ''' <remarks></remarks> <System.Security.SuppressUnmanagedCodeSecurity()> Friend NotInheritable Class NativeMethods Inherits Attribute Private Sub New() End Sub ''' <summary> ''' Función que devuelve el identificador de una ventana ''' </summary> ''' <param name="lpClassName">Nombre de la clase de la ventana</param> ''' <param name="lpWindowName">El nombre de la ventana (el título de la ventana)</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="FindWindowA", SetLastError:=True)> _ Private Shared Function FindWindow( <MarshalAs(UnmanagedType.LPStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPStr)> ByVal lpWindowName As String) As IntPtr End Function ''' <summary> ''' Recupera un identificador a una ventana cuyo nombre de clase ''' y nombre de la ventana que coincida con las cadenas especificadas. ''' La función busca en ventanas secundarias, comenzando por la raíz de la ''' ventana secundaria especificada. Esta función no realiza una búsqueda ''' entre mayúsculas y minúsculas. ''' </summary> ''' <param name="hWnd1">Un identificador de la ventana padre cuyo hijo son ventanas que se debe buscar</param> ''' <param name="hWnd2">Un identificador de una ventana secundaria</param> ''' <param name="lpsz1">El nombre de la clase o un átomo de clase creada por una llamada previa a la RegisterClass o RegisterClassEx función</param> ''' <param name="lpsz2">El nombre de la ventana (el título de la ventana)</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="FindWindowExA", SetLastError:=True)> _ Private Shared Function FindWindowEx( ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, <MarshalAs(UnmanagedType.LPStr)> ByVal lpsz1 As String, <MarshalAs(UnmanagedType.LPStr)> ByVal lpsz2 As String) As IntPtr End Function ''' <summary> ''' Envía el mensaje especificado a una ventana o ventanas. ''' La función SendMessagellama al procedimiento de ventana de la ventana especificada ''' y no vuelve hasta que el procedimiento de la ventana ha procesado el mensaje. ''' </summary> ''' <param name="hwnd">Un identificador de la ventana</param> ''' <param name="wMsg">El mensaje que se enviará.</param> ''' <param name="wParam">Información adicional-mensaje específico.</param> ''' <param name="lParam">Información adicional-mensaje específico.</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="SendMessageA", SetLastError:=True)> _ Private Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, lParam As Integer) As Boolean End Function Private Const WM_COMMAND = &H111 ''' <summary> ''' Valores wParam para SendMessage que cambia el estilo de visualización ''' del escritorio ''' </summary> ''' <remarks></remarks> Public Enum viewOptIcon As Integer vIconosMuyGrandes = &H704D vIconosGrandes = &H704F vIconosMedianos = &H704E vIconosPequeños = &H7050 vLista = &H7051 vDetalle = &H704B vContenido = &H7052 vMosaico = &H704C vOcultarIconos = &H7073 '(no bloquea el escritorio) vQuitarEtiquetas = &H7037 End Enum ''' <summary> ''' Cambia el estilo de visualización de los iconos del escritorio [by @Okik] ''' </summary> ''' <param name="intValueView">Valor wParam para SendMessage</param> ''' <remarks></remarks> Public Shared Sub ViewModeIconDesktop(ByVal intValueView As viewOptIcon) Dim hProgMan As IntPtr = FindWindow("Progman", "Program Manager") Dim hDefView As IntPtr = FindWindowEx(hProgMan, IntPtr.Zero, "SHELLDLL_DefView", vbNullString) SendMessage(hDefView, WM_COMMAND, intValueView, &H0) End Sub End Class
Para usarlo se realiza de la forma siguiente:
Código
NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vLista)
Aquí dejo un código completo de ejemplo para cambiar todas las vistas:
Código
Imports System.Runtime.InteropServices Public NotInheritable Class Form1 : Inherits Form Friend rdButton(7) As RadioButton Friend chkBox(1) As CheckBox Sub New() ' Llamada necesaria para el diseñador. InitializeComponent() ' Agregue cualquier inicialización después de la llamada a InitializeComponent(). Dim N As Integer = 10 For Index As Integer = 0 To 7 rdButton(Index) = New RadioButton With {.AutoSize = True, .Location = New Point(10, N)} N = N + 20 AddHandler rdButton(Index).Click, AddressOf rdButton_Click Next Index rdButton(0).Text = "Iconos Muy Grandes" rdButton(1).Text = "Iconos Grandes" rdButton(2).Text = "Iconos Medianos" rdButton(3).Text = "Iconos Pequeños" rdButton(4).Text = "Lista" rdButton(5).Text = "Detalle" rdButton(6).Text = "Mosaico" rdButton(7).Text = "Contenido" rdButton(3).Checked = True chkBox(0) = New CheckBox With { .Location = New Point(10, rdButton(7).Top + 30), .AutoSize = True, .Text = "Ocultar/Mostrar Etiquetas (Solo en modo Icono y Detalle)" } chkBox(1) = New CheckBox With { .Location = New Point(10, chkBox(0).Top + 25), .AutoSize = True, .Text = "Ocultar/Mostrar Iconos" } For Index As Integer = 0 To 1 AddHandler chkBox(Index).CheckedChanged, AddressOf chkBox_CheckedChanged Next End Sub Private Sub chkBox_CheckedChanged(sender As Object, e As EventArgs) Dim Index As Integer = Array.IndexOf(chkBox, sender) Select Case Index Case 0 If chkBox(1).Checked = True Then NativeMethods.ViewModeIconDesktop(NativeMethods.viewOptIcon.vQuitarEtiquetas) Else NativeMethods.ViewModeIconDesktop(NativeMethods.viewOptIcon.vQuitarEtiquetas) End If Case 1 If chkBox(0).Checked = True Then NativeMethods.ViewModeIconDesktop(NativeMethods.viewOptIcon.vOcultarIconos) Else NativeMethods.ViewModeIconDesktop(NativeMethods.viewOptIcon.vOcultarIconos) End If End Select 'NOTA: 'Ten en cuenta que esta aplicación no tiene medio para saber, al iniciarse, si el escritorio tiene 'los iconos ocultos o no, o sin etiquetas, para establecer el valor verdadero o falso de 'los objetos CheckBox End Sub Private Sub rdButton_Click(sender As Object, e As EventArgs) Dim Index As Integer = Array.IndexOf(rdButton, sender) Select Case Index Case 0 : NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vIconosMuyGrandes) Case 1 : NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vIconosGrandes) Case 2 : NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vIconosMedianos) Case 3 : NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vIconosPequeños) Case 4 : NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vLista) Case 5 : NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vDetalle) Case 6 : NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vContenido) Case 7 : NativeMethods.ViewModeIconDesktop(intValueView:=NativeMethods.viewOptIcon.vMosaico) End Select End Sub Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load For Index As Integer = 0 To 7 Me.Controls.Add(Me.rdButton(Index)) Next For Index As Integer = 0 To 1 Me.Controls.Add(Me.chkBox(Index)) Next End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) End Sub End Class ''' <summary> ''' Clase NativeMethods ''' </summary> ''' <remarks></remarks> <System.Security.SuppressUnmanagedCodeSecurity()> Friend NotInheritable Class NativeMethods Inherits Attribute Private Sub New() End Sub ''' <summary> ''' Función que devuelve el identificador de una ventana ''' </summary> ''' <param name="lpClassName">Nombre de la clase de la ventana</param> ''' <param name="lpWindowName">El nombre de la ventana (el título de la ventana)</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="FindWindowA", SetLastError:=True)> _ Private Shared Function FindWindow( <MarshalAs(UnmanagedType.LPStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPStr)> ByVal lpWindowName As String) As IntPtr End Function ''' <summary> ''' Recupera un identificador a una ventana cuyo nombre de clase ''' y nombre de la ventana que coincida con las cadenas especificadas. ''' La función busca en ventanas secundarias, comenzando por la raíz de la ''' ventana secundaria especificada. Esta función no realiza una búsqueda ''' entre mayúsculas y minúsculas. ''' </summary> ''' <param name="hWnd1">Un identificador de la ventana padre cuyo hijo son ventanas que se debe buscar</param> ''' <param name="hWnd2">Un identificador de una ventana secundaria</param> ''' <param name="lpsz1">El nombre de la clase o un átomo de clase creada por una llamada previa a la RegisterClass o RegisterClassEx función</param> ''' <param name="lpsz2">El nombre de la ventana (el título de la ventana)</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="FindWindowExA", SetLastError:=True)> _ Private Shared Function FindWindowEx( ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, <MarshalAs(UnmanagedType.LPStr)> ByVal lpsz1 As String, <MarshalAs(UnmanagedType.LPStr)> ByVal lpsz2 As String) As IntPtr End Function ''' <summary> ''' Envía el mensaje especificado a una ventana o ventanas. ''' La función SendMessagellama al procedimiento de ventana de la ventana especificada ''' y no vuelve hasta que el procedimiento de la ventana ha procesado el mensaje. ''' </summary> ''' <param name="hwnd">Un identificador de la ventana</param> ''' <param name="wMsg">El mensaje que se enviará.</param> ''' <param name="wParam">Información adicional-mensaje específico.</param> ''' <param name="lParam">Información adicional-mensaje específico.</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="SendMessageA", SetLastError:=True)> _ Private Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, lParam As Integer) As Boolean End Function Private Const WM_COMMAND = &H111 ''' <summary> ''' Valores wParam para SendMessage que cambia el estilo de visualización ''' del escritorio ''' </summary> ''' <remarks></remarks> Public Enum viewOptIcon As Integer vIconosMuyGrandes = &H704D vIconosGrandes = &H704F vIconosMedianos = &H704E vIconosPequeños = &H7050 vLista = &H7051 vDetalle = &H704B vContenido = &H7052 vMosaico = &H704C vOcultarIconos = &H7073 '(no bloquea el escritorio) vQuitarEtiquetas = &H7037 End Enum ''' <summary> ''' Cambia el estilo de visualización de los iconos del escritorio [by @Okik] ''' </summary> ''' <param name="intValueView">Valor wParam para SendMessage</param> ''' <remarks></remarks> Public Shared Sub ViewModeIconDesktop(ByVal intValueView As viewOptIcon) Dim hProgMan As IntPtr = FindWindow("Progman", "Program Manager") Dim hDefView As IntPtr = FindWindowEx(hProgMan, IntPtr.Zero, "SHELLDLL_DefView", vbNullString) SendMessage(hDefView, WM_COMMAND, intValueView, &H0) End Sub End Class
se me olvidaba, tiene un pero y es que si se deja en modo Lista en un principio la lista se ve en modo vertical, pero al reiniciar o cerrar sesión, la lista se extiende horizontalmente, y claro ya no queda bien. La manera de volver a conseguir la lista vertical es cambiar a modo icono, cerrar sesión y volver a establecer modo lista.
No se si alguien sabrá porque ocurre esto y si hay forma de solventarlo.
chau
Como el estado de modo detalle no se ve alterado al reiniciar o cerrar sesión de windows, se me ha ocurrido ocultar/mostrar la
Código
''' <summary> ''' Oculta la cabecera del modo 'Detalle' del escritorio ''' </summary> ''' <param name="sH32State">Valor ncmdShow para ShowWindow// True=Hide, False=Normal </param> ''' <remarks></remarks> Public Shared Sub HideHeaderListView(ByVal sH32State As Boolean) Dim hProgMan As IntPtr = FindWindow("Progman", "Program Manager") Dim hDefView As IntPtr = FindWindowEx(hProgMan, IntPtr.Zero, "SHELLDLL_DefView", vbNullString) Dim hSysListView32 As IntPtr = FindWindowEx(hDefView, IntPtr.Zero, "SysListView32", vbNullString) Dim hSysHeader32 As IntPtr = FindWindowEx(hSysListView32, IntPtr.Zero, "SysHeader32", vbNullString) ShowWindow(hSysHeader32, Convert.ToInt32(sH32State)) End Sub
para ocultar se llamaría así
Código
HideHeaderListView(True)
hoy he cambiado HideColumnListView por HideHeaderListView para evitar confusión. Ya que en realidad oculta la cabecera no la columna.
chau
6 Octubre 2016, 17:50
WorkerW
Hoy he ejecutado el código en otro ordenador con W764bits, y se me ha planteado un problema y es que este ordenador tiene el objeto Listview de nombre de clase SHELLDLL_DefView en WorkerW, y Progman no tiene ventanas "hijo". Como resultado el snippet no funciona
Resulta que hay más de una ventana con nombre de clase WorkerW. Me he tirado un buen rato intentado encontrar la manera de encontrar el correcto.
En realidad es simple vas rastreando en un bucle todos las ventanas hasta que des con una con hijo que tenga nombre de clase SHELLDLL_DefView.
Código
''' <summary> ''' Obtiene el identificador de WorkerW del escritorio ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Public Shared Function GetHWorkerW() As IntPtr Dim ClassNameChild As New System.Text.StringBuilder(255) Dim hWorkerW As IntPtr Dim hwnd As IntPtr = FindWindow(Nothing, Nothing) Do While Not ClassNameChild.ToString.Equals("SHELLDLL_DefView") hwnd = GetNextWindow(hwnd, GW_Const.GW_HWNDNEXT) hWorkerW = GetWindow(hwnd, GW_Const.GW_CHILD) GetClassName(hWorkerW, ClassNameChild, 260) Loop Return hwnd End Function '//Otra forma de obtener el handle de WorkerW ' ''' <summary> ' ''' Obtiene el identificador de WorkerW del escritorio ' ''' </summary> ' ''' <returns></returns> ' ''' <remarks></remarks> 'Public Shared Function GetHWorkerW() As IntPtr ' Dim ClassNameChild As New System.Text.StringBuilder(255) ' Dim hWorkerW As IntPtr ' Dim hwnd As IntPtr = FindWindow("Progman", Nothing) ' Do While Not ClassNameChild.ToString.Equals("SHELLDLL_DefView") ' hwnd = GetWindow(hwnd, GW_Const.GW_HWNDPREV) ' hWorkerW = GetWindow(hwnd, GW_Const.GW_CHILD) ' GetClassName(hWorkerW, ClassNameChild, 260) ' Loop ' Return hwnd 'End Function
Modificando el código quedaría así .
Código
''' <summary> ''' Clase NativeMethods ''' </summary> ''' <remarks></remarks> <System.Security.SuppressUnmanagedCodeSecurity()> Friend NotInheritable Class NativeMethods Inherits Attribute Private Sub New() End Sub ''' <summary> ''' Función que devuelve el identificador de una ventana ''' </summary> ''' <param name="lpClassName">Nombre de la clase de la ventana</param> ''' <param name="lpWindowName">El nombre de la ventana (el título de la ventana)</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="FindWindowA", SetLastError:=True)> _ Private Shared Function FindWindow( <MarshalAs(UnmanagedType.LPStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPStr)> ByVal lpWindowName As String) As IntPtr End Function ''' <summary> ''' Recupera un identificador a una ventana cuyo nombre de clase ''' y nombre de la ventana que coincida con las cadenas especificadas. ''' La función busca en ventanas secundarias, comenzando por la raíz de la ''' ventana secundaria especificada. Esta función no realiza una búsqueda ''' entre mayúsculas y minúsculas. ''' </summary> ''' <param name="hWnd1">Un identificador de la ventana padre cuyo hijo son ventanas que se debe buscar</param> ''' <param name="hWnd2">Un identificador de una ventana secundaria</param> ''' <param name="lpsz1">El nombre de la clase o un átomo de clase creada por una llamada previa a la RegisterClass o RegisterClassEx función</param> ''' <param name="lpsz2">El nombre de la ventana (el título de la ventana)</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="FindWindowExA", SetLastError:=True)> _ Private Shared Function FindWindowEx( ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, <MarshalAs(UnmanagedType.LPStr)> ByVal lpsz1 As String, <MarshalAs(UnmanagedType.LPStr)> ByVal lpsz2 As String) As IntPtr End Function ''' <summary> ''' Envía el mensaje especificado a una ventana o ventanas. ''' La función SendMessagellama al procedimiento de ventana de la ventana especificada ''' y no vuelve hasta que el procedimiento de la ventana ha procesado el mensaje. ''' </summary> ''' <param name="hwnd">Un identificador de la ventana</param> ''' <param name="wMsg">El mensaje que se enviará.</param> ''' <param name="wParam">Información adicional-mensaje específico.</param> ''' <param name="lParam">Información adicional-mensaje específico.</param> ''' <returns></returns> ''' <remarks></remarks> <DllImport("user32", EntryPoint:="SendMessageA", SetLastError:=True)> _ Private Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, lParam As Integer) As Boolean End Function <DllImport("user32.dll")> _ Shared Function ShowWindow(ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As Boolean End Function Private Const WM_COMMAND = &H111 ''' <summary> ''' Valores wParam para SendMessage que cambia el estilo de visualización ''' del escritorio ''' </summary> ''' <remarks></remarks> Public Enum viewOptIcon As Integer vIconosMuyGrandes = &H704D vIconosGrandes = &H704F vIconosMedianos = &H704E vIconosPequeños = &H7050 vLista = &H7051 vDetalle = &H704B vContenido = &H7052 vMosaico = &H704C vOcultarIconos = &H7073 '(no bloquea el escritorio) vQuitarEtiquetas = &H7037 End Enum Public Const GW_HWNDNEXT = 2 <DllImport("user32", EntryPoint:="GetWindow", SetLastError:=True)> _ Public Shared Function GetNextWindow(ByVal hwnd As IntPtr, ByVal wFlag As Integer) As IntPtr End Function <DllImport("user32", SetLastError:=True)> _ Private Shared Function GetWindow(ByVal hwnd As IntPtr, ByVal wCmd As Integer) As IntPtr End Function <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Private Shared Function GetClassName(ByVal hWnd As System.IntPtr, _ ByVal lpClassName As System.Text.StringBuilder, _ ByVal nMaxCount As Integer) As Integer End Function Public Enum GW_Const GW_CHILD = 5 GW_HWNDFIRST = 0 GW_HWNDLAST = 1 GW_HWNDNEXT = 2 GW_HWNDPREV = 3 GW_MAX = 5 GW_OWNER = 4 End Enum ''' <summary> ''' Cambia el estilo de visualización de los iconos del escritorio [by @Okik] ''' </summary> ''' <param name="intValueView">Valor wParam para SendMessage</param> ''' <remarks></remarks> Public Shared Sub ViewModeIconDesktop(ByVal intValueView As viewOptIcon) Dim hProgMan As IntPtr = FindWindow("Progman", "Program Manager") Dim hDefView As IntPtr = FindWindowEx(hProgMan, IntPtr.Zero, "SHELLDLL_DefView", Nothing) If hDefView = IntPtr.Zero Then Dim hWorkerW As IntPtr = GetHWorkerW() hDefView = FindWindowEx(hWorkerW, IntPtr.Zero, "SHELLDLL_DefView", Nothing) End If SendMessage(hDefView, WM_COMMAND, intValueView, &H0) End Sub ''' <summary> ''' Oculta las cabeceras de modo 'detalle' del escritorio ''' </summary> ''' <param name="sH32State">Valor ncmdShow para ShowWindow// True=Hide, False=Normal </param> ''' <remarks></remarks> Public Shared Sub HideHeaderListView(ByVal sH32State As Boolean) Dim hProgMan As IntPtr = FindWindow("Progman", "Program Manager") Dim hDefView As IntPtr = FindWindowEx(hProgMan, IntPtr.Zero, "SHELLDLL_DefView", Nothing) If hDefView = IntPtr.Zero Then Dim hWorkerW As IntPtr = GetHWorkerW() hDefView = FindWindowEx(hWorkerW, IntPtr.Zero, "SHELLDLL_DefView", Nothing) End If Dim hSysListView32 As IntPtr = FindWindowEx(hDefView, IntPtr.Zero, "SysListView32", Nothing) Dim hSysHeader32 As IntPtr = FindWindowEx(hSysListView32, IntPtr.Zero, "SysHeader32", Nothing) ShowWindow(hSysHeader32, Convert.ToInt32(sH32State)) End Sub ''' <summary> ''' Obtiene el identificador de WorkerW del escritorio ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Public Shared Function GetHWorkerW() As IntPtr Dim ClassNameChild As New System.Text.StringBuilder(255) Dim hWorkerW As IntPtr Dim hwnd As IntPtr = FindWindow(Nothing, Nothing) Do While Not ClassNameChild.ToString.Equals("SHELLDLL_DefView") hwnd = GetNextWindow(hwnd, GW_Const.GW_HWNDNEXT) hWorkerW = GetWindow(hwnd, GW_Const.GW_CHILD) GetClassName(hWorkerW, ClassNameChild, 260) Loop Return hwnd End Function '//Otra forma de obtener el handle de WorkerW ' ''' <summary> ' ''' Obtiene el identificador de WorkerW del escritorio ' ''' </summary> ' ''' <returns></returns> ' ''' <remarks></remarks> 'Public Shared Function GetHWorkerW() As IntPtr ' Dim ClassNameChild As New System.Text.StringBuilder(255) ' Dim hWorkerW As IntPtr ' Dim hwnd As IntPtr = FindWindow("Progman", Nothing) ' Do While Not ClassNameChild.ToString.Equals("SHELLDLL_DefView") ' hwnd = GetWindow(hwnd, GW_Const.GW_HWNDPREV) ' hWorkerW = GetWindow(hwnd, GW_Const.GW_CHILD) ' GetClassName(hWorkerW, ClassNameChild, 260) ' Loop ' Return hwnd 'End Function End Class
En GetHWorkerW podría devolver directamente el handle de 'SHELLDLL_DefView' y ahorrarme alguna línea. Pero lo dejo así.