Como Ocultar o deshabilitar un botón de cierre de VBA UserForm [X]

Índice
  1. Ocultar o no ocultar, esa es la cuestión
  2. Acerca de los códigos API de Windows
  3. 3 opciones para deshabilitar/ocultar un botón de cierre de UserForm
    1. (1) La desactivación no obvia con un cuadro de mensaje
    2. (2) Deshabilite el botón de cerrar (API de Windows)
    3. (3) Ocultar menú del sistema (API de Windows)

Mientras trabajaba en un proyecto recientemente, pensé en ocultar el botón de cierre [X] que se encuentra en la parte superior del formulario de usuario de VBA. Logré identificar tres opciones para lograrlo. Si estás pensando en lo mismo, esta publicación te dará las respuestas que estás buscando.

Descargue el archivo de ejemplo: únase al programa Insiders gratuito y obtenga acceso al archivo de ejemplo utilizado para esta publicación.

Nombre del archivo: 0173 Ocultar o deshabilitar usuario desde el botón Cerrar.zip

Tener acceso

Ocultar o no ocultar, esa es la cuestión

Antes de comenzar a analizar las tres opciones, quiero abordar la pregunta más crítica de todas: ¿ deberíamos ocultar el botón de cierre de un formulario de usuario?

El botón Cerrar

El botón de cerrar es una parte reconocida del entorno de Windows. Prácticamente todas las aplicaciones utilizan una cruz en la esquina superior derecha para cerrar una ventana. Por lo tanto, según su experiencia con otras aplicaciones, todos los usuarios ya saben lo que debe hacer la cruz. No importa en qué país se encuentre el usuario o qué idioma hable, es un icono universalmente entendido para cerrar una ventana. Por lo tanto, debería preguntarse por qué desea ocultar el botón de cierre. Teniendo esto en cuenta, diría que, en general, el botón de cerrar no debe estar oculto ni deshabilitado.

Sin embargo, hay algunas circunstancias en las que es posible que queramos romper esta regla general. Un ejemplo de ello es una barra de progreso. Si el usuario cierra una barra de progreso, es posible que no sepa cuándo terminó de ejecutarse la macro o cuánto tiempo queda. Por lo tanto, podría resultar útil ocultar el botón de cerrar en este escenario.

De forma predeterminada, el botón de cerrar descargará un formulario de usuario, pero se puede adaptar para tener un procedimiento de cierre personalizado . Como podemos controlar esta funcionalidad, puede ser mejor controlarla en lugar de ocultarla o desactivarla.

Acerca de los códigos API de Windows

De las tres soluciones, dos se basan en llamadas a la API de Windows. Aquí es donde el código VBA hace uso de funciones que no forman parte de Excel, sino de la aplicación principal de Windows. Como se trata de algo complicado, no lo analizaré en detalle aquí. Pero los puntos clave a tener en cuenta sobre los códigos API de Windows son:

  • No funcionarán en una Mac, sólo en Windows. Entonces, si diseña para Windows y Mac, deberá identificar qué plataforma se utiliza y adaptar el código en consecuencia.
  • Las secciones de código marcadas como "Incluir este código en la parte superior del módulo" deben incluirse antes de declarar cualquier otro Subs o Función, y deben estar debajo de la declaración Explícita de Opción (si tiene una).

3 opciones para deshabilitar/ocultar un botón de cierre de UserForm

Si todavía tiene la intención de ocultar o deshabilitar el botón de cerrar, siga leyendo para comprender las tres opciones.

(1) La desactivación no obvia con un cuadro de mensaje

Esta primera opción es la peor de las tres. No desactiva ni oculta el botón de cerrar, pero impide que el usuario lo utilice para cerrar la ventana.

Aunque es la peor opción, es la más fácil de usar y entender. El siguiente código se puede utilizar dentro del evento QueryClose del UserForm.

Private Sub UserForm_QueryClose(Cancelar como entero, CloseMode como entero)If CloseMode = vbFormControlMenu Then Cancel = True MsgBox "Utilice el botón Cerrar para cerrar el formulario", vbOKOnlyEnd IfEnd Sub

