“New” technologies (Discovering the TI world)

Today’s post describes my adventure into the world of TI (Texas Instruments) programming. A little bit out of its time but nevertheless interesting to anyone who likes to learn new things and open their horizons.

My cousin is a few months away of completing his Civil engineering degree and is really interested in TI programming, doing scripts that help him solve problems really fast instead of having to do them manually (most useful in exams). He does all the programming in TI-Basic, a language similar to Basic but specific to TI calculators and like most (if not all) of these interpreted languages, they don’t provide any security if you want to sell your programs. Thus he turned to C programming. Now, C is a whole new beast when compared with this TI-Basic language and it’s much harder to start doing some interesting things without your programs crashing all over the place.

He asked me for help but having no knowledge of this TI-Basic or C tools/libraries/APIs available for these calculators and without access to internet and limited documentation and samples I wasn’t able to get complete the program although I did manage to make half of it. This was a 4 hour marathon that started around 22h30 till 2h30 and I had to admit defeat at the time since I was very tired but I promised to help him to finish the program. I don’t have a TI calculator so I needed to find a way to test it in my PC and fortunately there is an IDE along with an emulator and ROM image available for free on the internet. I’ll list what’s needed to be able to run and the debug C programs for TI calculators because it took me a while to get everything up and running due to incompatible versions of software.

  1. Download and install TIGCC 0.96 beta 8 (Unofficial version)
  2. Download and install TiEmu 3.02a
  3. Download TI Voyage 200 ROM image (my cousin’s model)
  4. Create a project in TIGCC
  5. Run the project (Debug –> Run)
  6. When the TiEmu wizard appears select “You have downloaded a FLASH upgrade on the TI website”
  7. Then select the TI Voyage 200 ROM image you’ve downloaded before.

Voilà! If everything went well you should see the program running on the emulator.

If you want to debug your project, follow these steps:

  1. Project –> Options
  2. Select the “Compilation” tab and then the option “Generate debug information”
  3. Run the project (Debug –> Run)

You should see new windows open if you followed these steps. These are the debug windows that will help you find your bugs.

Here are a few snippets I had to discover here and there through samples / documentation:

/* Retrieves strings passed into the program */
ESI argptr;
int argtype;
char *str;
InitArgPtr (argptr);
while ((argtype = GetArgType (argptr)) != END_TAG)
{
  if (argtype == STR_TAG)
  {
    str = GetStrnArg(argptr);
    printf("%s", str);
  }
  else
    break;
}
/* Get a variable from TI-Basic into C */
SYM_ENTRY *sym_entry = SymFindPtr (SYMSTR ("variableName"), 0);
if (!sym_entry)
  return FALSE;
ESI expr = HToESI(sym_entry->handle);
int argType = GetArgType(expr); /* Retrieves the type of the expression */
long num = GetIntArg(expr); /* Retrieves an integer if the expression holds an integer (positive or negative) */
/* Directly from TIGCC documentation: Run a TI-Basic program or statement from C */
char fname[25];
HANDLE h;
strcpy (fname, name);
strcat (fname, "()");
push_parse_text (fname);
h = HS_popEStack ();
TRY
  NG_execute (h, FALSE);
FINALLY
  HeapFree (h);
ENDFINAL

Including tigcclib.h will make sure that you have all the TI library functions available in C. For the last snippet you need to follow these steps if you have an error regarding push_parse_text function:

  1. go to Project->Options
  2. select the “Compilation” tab
  3. click on “Program Options…”
  4. select the “Operating System” tab
  5. and set the “Minimum AMS Version” as 1.01

Kinect Calibration

This program adjusts Kinect to better see the user, this way the user doesn’t have to move back or forward (unless Kinect’s angles aren’t enough to see the user). I think this is a useful thing to have when you start your Kinect application.

The code is very simple to follow. Use Kinect’s elevation angle to change the Kinect’s “view” and track the user in sight. For each angle count how many joints Kinect is tracking and save that angle as the best if we reach a new maximum number of tracked joints.

void KinectSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
	// Get skeleton information
	using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
	{
		if (skeletonFrame != null && m_skeletonData != null)
		{
			skeletonFrame.CopySkeletonDataTo(m_skeletonData);
		}
	}

	m_curTime = m_watch.ElapsedMilliseconds;

	if (m_calibrationState == CalibrateState.GoingDown)
	{
		// If the sensor reach its lowest angle, let's do a full scan from min angle to max angle.
		if (m_curTime >= WaitTime)
		{
			m_watch.Reset();
			m_watch.Start();

			m_bestAngle = m_kinect.MinElevationAngle;
			m_maxNumTracked = 0;

			m_calibrationState = CalibrateState.GoingUp;
			m_kinect.ElevationAngle = m_angles[m_curAngleIndex++];
		}
	}
	else if (m_calibrationState == CalibrateState.GoingUp)
	{
		if (m_curTime >= WaitTimeGoingUp)
		{
			m_watch.Reset();
			m_watch.Start();

			// If we scanned all the angles, lets adjust kinect to the best angle.
			if (m_curAngleIndex > m_angles.Length - 1)
			{
				m_calibrationState = CalibrateState.GoingBest;
				m_kinect.ElevationAngle = m_bestAngle;
				return;
			}

			m_kinect.ElevationAngle = m_angles[m_curAngleIndex++];
		}

		// For each skeleton, count the number of tracked joints and save the best
		// angle when the number of tracked joints is greater than previous values.
		foreach (Skeleton skeleton in m_skeletonData)
		{
			if (skeleton == null)
				continue;

			if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
			{
				//TODO: Improve algorithm by using the number of inferred joints.
				int numTracked = 0;
				int numInferred = 0;
				foreach (Joint joint in skeleton.Joints)
				{
					if (joint.TrackingState == JointTrackingState.Tracked)
						numTracked++;
					else if (joint.TrackingState == JointTrackingState.Inferred)
						numInferred++;
				}

				if (numTracked >= m_maxNumTracked)
				{
					m_maxNumTracked = numTracked;
					m_bestAngle = m_kinect.ElevationAngle;
				}
			}
		}
	}
	else if (m_calibrationState == CalibrateState.GoingBest)
	{
		// Just wait until kinect adjusts itself to match the best angle.
		if (m_curTime >= WaitTime)
		{
			m_watch.Reset();

			m_calibrationState = CalibrateState.Idle;
			m_kinect.SkeletonFrameReady -= KinectSkeletonFrameReady;

			// Reset Kinect state.
			DisableStreams();
			EnableStreams();

			// Signal that we finished the calibration.
			if (OnCalibrationComplete != null)
				OnCalibrationComplete();
		}
	}
}

You may notice two things about the code:

  • First is that I’m using time to control between Kinect movements. The reason for this is that if we try to compare Kinect with the angle we set, we might not get the same value for different reasons (Kinect sensor is not 100% accurate or it couldn’t physically rotate the sensor to that exact angle).
  • And second is the fact that I’m only scanning the skeleton for some angles. I don’t know if this is a Kinect’s limitation or if I did something wrong in the code but I couldn’t track any joints while Kinect was moving. So what I did was move the sensor between some angles and wait there a bit to count the bones for each one of those angles.

Known limitations:

  • it only supports 1 user at this moment;
  • the scanning process is not ideal.

Download:

Kinect Calibration (13Kb)

Visual Studio 2010/11 Utilities

Here is a compilation of very useful utilities for VS 2010 and VS 11.
Note: Utilities with an asterisk (*) beside the name are not available to VS 11 yet.

CLIArgs Made Easy

http://www.ricardosabino.com/?p=214
CLI Args Made Easy (Command Line Arguments Made Easy) is an add-in that allow you to change the command line arguments of the startup project very easily by adding a combobox in the toolbar. It also saves all the arguments you insert for future use.

Debugger Canvas (*)

http://msdn.microsoft.com/en-us/devlabs/debuggercanvas.aspx
Debugger Canvas is a new user experience for the debugger in Visual Studio Ultimate. It pulls together the code you’re exploring onto a single pan-and-zoom display. Visual debugger and multithreading debugging goodies.

Productivity Power Tools (*)

http://visualstudiogallery.msdn.microsoft.com/d0d33361-18e2-46c0-8ff2-4adea1e34fef
A set of extensions to Visual Studio Professional (and above) which improves developer productivity. Very useful enhanced scrollbar, vertical tabs, quick find files, searchable references and editing tools.

ReSharper

http://www.jetbrains.com/resharper/
With unparalleled support for C#, VB.NET, XAML, JavaScript, XML, HTML, CSS, ASP.NET and ASP.NET MVC, including comprehensive cross-language functionality, ReSharper will help Visual Studio users write better code, easily examine and refactor existing code bases. A must have for anyone who’s doing C# code.

