Cerrar Aplicaciones

Ejemplo para cerrar aplicaciones y otras utilidades, por ejemplo obtener el ClassName de una ventana...

 

Publicado el 2/Ene/1999
Revisado el 12/Ago/2005


Este ejemplo usa la clase cWindows para cerrar ventanas, obtener el ClassName de una ventana, etc.

Estos son los m�todos de esa clase:

M�todo Utilidad
ClassName Devuelve el ClassName del nombre de la ventana indicada
CloseApp Cierra la ventana indicada en el par�metro, opcionalmente se puede especificar el ClassName.
EnumTopWindows Enumera las ventanas que tienen t�tulo y son visibles, devuelve una colecci�n (Variant) con el t�tulo y hWnd de cada ventana, opcionalmente a�ade esta informaci�n a un ListBox (o ComboBox) indicado en el segundo par�metro.
MinimizeAll Minimiza todas las ventanas, si se indica el ClassName, s�lo minimiza las ventanas que tengan ese ClassName.

 

El primer ejemplo que vamos a ver simplemente cierra todas las carpetas abiertas, para ello se usa CloseApp con el ClassName "CabinetWClass", que es como se llaman este tipo de "ventanas", hay que hacer notar que el navegador Internet Explorer, al menos el que viene con Windows 98, tiene tambi�n ese ClassName, por tanto tambi�n se cerrar�, si es que est� abierto.

Veamos el c�digo:
Para crear este ejecutable, a�ade la clase cWindows y un m�dulo BAS, en las propiedades del proyecto selecciona Sub Main como el objeto de entrada al programa, e inserta el siguiente c�digo en el m�dulo BAS:

'
Public Sub Main()
    Dim m_UtilVentanas As cWindows
    Dim col As Collection
    Dim numItems As Long
    Dim i As Long
    Dim sTitulo As String
    
    Set m_UtilVentanas = New cWindows
    Set col = New Collection
    
    Set col = m_UtilVentanas.EnumTopWindows
    numItems = col.Count
    For i = 1 To numItems Step 2
        sTitulo = col.Item(i)
        Call m_UtilVentanas.CloseApp(sTitulo, "CabinetWClass")
    Next
    
    Set col = Nothing
    Set m_UtilVentanas = Nothing
    End
End Sub

Como puedes ver, no tiene mayor misterio, ya que casi todo el trabajo lo hace la clase.
A�n as�, te explicar� un poco el c�digo:
La funci�n EnumTopWindows de la clase cWindows, devuelve una colecci�n con el t�tulo de cada ventana adem�s del hWnd, aunque esto �ltimo no lo usamos en este caso.
Como lo que guarda EnumTopWindows son dos datos: el nombre de la ventana y el handle, los items de la colecci�n hay que recorrerlos de dos en dos, pero como lo que nos interesa es s�lo el t�tulo de la ventana, tomamos ese valor y se lo pasamos a CloseApp, con el ClassName de las ventanas del Explorer, para que s�lo cierre ese tipo de ventanas.

Veamos ahora una utilidad que nos mostrar� las ventanas abiertas y nos dar� cierta informaci�n de cada una de esas ventanas, cosa que se hace al seleccionar una de las ventanas de la lista, la informaci�n que nos da es:
El t�tulo de la ventana (normalmente es el Caption),
el handle de esa ventana,
el ClassName de la ventana.

Adem�s del ListBox con los nombres de las ventanas, hay una serie de botones para cerrar las ventanas seleccionadas del ListBox, Refrescar la informaci�n de las ventanas abiertas (cosa que se podr�a solucionar con un Timer, pero...), Minimizar las ventanas del IExplorer (incluidas las carpetas) y otro para Cerrar esas carpetas.

Este es el aspecto del Formulario, (el item seleccionado es el nombre de un directorio o carpeta):

Cuando lo pruebes, te dar�s cuenta de que el VB usa nombres de clase diferentes para los ejecutables que para el tiempo de dise�o, adem�s, cuando es un form del programa tiene este "ClassName": ThunderForm y para la aplicaci�n ThunderMain, esto en tiempo de dise�o, en un ejecutable se cambian a estos nombres: ThunderRT5Form y ThunderRT5Main (para el VB5)
Para el VB6, los nombres de los formularios cambian a ThunderFormDC y ThunderFormRT6DC, para el programa en s� ser� igual en tiempo de dise�o y ThunderRT6Main en tiempo de ejecuci�n.

Para cerrar una ventana de VB, hay que cerrar la que indica Main en el Class Name, ya que el Formulario no se cierra...

 

Ahora es tiempo de seguir viendo c�digo,

Como ya te coment� antes, casi todo el trabajo lo hace la clase, por tanto en el formulario poco se hace, pero vamos a verlo:

