VBA Code to close an opened pdf amendment needed

kelly mort

Well-known Member
Joined
Apr 10, 2017
Messages
2,169
Office Version
  1. 2016
Platform
  1. Windows
Hello everyone.
I found this code on stack overflow:

I want to be able to detect the specific app in which the pdf file is opened.

On this line:
Code:
    Hwnd = FindWindow(vbNullString, "Current Letter Preview.pdf - Adobe Reader")





Code:
Option Explicit

Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
(ByVal Hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
lParam As Any) As Long

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassname As String, ByVal lpWindowName As String) As Long

Private Const WM_CLOSE = &H10

Sub Sample()
    Dim Hwnd As Long

    '~~> Find the window of the pdf file
    Hwnd = FindWindow(vbNullString, "Current Letter Preview.pdf - Adobe Reader")

    If Hwnd Then
        '~~> Close the file
        PostMessage Hwnd, WM_CLOSE, 0, ByVal 0&
    Else
        MsgBox "Pdf File not found"
    End If
End Sub

How do I go about that?

Thanks in advance.
 

Excel Facts

Control Word Wrap
Press Alt+Enter to move to a new row in a cell. Lets you control where the words wrap.
Bump

I just noticed that my question was not clear enough and I want to make it right this time:

Code:
    Hwnd = FindWindow(vbNullString, "Current Letter Preview.pdf - Adobe Reader")

what I want to do is to be able to close the file in whichever app it’s opene.

for example if it is opened in Foxit Reader, I need to amend the code like this:

Code:
    Hwnd = FindWindow(vbNullString, "Current Letter Preview.pdf - Foxit Reader")

but since I don’t know which app will be used to open the pdf file, I need a way to be able to close the file no matter which pdf reader was used.

I hope this is clearer.
 
Upvote 0
Hello @Jaafar Tribak
I have checked out the link - cool.

But I have one issue:
I don’t know how to do the partial search.
I have not mastered APIs yet.

I will be glad if you could assist me with the twea.

Regards.
 
Upvote 0
See if this works for you :

In a Standard Module:
VBA Code:
Option Explicit

#If Win64 Then
    Private Const NULL_PTR = 0^
#Else
    Private Const NULL_PTR = 0&
#End If

#If VBA7 Then
    Private Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
    Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal wCmd As Long) As LongPtr
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
#Else
    Private Enum LongPtr
        [_]
    End Enum
    Private Declare Function GetDesktopWindow Lib "user32" () As LongPtr
    Private Declare Function GetWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal wCmd As Long) As LongPtr
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
#End If


Function CloseWindowByPartialCaption(ByVal PartialCaption As String) As Boolean

    Const SC_CLOSE = &HF060&, WM_SYSCOMMAND = &H112
    Dim hwnd As LongPtr, sFullCaption As String
    
    sFullCaption = FindWindowLike(GetDesktopWindow(), PartialCaption)
    If Len(sFullCaption) Then
        hwnd = FindWindow(vbNullString, sFullCaption)
        Call SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)
        CloseWindowByPartialCaption = True
    End If
    
End Function

Private Function FindWindowLike(hWndParent As LongPtr, Caption As String) As String

    Const GW_HWNDNEXT = 2&, GW_CHILD = 5&
    Dim hwnd As LongPtr
    
    hwnd = GetWindow(hWndParent, GW_CHILD)
    Do Until hwnd = NULL_PTR
        If WindowText(hwnd) Like "*" & Caption & "*" Then
            FindWindowLike = WindowText(hwnd)
            Exit Do
        End If
        hwnd = GetWindow(hwnd, GW_HWNDNEXT)
    Loop
    
End Function

Private Function WindowText(hwnd As LongPtr) As String

  Const WM_GETTEXT = &HD, WM_GETTEXTLENGTH = &HE
  Dim lRet As LongPtr, str As String
    
    If hwnd <> NULL_PTR Then
        lRet = SendMessage(hwnd, WM_GETTEXTLENGTH, NULL_PTR, ByVal 0&) + 1&
        If lRet > NULL_PTR Then
            str = String$(CLng(lRet), vbNullChar)
            lRet = SendMessage(hwnd, WM_GETTEXT, lRet, ByVal str)
            If lRet > NULL_PTR Then WindowText = Left$(str, CLng(lRet))
        End If
    End If
    
End Function



