Solved

Close window by window Header name even if not in focus

Posted on 2010-09-15
10
461 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
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 85

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
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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 500 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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Convert VB6 MSXML2.ServerXMLHTTP process to C# 2 58
Problem to start Neon 20 120
vbModal 12 57
Inserting a datasheet query into the body of an email using VBA? 4 18
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…
This article will show, step by step, how to integrate R code into a R Sweave document
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

856 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