|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic System Services FindWindow: Window Title and Class Name Demo |
||
Posted: | Saturday March 1, 1997 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB4-32, VB5, VB6 | |
Developed with: | VB6, Windows NT4 | |
OS restrictions: | None | |
Author: | VBnet - Randy Birch | |
Prerequisites |
None. |
|
Although setup of the following project appears complicated, all setup code is performed in the form load event. Thus it's just a matter of adding the controls as specified below and running the demo. This demo implements the FindWindowLike routine. The FindWindowLike method does not require you to first know the precise (current) window name of the application you're trying to locate, allowing even partial strings in searching out the window. The only condition that the code makes is that, at a minimum, the ClassName parameter be at least "*". The original author of the FindWindowLike routine is unknown. |
BAS Module Code |
None. |
|
Form Code |
Start a new project, and add the following controls to the form:
Add the following code: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Dim hwndSelected As Long Dim sClassSelected As String Dim sTitleSelected As String Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Private Type POINTAPI x As Long y As Long End Type Private Type WINDOWPLACEMENT Length As Long flags As Long showCmd As Long ptMinPosition As POINTAPI ptMaxPosition As POINTAPI rcNormalPosition As RECT End Type Private Const LB_SETTABSTOPS = &H192 Private Const GW_HWNDNEXT = 2 Private Const GW_CHILD = 5 Private Const GWW_ID = (-12) Private Const SW_SHOWNORMAL = 1 Private Const SW_SHOWMINIMIZED = 2 Private Const SW_SHOWMAXIMIZED = 3 Private Const SW_SHOWNOACTIVATE = 4 Private Declare Function FindWindow Lib "user32" _ Alias "FindWindowA" _ (ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Private Declare Function GetDesktopWindow Lib "user32" () As Long Private Declare Function GetWindow Lib "user32" _ (ByVal hwnd As Long, _ ByVal wCmd As Long) As Long Private Declare Function GetWindowPlacement Lib "user32" _ (ByVal hwnd As Long, _ lpwndpl As WINDOWPLACEMENT) As Long Private Declare Function GetWindowRect Lib "user32" _ (ByVal hwnd As Long, _ lpRect As RECT) 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 GetClassName Lib "user32" _ Alias "GetClassNameA" _ (ByVal hwnd As Long, _ ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Private Declare Function MoveWindow Lib "user32" _ (ByVal hwnd As Long, _ ByVal x As Long, ByVal y As Long, _ ByVal nWidth As Long, ByVal nHeight As Long, _ ByVal bRepaint As Long) 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 Declare Function SetForegroundWindow Lib "user32" _ (ByVal hwnd As Long) As Long Private Declare Function SetWindowPlacement Lib "user32" _ (ByVal hwnd As Long, _ lpwndpl As WINDOWPLACEMENT) As Long Private Declare Function ShowWindow Lib "user32" _ (ByVal hwnd As Long, _ ByVal nCommand5 As Long) As Long Private Sub Form_Load() 'The control positioning in this routine 'was calculated on a screen using small fonts. 'If you use large fonts you'll have to tweak the 'settings slightly. Load Command4(1) Load Command4(2) Command4(0).Visible = True Command4(1).Visible = True Command4(2).Visible = True Load Label2(1) Load Label2(2) Load Label2(3) Load Label2(4) Label2(0).Visible = True Label2(1).Visible = True Label2(2).Visible = True Label2(3).Visible = True Label2(4).Visible = True Label2(0).AutoSize = True Label2(1).AutoSize = True Label2(2).AutoSize = True Label2(3).AutoSize = True Label2(4).AutoSize = True With Me .Width = 8225 .Height = 5065 .Move (Screen.Width - .Width) \ 2, (Screen.Height - .Height) \ 2 .Caption = "VBnet FindWindow / Window Title and Class Name Demo" End With Command1.Caption = "Reset Names" Command2.Caption = "Find" Command3.Caption = "Show" Command4(0).Caption = "< Tab" Command4(1).Caption = "Tab >" Command4(2).Caption = "Reset" Command5.Caption = "Use as Window Class" Command6.Caption = "Use as Window Title" Command7.Caption = "End" Label1.Caption = "<results here>" Lable1.AutoSize = True Label2(0).Caption = "Class name (* for any)" Label2(1).Caption = "Full or partial title (* for any)" Label2(2).Caption = "hwnd:" Label2(3).Caption = "Class name:" Label2(4).Caption = "Full window title:" Text1.Move 200, 400, 1700, 285 Text2.Move 2000, 400, 3000, 285 Label2(0).Move Text1.Left, Text1.Top - 200 Label2(1).Move Text2.Left, 150 Command1.Move 5300, Text1.Top - 50, 1500, 365 Label1.Move 200, 800 List1.Move 200, 1400, Me.ScaleWidth - 400, 2200 Label2(2).Move List1.Left, List1.Top - 250 Label2(3).Move List1.Left + 940, List1.Top - 250 Label2(4).Move List1.Left + 2500, List1.Top - 250 Command2.Move 200, 3700, 2200, 365 Command3.Move 200, 4100, 2200, 365 Command4(0).Move 2500, Command2.Top, 800, 365 Command4(1).Move 3300, Command2.Top, 800, 365 Command4(2).Move 4100, Command2.Top, 800, 365 Command5.Move 5000, Command2.Top, 1800, 365 Command6.Move 5000, Command3.Top, 1800, 365 Command7.Move 7000, Command5.Top, 800, 365 'Initialize controls Text2.Text = "*Microsoft Internet Explorer" Text1.Text = "*" Command4_Click 2 End Sub Private Sub Command1_Click() 'Initialize controls Text2.Text = "*Microsoft Internet Explorer" Text1.Text = "*" End Sub Private Sub Command2_Click() 'FIND Dim hWnds() As Long 'Used to return window handles Dim cnt As Long Dim sTitle As String Dim sClass As String 'Initialize controls Command6.Enabled = False Command5.Enabled = False Command3.Enabled = False List1.Clear 'Set the FindWindowLike text values sTitle = Text2.Text & "*" sClass = Text1.Text cnt = FindWindowLike(hWnds(), 0, sTitle, sClass) Label1.Caption = "Found : " & cnt & " windows." Command4(0).Enabled = cnt > 0 Command4(1).Enabled = cnt > 0 End Sub Private Sub Command3_Click() 'SHOW Dim msg As String Dim currRect As RECT Dim currWinP As WINDOWPLACEMENT currWinP.Length = Len(currWinP) Call GetWindowPlacement(hwndSelected, currWinP) If currWinP.showCmd = SW_SHOWMINIMIZED Then msg = "The selected window is presently minimized." & vbCrLf & vbCrLf msg = msg & "Select: " & vbCrLf msg = msg & " Yes to restore it to the top," & vbCrLf msg = msg & " No to restore it without activating, or" & vbCrLf msg = msg & " Cancel to abort this action." Select Case MsgBox(msg, 291, sTitleSelected) Case vbYes currWinP.Length = Len(currWinP) currWinP.flags = 0& currWinP.showCmd = SW_SHOWNORMAL Call SetWindowPlacement(hwndSelected, currWinP) Case vbNo currWinP.Length = Len(currWinP) currWinP.flags = 0& currWinP.showCmd = SW_SHOWNOACTIVATE Call SetWindowPlacement(hwndSelected, currWinP) Case Else End Select Else Select Case MsgBox("Bring the selected window to the top?", 292, sTitleSelected) Case vbYes Call SetForegroundWindow(hwndSelected) Case Else End Select End If If Err Then MsgBox "Couldn't activate " & sTitleSelected, , Me.Caption End Sub Private Sub Command4_Click(Index As Integer) 'TAB ADJUST - moves tabstops to align wide items Static classTab As Long Static winTab As Long Select Case Index Case 0: classTab = classTab& - 2: winTab = winTab - 3 Case 1: classTab = classTab& + 2: winTab = winTab + 3 Case 2: classTab = 42: winTab = 110 End Select If classTab < 26 Then classTab = 26 If winTab < 90 Then winTab = 90 Command4(0).Enabled = (classTab <> 35 And winTab <> 90) ReDim tabs(1 To 2) As Long tabs(1) = classTab 'class tabs(2) = winTab 'window title 'reset the initial tabstops then set the defined ones Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 0&, ByVal 0&) Call SendMessage(List1.hwnd, LB_SETTABSTOPS, UBound(tabs), tabs(1)) List1.Refresh Command4(2).Enabled = (classTab <> 42) And (winTab <> 110) End Sub Private Sub Command5_Click() 'SET CLASS TEXT - if item selected in list If Len(sClassSelected) > 0 Then Text1.Text = sClassSelected End If End Sub Private Sub Command7_Click() Unload Me End Sub Private Sub Command6_Click() 'SET TITLE TEXT - if item selected in list If Len(sTitleSelected) > 0 Then Text2.Text = sTitleSelected End If End Sub Private Sub List1_Click() Dim sItem As String Dim pos1 As Integer Dim pos2 As Integer Command3.Enabled = List1.ListIndex > -1 'Show button Command5.Enabled = List1.ListIndex > -1 'Use as Class button Command6.Enabled = List1.ListIndex > -1 'Use as Title button 'extract the data from the selected list item 'get the selected item's handle sItem = List1.List(List1.ListIndex) pos1 = InStr(sItem, vbTab) 'get the selected item class name If pos1 Then hwndSelected = CLng(Left$(sItem, pos1 - 1)) 'get the selected item window class and title sItem = Mid$(sItem, pos1 + 1, Len(sItem)) pos2 = InStr(sItem, vbTab) If pos2 Then sClassSelected = Left$(sItem, pos2 - 1) sTitleSelected = Mid$(sItem, pos2 + 1, Len(sItem)) End If End Sub Private Function FindWindowLike(hWndArray() As Long, _ ByVal hWndStart As Long, _ WindowText As String, _ Classname As String) As Long Dim hwnd As Long Dim sWindowText As String Dim sClassname As String Dim r As Long 'Hold the level of recursion and 'hold the number of matching windows Static level As Long Static found As Long 'Initialize if necessary If level = 0 Then found = 0 ReDim hWndArray(0 To 0) If hWndStart = 0 Then hWndStart = GetDesktopWindow() End If 'Increase recursion counter level = level + 1 'Get first child window hwnd = GetWindow(hWndStart, GW_CHILD) Do Until hwnd = 0 'Search children by recursion Call FindWindowLike(hWndArray(), hwnd, WindowText, Classname) 'Get the window text and class name sWindowText = Space(255) r = GetWindowText(hwnd, sWindowText, 255) sWindowText = Left(sWindowText, r) sClassname = Space(255) r = GetClassName(hwnd, sClassname, 255) sClassname = Left(sClassname, r) 'Check that window matches the search parameters If (sWindowText Like WindowText) And (sClassname Like Classname) Then found = found + 1 ReDim Preserve hWndArray(0 To found) hWndArray(found) = hwnd List1.AddItem hWndArray(found) & vbTab & sClassname & vbTab & sWindowText End If 'Get next child window hwnd = GetWindow(hwnd, GW_HWNDNEXT) Loop 'Decrement recursion counter level = level - 1 'Return the number of windows found FindWindowLike = found End Function |
Comments |
Save the project, then run. Enter the full or partial
window title to locate, and/or the class name, if known. Note that the search is case-sensitive.
Pressing Find, the list box will return the matches. Select an item, and either:
Press Find again to narrow the search, repeating as needed. At any point, once an item is selected, the Show Selected button will become enabled. When pressed, depending on the current window state of the selected item, one of two Message boxes will appear. Use the buttons to change the column spacing of the list, if needed. Note as well that the textbox containing the text you've entered will also appear in the list because of the call to the GetWindowText API. You could code the routine to only list parent windows by discarding those who return a value to an IsChild() API call. |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |