【发布时间】:2021-04-13 05:24:58
【问题描述】:
我有一个可爱的小程序,它可以关闭带有 Acrobat 显示的窗口,或者只关闭其中的一个文档。只有设计是我自己制作的,这意味着我不完全理解代码,但我知道它只是部分起作用。它将完全退出 Adobe Acrobat,无论显示多少文档,但它不能只关闭一个(因为它被转录的原件声称它可以而且应该)。
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
逻辑是,参数MailIdx 标识了一个足以找到顶部窗口的文件名。如果没有给出值,则应关闭应用程序。这部分有效。另一部分也有效,但前提是只有一个文档打开,在这种情况下,不是关闭文档,而是关闭整个应用程序。我相信此关闭可能是由 Acrobat Reader 本身引起的,它没有看到保持打开状态而没有显示文档的原因。我还认为,如果有多个文档,则可能找不到窗口句柄,因为FindWindow 仅找到顶部窗口,而我要关闭的窗口将是第二个。在实践中,我尝试了两种方法,在打开另一个之前和之后关闭现有的。在一种情况下,应用程序被关闭,在另一种情况下,什么也没有发生。
我不知道为什么我的导师在一种情况下使用SendMessage 而在另一种情况下使用PostMessage。我也不知道我所追求的窗口是否是子窗口,或者如果是,如何处理它。有什么建议吗?
2021 年 1 月 11 日编辑
我使用下面的代码来测试@FaneDuru 的解决方案。
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
该代码对 1 个或 2 个文件都运行良好,直到使用参数 0 调用时才关闭应用程序。但在第二次尝试时它未能找到窗口,因此没有采取任何行动。
我启动了 Acrobat 并从其文件>打开菜单中选择了 2 个以前打开的文件。 File1 在第一个选项卡中,File2 在第二个选项卡中,处于活动状态。然后我试图删除失败的 File1。然后我用 2 作为参数调用代码,关闭了顶层文件。此后代码找到 File1 的窗口并关闭它。
但是,我认为并没有始终如一地遵循明显的规则。文件的打开方式似乎有所不同。在我的项目中,文件是通过超链接打开的,一次一个。因此,我的上述测试并不能说明 FaneDuru 的建议将如何在我的项目中发挥作用,但它证明了该解决方案是有效的。
【问题讨论】:
-
这是您以前以编程方式打开的窗口吗?如果是这样,您能否确保它 a) 在 Acrobat Reader 的单独实例中打开并 b) 在需要关闭它时保持引用?
-
您用来打开文件的默认 Acrobat 应用程序是什么?我的意思是,它是 Acrobat Pro 还是 Acrobat reader?
-
@Rich Harding Acrobat 已通过超链接打开。我不想要另一个实例,我也没有得到一个。如果我每次更改文档时都关闭应用程序,那么如果快速连续单击“下一步”,定位窗口似乎会出现问题。我想通过保持 Acrobat 实例处于活动状态来避免“等待”。基本上,虽然只有一个文档,但它是“关闭文档”,而不是我的代码适用的“关闭窗口”。当有多个时,我的代码无法处理正确的窗口。
-
@FaneDuru 我使用 Acrobat Reader DC,类名
AcrobatSDIWindow。我的代码通过任一标准在两个版本中找到应用程序的窗口,然后将其关闭。我认为这是因为FindWindow只能找到顶部窗口。我想知道我是否应该尝试FindWindowEx或者WM_CLOSE是否是错误的参数。我试图缩小范围以进行更好的研究。您知道非顶级应用程序窗口(第二个 PDF)是否位于所谓的“子窗口”中? -
@Variatus 我只是建议我尝试的方法,如果我尝试了您当前使用的方法并发现它不起作用。这相当于总是创建一个对新工作簿/工作表的对象引用,而不是只创建一个然后尝试再次找到它 - 但删除了一个应用程序。我负责由 Excel 控制的大量 VBA 多应用程序位,我不会梦想在不控制其他应用程序的生成的情况下尝试这样做。