开发者

Writing/Reading text in the Text box of a application from another application

Is there any way to write/Read the text in the Text box of a application from another application. What i am able to do is that i can get the handle of that text box using win32 api. But don't know how to write the text in the text box. My code is as follow. Please see the WriteTextUsingHandle Method

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 r开发者_运维技巧eference 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>();
    }
}


Use the GetWindowText method to read the text and SetWindowText to set the text.

However, if you control both applications, you really should think about implementing some kind of inter process communication either using old school named pipes, shared memory or up-to-date WCF.


You should be concentrating on interprocess communication to achieve your goal. Being two processes on the same machine I suggest you create a named pipe.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