How can I retrieve the name of the printer chosen in Acrobat?
Asked Answered
G

1

9

I want to get the name of the printer chosen in Acrobat PrintDialog using SendMessage Windows API.

This is sample code.

static string GetWindowText( hwnd_printDialog_in_Acrobat )
{
    int comboBoxCount = 0;
    int HWND_PRINTER_NAME = 1 ;

    List<IntPtr> ChildPtrList = GetChildWindows(hwnd_printDialog_in_Acrobat);
    for( i=0 ;  i < ChildPtrList.Size(); i++)   {
        GetClassName( ChildPtrList[i], sClass, 100);
        if (sClass.ToString() == "ComboBox") {
            comboBoxCount++;
            if (comboBoxCount == HWND_PRINTER_NAME )   {
                 hwnd = ChildPtrList[i];
                 break;
            }
        }
    }
    ChildPtrList.Clear();

    int sSize ;
    sSize = SendMessageW( hwnd, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero )+1;
    StringBuilder  sbTitle = new StringBuilder( sSize );
    SendMessageW( hwn, WM_GETTEXT, (IntPtr)sSize, sbTitle);
    return (sbTitle.ToString());
}

The return value of sSize is 4; The value of sbTitle.ToString() is "?-" etc. The expected resu What is wrong?

Galinagalindo answered 12/9, 2012 at 5:14 Comment(1)
using spy++ i was able to find the printer combobox that is class "ComboBoxEx32" which is a child of a groupbox. it also seems that ComboBoxEx32 has a child "ComboBox" with window caption "㚘\"... this can best be solved by using spy++ on your machine to enumerate the window... some windows may not have handles (knowing Adobe) in that case you will need to use the MS accessibility API's to get the control properties....Abutilon
H
1

Here are my current guesses to your problem:

  • HWND_PRINTER_NAME is not 1
  • The class name you are looking for is not "ComboBox"
  • Problem in the code not listed:
    • Grabbing the wrong parent window or treating the handle incorrectly
    • SendMessageW DllImport is wrong, or parameters are treated incorrectly

You do have some bugs in the code listed so, my code isn't exactly the same, but here is the code I used to try to figure your problem. I could not get it to behave the way you describe. My code simply never finds a Child Window with the Class name "ComboBox".

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace PrinterChoosenInAcrobat
{
class Program
{
    public const uint WM_GETTEXTLENGTH = 0x000E;
    private const uint WM_GETTEXT = 0x000D;

    // External OS calls
    [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
    public static extern bool SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
        StringBuilder lParam);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wparam,
        IntPtr lparam);

    [DllImport("User32.dll")]
    public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

    [DllImport("user32.dll")]
    static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName,
    int nMaxCount);

    static void Main(string[] args)
    {
        try
        {
            IntPtr windowHandle = (IntPtr)FindWindow("AcrobatSDIWindow", null);
            string text = GetWindowText(windowHandle);

            Console.WriteLine(text);

        }
        catch (Exception ex)
        {
            Console.Out.WriteLine(ex.Message);
        }

        // Don't close before I get to read the results
        Console.WriteLine();
        Console.WriteLine("Press Enter to quit.");
        Console.ReadLine();
    }

    static string GetWindowText(IntPtr hwnd_printDialog_in_Acrobat)
    {
        int comboBoxCount = 0;
        int HWND_PRINTER_NAME = 1;

        List<IntPtr> ChildPtrList = GetChildWindows(hwnd_printDialog_in_Acrobat);
        IntPtr hwnd = IntPtr.Zero;
        for (int i = 0; i < ChildPtrList.Count; i++)
        {
            StringBuilder sClass = new StringBuilder();
            GetClassName(ChildPtrList[i], sClass, 100);
            if (sClass.ToString() == "ComboBox")
            {
                comboBoxCount++;
                if (comboBoxCount == HWND_PRINTER_NAME)
                {
                    hwnd = ChildPtrList[i];
                    break;
                }
            }
        }
        ChildPtrList.Clear();

        int sSize;
        sSize = (int)SendMessage(hwnd, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero) + 1;

        StringBuilder sbTitle = new StringBuilder(sSize);
        SendMessage(hwnd, WM_GETTEXT, (IntPtr)sSize, sbTitle);
        return (sbTitle.ToString());
    }

    #region Code from http://pinvoke.net/default.aspx/user32/EnumChildWindows.html
    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

    /// <summary>
    /// Returns a list of child windows
    /// </summary>
    /// <param name="parent">Parent of the windows to return</param>
    /// <returns>List of child windows</returns>
    public static List<IntPtr> GetChildWindows(IntPtr parent)
    {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try
        {
            EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
            EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
        }
        finally
        {
            if (listHandle.IsAllocated)
                listHandle.Free();
        }
        return result;
    }

    /// <summary>
    /// Callback method to be used when enumerating windows.
    /// </summary>
    /// <param name="handle">Handle of the next window</param>
    /// <param name="pointer">Pointer to a GCHandle that holds a reference to the list to fill</param>
    /// <returns>True to continue the enumeration, false to bail</returns>
    private static bool EnumWindow(IntPtr handle, IntPtr pointer)
    {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
        {
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
        }
        list.Add(handle);
        //  You can modify this to check to see if you want to cancel the operation, then return a null here
        return true;
    }

    /// <summary>
    /// Delegate for the EnumChildWindows method
    /// </summary>
    /// <param name="hWnd">Window handle</param>
    /// <param name="parameter">Caller-defined variable; we use it for a pointer to our list</param>
    /// <returns>True to continue enumerating, false to bail.</returns>
    public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
    #endregion

}
}
Henley answered 26/10, 2012 at 17:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.