【问题标题】:How to change printer dialog default name in VBA? (when using the handle of the printer dialog)如何在 VBA 中更改打印机对话框的默认名称? (使用打印机对话框的句柄时)
【发布时间】:2024-01-24 12:39:01
【问题描述】:

我从 SAP 获得了一些数据,然后我按下了 SAP 的“打印”按钮以打印数据。 然后出现打印窗口:

  1. 我已将其处理为 hWnd 变量(请在第 1 行评论中找到);

  2. 那我想把默认打印机名改成“Microsoft Print to PDF”(不知道怎么改);

  3. 然后我按下了按钮 OK(请找到第 4 行评论);

代码如下:

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
    (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 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
Const BM_CLICK = &HF5
'''
 hWnd = FindWindow("#32770", "Print")  'LINE 1 comment;
 Childhwnd = FindWindowEx(hWnd, ByVal 0&, "Button", "OK")';
'ON THIS LINE NEED TO INSERT CODE THAT CHANGES PRINTER NAME;
 SendMessage Childhwnd, BM_CLICK, 0, ByVal 0& 'LINE 4 comment;

请帮我更改打印机名称。

【问题讨论】:

  • 请注意我的 PRINT 窗口如下图所示:google.ro/…:
  • 可以在弹出对话框之前设置默认打印机,然后再改回来吗?可能会容易一些。
  • 这篇文章有很多有价值的信息:lessanvaezi.com/changing-printer-settings-using-the-windows-api
  • UI 自动化最好使用 UI 自动化来完成。有关示例代码,请参阅 this answer。使用 UI 自动化有很多好处。一方面,如果在按钮没有标题 "OK" 的系统上运行,代码不会中断(例如在俄罗斯系统上)。也没有理由调用 Windows API 的 ANSI 版本。只需使用 Unicode 版本,每次 API 调用您不必在字符集之间转换多达 4 次。

标签: vba winapi printing sap


【解决方案1】:

已解决的问题(适用于 Windows 10): 请注意,需要的代码是:

'Declarations
    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
    Public Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, ByVal wCmd As Long) As Long
    Dim i                          'index to the selected item
    Dim getPrintName As String     ' the text of the selected item
    Dim getPrintNameLength As Long ' the length of the selected item's text
    Dim printPDFFound As Boolean
    Dim ChildhwndPrint11 As Long
    Dim ChildhwndPrint1 As Long
    Dim ChildhwndPrint As Long
    Dim hwndPrint As Long
    Const GW_CHILD = 5
    Const GW_HWNDNEXT = 2
    Const CB_GETLBTEXTLEN = &H149
    Const CB_GETLBTEXT = &H148

     getPrintName = Space(20)


    'Code Between Previous Lines LINE1 and LINE4 Used To Change The Print Name 

hwndPrint = hwnd
        ChildhwndPrint = GetWindow(hwndPrint, GW_CHILD)
        If ChildhwndPrint = 0 Then
            MsgBox "ChildhwndPrint not found."
            Exit Sub
        End If
        ChildhwndPrint1 = GetWindow(ChildhwndPrint, GW_HWNDNEXT)
        If ChildhwndPrint1 = 0 Then
            MsgBox "ChildhwndPrint1 not found."
            Exit Sub
        End If
        ChildhwndPrint11 = GetWindow(ChildhwndPrint1, GW_HWNDNEXT)
        If ChildhwndPrint11 = 0 Then
            MsgBox "ChildhwndPrint11 not found."
            Exit Sub
        End If

Call SendMessage(ChildhwndPrint11, CB_SHOWDROPDOWN, True, 0)

    i = 0
            printPDFFound = False
            'getPrintName = ""
            Do Until (i = 30) Or (getPrintName = "Microsoft Print to PDF")
                    Call SendMessage(ChildhwndPrint11, CB_SETCURSEL, i, 0)
                    'Call SendMessage(ChildhwndPrint11, CB_GETLBTEXT, 2, buffer)
                    getPrintNameLength = SendMessage(ChildhwndPrint11, CB_GETLBTEXTLEN, ByVal CLng(i), ByVal CLng(0))
                    getPrintName = Space(getPrintNameLength) & vbNullChar
                    getPrintNameLength = SendMessage(ChildhwndPrint11, CB_GETLBTEXT, ByVal CLng(i), ByVal getPrintName)
                    getPrintName = Left(getPrintName, getPrintNameLength)
                    'MsgBox getPrintName
                    If getPrintName = "Microsoft Print to PDF" Then
                        printPDFFound = True
                    End If
                    i = i + 1
            Loop
            If printPDFFound = False Then
                MsgBox "<Microsoft Print to PDF> print name was not found."
                Exit Sub
            End If

解释代码: 我认为它们最多可以是 30 台打印机:

  • 我搜索了 print-name drop-down= ChildhwndPrint11 的处理程序(我使用了一个名为 Spy++ 的 Visual Studio 工具,分别用于我的宏,该工具显示桌面上打开窗口的所有子项)[另外,请在 Windows API Viewer for MS Excel x64 中找到上述标准声明,我已从 Internet 下载)
  • 我使用 CB_SHOWDROPDOWN 显示了下拉菜单
  • 所以我循环直到遇到最大打印机(直到 30 台打印机)或循环直到打印名称为“Microsoft Print to PDF”
  • 我使用了包含打印机名称的向下滚动下拉列表
  • 对于每个 CURSEL(下拉列表中的元素),我提取了打印机名称和打印机长度名称
  • 如果找到打印机,我将 printPDFFound 设置为 TRUE

【讨论】:

    最近更新 更多