I have this lovely little procedure that is supposed to either shut down the window with the Acrobat display or just one document in it. Only the design is of my own making, meaning I don't fully understand the code, but I do know that it works only partially. It will quit Adobe Acrobat in full, regardless of how many documents are displayed but it can't close just one (as the original from which it was transcribed claimed that it could and should).
Private Sub CloseReaderDC(Optional ByVal MailIdx As Integer)
Dim WinId As String
Dim Wnd As LongPtr
If MailIdx Then
WinId = AcrobatWindowID(Mail(MailIdx))
Wnd = FindWindow(vbNullString, WinId)
PostMessage Wnd, WM_CLOSE, 0, ByVal 0&
Else
WinId = AcrobatWindowID
Wnd = FindWindow(WinId, vbNullString)
SendMessage Wnd, WM_CLOSE, 0, ByVal 0&
End If
End Sub
The logic is that the parameter MailIdx identifies a file name which is sufficient to find a top window. If no value is given the app should be shut down. This part works. The other part also works, but only if there is a single document open, in which case not the document is closed but the entire application. I believe this shutdown may be caused by Acrobat Reader itself which doesn't see a reason for staying open with no document to display. I also think that the window handle may not be found if there are several documents because FindWindow finds a top window only and the one I want to close would be the second one. In practice, I tried both, to close the existing before opening another one and after. In the one case the app gets shut down, in the other nothing happens.
I don't know why my tutor uses SendMessage in one case and PostMessage in the other. I also don't know if the window I'm after is a Child Window or how to get a handle on it if it is. Any suggestions?
Edit 11 Jan 2021
I used the following code to test @FaneDuru's solution.
Private Sub Test_CloseReaderDC()
ReDim Mail(2)
Mail(0) = ""
Mail(1) = "File1.PDF"
Mail(2) = "File2.PDF"
CloseReaderDC 1
End Sub
Private Sub CloseReaderDC(Optional ByVal MailIdx As Integer)
' NIC 003 ++ 10 Jan 2021
Dim WinTitle As String
Dim WinCap As String
Dim Wnd As LongPtr
WinTitle = AcrobatWindowID
If MailIdx Then
WinCap = AcrobatWindowID(Mail(MailIdx))
Wnd = FindWindow(vbNullString, WinCap)
Debug.Print Wnd
SendMessage Wnd, WM_CloseClick, 6038, ByVal 0&
Else
Wnd = FindWindow(WinTitle, vbNullString)
Debug.Print Wnd
SendMessage Wnd, WM_CLOSE, 0, ByVal 0&
End If
End Sub
Function AcrobatWindowID(Optional ByVal Wn As String)
' NIC 003 ++ 07 Jan 2021
Dim Fun As Boolean
Fun = CBool(Len(Wn))
If Fun Then Wn = Wn & " - "
AcrobatWindowID = Wn & Split("AcrobatSDIWindow,Adobe Acrobat Reader DC", ",")(Abs(Fun))
End Function
The code worked perfectly for both 1 or 2 files, not closing the app until called with a parameter of 0. But on second try it failed to find the window and therefore took no action.
I started Acrobat and selected the 2 previously opened files from its File>Open menu. File1 was in the first tab, File2 in the second, active. Then I attempted to delete File1 which failed. Then I called the code with 2 as parameter which closed the top file. Thereafter the code found the window for File1 and closed it.
I don't think the apparent rule is followed consistently, however. How the files were opened seems to make a difference. In my project the files are opened by hyperlink, one at a time. My above test therefore is not indicative of how FaneDuru's suggestion will work in my project but it proves that the solution works.
AcrobatSDIWindow. My code finds the app's window in both versions, by either criterium, and closes it. I think it's becauseFindWindowonly finds top windows. I wonder if I should tryFindWindowExor whetherWM_CLOSEis the wrong parameter. I try to narrow down the field for better research. Do you know if the non-top app window (2nd PDF) is in what's called a "child window"? - Variatus