9

我想使用 SendMessage Windows API 获取在 Acrobat PrintDialog 中选择的打印机的名称。

这是示例代码。

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());
}

sSize的返回值为4;的值为sbTitle.ToString()"?-" 等 预期的 resu 有什么问题?

4

1 回答 1

1

以下是我目前对您的问题的猜测:

  • HWND_PRINTER_NAME 不是 1
  • 您要查找的类名不是“ComboBox”
  • 未列出代码中的问题:
    • 抓取错误的父窗口或错误地处理句柄
    • SendMessageW DllImport 错误,或参数处理不当

您在列出的代码中确实存在一些错误,因此我的代码并不完全相同,但这是我用来尝试解决您的问题的代码。我无法让它表现得像你描述的那样。我的代码根本找不到类名称为“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

}
}
于 2012-10-26T17:24:46.550 回答