Visual Assist X

http://www.wholetomato.com/
Read, write, navigate, and refactor code FAST with more than 50 productivity-boosting features for C++/C, C#, VB, ASP, JavaScript. A must have for anyone who’s doing C++ code.

VisualHG (*)

http://visualhg.codeplex.com/
Mercurial Source Control Plugin for MS Visual Studio.

Back To The Future as Code

David Amador twitted about this cool site Movies as Code and I decided to make a simple entry for Back To The Future as C++. Here is my entry: http://moviesascode.net/adventure/back-to-the-future-2/

The code doesn’t appear correctly on that site so here it is the full version:

#include <future>
#include <iostream>

int main()
{
  auto future = std::async([] { return "Future"; });
  std::cout << "Back To The " << future.get() << std::endl;
  return 0;
}

For those who didn’t get it: C++11 added a new feature that is used in the sample called “future” that will hold the result of an async function somewhere in the future. It was just to play around with the name of that feature :)

Jumping Jack for WP7 – GameDev Fun Facts

Last night was time for another XNA Pizza Night event at Microsoft Portugal (Tagus Park). Once again ZPX presented a “new” game. “New” between quotes because the original game is from 1983 and it was older than 90-95% of the people in the audience. The game is none other than Jumping Jack for ZX Spectrum.

I played this game for the first time almost 27 years ago when I had just made 5. In fact, this was the first game I ever played on a computer and it’s probably because of it I’m here making games.

I want to dedicate this game to the memory of Nuno Sabino, my brother. It was him who received the ZX Spectrum 48k as a Christmas present and it was him who got this great game and so many others that influenced me and made me want to program and make games since then. Thanks for everything bro.

jumping_jack_wp7

Let’s get into the development fun facts:

  • It took me about two weeks working after my daily job to get this working for the demo. This would take less time if I worked on it regularly everyday, I would say 1 week. I don’t know how much time it took Albert Ball to program the original version but my guess is that it took him a little longer. He had  to program it in Z80 assembly and didn’t have help from tools we have available today, specially for debugging, it must have been a challenge at that time.
  • Although we had the Spectrum 48k, the original version of the game ran on the Spectrum 16k, i.e., it ran in less than 16k of memory. The actual version for WP7 takes about 10-16 MB, more than 1000 times larger than the original version. I didn’t and won’t make an effort at this time to make the game as smaller as the original version and I probably couldn’t do it for the WP7 but I think I could do it for the PC version if I had some time. Maybe someday, who knows.
  • The game took around 23 seconds to display a splash screen and 55 seconds to load the game making that 1 minute and 18 seconds total to be able to play it. The WP7 version takes about takes 3 seconds to load (and that’s because it displays the splash screen for 3 seconds otherwise the splash screen would pop in and out too quickly.)
  • At this moment this version has about 2000 lines of code. Once again I don’t know the exact number of lines for the original version but I think it will probably be more than 2k lines of Z80.
  • I started by using Farseer Physics but during development I realized that doing the “physics” by hand would be easier than tweaking Farseer Physics. In this demo I’m still using Farseer doing raycasts to see if the player can jump or falls and the debug to draw the lines “Fixtures”. I will probably end up removing Farseer completely in the final version.
  • The graphics and sounds are exact replicas of the original game. I took screenshots from the game playing on a Spectrum emulator and edited them to adjust the transparencies. I was going to record the sounds from the emulator but Zalo had already done that and I used the sounds from his 3d version.
  • The last thing I want to talk about comes from a Spectrum limitation in the graphics display. Spectrum machines had a 256×192 resolution and 15 available colors (3-bit palette that makes 8 colors and another additional bit that says if a color is bright or dark but since one of those colors was black, that didn’t have the bright version making the 15 colors.) The way the information was drawn on the screen was in blocks of 8×8 pixels known as attribute blocks. Only two colors could be used in each of these blocks and if a program tried to display 3 colors in any attribute block one of the colors would change to match one of the other colors, this was known as attribute clash. In Jumping Jack this problem was evident in various situations, one of them was when Jack crashed against a line/wall as seen in the following image:

jumping_jack_wp7_headcrash

Jack was rendered in red due to this limitation and I decided to keep it rendered in red as I thought it was funnier and made sense to show the shocking moment.