Code Usage example:
VBA Code:
Sub Test()
    If CloseWindowByPartialCaption(PartialCaption:="Current Letter Preview") Then
        MsgBox "Window successfully colsed."
    Else
        MsgBox "Unable to find and\or close window."
    End If
End Sub
 
Upvote 0
Try this variation :
VBA Code:
Option Explicit

#If Win64 Then
    Private Const NULL_PTR = 0^
#Else
    Private Const NULL_PTR = 0&
#End If

#If VBA7 Then
    Private Declare PtrSafe Function GetTopWindow Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
    Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal wCmd As Long) As LongPtr
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
#Else
    Private Enum LongPtr
        [_]
    End Enum
    Private Declare Function GetTopWindow Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
    Private Declare Function GetWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal wCmd As Long) As LongPtr
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
#End If


Function CloseWindowByPartialCaption(ByVal PartialCaption As String) As Boolean

    Const SC_CLOSE = &HF060&, WM_SYSCOMMAND = &H112
    Dim hwnd As LongPtr, sFullCaption As String
    
    sFullCaption = FindWindowLike(GetTopWindow(NULL_PTR), PartialCaption)
    If Len(sFullCaption) Then
        hwnd = FindWindow(vbNullString, sFullCaption)
        Call SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)
        CloseWindowByPartialCaption = True
    End If
    
End Function

Private Function FindWindowLike(hWndParent As LongPtr, Caption As String) As String

    Const GW_HWNDNEXT = 2&, GW_CHILD = 5&
    
    Do While hWndParent <> NULL_PTR
            If WindowText(hWndParent) Like "*" & Caption & "*" Then
            FindWindowLike = WindowText(hWndParent)
            Exit Do
        End If
        hWndParent = GetWindow(hWndParent, GW_HWNDNEXT)
    Loop
    
End Function

Private Function WindowText(hwnd As LongPtr) As String

  Const WM_GETTEXT = &HD, WM_GETTEXTLENGTH = &HE
  Dim lRet As LongPtr, str As String
    
    If hwnd <> NULL_PTR Then
        lRet = SendMessage(hwnd, WM_GETTEXTLENGTH, NULL_PTR, ByVal 0&) + 1&
        If lRet > NULL_PTR Then
            str = String$(CLng(lRet), vbNullChar)
            lRet = SendMessage(hwnd, WM_GETTEXT, lRet, ByVal str)
            If lRet > NULL_PTR Then WindowText = Left$(str, CLng(lRet))
        End If
    End If
    
End Function
 
Upvote 0
Solution
Hi @Jaafar Tribak
Your new variation solved it.

I took away this function:

Code:
Function CloseWindowByPartialCaption(ByVal PartialCaption As String) As Boolean

    Const SC_CLOSE = &HF060&, WM_SYSCOMMAND = &H112
    Dim hwnd As LongPtr, sFullCaption As String
    
    sFullCaption = FindWindowLike(GetTopWindow(NULL_PTR), PartialCaption)
    If Len(sFullCaption) Then
        hwnd = FindWindow(vbNullString, sFullCaption)
        Call SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)
        CloseWindowByPartialCaption = True
    End If
    
End Function

and modified it as:

Code:
Sub Test_2()
Const SC_CLOSE = &HF060&, WM_SYSCOMMAND = &H112
    Dim hwnd As LongPtr, sFullCaption As String
    Dim PartialCaption As String 

PartialCaption = “Current Letter Preview“

    sFullCaption = FindWindowLike(GetTopWindow(NULL_PTR), PartialCaption)
    If Len(sFullCaption) Then
        hwnd = FindWindow(vbNullString, sFullCaption)
        Call SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)
    Else
         
MsgBox "Unable to find and\or close window."
   
    End If
End Sub

Thanks once again .

Cheers
 
Upvote 0
Hello @Jaafar Tribak
I have observed somethin:
I tried to open multiple files and run the code.

(a). When the “Current Letter Preview” is the active tab, the code works but tries closing the entire app (pdf reader).

(b). When the “Current Letter Preview” is not the active tab, though, opened is not closed.

So I was thinking is there a way to close only the file that has been found?

And also, is it possible to point the file to a certain folder?

Which is to say that even if a file is opened and that file is not from the given folder, don’t close it.
 
Upvote 0
Cross posted at:

Reason:
I still need help with it.
 
Upvote 0

Forum statistics

Threads
1,215,523
Messages
6,125,318
Members
449,218
Latest member
Excel Master

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top