Posts Tagged ‘indexOf

05
May
09

[VB.Net] FindWindowsIndexOf – .Netish Version

A more .net style function for getting a window using an indexOf:

    ''API Imports
    <Runtime.InteropServices.DllImport("user32.dll", CharSet:=Runtime.InteropServices.CharSet.Auto)> Private Shared Sub GetClassName(ByVal hWnd As System.IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer)
    End Sub
    <Runtime.InteropServices.DllImport("user32.dll", CharSet:=Runtime.InteropServices.CharSet.Auto)> Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    End Function

    ''FoundWindow stricture
    Public Structure FoundWindow
        Dim strWindowName As String
        Dim strClassName As String
        Dim hWnd As IntPtr
    End Structure

    ''' <summary>
    ''' This function is used to loop through all running processes, checking their main windows to see which ones contain a specific string
    ''' </summary>
    ''' <param name="strIndexOf">The string that you wish to check for in the window captions</param>
    ''' <param name="boolCase">Whether the function is should check for case</param>
    ''' <returns>A list of FoundWindow's containing the window name, class and handle</returns>
    ''' <remarks>As this function only loops through running processes main windows, it may miss some windows.</remarks>
    Public Function FindWindowsIndexOf(ByVal strIndexOf As String, ByVal boolCase As Boolean) As List(Of FoundWindow)
        Dim foundWindows As New List(Of FoundWindow)
        If boolCase = False Then
            strIndexOf = strIndexOf.ToLower
        End If
        For Each p As Process In Process.GetProcesses
            Dim windowCaption As String = p.MainWindowTitle
            If boolCase = False Then
                windowCaption = windowCaption.ToLower
            End If
            If windowCaption.IndexOf(strIndexOf) > -1 Then
                Dim foundWindow As New FoundWindow
                foundWindow.hWnd = FindWindow(vbNullString, p.MainWindowTitle)
                foundWindow.strWindowName = p.MainWindowTitle
                Dim sbClassName As New System.Text.StringBuilder("", 256)
                GetClassName(foundWindow.hWnd, sbClassName, 256)
                foundWindow.strClassName = sbClassName.ToString
                foundWindows.Add(foundWindow)
            End If
        Next
        Return foundWindows
    End Function

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        For Each fWnd As FoundWindow In FindWindowsIndexOf("TeST", False)
            Debug.WriteLine(fWnd.strWindowName & " : " & fWnd.hWnd.ToString)
        Next
    End Sub

Same as the last function, you can choose whether or not the function is case sensitive.

05
May
09

[VB.Net] FindWindowsIndexOf – API Version

Somebody on VBForums was asking how to do something similar to this, so after answering his question, I created this fairly useful function – for windows that names change each time you load them up or something…

    ''API Declarations
    Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As EnumWindowProc, ByVal lParam As IntPtr) As Integer
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Integer, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
    Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Integer) As Integer
    <Runtime.InteropServices.DllImport("user32.dll", CharSet:=Runtime.InteropServices.CharSet.Auto)> Private Shared Sub GetClassName(ByVal hWnd As System.IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer)
    End Sub

    ''EnumWindow Callback Delegate Function
    Private Delegate Function EnumWindowProc(ByVal hwnd As Integer, ByVal lParam As IntPtr) As Boolean

    ''Found Window Structures
    Public Structure FoundWindows
        Dim boolCase As Boolean
        Dim strFindWindow As String
        Dim lstFoundWindows As List(Of FoundWindow)
    End Structure
    Public Structure FoundWindow
        Dim strWindowName As String
        Dim strClassName As String
        Dim hWnd As IntPtr
    End Structure

    ''' <summary>
    ''' ''EnumWindow Callback Function
    ''' </summary>
    ''' <param name="hwnd">Current windows handle</param>
    ''' <param name="lParam">Contains the FoundWindows structure</param>
    ''' <returns>The function passes the currently found windows in the lParam using a GCHandle to reform the data</returns>
    ''' <remarks>This function is called for each of the windows found, and is where the indexOf is called</remarks>
    Public Function EnumWindowsProc(ByVal hwnd As Integer, ByVal lParam As IntPtr) As Boolean
        Dim foundWindows As FoundWindows = CType(System.Runtime.InteropServices.GCHandle.FromIntPtr(lParam).Target, FoundWindows)
        Dim windowTitle As String = foundWindows.strFindWindow
        Dim wndTxtLen As Integer = GetWindowTextLength(hwnd)
        If Not wndTxtLen = 0 Then
            Dim sb As New System.Text.StringBuilder("", wndTxtLen + 1)
            GetWindowText(hwnd, sb, sb.Capacity)
            Dim windowCaption As String = sb.ToString
            If foundWindows.boolCase = False Then
                windowCaption = windowCaption.ToLower
                windowTitle = windowTitle.ToLower
            End If
            If windowCaption.IndexOf(windowTitle) > -1 Then
                Dim foundWindow As New FoundWindow
                foundWindow.hWnd = CType(hwnd, IntPtr)
                Dim sbClassName As New System.Text.StringBuilder("", 256)
                GetClassName(foundWindow.hWnd, sbClassName, 256)
                foundWindow.strClassName = sbClassName.ToString
                foundWindow.strWindowName = sb.ToString
                foundWindows.lstFoundWindows.Add(foundWindow)
            End If
        End If
        Return True
    End Function

    ''' <summary>
    ''' This function is used to loop through all open windows and check which ones contain a specific string
    ''' </summary>
    ''' <param name="strIndexOf">The string that you wish to check for in the window captions</param>
    ''' <param name="boolCase">Whether the function is should check for case</param>
    ''' <returns>A FoundWindows structure containing a list of FoundWindow</returns>
    ''' <remarks>The FoundWindows structure also contains the strIndexOf that was used to search the windows caption</remarks>
    Public Function FindWindowsIndexOf(ByVal strIndexOf As String, ByVal boolCase As Boolean) As FoundWindows
        Dim foundWindows As New FoundWindows
        foundWindows.boolCase = boolCase
        foundWindows.strFindWindow = strIndexOf
        foundWindows.lstFoundWindows = New List(Of FoundWindow)
        Dim ListHandle As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(foundWindows)
        Try
            EnumWindows(AddressOf EnumWindowsProc, System.Runtime.InteropServices.GCHandle.ToIntPtr(ListHandle))
        Finally
            If ListHandle.IsAllocated Then ListHandle.Free()
        End Try
        Return foundWindows
    End Function

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        For Each fWnd As FoundWindow In FindWindowsIndexOf("Test", True).lstFoundWindows
            Debug.WriteLine(fWnd.strWindowName & " : " & fWnd.hWnd.ToString)
        Next
    End Sub

The function can check for casing as well. For example if you are running two windows one named “test” and another named “Test” if you use the function like this:

FindWindowsIndexOf("Test", True)

It will only return one window, however if you set the boolCase to false:

FindWindowsIndexOf("Test", False)

It will return both windows