And that’s it, Jumping Jack for Windows Phone 7 will be released eventually (soon I hope), maybe by other name.

SilverMenu library for WP7

Inspired by the menus of WP7 game Puzzle Jumble, I decided to write a library that would help me and others to build menus for WP7 games easily. The Puzzle Jumble’s GUI code is a bit of a mess because it wasn’t thought for this kind of interface from the beginning so I decided to write SilverMenu from scratch.

Puzzle Jumble’s GUI

 

SilverMenu aims to bring some of the Silverlight user interface that is now present on WP7 to the XNA. To make it simple to use you can build simple animated menus with just a few lines of XML. It has only one week of development but you can see some progress already:

First SilverMenu sample.

 

With time I hope it grows into something more complete and useful. I’ll still update my blog about this project but if you want to follow the project closely and keep up to date, as well as, download the last build, you can do it at http://silvermenu.codeplex.com. I hope you find it useful and I appreciate all the feedback I can get. Thanks!

Windows Phone 7 – Tips for programming games

Puzzle Jumble started as an experiment to test and learn a little bit about XNA and Windows Phone 7. I decided to write some tips to help those who like me started experimenting with XNA and WP7.

Stencil

The stencil was used to cut the hole for doors so that pieces would appear to be sliding over the doors but under the board. The stencil was active in every frame which lowered the frame rate quite a lot (18-20 FPS). The solution was to activate the stencil only when a piece is going to leave through a door, so be careful when using the stencil buffer on the WP7.

DXT

GPUs like the DXT format and the WP7 is no exception, but unlike desktop’s GPUs the WP7 processor only loads DXTs that are power of two. My regret is not using DXT from the beginning when I started working on Puzzle Jumble. When I changed all my textures to DXT I had to change a lot of code, all the draw calls where I was using a position to draw a sprite had to be changed to a rectangle because the textures had a different resolution (power of two).
But the change was very useful:
– I gain some FPS;
– the memory footprint was reduced from 95MB (total peak) to about 45MB;
– the XAP file was reduced from 25MB to 9MB;
– thus, as a consequence reduced the loading times.

Floats (culture)

When parsing floats it’s easy to add bugs in your application if you ignore the culture format. Make sure to use the correct format provider or at least use the culture independent System.Globalization.NumberFormatInfo.InvariantInfo.

Float precision

Another problem that I found when using floats was that this comparison: if(a < float.Epsilon) (when a = 0) would work everywhere except on the WP7 device itself where it would always return false.

HTML page requests

This is not a WP7 specific problem but I thought it was worth mentioning it. Since Microsoft didn’t provide us with an API for leader boards I implemented an online score system using our servers to keep track of the users’ scores and best times.
The system was working fine to post data online but there was a problem when retrieving it. The first time the data was retrieved everything was fine but the subsequent retrievals would always be the same as if the data was cached somewhere.
After searching for a while I found out that the problem was that the HTTP request was being cached since the URL didn’t change, it would cache the result for that URL. The solution was to add a random attribute to the URL so that the the request couldn’t be cached. Not pretty but it was the only way I found to make it work.

And those were the problems that I found during the Puzzle Jumble’s development phase. I hope this useful for you!

CLI Args Made Easy 2010 / 2012

Find the new CLIArgsMadeEasy version here.

 

Summary

Improved version of the CLI Args Made Easy for Visual Studio 2005 and 2008.
Visual Studio Add-in that puts the project’s command line arguments more accessible.

Description:

Command Line Arguments Made Easy (CLIArgsMadeEasy) is a Visual Studio Add-in that eases the access and change of the startup project’s command line arguments. Instead of having to go to project properties or instead of using the command window to run your program with different arguments, CLIArgsMadeEasy adds a field in the toolbar for you to edit and saves everything you enter. A button is also added that opens a console window in the project’s working directory or home directory (if there’s no working directory set for this project).

Features:

  • More stable and faster than it’s predecessor CLIArgsMadeEasy.
  • Rapidly change startup project’s command line arguments in toolbar.
  • Saves command arguments history per user per machine.
  • Open console window in working directory or project’s directory (if there’s no working directory set).
  • Easily set a new startup project in the toolbar.

Screen shot:

cliargs

Changelog:

  • v1.3 – fixed bug that prevented resizing the CLIArgs input box.
  • v1.2 – added new combo box to easily choose a new startup project.
  • v1.1 – fixed bug parsing solutions with projects inside project folders.

