Mark S. Rasmussen improve.dk
Apr 06
2007

Until now we’ve seen how to retrieve basic properties of windows as well as how to interact with them by sending keypresses. Up until now we’ve had to find the handle by using Winspector or a similar program. This time I’ll present a way of finding the handles programmatically.

using System.Runtime.InteropServices;
using System.Text;
using System;

namespace Enumerating_windows
{
	class Program
	{
		// These are two Win32 constants that we'll need, they were explained in an earlier blog.
		const int WM_GETTEXT		= 0x000D;
		const int WM_GETTEXTLENGTH	= 0x000E;

		// SendMessage overload.
		[DllImport("User32.dll")]
		public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, int lParam);

		// SendMessage overload.
		[DllImport("User32.dll")]
		public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam);

		// The GetClassName function takes a handle as a parameter as well as a StringBuilder
		// and the max capacity of the StringBuilder as parameters. It'll return the windows
		// class name by filling up the StringBuilder - though not any longer than the max capacity.
		// If the class is longer than the max capacity it will simply be cropped. Having a larger
		// capacity than necessary is simply a matter of performance.
		[DllImport("User32.Dll")]
		public static extern void GetClassName(int hWnd, StringBuilder s, int nMaxCount);

		// The EnumWindows function will enumerate all windows in the system. Each window will cause
		// the PCallBack callback function to be called.
		[DllImport("user32.Dll")]
		static extern bool EnumWindows(PCallBack callback, int lParam);

		// This is the delegate that sets the signature for the callback function of the EnumWindows function.
		private delegate bool PCallBack(int hwnd, int lParam);

		static void Main(string[] args)
		{
			// All we'll do is to invoke the EnumWindows function, passing in a new delegate specifying the EnumWindowsCallback
			// function as the callback function. The lParam parameter can be used to send in an integer that will be passed
			// onto the callback function unmodified. It's optional, but it may be useful in some situations.
			EnumWindows(new PCallBack(EnumWindowsCallback), 0);

			Console.Read();
		}

		// This function will be called exactly once for each window the EnumWindows function finds. We have no idea what
		// window / type of windows it'll get called for, so we'll have to identify the windows somehow. The lParam
		// parameter contains the value we passed when we called the EnumWindows function.
		private static bool EnumWindowsCallback(int handle, int lParam)
		{
			// First we'll find the class of the window as that is usually the parameter that narrows our search down the furthest.
			// As classes are usually rather short, a capacity of 256 ought to be plenty.
			StringBuilder sbClass = new StringBuilder(256);
			GetClassName(handle, sbClass, sbClass.Capacity);

			// As explained in an earlier blog we then get the text of the window.
			int txtLength = SendMessage(handle, WM_GETTEXTLENGTH, 0, 0);
			StringBuilder sbText = new StringBuilder(txtLength + 1);
			SendMessage(handle, WM_GETTEXT, sbText.Capacity, sbText);

			// Now we can write out the information we have on the window:
			Console.WriteLine("Handle: " + handle);
			Console.WriteLine("Class : " + sbClass);
			Console.WriteLine("Text  : " + sbText);
			Console.WriteLine();

			// When we return true, the EnumWindows function will proceed to call the callback function with the next window.
			// If we returned false, the EnumWindows function would stop and the callback function wouldn't get called again.
			// This can be useful if we're looking for a specific window - once it's found we can just return false, no reason
			// to handle any other windows.
			return true;
		}
	}
}

And the result:

Apr 06
2007

Now to complete the toolset required to make a great spyware / browser hijacking application, we’ll make Internet Explorer navigate to the address we set.

Like before, open an Internet Explorer browser and obtain a handle to the address field.

using System;
using System.Runtime.InteropServices;
using System.Globalization;

namespace Sending_keypresses_to_a_window
{
	class Program
	{
		// A Win32 constant
		const int WM_SETTEXT = 0x000C;
		const int WM_KEYDOWN = 0x0100;
		const int VK_RETURN  = 0x0D;

		// An overload of the SendMessage function, this time taking in a string as the lParam.
		[DllImport("User32.dll")]
		public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, string lParam);

		// PostMessage is very similar to SendMessage. They both send a message to the given
		// handle / window, the difference being that SendMessage sends the message and waits
		// for the window to "handle" the message and return a return code. PostMessage on the
		// other hand simply posts the message and returns instantly, whether the window
		// handles the message or not, we don't care.
		[DllImport("User32.Dll")]
		public static extern Int32 PostMessage(int hWnd, int msg, int wParam, int lParam);