Si el usuario hace clic en el botón cerrar, aparecerá el siguiente cuadro de mensaje.

Cuadro de mensajes VBA

Esto efectivamente deshabilita el botón de cerrar, ya que el formulario de usuario no se cerrará. Pero desde la perspectiva del usuario, esta solución es simplemente frustrante. ¿Por qué habría un botón que no hace nada más que decirnos que no hace nada? Por eso no es una gran opción.

(2) Deshabilite el botón de cerrar (API de Windows)

La segunda opción desactivará el botón de cerrar; Será visible, pero estará atenuado y no se podrá hacer clic en él.

La primera imagen a continuación muestra el botón de cerrar cuando está habilitado; la segunda imagen muestra el botón de cerrar cuando está deshabilitado.

Botones de cierre habilitados y deshabilitados

Desde la perspectiva del usuario, esta opción es mejor que la primera, pero aún así no es excelente. ¿Cuál es el punto de un botón en el que no se puede hacer clic? ¿Simplemente crea confusión?

código básico

El siguiente código debe copiarse en un nuevo módulo estándar y debe incluirse antes de cualquier otro código, pero después de la declaración Option Explicit (si existe).

'Incluya este código en la parte superior del móduloPrivate Const GWL_STYLE = -16Private Const WS_CAPTION = HC00000Private Const WS_SYSMENU = H80000Private Const SC_CLOSE = HF060#If VBA7 Then Private Declare la función PtrSafe FindWindowA _ Lib "user32" (ByVal lpClassName As String, _ ByVal lpWindow Nombre Como cadena) Mientras sea privado Declare la función PtrSafe DeleteMenu _ Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, _ ByVal wFlags Mientras) Mientras sea privado Declare la función PtrSafe As Long, ByVal bRevert As Long) As Long #Else Función de declaración privada FindWindowA _ Lib "user32" (ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Función de declaración privada DeleteMenu _ Lib "user32" (ByVal hMenu As Long, _ ByVal nPosition Mientras, ByVal wFlags Mientras) Mientras la función de declaración pública GetSystemMenu _ Lib "user32" (ByVal hWnd Mientras, ByVal bRevert Mientras) Mientras tanto #End If
'Incluya este código en el mismo módulo que las llamadas API anterioresPublic Sub CloseButtonSettings(frm As Object, show As Boolean)Dim windowHandle As LongDim menuHandle As LongwindowHandle = FindWindowA(vbNullString, frm.Caption)If show = True Then menuHandle = GetSystemMenu(windowHandle , 1)Else menuHandle = GetSystemMenu(windowHandle, 0) DeleteMenu menuHandle, SC_CLOSE, 0End IfEnd Sub

Los ejemplos de código anteriores crean una funcionalidad reutilizable para habilitar o deshabilitar el botón de cierre. El subprocedimiento CloseButtonSettings ahora se puede llamar desde cualquier otro módulo. Se requieren dos argumentos:

  • frm: una referencia al formulario de usuario para el cual se debe habilitar/deshabilitar el botón de cierre
  • mostrar: un valor Verdadero o Falso donde Verdadero = habilitar el botón de cerrar y Falso = deshabilitar el botón de cerrar

Deshabilite el botón de cerrar en la inicialización de UserForm

Si se inserta en el evento de inicialización del formulario de usuario, deshabilitará el botón cuando se cree el formulario.

Subusuario privadoForm_Initialize()Llamar a CloseButtonSettings(Yo, Falso)Fin Sub

Deshabilite o habilite el botón de cerrar en cualquier momento

El botón de cierre se puede habilitar o deshabilitar cuando sea necesario con las siguientes macros:

Deshabilitar el botón de cerrar

Sub DisableClose()Llamar a CloseButtonSettings(frmMyUserForm, False)End Sub

Habilitar el botón de cerrar

Sub EnableClose()Llamar a CloseButtonSettings(frmMyUserForm, True)End Sub

(3) Ocultar menú del sistema (API de Windows)

