在另一个应用程序的应用程序的文本框中编写/读取文本

时间:2011-09-15 13:19:46

标签: c# winapi pinvoke

有没有办法在另一个应用程序的应用程序的文本框中编写/读取文本。 我能做的是我可以使用win32 api获取该文本框的句柄。但不知道如何在文本框中写入文本。 我的代码如下。 请参阅WriteTextUsingHandle方法

public class WriteText
{        
    public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);

    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, long wParam, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    public static extern IntPtr GetParent(IntPtr hWnd);

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

    public static void WriteTextUsingHandle(String text)
    {
        Process reqProcess = null;
        foreach (Process aProcess in Process.GetProcessesByName("any app"))
        {
            reqProcess = aProcess;
            break;
        }

        if (reqProcess == null) return;

        HanldesInfo dialogClasses = WriteText.GetChildWindows(reqProcess.MainWindowHandle, true, "#32770", String.Empty);
        HanldesInfo editBoxHandle = WriteText.GetChildWindows(dialogClasses.ChildHandles[1], true, "Edit", String.Empty);

        //now i want to write/Read the text using editBoxHandle. But how ?
    }

    /// <summary>
    /// Returns a list of child windows
    /// </summary>
    /// <param name="parent">Parent of the windows to return</param>
    /// <returns>List of child windows</returns>
    private static HanldesInfo GetChildWindows(IntPtr parent, bool onlyImmediateChilds, String className, String text)
    {
        HanldesInfo result = new HanldesInfo(parent, onlyImmediateChilds, className, text);
        GCHandle listHandle = GCHandle.Alloc(result);
        try
        {
            EnumChildWindows(parent, WriteText.EnumWindowAllChildCallBackMethod, 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 fail</returns>
    private static bool EnumWindowAllChildCallBackMethod(IntPtr handle, IntPtr pointer)
    {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        HanldesInfo list = gch.Target as HanldesInfo;

        if (list == null) { throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); }

        if (list.OnlyImmediateChilds && list.ParentHandle != WriteText.GetParent(handle)) return true;

        if (list.ClassName.Length > 0)
        {
            StringBuilder className = new StringBuilder(100);
            WriteText.GetClassName(handle, className, className.Capacity);

            if (String.Compare(className.ToString().Trim(), list.ClassName, true) != 0) return true;
        }

        list.ChildHandles.Add(handle);

        //  if you want to cancel the operation, then return a null here
        return true;
    }
}

public class HanldesInfo
{
    public IntPtr ParentHandle { get; private set; }
    public bool OnlyImmediateChilds { get; private set; }
    public String ClassName { get; private set; }
    public String Text { get; private set; }
    public List<IntPtr> ChildHandles { get; private set; }

    internal HanldesInfo(IntPtr parentHandle, bool onlyImmediateChilds) : this(parentHandle, onlyImmediateChilds, String.Empty, String.Empty) { }
    internal HanldesInfo(IntPtr parentHandle, bool onlyImmediateChilds, String className) : this(parentHandle, onlyImmediateChilds, String.Empty, String.Empty) { }
    internal HanldesInfo(IntPtr parentHandle, bool onlyImmediateChilds, String className, String text)
    {
        this.ParentHandle = parentHandle;
        this.OnlyImmediateChilds = onlyImmediateChilds;
        this.ClassName = (className ?? String.Empty).Trim();
        this.Text = (text ?? String.Empty).Trim();
        this.ChildHandles = new List<IntPtr>();
    }
}

2 个答案:

答案 0 :(得分:2)

使用GetWindowText方法阅读文字,使用SetWindowText设置文字。

但是,如果你控制两个应用程序,你真的应该考虑使用旧学校命名管道,共享内存或最新的WCF来实现某种进程间通信。

答案 1 :(得分:1)

您应该专注于进程间通信以实现您的目标。作为同一台机器上的两个进程,我建议您创建一个named pipe.