This tutorial is written in C# and will address the following:

  1. Finding window handles using the .NET System.Diagnostics.Process class.

  2. Accessing a separate and completely independent application via the Win32 API using the handles we gathered. ( in this case we will be using !Yahoo Messenger)

  3. Gain access to a child window of the independent application and manipulate it (send a string or press a button) by passing a byte array.( in this case the child window will be the send message text box and the send message send button.)

//We'll need to import the System.Diagnostics library so we can access the Process class.

using System.Diagnostics;

 

//These methods are imported in from the user32.dll. I recommend putting them in a separate class under the same

//namespace in order to avoid cluttering up your code.

[DllImport("user32.dll")]

 public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);

[DllImport("user32.dll", SetLastError = true)]

public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

 

[DllImport("user32.dll")]

public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);

 

[DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

 

[DllImport("user32.dll")] public static extern uint SendMessage(IntPtr hWnd, uint MSG, uint zero, byte[] text);

 

[DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

/// Win32 SDK constants

/// </summary>

public const uint WM_SETTEXT = 0x000C;

public const uint WM_GETTEXT = 0x000D;

public const uint EM_SETSEL = 0x000000B1;

public const uint WM_GETTEXTLENGTH = 0x000E;

public const uint SMTO_ABORTIFHUNG = 0x0002;

public const int BM_CLICK = 0x00F5;

 

//We will call this method whenever we want to send a message to Yahoo Messenger from our application

public void PostToMessengerChat()

{

//you can find the name of the process that owns the windows you are trying to access by

//accessing the task-manager. Then load a process array with the following line.

Process[] processes = Process.GetProcessesByName("YahooMessenger");

//Declare a null window handle called hwnd.

IntPtr hwnd = IntPtr.Zero;

//Declare a null window handle called mainHand

IntPtr mainHand = IntPtr.Zero;

//Iterate through the process array until we find the window we want

foreach (Process p in processes)

{

//get WindowTitle and check it's the one you want

String checkString = p.MainWindowTitle;

//all !Yahoo chat rooms end with this patternString

String patternString = "-- Chat";

 

if (checkString.Contains(patternString))

{

//the pattern matches ! This is the window we want. Get it's handle.

mainHand = p.MainWindowHandle;

}

}

//find the class name of the child window using spy++ (YIMInputWindow)

//this function returns the handle of the window that matches the class name string.

IntPtr childWindow = Win32API.FindWindowEx(mainHand, IntPtr.Zero, "YIMInputWindow", IntPtr.Zero);

//WM_GETTEXTLENGTH - get the length of the users text in the text input window text if there is any

int textLength = Win32API.SendMessage(childWindow, Win32API.WM_GETTEXTLENGTH, 0, IntPtr.Zero);

//create a StringBuilder to hold users text input StringBuilders are {Zero Based}

StringBuilder writingtext = new StringBuilder(textLength + 1);

//WM_GETTEXT - sendmessage with a stringbuilder arg and length arg returns a stringbuilder that contains the

//current text in the YIMInputWindow. This is, so that when we send our message it doesnt mess up the current

//users text if they happen to be typing. This part is a bit weird because the method loads the stringbuilder

//yet we never assign it. By passing the stringbuilder to this method our result is a stringbuilder containing

//the users current text.

Win32API.SendMessage(childWindow, Win32API.WM_GETTEXT, textLength + 1, writingtext);

 

//create a byte array of the string we will be sending, in this case it is the currently playing MP3.

byte[] encryptedText_byte = System.Text.Encoding.ASCII.GetBytes((": hears: " +

playList.Items[currentSongNumber]).ToCharArray());

 

//WM_SETTEXT - send our song string byteArray

Win32API.SendMessage(childWindow, Win32API.WM_SETTEXT, 0, encryptedText_byte);

//find the send buttons window handle

IntPtr buttonWindow = Win32API.FindWindowEx(mainHand, IntPtr.Zero, "Button", "&Send");

//BM_CLICK - click the button to send the song message to the chat

Win32API.SendMessage(buttonWindow, Win32API.BM_CLICK, 0, encryptedText_byte);

//WM_SETTEXT - put the users current text back to it's original place

encryptedText_byte = System.Text.Encoding.ASCII.GetBytes((writingtext.ToString()).ToCharArray());

Win32API.SendMessage(childWindow, Win32API.WM_SETTEXT, 0, encryptedText_byte);

//WM_SETSEL - put the cursor at the end of the users text so they can keep typing

Win32API.SendMessage(childWindow, Win32API.EM_SETSEL, writingtext.Length, writingtext.Length);

}

Your feedback is welcome.