Just a Bit: Improving Graphics Card Performance

I spent a little of time with some people over at AMD the other day, looking at ways to better utilize the video card using WPF.

A useful little chunk that came from that was using the Freeze method on UI elements that are being manipulated. This tells the video card to use the texture already in video memory instead of unloading the old one, performing the manipulation, and loading a new texture into memory. Since this is the most expensive action that can be done with a video card, using Freezable members can make things look much smoother.

Here’s an example:

private void Window_TouchMove(object sender, TouchEventArgs e)
{
    Point touchLoc = e.GetTouchPoint(this).Position;
    TranslateTransform unfrozenTransform = new TranslateTransform(touchLoc.X, touchLoc.Y);
    ManipulatingChild.RenderTransform = (TranslateTransform)unfrozenTransform.GetAsFrozen();
}

Just a Bit: Make Your WPF Application Resolution and DPI Independent

We’ve all seen it. Lower your resolution to 800×600? The application’s UI is giant, hard to navigate, and ugly. Bring it up to 1920×1200? Now, you can’t see it. Here’s an easy way to make your application’s content size relative to your window’s size (which will lead it to size independently of the resolution or DPI).

All you have to do is surround your content in a Viewbox, with a uniform Stretch (to ensure the aspect ratio is maintained). You may need to specify a particular size for your content, in order to ensure proper aspect ratio and distance for your elements.

<Viewbox Stretch="Uniform">
    <Grid Width="800" Height="600">
        <!-- Content -->
    </Grid>
</Viewbox>

Just a Bit: Loading Images Asynchronously in WPF

Multithreading using WPF is a little tricky at first (I’m planning a more thorough post on that later), but the basic thing you need to know is that you can’t access WPF elements outside of the UI thread, because they aren’t thread safe.  There are some things you can do to speed loading up, however.  Here’s a method for loading images on a separate thread:

private void LoadImage(string fname)
{
	// instantiate and initialize the image source
	BitmapImage bmi = new BitmapImage();
	bmi.BeginInit();
	bmi.UriSource = new Uri(fname, UriKind.Relative);
	bmi.EndInit();
 
	bmi.Freeze();		// freeze the image source, used to move it across the thread
 
	// this method tells the separate thread to run the following method to run on the UI thread
	// the (ThreadStart)delegate(){ } notation is a shorthand for creating a method and a delegate for that method
	TheImage.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (ThreadStart)delegate ()
	{
		TheImage.Source = bmi;
	});
}

The meat of the method is the BitmapImage.Freeze method – this is specifically useful for loading images.  The Dispatcher.BeginInvoke is also important, but I’ll leave more explanation on that for the threading post.

Just a Bit: Copying Text to the Clipboard

A bit is the difference between true and false

So when working on this blog sometimes I spend a little too much time getting code together. I’m sure I’ll get better, faster, and care less about what it looks like over time.

Until then, I’ll use these ‘Just a Bit’ posts. The idea being that I post a tiny bit of code that I found useful recently. Sure, about 400,000,000 pages can be found elsewhere with this information, but they don’t have clever wordplay in their titles!

So, the first “Just a Bit” is using .NET to add text to the Windows clipboard.  First, put together a string using the StringBuilder class – the reason for this is that any formatting characters (‘\n’, ‘\t’, etc.) won’t necessarily translate correctly onto the clipboard correctly if you simply put them into a string.  Finally use the System.Windows.Clipboard static method SetDataObject to copy the text to the clipboard.

// build the string, with new lines between entries
StringBuilder clipStr = new StringBuilder();
foreach (string itm in TheItemCollection.Items)
{
	clipStr.Append(itm);
	clipStr.Append("\n");
}
// copy to clipboard, clear the box, and notify user
Clipboard.SetDataObject(clipStr.ToString(), true);

Enjoy that one.