Note: to resize the add-in input boxes you can click on the toolbar options button on the right and choose: “Add or Remove Buttons”->“Customize”. Then select the input box you want to change and choose “Modify Selection” and set the width as you like.

Known limitations:

  • Doesn’t work with XBox 360 projects.

I’d really appreciate if someone could give me a hand to solve this problem since I don’t have access to the XBox 360 SDK.

If you notice any slow downs or other problems because of CLIArgsMadeEasy 2010, let me know.

If you like this add-in and want to support it, donate by clicking in the button:

Download

You can download CLIArgsMadeEasy2010 v1.3 here. (for Visual Studio 2010)

ATTENTION: There is a known bug in CLIArgsMadeEasy2012. If you want the add-in to work properly, please make sure that it is visible in the Visual Studio’s toolbar BEFORE you open a solution, otherwise the add-in won’t behave like it should. This bug doesn’t impact your IDE experience. I’m currently working on a fix but it will take me some time to get it 100%. In the meanwhile you can use the version below.
You can download CLIArgsMadeEasy2012 v1.0 RC2 here. (for Visual Studio 2012)

Many thanks to Diogo Teixeira (aka fozi) for the add-in idea and testing of the program. And I also have to thank Matt Phillips for showing interest in the add-in which inspired me to make this second release.
Thanks to everyone who’s been reporting bugs and helping me building a stable version of CLIArgsMadeEasy.

VSX: How to detect when Property Pages (Project Properties) window is closed

I posted a thread on the MSDN forums to seek for help in detecting when the property pages window (accessible through project->properties) in Visual Studio is closed. You can follow up the thread here: Detect when project properties window is closed. Ziwei Chen was really helpful and could find me a way to achieve this in C# projects but to my surprise, to achieve the same results for C++ projects proved to be harder than I thought.

I decided to write this short tutorial to help those who have the same problem in future.

First of we need to detect when the user click in any project->properties menu selection. Put this code where you initialize your add-in:

