Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Close window by window Header name even if not in focus

Posted on 2010-09-15
10
Medium Priority
?
478 Views
Last Modified: 2012-05-10
I need a vb6 example of closing a window that is or is not in focus and all i know is the window name.
0
Comment
Question by:rjef
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
10 Comments
 
LVL 17

Expert Comment

by:Daniel Reynolds
ID: 33685637
Here are a couple of links to help you out with the win32 API required to do this.

http://www.dreamincode.net/code/snippet2732.htm
http://www.vb6.us/tutorials/activate-window-api
http://www.codeproject.com/KB/dialog/closewindow.aspx

hope that helps
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 33685739
Bare bones example:
*requires an exact match on window title!
Private Const WM_CLOSE = &H10

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 Sub Command1_Click()
    Dim targetHwnd As Long
    targetHwnd = FindWindow(vbNullString, "exact window title in here")
    SendMessage targetHwnd, WM_CLOSE, 0, 0 
End Sub

Open in new window

0
 

Author Comment

by:rjef
ID: 33685772
Private Const WM_CLOSE = &H10

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 Sub Command1_Click()
    Dim targetHwnd As Long
    targetHwnd = FindWindow(vbNullString, "Printers and Faxes")
    SendMessage targetHwnd, WM_CLOSE, 0, 0
End Sub

this did not close the 'Printers and Faxes" window
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 11

Expert Comment

by:kbirecki
ID: 33690313
Cutting from a working program I have, paste the first portion of the code onto a form with a button "Command1", and the second portion into it's own module.  Open the Printers anf Faxes windows, run the app, and click the btn.

I prefer this FindWindowLike function because it allows for wildcards.  I can't take credit for the whole solution; I put it together many years ago from stuff I found on the Internet.  I left the debugging code I had in there.
'Form Code:
Private Sub Command1_Click()
    Dim lngResult As Long
    Dim lngReturnValue As Long
    Dim lNumAppsFound As Long
    Static varHWnds() As Variant
    
    lNumAppsFound = FindWindowLike(varHWnds(), 0, "Printers and *", "*", Null)
    For lLoop = 1 To lNumAppsFound
        lngReturnValue = PostMessage(varHWnds(lLoop), WM_CLOSE, vbNull, vbNull)
        lngResult = WaitForSingleObject(varHWnds(lLoop), INFINITE)
    Next lLoop

End Sub

'*********************************
'Separate Module Code
Option Explicit

Declare Function SetFocusAPI Lib "user32" Alias "SetForegroundWindow" _
   (ByVal hwnd As Long) As Long
Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _
 ByVal wCmd As Long) As Long