'
'----------------------------------------------------------------------------------
'Varias pruebas con ventanas                                            (01/Ene/99)
'Para enumerar las ventanas visibles y poder cerrarlas.
'
'�Guillermo 'guille' Som, 1999
'----------------------------------------------------------------------------------
Option Explicit

Dim m_UtilVentanas As cWindows

Private Sub cmdCerrarCarpetas_Click()
    'Cierra las carpetas abiertas, el ClassName es: CabinetWClass
    'Nota: el IE4 tambi�n tiene ese ClassName
    Dim sTitulo As String
    Dim i As Long
    
    With List1
        For i = 0 To .ListCount - 1
            sTitulo = .List(i)
            Call m_UtilVentanas.CloseApp(sTitulo, "CabinetWClass")
            DoEvents
        Next
    End With
    
    'No se refresca bien, as� que seguramente tendr�s que pulsar en el bot�n...
    cmdRefrescar_Click
    
End Sub

Private Sub cmdCerrarVentanas_Click()
    'Cerrar las ventanas seleccionadas del ListBox
    '
    Dim sTitulo As String
    Dim i As Long
    
    With List1
        For i = 0 To .ListCount - 1
            If .Selected(i) Then
                sTitulo = .List(i)
                'No cerrar esta aplicaci�n
                If (sTitulo <> App.Title) And (sTitulo <> Caption) Then
                    Call m_UtilVentanas.CloseApp(sTitulo)
                    DoEvents
                End If
            End If
        Next
    End With
    
    'No se refresca bien, as� que seguramente tendr�s que pulsar en el bot�n...
    cmdRefrescar_Click
End Sub

Private Sub cmdMinimizeAll_Click()
    '�Cuidado!
    'Si no se especifica el ClassName se minimizan todas las ventanas,
    'si tienes alguna aplicaci�n de VB, se minimiza una ventana que no es el form
    'y despu�s no se puede restaurar...
    '
    'por eso en este ejemplo uso "CabinetWClass" para minimizar las carpetas
    '
    Call m_UtilVentanas.MinimizeAll("CabinetWClass")
End Sub

Private Sub cmdRefrescar_Click()
    
    Call m_UtilVentanas.EnumTopWindows(List1)
    With List1
        Label1(1) = .ListCount
        If .ListCount Then
            .ListIndex = 0
        End If
    End With
End Sub

Private Sub cmdSalir_Click()
    Unload Me
    End
End Sub

Private Sub Form_Load()
    Set m_UtilVentanas = New cWindows
    
    
    If App.PrevInstance Then
        Caption = Caption & " (otra m�s)"
        App.Title = App.Title & " (otra m�s)"
    End If
    
    Show
        
    cmdRefrescar_Click
    
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Set m_UtilVentanas = Nothing
    Set Form1 = Nothing
End Sub

Private Sub List1_Click()
    Dim i As Long
    
    With List1
        i = .ListIndex
        If i > -1 Then
            Label2(0) = .List(i)
            Label2(1) = .ItemData(i)
            Label2(2) = m_UtilVentanas.ClassName(Label2(0))
        Else
            Label2(0) = ""
            Label2(1) = ""
            Label2(2) = ""
        End If
    End With
End Sub

Por �ltimo, el c�digo de la clase cWindows:

Si te preguntas por qu� no he usado EnumWindows para enumerar las ventanas, te dir� que es porque no es necesario, ya que con GetWindow se hace lo mismo y adem�s no es necesario crear un m�dulo BAS para la funci�n "CallBack", si quieres ver un ejemplo de c�mo usar EnumWindows, puedes ver la colaboraci�n de Nacho Cassou que est� en la secci�n de Colaboraciones y en VBAvanzado: Enumerando ventanas (Subclasificaci�n)

'
'----------------------------------------------------------------------------------
'Clase para manipular ventanas de Windows                               (01/Ene/99)
'
'Esta clase enumera las ventas visibles, cierra la indicada, etc.
'
'�Guillermo 'guille' Som, 1999
'----------------------------------------------------------------------------------
Option Explicit

