Reputation:
Im trying to get this thing to work all day. Im trying to paste an input text to a textbox in another windows application, (lets say Chrome's URL bar) I managed to get the main window hwnd, but when I used SendMessage, it just changed the title of the window
SO I am trying to figure out how exactly do I find out, dynamically, the hwnd of my textbox. I also tried Spy++ but it gave me the same hwnd for all child windows for some reason, must did something wrong.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
private static IntPtr WinGetHandle(string wName)
{
IntPtr hWnd = IntPtr.Zero;
foreach (Process pList in Process.GetProcesses())
{
if (pList.MainWindowTitle.Contains(wName))
{
hWnd = pList.MainWindowHandle;
}
}
return hWnd;
}
static void Main(string[] args)
{
List<IntPtr> myList = GetChildWindows(WinGetHandle("chrome"));
foreach(IntPtr ptr in myList)
{
//No idea which one of those IntPtr is actually my textbox
//SendMessage((IntPtr)788018, 0x000C, 0, "text here");
}
Console.ReadLine();
}
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
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;
}
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;
}
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
}
}
Upvotes: 2
Views: 2368
Reputation:
Sadly I couldnt find a way to make it the way I wanted, but I found a workaround that works pretty well:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
static void Main(string[] args)
{
IntPtr hWnd = FindWindow(null, "Origin");
if (!hWnd.Equals(IntPtr.Zero))
{
// activate Notepad window
if (SetForegroundWindow(hWnd))
{
// send "Hello World!"
SendKeys.SendWait("Hello World!");
// send key "Tab"
SendKeys.SendWait("{TAB}");
// send key "Enter"
SendKeys.SendWait("{ENTER}");
}
}
}
}
}
Upvotes: 0
Reputation: 39142
I also tried Spy++ but it gave me the same hwnd for all child windows for some reason, must did something wrong.
Not all applications use old-school "heavy" controls backed by a windows handle. For example, .Net WPF applications will exhibit the same behavior of just one handle for the main window itself. Everything is else drawn directly to the screen as needed via DirectX. Web browsers are "light" as well and don't use controls backed by a handles. Basically if Spy++ doesn't show child windows inside the main window then you won't be able to use the traditional window manipulation APIs or SendMessage().
Upvotes: 2