La tercera opción es ocultar la sección del menú del sistema de la ventana. La sección del menú Sistema incluye los botones maximizar, minimizar y cerrar. La siguiente captura de pantalla muestra que el botón de cerrar no está visible.

API Sin botón de cierre

Al ocultar la sección del menú del sistema, también eliminamos la posibilidad de ver los botones minimizar y maximizar. De forma predeterminada, un formulario de usuario no tiene estos botones visibles (se requieren llamadas a la API de Windows por separado para habilitar esto), por lo tanto, esta es probablemente una buena opción en el 99,9% de las circunstancias.

Código básico

El siguiente código debe copiarse en un nuevo módulo estándar y debe incluirse antes de cualquier otro código, pero después de la declaración Option Explicit (si existe).

'Incluya este código en la parte superior del móduloPrivate Const GWL_STYLE = -16Private Const WS_CAPTION = HC00000Private Const WS_SYSMENU = H80000#If VBA7 Then Private Declare la función PtrSafe GetWindowLong _ Lib "user32" Alias ​​"GetWindowLongA" (ByVal hWnd As Long, _ ByVal nIndex As Long) As Long Private Declare la función PtrSafe SetWindowLong _ Lib "user32" Alias ​​"SetWindowLongA" (ByVal hWnd As Long, _ ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Private Declare la función PtrSafe FindWindowA _ Lib "user32" (ByVal lpClassName como cadena, _ ByVal lpWindowName como cadena) Mientras función de declaración privada PtrSafe DrawMenuBar _ Lib "user32" (ByVal hWnd As Long) Mientras #Else Función de declaración privada GetWindowLong _ Lib "user32" Alias ​​"GetWindowLongA" ( _ ByVal hWnd As Long, ByVal nIndex As Long) As Long Función de declaración privada SetWindowLong _ Lib "user32" Alias ​​"SetWindowLongA" ( _ ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Función de declaración privada FindWindowA _ Lib "user32" (ByVal lpClassName como cadena, _ ByVal lpWindowName como cadena) Mientras función de declaración privada DrawMenuBar _ Lib "user32" (ByVal hWnd Mientras) Mientras #End If
'Incluya este código en el mismo módulo que las llamadas API anterioresPublic Sub SystemButtonSettings(frm As Object, show As Boolean)Dim windowStyle As LongDim windowHandle As LongwindowHandle = FindWindowA(vbNullString, frm.Caption)windowStyle = GetWindowLong(windowHandle, GWL_STYLE)If show = Falso Entonces SetWindowLong windowHandle, GWL_STYLE, (windowStyle y no WS_SYSMENU)De lo contrario SetWindowLong windowHandle, GWL_STYLE, (windowStyle + WS_SYSMENU)End IfDrawMenuBar(windowHandle)End Sub

Estos códigos crean una funcionalidad reutilizable para mostrar u ocultar los botones. El subprocedimiento SystemButtonSettings se puede llamar desde cualquier otro módulo. Se requieren dos argumentos.

  • frm: una referencia al formulario de usuario para el cual se debe mostrar/ocultar el botón de cierre
  • mostrar: un valor Verdadero o Falso donde Verdadero = mostrar el menú del sistema y Falso = ocultar el menú del sistema

Ocultar los botones del menú del sistema en la inicialización de UserForm

Si se inserta en el evento de inicialización del formulario de usuario, deshabilitará el botón cuando se cree el formulario.

Subusuario privadoForm_Initialize()Llamar a SystemButtonSettings(Yo, Falso)Fin Sub

Mostrar u ocultar el botón de cerrar en cualquier momento

El botón de cerrar se puede mostrar u ocultar cuando sea necesario utilizando las siguientes macros.

Ocultar el botón de cerrar

Sub HideClose()Llamar a SystemButtonSettings(frmMyUserForm, False)End Sub

Mostrar el botón de cerrar

Sub ShowClose()Llamar a SystemButtonSettings(frmMyUserForm, True)End Sub

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Este sitio web utiliza cookies para mejorar la experiencia del usuario y garantizar un funcionamiento eficiente. Al utilizar nuestro sitio web, aceptas todas las cookies de acuerdo con nuestra política de cookies. Leer mas...