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 SubComo 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 SubPor �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 SubEspero 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)