Private Declare Function IsWindowVisible Lib "user32" _
    (ByVal hWnd As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" _
    (ByVal hWnd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
    (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Declare Function GetDesktopWindow Lib "user32" () As Long

' GetWindow() Constants
Private Const GW_HWNDFIRST = 0&
Private Const GW_HWNDNEXT = 2&
Private Const GW_CHILD = 5&

Private Declare Function GetWindow Lib "user32" _
    (ByVal hWnd As Long, ByVal wFlag As Long) As Long

'
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Const SC_MINIMIZE = &HF020&
Private Const SC_CLOSE = &HF060&
Private Const WM_SYSCOMMAND = &H112
Private Const WM_CLOSE = &H10

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
    (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long


Public Sub CloseApp(ByVal Titulo As String, Optional ClassName As String)
    'Cerrar la ventana indicada, mediante el men� del sistema (o de windows)
    'Esto funcionar� si la aplicaci�n tiene men� de sistema
    '(aunque lo he probado con una utilidad sin controlBox y la cierra bien)
    '
    'Si se especifica ClassName, se cerrar�n la ventana si es de ese ClassName
    '
    Dim hWnd As Long
    
    'No cerrar la ventana "Progman"
    If Titulo <> "Progman" Then
        hWnd = FindWindow(ClassName, Titulo)
        
        Call SendMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)
    End If
End Sub

Private Function WindowTitle(ByVal hWnd As Long) As String
    'Devuelve el t�tulo de una ventana, seg�n el hWnd indicado
    '
    Dim sTitulo As String
    Dim lenTitulo As Long
    Dim ret As Long
    
    'Leer la longitud del t�tulo de la ventana
    lenTitulo = GetWindowTextLength(hWnd)
    If lenTitulo > 0 Then
        lenTitulo = lenTitulo + 1
        sTitulo = String$(lenTitulo, 0)
        'Leer el t�tulo de la ventana
        ret = GetWindowText(hWnd, sTitulo, lenTitulo)
        WindowTitle = Left$(sTitulo, ret)
    End If
End Function

Public Function EnumTopWindows(Optional unListBox As Control) As Variant
    'Enumera las ventanas que tienen t�tulo y son visibles
    'Devuelve un array del tipo Variant con los nombres de las ventanas
    'y su hWnd
    'Por tanto la forma de acceder a este array ser�a:
    '   Set col = EnumTopWindows
    '   numItems = col.Count
    '   For i = 1 To numItems Step 2
    '       With List2
    '           .AddItem col.Item(i)
    '           .ItemData(.NewIndex) = col.Item(i + 1)
    '       End With
    '   Next
    '
    'Opcionalemente se puede especificar como par�metro un ListBox o ComboBox
    'y los datos se a�adir�n a ese control
    '
    Dim sTitulo As String
    Dim hWnd As Long
    Dim col As Collection
    
    Set col = New Collection
    
    If Not unListBox Is Nothing Then
        unListBox.Clear
    End If
    
    'Primera ventana
    hWnd = GetWindow(GetDesktopWindow(), GW_CHILD)
    
    'Recorrer el resto de las ventanas
    Do While hWnd <> 0&
        'Si la ventana es visible
        If IsWindowVisible(hWnd) Then
            'Leer el caption de la ventana
            sTitulo = WindowTitle(hWnd)
            If Len(sTitulo) Then
                'A�adimos el t�tulo
                col.Add sTitulo
                'y el hWnd por si fuese �til
                col.Add hWnd
                'Si se especifica el ListBox
                If Not unListBox Is Nothing Then
                    With unListBox
                        .AddItem sTitulo
                        .ItemData(.NewIndex) = hWnd
                    End With
                End If
            End If
        End If
        'Siguiente ventana
        hWnd = GetWindow(hWnd, GW_HWNDNEXT)
    Loop
    Set EnumTopWindows = col
End Function

Public Function ClassName(ByVal Title As String) As String
    'Devuelve el ClassName de una ventana, indicando el t�tulo de la misma
    Dim hWnd As Long
    Dim sClassName As String
    Dim nMaxCount As Long
    
    hWnd = FindWindow(sClassName, Title)
    
    nMaxCount = 256
    sClassName = Space$(nMaxCount)
    nMaxCount = GetClassName(hWnd, sClassName, nMaxCount)
    ClassName = Left$(sClassName, nMaxCount)
End Function

Public Sub MinimizeAll(Optional ClassName As String)
    'Minimizar todas las ventanas
    '
    Dim col As Collection
    Dim numItems As Long
    Dim i As Long
    Dim sTitulo As String
    Dim hWnd As Long
    
    Set col = New Collection
    
    Set col = Me.EnumTopWindows
    numItems = col.Count
    For i = 1 To numItems Step 2
        sTitulo = col.Item(i)
        hWnd = FindWindow(ClassName, sTitulo)
        Call SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, ByVal 0&)
    Next
    
    Set col = Nothing
End Sub

Espero que todo esto te pueda ser de utilidad... si no es as�, lo siento...

Aqu� tienes el c�digo con los listados, adem�s de una utilidad que se instala en la barra de tareas y permite cerrar las carpetas abiertas.

Pulsa este link para bajarte el c�digo de ejemplo (cerrarApp.zip 10.1 KB)


Mis Utilidades

ir al índice