		static void Main(string[] args)
		{
			// First, read the handle from the console, remember this has to be in HEX format!
			int handle = int.Parse(Console.ReadLine(), NumberStyles.HexNumber);

			// Now we'll send the WM_SETTEXT message to the window, passing the text
			// through the lParam parameter.
			SendMessage(handle, WM_SETTEXT, 0, "http://www.improve.dk");
			Console.WriteLine("Text set!");

			// Now send a message telling the Edit box that the Return key has been pressed,
			// resulting in Internet Explorer navigating to the page.
			PostMessage(handle, WM_KEYDOWN, VK_RETURN, 1);
			Console.WriteLine("Return keypress sent!");

			// And we're done
			Console.Read();
		}
	}
}

And the result:

Apr 04
2007

This time we want to retrieve the text from a given window, represented by a handle. Like last time, open an Internet Explorer instance. Now open Winspector and select the address field, ensure that it is the address field itself (class = Edit) and not the ComboBox that you select.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;

namespace Get_text_from_handle
{
	class Program
	{
		// These are two Win32 constants that we'll need, they'll be explained later.
		const int WM_GETTEXT		= 0x000D;
		const int WM_GETTEXTLENGTH = 0x000E;

		// The SendMessage function sends a Win32 message to the specified handle, it takes three
		// ints as parameters, the message to send, and to optional parameters (pass 0 if not required).
		[DllImport("User32.dll")]
		public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, int lParam);

		// An overload of the SendMessage function, this time taking in a StringBuilder as the lParam.
		// Through the series we'll use a lot of different SendMessage overloads as SendMessage is one
		// of the most fundamental Win32 functions.
		[DllImport("User32.dll")]
		public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam);

		static void Main(string[] args)
		{
			// First, read the handle from the console, remember this has to be in HEX format!
			int handle = int.Parse(Console.ReadLine(), NumberStyles.HexNumber);

			// This is a bit tricky. To retrieve the text from a window, we have to know it's length beforehand.
			// This is because we have to send a StringBuilder of the correct length as a parameter. If it's too
			// small, it won't be able to contain the full text. If it's too large, it's inefficient. When using
			// the SendMessage function with the WM_GETTEXTLENGTH message, it returns the length of the
			// window text.
			int txtLength = SendMessage(handle, WM_GETTEXTLENGTH, 0, 0);

			// After having retrieved the length of the string, we create a StringBuilder to hold it.
			StringBuilder sb = new StringBuilder(txtLength + 1);

			// Sending the message WM_GETTEXT to the window, passing int he length of the text (the capacity
			// of the StringBuilder) as well as a reference to the StringBuilder will result in the
			// StringBuilder being filled up with the windows text.
			SendMessage(handle, WM_GETTEXT, sb.Capacity, sb);

			// Finally we'll write out the window text by ToString()'ing the StringBuilder.
			Console.Write(sb.ToString());
			Console.Read();
		}
	}
}

And the result:

Apr 04
2007

This time we won’t be reading the text from a window, we’ll be setting it.

Like last time, open an Internet Explorer browser and obtain a handle to the address field.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;

namespace Set_text_by_handle
{
	class Program
	{
		// A Win32 constant
		const int WM_SETTEXT = 0x000C;

		// An overload of the SendMessage function, this time taking in a string as the lParam.
		[DllImport("User32.dll")]
		public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, string lParam);

		static void Main(string[] args)
		{
			// First, read the handle from the console, remember this has to be in HEX format!
			int handle = int.Parse(Console.ReadLine(), NumberStyles.HexNumber);

			// Now we'll send the WM_SETTEXT message to the window, passing the text
			// through the lParam parameter.
			SendMessage(handle, WM_SETTEXT, 0, "http://www.improve.dk");

			// And we're done
			Console.Write("Text set!");
			Console.Read();
		}
	}
}

And the result:

Note that we have not navigated to the address, we have only set it!

Apr 03
2007

So we have a handle, what process does it belong to? Our goal is to obtain a .NET System.Diagnostics.Process object that corresponds to the owner process of the handle we input.

Let’s first open up an Internet Explorer window, just leave it at the start page, whatever yours is.

Now fire up Winspector and locate the Internet Explorer window, you’ll see the handle in HEX format in the treeview.

using System;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Diagnostics;

