Question FindWindow - what if caption changes?

Zexor

Well-known member
Joined
Nov 28, 2008
Messages
520
Programming Experience
3-5
If i use this, it will give me the handle of the window "Test Window 1.0"

VB.NET:
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr

        Dim hwnd As IntPtr = FindWindow(Nothing, "Test Window 1.0")

but what if the caption of the window changes? how do you find it? If it change to "Test Window 2.0" ? Program like Explorer caption always changes.
 
That's just something you have to allow for. Think about it. It's exactly the same in real life. If I tell you to ring Jim on a particular phone number, you ring that phone number and you speak to Jim. Now, what if Jim changes his phone number? There is no magic. If you don't know the new phone number then you can't call Jim, plain and simple.

The same goes for your code: if your app doesn't know the new name then it simply can't work with the changed window. This is one of the problems when interacting with external systems that just doesn't have a simple solution. You have to know how the external system is going to behave or you simply cannot interact with it. If it changes from what you coded for then your app must adapt. That means you need to either get the required information from an external source, e.g. the config file, that the user can edit themselves, or else you will need to update your source, recompile and re-release.
 
As far as I'm aware, FindWindow requires a complete name, but you can read the documentation for yourself to confirm that. You can always call EnumWindows and then choose the best match from the list it returns.
 
Perhaps this is more like what you needed, Zexor. It finds all processes with the process-name "notepad" then it restores the first process with the name and gives it focus. (For no real reason, just to show you that you can use win-API functions)
VB.NET:
    <DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function SetActiveWindow(ByVal hWnd As IntPtr) As IntPtr
    End Function
    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Private Shared Function ShowWindow(ByVal hWnd As IntPtr, ByVal flags As ShowWindowEnum) As <System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Sub SwitchToThisWindow(ByVal hWnd As IntPtr, ByVal fAltTab As Boolean)
    End Sub

    Private Enum ShowWindowEnum
        Hide = 0
        ShowNormal = 1
        ShowMinimized = 2
        ShowMaximized = 3
        Maximize = 3
        ShowNormalNoActivate = 4
        Show = 5
        Minimize = 6
        ShowMinNoActivate = 7
        ShowNoActivate = 8
        Restore = 9
        ShowDefault = 10
        ForceMinimized = 11
    End Enum
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim apps = From app In Process.GetProcesses() _
      Where app.ProcessName.Contains("notepad") AndAlso app.MainWindowHandle <> IntPtr.Zero _
      Select app
        Dim first As Process = apps.First
        Dim ptr As IntPtr = SetActiveWindow(first.MainWindowHandle)
        ShowWindow(first.MainWindowHandle, ShowWindowEnum.Restore)
        SwitchToThisWindow(first.MainWindowHandle, False)
    End Sub
 
Back
Top