m_commandEventsAfterExecuteProperties1 =
    m_applicationObject.DTE.Events.get_CommandEvents("{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 396);
m_commandEventsAfterExecuteProperties1.AfterExecute +=
    new _dispCommandEvents_AfterExecuteEventHandler(CommandEvents_AfterExecuteProperties);

m_commandEventsAfterExecuteProperties2 =
    m_applicationObject.DTE.Events.get_CommandEvents("{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 397);
m_commandEventsAfterExecuteProperties2.AfterExecute +=
    new _dispCommandEvents_AfterExecuteEventHandler(CommandEvents_AfterExecuteProperties);

These command events ids were found using the technique described in this post: How to find Visual Studio command bars. When registering the event handlers be careful with this: Visual Studio .NET events being disconnected from add-in. So declare these as member attributes and not as method variables:

private CommandEvents m_commandEventsAfterExecuteProperties1;
private CommandEvents m_commandEventsAfterExecuteProperties2;

Now, lets dig into some rather awful code to get our property pages handle. Property pages in .NET projects are document windows but, unfortunately, if we try to call the ActiveDocument property directly through the ActiveEnvDTE library, it will throw an exception. So, with the precious help of Chen, this is the code came up with:

// For C# projects the property pages is a document window, lets try to find it.
// I was unable to get a handle using the EnvDTE library which could have eased things a bit.
bool propertyPagesFound = false;

IVsWindowFrame[] frames = new IVsWindowFrame[1];
uint numFrames;

IEnumWindowFrames ppenum;
m_uiShell.GetDocumentWindowEnum(out ppenum);

while (ppenum.Next(1, frames, out numFrames) == VSConstants.S_OK && numFrames == 1)
{
	m_frame = frames[0] as IVsWindowFrame;
	object title;
	m_frame.GetProperty((int)__VSFPROPID.VSFPROPID_Caption, out title);

	// I really don't like the way I'm using to retrieve the property pages handle.
	//TODO: CHANGE IF BETTER SOLUTION IS FOUND.
	if ((title as String).ToLowerInvariant() == GetStartupProject().Name.ToLowerInvariant())
	{
		propertyPagesFound = true;
		((IVsWindowFrame2)m_frame).Advise(this, out m_cookieWindowFrameNotify);
	}
}

First, all document windows are retrieved to the ppenum variable and next we go one by one and test its caption name to see if it’s equal to the project’s name. After we got our desired window frame we register the IVsWindowNotifyFrame event handler.

In the C++ case, things are a bit different. The property pages window isn’t an instance of document or frame, it’s a dialog window. To catch the dialog window events we use an auxiliary class that listens for the destroy message in the WndProc method.

// If we didn't find any property pages before then we need to go and search for a C++ one since they're
// different from C# property pages.
if (!propertyPagesFound)
{
	//NOTE: This might not work well if we happen to have two Visual Studio instances with the same
	//      project names.
	//TODO: TRY TO FIND A WAY TO FIX IT.
	//HACK: Go through all windows to find the project properties dialog window that matters.
	FindWindowLike.Window[] list =
	    FindWindowLike.Find(IntPtr.Zero, GetStartupProject().Name.ToLowerInvariant() + " property pages", "");
	
	// Release any handle we might have.
	if (m_subclassedMainWindow != null)
	{
		m_subclassedMainWindow.ReleaseHandle();
		m_subclassedMainWindow = null;
	}

	if (m_subclassedMainWindow == null && list != null && list.Length >= 1)
	{
		m_subclassedMainWindow = new SubclassedWindow(list[0].Handle);
	}
}

Apart from that FindWindowLike that we’ll check later, I think the code is pretty simple to understand. I really don’t like to have to search through all windows in the system but apparently the dialog window couldn’t be found under the dte’s MainWindow.HWnd hierarchy.

 

As for the event implementations, here is the C# first:

public int OnShow(int fShow)
{
	switch (fShow)
	{
		case (int)__FRAMESHOW.FRAMESHOW_TabDeactivated:
			// Property pages lost focus, put your code here!
			((IVsWindowFrame2)m_frame).Unadvise(m_cookieWindowFrameNotify);
			m_cookieWindowFrameNotify = 0;
			break;

		default:
			break;

	}

	return VSConstants.S_OK;
}

We need to implement the IVsWindowFrameNotify interface and in the OnShow you can check when the tab is closed. I used the FRAMESHOW_TabDeactivated because it is called when the tab loses focus and also when the tab closes.

Now for the C++ version:

/// 
/// Auxiliary window to intercept messages sent to the property pages dialog window.
/// 
public class SubclassedWindow : NativeWindow
{
	private const int WM_NCDESTROY = 0x0082;

	public SubclassedWindow(IntPtr hWnd)
	{
		AssignHandle(hWnd);
	}

	protected override void WndProc(ref Message m)
	{
		if (m.Msg == WM_NCDESTROY)
		{
			// Property pages window was closed, put your code here!
		}
		base.WndProc(ref m);
	}
}

As explained before, in this case we have an auxiliary window to catch the destroy event for the dialog window.

I found this script over at FindWindowLike for C# and changed it a bit to fit my needs. I modified the code that compared the window title; created a new class and changed p/invoke methods’ signature just to keep VS quiet about some warnings.

/// <summary>
/// Now we have to declare p/invoke methods in a class called NativeMethods (or similar) to
/// shut up some VS warnings.
/// </summary>
internal static class NativeMethods
{
	[DllImport("user32")]
	internal static extern IntPtr GetWindow(IntPtr hwnd, int wCmd);

	[DllImport("user32")]
	internal static extern IntPtr GetDesktopWindow();

	[DllImport("user32", EntryPoint = "GetWindowLongW")]
	internal static extern int GetWindowLong(IntPtr hwnd, int nIndex);

	[DllImport("user32")]
	internal static extern IntPtr GetParent(IntPtr hwnd);

	[DllImport("user32", EntryPoint = "GetClassNameW", CharSet = CharSet.Unicode)]
	internal static extern int GetClassName(IntPtr hWnd, [Out] StringBuilder lpClassName, int nMaxCount);

	[DllImport("user32", EntryPoint = "GetWindowTextW", CharSet = CharSet.Unicode)]
	internal static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder lpString, int nMaxCount);
}

// FROM: http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21611201.html
// Just changed the way it checked strings.
internal class FindWindowLike
{
	internal class Window
	{
		public string Title;
		public string Class;
		public IntPtr Handle;
	}

	private const int GWL_ID = (-12);
	private const int GW_HWNDNEXT = 2;
	private const int GW_CHILD = 5;

	public static Window[] Find(IntPtr hwndStart, string findText, string findClassName)
	{
		ArrayList windows = DoSearch(hwndStart, findText, findClassName);

		return (Window[])windows.ToArray(typeof(Window));

	} //Find


	private static ArrayList DoSearch(IntPtr hwndStart, string findText, string findClassName)
	{
		ArrayList list = new ArrayList();

		if (hwndStart == IntPtr.Zero)
			hwndStart = NativeMethods.GetDesktopWindow();

		IntPtr hwnd = NativeMethods.GetWindow(hwndStart, GW_CHILD);
		while (hwnd != IntPtr.Zero)
		{
			// Recursively search for child windows.
			list.AddRange(DoSearch(hwnd, findText, findClassName));

			StringBuilder text = new StringBuilder(255);
			int rtn = NativeMethods.GetWindowText(hwnd, text, 255);
			string windowText = text.ToString();
			windowText = windowText.Substring(0, rtn);

			StringBuilder cls = new StringBuilder(255);
			rtn = NativeMethods.GetClassName(hwnd, cls, 255);
			string className = cls.ToString();
			className = className.Substring(0, rtn);

			if (NativeMethods.GetParent(hwnd) != IntPtr.Zero)
				rtn = NativeMethods.GetWindowLong(hwnd, GWL_ID);

			if (windowText.Length > 0 &&
				windowText.ToUpperInvariant().Contains(findText.ToUpperInvariant()) &&
				(className.Length == 0 ||
					className.ToUpperInvariant().Contains(findClassName.ToUpperInvariant())))
			{
				Window currentWindow = new Window();

				currentWindow.Title = windowText;
				currentWindow.Class = className;
				currentWindow.Handle = hwnd;

				list.Add(currentWindow);
			}

			hwnd = NativeMethods.GetWindow(hwnd, GW_HWNDNEXT);
		}

		return list;
	} //DoSearch
} //Class

And that’s it! I’d really appreciate if someone could tell me how to improve some of this code, mostly the parts where I have TODOs and/or HACK.
Thank you and I hope you find this useful!

Thanks to:

I wanted to thank Ziwei Chen for the excellent help at the forums.

References

VSSDK IDE Sample: Combo Box
Detect when project properties window is closed
I need FindWindowLike for C#
How to find Visual Studio command bars
Visual Studio .NET events being disconnected from add-in

Links:

Visual Studio Extensibility Forum
VSX Home on Code Gallery
Visual Studio on MSDN

CLI Args Made Easy

Find the new CLIArgsMadeEasy version here.

Summary

Visual Studio Add-in that puts the project’s command line arguments more accessible.

Description:

Command Line Arguments Made Easy (CLIArgsMadeEasy) is a Visual Studio Add-in that eases the access and change of the startup project’s command line arguments. Instead of having to go to project properties or instead of using the command window to run your program with different arguments, CLIArgsMadeEasy adds a field in the toolbar for you to edit and saves everything you enter. A button is also added that opens a console window in the project’s working directory or home directory (if there’s no working directory set for this project).

Features:

  • Rapidly change startup project’s command line arguments in toolbar.
  • Current session command arguments history.
  • Open console window in working directory or project’s directory (if there’s no working directory set).

Screenshot:

cliargscliargs_options

Future:

  • Support keyboard shortcuts.
  • Save command line arguments history per startup project and between VS sessions.
  • Support for multiple startup projects.

Known limitations:

  • The commands that you insert in the combo box will not do anything if you remove the focus from the combo with a mouse click on any other place. For some reason that I do not understand, when you use the mouse to change the focus, the value that is sent to the event handler is the old value that was in the box, not the new one that the user inserted. So, if you want to change the focus using a mouse click, make sure that you press the enter key in the combo box first.
  • Visual Studio’s extensibility API doesn’t provide an easy way to get a reference to a startup project, so we have to parse the solution which takes some time.
  • Since Visual Studio’s extensibility API doesn’t provide a way to catch any “startup project has change” event, there’s a timer that from time to time checks if there was any change.

I’d really appreciate if someone could give me some tips on how to solve any of these problems.

If you notice any slow downs because of CLIArgsMadeEasy, let me know.

If you like this add-in and want to support it, donate by clicking in the button:

CLIArgsMadeEasy is a free add-in, use it at your own risk. The authors can not be held responsible if anything wrong happens when using this add-in.

Download

You can download CLIArgsMadeEasy 1.0 Beta here.

Many thanks to Diogo Teixeira (aka fozi) for the add-in idea and testing of the program.