Microsoft Developer Network >
Página principal de foros
>
Visual Basic General
>
i need to close a specific child window
i need to close a specific child window
Within my program, I have identified a process via System.Diagnostics.Processand.GetProcesses. Now I need to close one and only one of its windows whose window title i know. How do I do that?
Respuestas
- VB.NET does not have methods for doing this (well, maybe you could do it with the System.Windows.Automation library, but few people are familiar with it).
The way I would do this is by using P/Invoke on the applicable Windows system APIs. Unfortunately, if you are not familiar with the windows APIs, you are going to wonder how I ever figured this out...
Option Explicit On Option Strict On Imports System.ComponentModel Imports System.Runtime.InteropServices Imports System.Text Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim wc As New WindowCloser Dim p As Process = Process.GetProcessesByName("ExeNameWithoutExeExtension")(0) wc.CloseWindow(p, "Exact Title of Window in Process") End Sub End Class Public Class WindowCloser Private m_ProcessIdToFind As Integer Private m_TitleToFind As String Private m_TopLevelWindowsInProcess As New List(Of IntPtr) Private m_MatchingWindowsInProcess As New List(Of IntPtr) Public Sub CloseWindow(ByVal proc As Process, ByVal title As String) m_ProcessIdToFind = proc.Id m_TitleToFind = title m_TopLevelWindowsInProcess.Clear() m_MatchingWindowsInProcess.Clear() If Not EnumWindows(AddressOf EnumWindowsImpl, IntPtr.Zero) Then Throw New Win32Exception End If For Each hwnd As IntPtr In m_TopLevelWindowsInProcess EnumChildWindows(hwnd, AddressOf EnumChildWindowsImpl, IntPtr.Zero) Next hwnd For Each hwnd As IntPtr In m_MatchingWindowsInProcess SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero) Next hwnd End Sub Private Function EnumWindowsImpl(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Boolean Dim processId As Integer = 0 GetWindowThreadProcessId(hwnd, processId) If processId = m_ProcessIdToFind Then m_TopLevelWindowsInProcess.Add(hwnd) CheckWindow(hwnd) End If Return True End Function Private Function EnumChildWindowsImpl(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Boolean CheckWindow(hwnd) Return True End Function Private Function CheckWindow(ByVal hwnd As IntPtr) As Boolean Dim sb As New StringBuilder(255) If GetWindowText(hwnd, sb, sb.Capacity) <> 0 Then If sb.ToString() = m_TitleToFind Then m_MatchingWindowsInProcess.Add(hwnd) End If End If End Function <DllImport("user32.dll")> _ Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, <Out()> ByRef lpdwProcessId As Integer) As Integer End Function <DllImport("user32.dll", SetLastError:=True)> _ Private Shared Function EnumWindows(ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As IntPtr) As <MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean End Function <DllImport("user32.dll")> _ Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As IntPtr) As <MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean End Function Private Delegate Function EnumWindowsProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ Private Shared Function GetWindowText(ByVal hWnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer End Function Private Const WM_CLOSE As Integer = 16 <DllImport("user32.dll")> _ Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr End Function End Class
- Propuesto como respuestaYiChun ChenMSFT, Moderatorjueves, 08 de octubre de 2009 8:41
- Marcado como respuestaYiChun ChenMSFT, Moderatorviernes, 09 de octubre de 2009 8:53
Within my program, I have identified a process via System.Diagnostics.Processand.GetProcesses. Now I need to close one and only one of its windows whose window title i know. How do I do that?
You'll need to modify the following code so that it will close the correct form (replace form_to_close with the known title of the window you want to close):
Dim wdw As Form For Each wdw In My.Application.OpenForms If wdw.Text = "form_to_close" Then wdw.Close() Exit Sub End If Next
:)
Doug
SEARCH ... then ask- Marcado como respuestaYiChun ChenMSFT, Moderatorviernes, 09 de octubre de 2009 8:54
Hi YiChun,
It looks like the code will do the trick. Unfortunately we have moved to c#. Would you have equivalent code in c#?Thanks,gus
You can convert the code to C# at http://www.carlosag.net/Tools/CodeTranslator/
kaymaf
If that what you want, take it. If not, ignored it and no complain- Marcado como respuestaYiChun ChenMSFT, Moderatordomingo, 08 de noviembre de 2009 4:14
- Hi Barillas,
Thank you for your reply.
You also can try: http://www.developerfusion.com/tools/convert/vb-to-csharp/ to convert VB.NET code to C#.
Hope this helps. If you have any concern, please feel free to let me know.
Best regards,
Yichun Chen
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.- Marcado como respuestaYiChun ChenMSFT, Moderatorlunes, 09 de noviembre de 2009 3:07
Todas las respuestas
- VB.NET does not have methods for doing this (well, maybe you could do it with the System.Windows.Automation library, but few people are familiar with it).
The way I would do this is by using P/Invoke on the applicable Windows system APIs. Unfortunately, if you are not familiar with the windows APIs, you are going to wonder how I ever figured this out...
Option Explicit On Option Strict On Imports System.ComponentModel Imports System.Runtime.InteropServices Imports System.Text Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim wc As New WindowCloser Dim p As Process = Process.GetProcessesByName("ExeNameWithoutExeExtension")(0) wc.CloseWindow(p, "Exact Title of Window in Process") End Sub End Class Public Class WindowCloser Private m_ProcessIdToFind As Integer Private m_TitleToFind As String Private m_TopLevelWindowsInProcess As New List(Of IntPtr) Private m_MatchingWindowsInProcess As New List(Of IntPtr) Public Sub CloseWindow(ByVal proc As Process, ByVal title As String) m_ProcessIdToFind = proc.Id m_TitleToFind = title m_TopLevelWindowsInProcess.Clear() m_MatchingWindowsInProcess.Clear() If Not EnumWindows(AddressOf EnumWindowsImpl, IntPtr.Zero) Then Throw New Win32Exception End If For Each hwnd As IntPtr In m_TopLevelWindowsInProcess EnumChildWindows(hwnd, AddressOf EnumChildWindowsImpl, IntPtr.Zero) Next hwnd For Each hwnd As IntPtr In m_MatchingWindowsInProcess SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero) Next hwnd End Sub Private Function EnumWindowsImpl(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Boolean Dim processId As Integer = 0 GetWindowThreadProcessId(hwnd, processId) If processId = m_ProcessIdToFind Then m_TopLevelWindowsInProcess.Add(hwnd) CheckWindow(hwnd) End If Return True End Function Private Function EnumChildWindowsImpl(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Boolean CheckWindow(hwnd) Return True End Function Private Function CheckWindow(ByVal hwnd As IntPtr) As Boolean Dim sb As New StringBuilder(255) If GetWindowText(hwnd, sb, sb.Capacity) <> 0 Then If sb.ToString() = m_TitleToFind Then m_MatchingWindowsInProcess.Add(hwnd) End If End If End Function <DllImport("user32.dll")> _ Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, <Out()> ByRef lpdwProcessId As Integer) As Integer End Function <DllImport("user32.dll", SetLastError:=True)> _ Private Shared Function EnumWindows(ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As IntPtr) As <MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean End Function <DllImport("user32.dll")> _ Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As IntPtr) As <MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean End Function Private Delegate Function EnumWindowsProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ Private Shared Function GetWindowText(ByVal hWnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer End Function Private Const WM_CLOSE As Integer = 16 <DllImport("user32.dll")> _ Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr End Function End Class
- Propuesto como respuestaYiChun ChenMSFT, Moderatorjueves, 08 de octubre de 2009 8:41
- Marcado como respuestaYiChun ChenMSFT, Moderatorviernes, 09 de octubre de 2009 8:53
Within my program, I have identified a process via System.Diagnostics.Processand.GetProcesses. Now I need to close one and only one of its windows whose window title i know. How do I do that?
You'll need to modify the following code so that it will close the correct form (replace form_to_close with the known title of the window you want to close):
Dim wdw As Form For Each wdw In My.Application.OpenForms If wdw.Text = "form_to_close" Then wdw.Close() Exit Sub End If Next
:)
Doug
SEARCH ... then ask- Marcado como respuestaYiChun ChenMSFT, Moderatorviernes, 09 de octubre de 2009 8:54
- Thanks Doug. A couple of problems. The child window that I need to close belongs to an external app. So, I need to traverse that app's children.The other problem, is that we have moved to c#.Thanks again,gus
- Hi YiChun,It looks like the code will do the trick. Unfortunately we have moved to c#. Would you have equivalent code in c#?Thanks,gus
Hi YiChun,
It looks like the code will do the trick. Unfortunately we have moved to c#. Would you have equivalent code in c#?Thanks,gus
You can convert the code to C# at http://www.carlosag.net/Tools/CodeTranslator/
kaymaf
If that what you want, take it. If not, ignored it and no complain- Marcado como respuestaYiChun ChenMSFT, Moderatordomingo, 08 de noviembre de 2009 4:14
- Hi Barillas,
Thank you for your reply.
You also can try: http://www.developerfusion.com/tools/convert/vb-to-csharp/ to convert VB.NET code to C#.
Hope this helps. If you have any concern, please feel free to let me know.
Best regards,
Yichun Chen
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.- Marcado como respuestaYiChun ChenMSFT, Moderatorlunes, 09 de noviembre de 2009 3:07
- Kaymaf,I used YiChun's translator and it works pretty well. However, I wanted to compare it with yours, but the link seems to be broken. Did it get moved?Gus