Declare Function GetDesktopWindow Lib "user32" () As Long
Declare Function GetWindowLW Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
 (ByVal hwnd As Long, ByVal lpClassName As String, _
  ByVal nMaxCount As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
 (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) _
  As Long
Declare Function GetWindowPlacement Lib "user32" _
    (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long
Private Declare Function SetForegroundWindow Lib "user32" _
    (ByVal hwnd As Long) As Long
Private Declare Function ShowWindow Lib "user32" _
    (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long

Public Declare Function WaitForSingleObject Lib "kernel32" _
   (ByVal hHandle As Long, _
   ByVal dwMilliseconds As Long) As Long
Public Declare Function PostMessage Lib "user32" _
   Alias "PostMessageA" _
   (ByVal hwnd As Long, _
   ByVal wMsg As Long, _
   ByVal wParam As Long, _
   ByVal lParam As Long) As Long

Public Declare Function IsWindow Lib "user32" _
   (ByVal hwnd As Long) As Long

Public Declare Function SetWindowPos Lib "user32" _
    (ByVal hwnd As Long, _
    ByVal hWndInsertAfter As Long, _
    ByVal x As Long, _
    ByVal y As Long, _
    ByVal cx As Long, _
    ByVal cy As Long, _
    ByVal wFlags As Long) As Long

Private lpwndpl   As WINDOWPLACEMENT

Private Type POINTAPI
    x As Long
    y As Long
End Type

Private Type RECT
    Left   As Long
    Top    As Long
    Right  As Long
    Bottom 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 GWL_ID = (-12)
Private Const GW_HWNDNEXT = 2
Private Const GW_CHILD = 5
Private Const SWP_NOMOVE = 2
Private Const SWP_NOSIZE = 1
Private Const FLAGS = SWP_NOMOVE Or SWP_NOSIZE
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Const GWL_STYLE = (-16)
Private Const GWL_EXSTYLE = (-20)
Private Const WM_GETTEXT = &HD
Private Const WM_GETTEXTLENGTH = &HE
Private Const GWL_HWNDPARENT = (-8)
Private Const WM_COMMAND = &H111
Private Const MIN_ALL = 419
Private Const MIN_ALL_UNDO = 416
Private Const MAX_PATH = 260
Private Const SW_SHOW = 5
Private Const SW_RESTORE = 9
Private Const SW_SHOWMINIMIZED = 2
Private Const SW_SHOWMAXIMIZED = 3
Private Const SW_SHOWNORMAL = 1

'Constants used by the API functions
Public Const WM_CLOSE = &H10
Public Const INFINITE = &HFFFFFFFF

'FindWindowLike
' - Finds the window handles of the windows matching the specified
'   parameters
'
'hwndArray()
' - An integer array used to return the window handles
'
'hWndStart
' - The handle of the window to search under.
' - The routine searches through all of this window's children and their
'   children recursively.
' - If hWndStart = 0 then the routine searches through all windows.
'
'WindowText
' - The pattern used with the Like operator to compare window's text.
'
'ClassName
' - The pattern used with the Like operator to compare window's class
'   name.
'
'ID
' - A child ID number used to identify a window.
' - Can be a decimal number or a hex string.
' - Prefix hex strings with "&H" or an error will occur.
' - To ignore the ID pass the Visual Basic Null function.
'
'Returns
' - The number of windows that matched the parameters.
' - Also returns the window handles in hWndArray()
'
'----------------------------------------------------------------------
'Remove this next line to use the strong-typed declarations
#Const WinVar = True
#If WinVar Then
    Function FindWindowLike(hWndArray() As Variant, _
     ByVal hWndStart As Variant, WindowText As String, _
      Classname As String, _
      ID) As Integer
        ' Comments  :
        ' Parameters: hWndArray()
        '             hWndStart
        '             WindowText
        '             Classname
        '             ID -
        ' Returns   : Integer -
        ' Modified  :
        '
        ' --------------------------------------------------
        
        On Error GoTo PROC_ERR
        
        Dim hwnd
        Dim r
        Static level
        Static iFound
#ElseIf Win32 Then
    Function FindWindowLike(hWndArray() As Long, ByVal hWndStart As Long, _
     WindowText As String, Classname As String, ID) As Long
        Dim hwnd As Long
        Dim r As Long
        ' Hold the level of recursion:
        Static level As Long
        ' Hold the number of matching windows:
        Static iFound As Long
#ElseIf Win16 Then
    Function FindWindowLike(hWndArray() As Integer, _
     ByVal hWndStart As Integer, WindowText As String, _
     Classname As String, ID) As Integer
        Dim hwnd As Integer
        Dim r As Integer
        ' Hold the level of recursion:
        Static level As Integer
        'Hold the number of matching windows:
        Static iFound As Integer
#End If
Dim sWindowText As String
Dim sClassname As String
Dim sID
' Initialize if necessary:
If level = 0 Then
    iFound = 0
    ReDim hWndArray(0 To 0)
    If hWndStart = 0 Then
        hWndStart = GetDesktopWindow()
    End If
End If
' Increase recursion counter:
level = level + 1
' Get first child window:
hwnd = GetWindow(hWndStart, GW_CHILD)
Do Until hwnd = 0
    DoEvents ' Not necessary
    ' Search children by recursion:
    r = FindWindowLike(hWndArray(), hwnd, WindowText, Classname, ID)
    ' Get the window text and class name:
    sWindowText = Space(255)
    r = GetWindowText(hwnd, sWindowText, 255)
    sWindowText = Left(sWindowText, r)
    'Debug.Print sWindowText
    sClassname = Space(255)
    r = GetClassName(hwnd, sClassname, 255)
    sClassname = Left(sClassname, r)
    
    'DEBUG CODE:
    'MsgBox sWindowText & " / " & sClassname
    
    ' If window is a child get the ID:
    If GetParent(hwnd) <> 0 Then
        r = GetWindowLW(hwnd, GWL_ID)
        sID = CLng("&H" & Hex(r))
    Else
        sID = Null
    End If
    ' Check that window matches the search parameters:
    If sWindowText Like WindowText And sClassname Like Classname Then
        If IsNull(ID) Then
            ' If find a match, increment counter and
            '  add handle to array:
            iFound = iFound + 1
            ReDim Preserve hWndArray(0 To iFound)
            hWndArray(iFound) = hwnd
        ElseIf Not IsNull(sID) Then
            If CLng(sID) = CLng(ID) Then
                ' If find a match increment counter and
                '  add handle to array:
                iFound = iFound + 1
                ReDim Preserve hWndArray(0 To iFound)
                hWndArray(iFound) = hwnd
            End If
        End If
        'Debug.Print "Window Found: "
        'Debug.Print "  Window Text  : " & sWindowText
        'Debug.Print "  Window Class : " & sClassname
        'Debug.Print "  Window Handle: " & CStr(hwnd)
        'MOD: 3/14/03/KB - Added stmt to jump out of loop when window is found
        Exit Do
        'ENDMOD: 3/14/03/KB
    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 = iFound
PROC_EXIT:
Exit Function

PROC_ERR:
'ErrorLog ThisProject, ThisModule, ThisProcedure, Format(Err.Number), Err.Description, bolErrCritical
'********
'Put some error handling routine here
'********
Resume PROC_EXIT

End Function

Open in new window

0
 

Author Comment

by:rjef
ID: 33715762
what is interesting is when i right click on one of my printers then properties then click on print test page then set the program to close the test page window the trouble shoot window is opened.
0
 
LVL 11

Expert Comment

by:kbirecki
ID: 33715940
What troubleshoot window do you mean?
0
 
LVL 11

Expert Comment

by:kbirecki
ID: 33715948
Can you post a screenshot?
0
 

Author Comment

by:rjef
ID: 33717015
when i try to close this window
trob.jpg
0
 
LVL 11

Accepted Solution

by:
kbirecki earned 2000 total points
ID: 33720445
That should work as well.  I just tested it on one of my printers and it worked, however, there's a caveat (I'll come back to that.)

Regarding your failing test of the app, here's one possiblity: I failed to mention that the routine FindWindowLike is case senstive (took me a while to figure that one out when I first started using it).  I never felt the need to change it, but you could make it case insensitive by changing this line in FindWindowLike() from:

If sWindowText Like WindowText And sClassname Like Classname Then

...to...

If UCASE(sWindowText) Like UCASE(WindowText) And sClassname Like Classname Then

(You may also want to change the comparison of the ClassName vars as well in case you use that.)

Another way you can troubleshoot this is to enable some of the debug.print statements and step through the code to see where exactly it fails, and where it misses what you expect.  That comparison line abov is where it finds the window you're looking for.  Watch the debug output until you see the window you're looking for.  I'd suggest doing this with as few applications and windows open as possible, including apps int he system tray, because it cycles through all of them.

That will definitely narrow down where you're having a problem with this routine.  It does work, so try those ideas.

The caveat:  I found that when I close the dialog you reference using the close command in this example app, Windows treats this just like I clicked [Troubleshoot] and pops up the Help window with printer troubleshooting tips (not helpful.)  So instead of sending a close command, you may want to simulate clicking the [OK] button instead.  One way would be to wait until you see that window (or a specified timeout), then issue a SendKeys command for <ENTER>, the default button.

Are you scripting a process to manage printers?
0
 

Author Closing Comment

by:rjef
ID: 33733952
this works
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

There is an easy way, in .NET, to centralize the treatment of all unexpected errors. First of all, instead of launching the application directly in a Form, you need first to write a Sub called Main, in a module. Then, set the Startup Object to th…
When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question