'DESACTIVAR EL BOTÓN CERRAR Y LA FUNCIÓN DE CIERRE CON ALT+F4
'NOTA de Miliuco:
'en esta aplicación se usa el tipo de dato IntPtr. Se ha diseñado
'el tipo IntPtr para que sea un número entero cuyo tamaño sea específico
'de la plataforma. Es decir, se espera que una instancia de este tipo tenga
'lugar en sistemas operativos y hardware de 32 bits, y en sistemas
'operativos y hardware de 64 bits. El tipo IntPtr se puede utilizar por idiomas
'que admiten punteros, y como un medio común para hacer referencia a los
'datos entre idiomas que admiten o no punteros. El tipo IntPtr es compatible
'con CLS (Common Language Specification) -> conjunto de características
'básicas de lenguaje englobadas en .NET Framework. El tipo IntPtr pertenece
'al espacio de nombres System
'Importar espacios de nombres necesarios para la aplicación
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
'Para leer procedimientos externos radicados en librerías de windows
'Imports System.Runtime.InteropServices
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Código generado por el Diseñador de Windows Forms "
Public Sub New()
MyBase.New()
'El Diseñador de Windows Forms requiere esta llamada.
InitializeComponent()
'Agregar cualquier inicialización después de la llamada a InitializeComponent()
End Sub
'Form reemplaza a Dispose para limpiar la lista de componentes.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Requerido por el Diseñador de Windows Forms
Private components As System.ComponentModel.IContainer
'NOTA: el Diseñador de Windows Forms requiere el siguiente procedimiento
'Puede modificarse utilizando el Diseñador de Windows Forms.
'No lo modifique con el editor de código.
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents Button2 As System.Windows.Forms.Button
Friend WithEvents GroupBox1 As System.Windows.Forms.GroupBox
Friend WithEvents Timer1 As System.Windows.Forms.Timer
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container
Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(Form1))
Me.Button1 = New System.Windows.Forms.Button
Me.Button2 = New System.Windows.Forms.Button
Me.GroupBox1 = New System.Windows.Forms.GroupBox
Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
Me.SuspendLayout()
'
'Button1
'
Me.Button1.FlatStyle = System.Windows.Forms.FlatStyle.System
Me.Button1.Font = New System.Drawing.Font("Verdana", 18.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.Button1.Location = New System.Drawing.Point(24, 32)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(208, 72)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Desactivar X"
'
'Button2
'
Me.Button2.FlatStyle = System.Windows.Forms.FlatStyle.System
Me.Button2.Font = New System.Drawing.Font("Verdana", 18.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.Button2.Location = New System.Drawing.Point(240, 32)
Me.Button2.Name = "Button2"
Me.Button2.Size = New System.Drawing.Size(112, 72)
Me.Button2.TabIndex = 1
Me.Button2.Text = "Salir"
'
'GroupBox1
'
Me.GroupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System
Me.GroupBox1.Location = New System.Drawing.Point(8, 8)
Me.GroupBox1.Name = "GroupBox1"
Me.GroupBox1.Size = New System.Drawing.Size(360, 112)
Me.GroupBox1.TabIndex = 2
Me.GroupBox1.TabStop = False
Me.GroupBox1.Text = "Botones de comando"
'
'Timer1
'
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(376, 130)
Me.Controls.Add(Me.Button2)
Me.Controls.Add(Me.Button1)
Me.Controls.Add(Me.GroupBox1)
Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
Me.MaximizeBox = False
Me.Name = "Form1"
Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
Me.Text = " Botón cerrar ->"
Me.ResumeLayout(False)
End Sub
#End Region
'Declaración de constantes necesarias (valores en hexadecimal)
Private Const MF_BYPOSITION As Integer = &H400
Private Const MF_REMOVE As Integer = &H1000
Private Const MF_DISABLED As Integer = &H2
''Otras constantes que se pueden encontrar en las declaraciones del API
'Private Const SC_SIZE As Integer = &HF000
'Private Const SC_MOVE As Integer = &HF010
'Private Const SC_MINIMIZE As Integer = &HF020
'Private Const SC_MAXIMIZE As Integer = &HF030
'Private Const SC_CLOSE As Integer = &HF060
'Private Const SC_RESTORE As Integer = &HF120
'Private Const MF_SEPARATOR As Integer = &H800
'Private Const MF_BYCOMMAND As Integer = &H0
'Variable para saber si ya está desactivado el botón X
Private pulsado As Boolean = True
'Importación de procedimientos externos almacenados
'en la librería de Windows USER32.DLL
'Obtener el menú de sistema
Private Declare Function GetSystemMenu Lib "User32" _
(ByVal hWnd As Integer, _
ByVal bRevert As Boolean) As IntPtr
'Obtener el número de elementos del menú de sistema
Private Declare Function GetMenuItemCount Lib "User32" _
(ByVal hMenu As Integer) As IntPtr
'Quitar elementos del menú de sistema
Private Declare Function RemoveMenu Lib "User32" _
(ByVal hMenu As Integer, _
ByVal nPosition As Integer, _
ByVal wFlags As Long) As IntPtr
'Redibujar la barra de título de la ventana
Private Declare Function DrawMenuBar Lib "User32" _
(ByVal hWnd As Integer) As IntPtr
'Método que desactiva el botón X (cerrar)
Private Sub DisableCloseButton(ByVal hWnd As IntPtr)
Try 'captura de excepciones
Dim menuItemCount As IntPtr
Dim hMenu As IntPtr
'Obtener el manejador del menú de sistema del formulario
hMenu = GetSystemMenu(hWnd.ToInt32(), False)
'Obtener la cuenta de los ítems del menú de sistema.
'Es el menú que aparece al pulsar sobre el icono a la izquierda
'de la Barra de título de la ventana, consta de los ítems: Restaurar, Mover,
'Tamaño,Minimizar, Maximizar, Separador, Cerrar.
menuItemCount = GetMenuItemCount(hMenu.ToInt32())
'Quitar el ítem Close (Cerrar), que es el último de ese menú
RemoveMenu(hMenu.ToInt32(), menuItemCount.ToInt32() - 1, MF_DISABLED Or MF_BYPOSITION)
'Quitar el ítem Separador, el penúltimo de ese menú, entre Maximizar y Cerrar
RemoveMenu(hMenu.ToInt32(), menuItemCount.ToInt32() - 2, MF_DISABLED Or MF_BYPOSITION)
'Redibujar la barra de menú
DrawMenuBar(hWnd.ToInt32())
'mostrar un mensaje con la excepción producida
Catch pollo As Exception
MessageBox.Show("Se ha producido la excepción: " + vbCrLf + pollo.Message, _
"Error del programa", MessageBoxButtons.OK)
End Try
End Sub
'Al pulsar el botón Desactivar
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Si no hemos desactivado el botón Cerrar
If (pulsado) Then
'Método desarrollado más arriba, pasando como parámetro
'el identificador de la ventana sobre la que vamos a actuar
DisableCloseButton(Me.Handle)
'Aviso al usuario, no funciona el botón cerrar ni las teclas ALT+F4
MessageBox.Show("El botón Cerrar ha sido desactivado." + vbCrLf + _
"Pulsa Salir para cerrar la aplicación", "Cerrar desactivado 1")
'para saber que ya hemos desactivado el botón
pulsado = False
Else
'Si ya hemos desactivado el botón Cerrar
MessageBox.Show("Ya habías pulsado aquí antes.", "Cerrar desactivado 2")
End If
End Sub
'Al pulsar el botón Salir
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Salir de la aplicación
Me.Close()
End Sub
Private bCerrar As Boolean = False
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Opacity -= 0.05
If Me.Opacity = 0.0 Then
'bCerrar = True
Application.Exit()
End If
End Sub
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
If bCerrar = False Then
e.Cancel() = True
Me.Timer1.Enabled = True
End If
End Sub
End Class