【问题标题】:Writing/Reading text in the Text box of a application from another application从另一个应用程序的应用程序的文本框中写入/读取文本
【发布时间】:2011-11-17 21:28:18
【问题描述】:

有什么方法可以从另一个应用程序的应用程序的文本框中写入/读取文本。 我能做的是,我可以使用 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>();
    }
}

【问题讨论】:

  • 您想要 SendMessage/wm_gettext/wm_settext - 搜索 [c#] wm_settext 时的示例

标签: c# winapi pinvoke


【解决方案1】:

使用GetWindowText方法读取文本,使用SetWindowText设置文本。

但是,如果您控制这两个应用程序,您确实应该考虑使用老式命名管道、共享内存或最新的 WCF 来实现某种进程间通信。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 其实另一个应用是第三方应用,所以我不能使用命名管道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    • 2019-03-06
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    相关资源
    最近更新 更多