namespace Get_process_from_handle
{
	class Program
	{
		// The DllImport attribute specifies the Win32 DLL that contains the function we're importing,
		// in this case it's the user32.dll file that resides in the C:WindowsSystem32 directory.
		// The function we're importing is GetWindowThreadProcessId, it takes a handle and a reference
		// to an outgoing integer that'll return the process ID of the handle.
		[DllImport("user32")]
		public static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);

		static void Main(string[] args)
		{
			// First, read the handle from the console, remember this has to be in HEX format!
			int handle = int.Parse(Console.ReadLine(), NumberStyles.HexNumber);

			// Now that we have the handle, create an uninitialized integer that'll hold the process ID
			// of the handle process.
			int processID;
			GetWindowThreadProcessId(handle, out processID);

			// Now that we have the process ID, we can use the built in .NET function to obtain a process object.
			Process p = Process.GetProcessById(processID);

			// Finally we'll write out the process name to confirm success.
			Console.Write(p.ProcessName);
			Console.Read();
		}
	}
}

And the result:

Apr 02
2007

First of all, to manipulate and use the Win32 API, we must know about the system itself, the windows, the controls and so forth. Visual Studio comes bundled with Spy++ which enables us to identity the various windows and controls of application, but honestly, it’s pretty bad. Instead you should download Winspector.

Threads & processes

Each application/window in Windows belongs to a given thread under a given process. A process may have multiple threads and windows, but a thread and a window can only belong to a single process.

Windows & handles

Usually we refer to a window as the overall container of visual representation of data in Windows, in this case it’s a bit more detailed though. In all API work a window is a standard Win32 control, that could be a button, a toolbar, a label, a window (as per the usual definition) and so forth. Each window is assigned a handle, and by using this handle we can uniquely reference any given window. A window may have any number of child windows, that could be the controls of a dialog box, and the children may have children themselves and so forth.

Try and mess around with Winspector a bit. Identify the various windows of the system (including those that are not visible). Inspect their properties, the process they belong to, their parent windows and so forth. Most, if not all, of the API tips & tricks posts will include references to windows, handles, processes and threads - so get used to them.

Mar 29
2007

So, tell me, do you notice anything unusual in the picture below?

For a month or so I’ve used my computer with the Windows Start menu at the top. Am I crazy? Most likely. I started out doing it on my home computer (on all monitors), while keeping the start menu at the bottom at work. Honestly, it is feels quite weird and wrong in the beginning, and I was constantly throwing my mouse southwards just to realize that my work had been for nothing, as the Start menu was actually up north. I really couldn’t impose this waste of time upon my employers, that’s why I kept it down south there.

After a couple of weeks had passed, things started to shift. I was now starting to notice how wrong it was for the Start menu to be at the bottom at work - and how cumbersome it really is! So I moved it. And everybody laughed at me.

So why’d you want to move your Start menu to the top of the monitor?

See how all the menus are in the top? Usually - excluding gaming and other special applications - our mouse will be working inside a menu, dragging a window, using the Start menu, or in the main content area of a browser/application. Common to most of these are that they all happen at the top of the monitor. As the monitor gets larger, the distance between the top and the bottom becomes greater.

Having the Start menu at the top really saves a lot of mouse movement. The only negative side that I’ve become aware of is that you can’t just toss the mouse top-right like a maniac and click to close a window - that’ll now activate the system clock. When using multiple monitors, that really isn’t an issue as you wouldn’t be able to do that anyways since your mouse would enther the other monitor.

The greatest opponent of this efficiency improvement really is… Tradition. I shall not try to hide the fact that it takes a lot of getting used to. After having moved my mouse towards the bottom and hammering a fist in the table for the 100th time, I was almost about to give up. But hang in, for the sake of your carpal tunnel syndrome suffering hand, MOVE THAT START MENU!

Mar 29
2007

Unfortunately it’s been quite silent around here for the last couple of months. I want to change that, so why not make a promise?

I’ve always been bullied by my wannabe developer friends for memorizing most of the Win32 (XP onwards) API. What they don’t realize is just how useful the API is - how powerful it is!

For the complete month of April 2007, I will post a new blog each day containing a Win32 API trick including demonstration code. Although my samples will be in C#, this being the Win32 API, it’s actually usable in more or less any language you want.

I look forward to my missionary work in the name of the holy Win32 API!

Mar 16
2007

Boy am I glad I’ve got my baby insured, guess I’ll need it now :(

Feb 25
2007

I was asked to make a graph of my most recent relationship, what other way is there to express oneself than UML?

My world:

My relationship: