Reviews and links for February 2010

Programming WPF by Chris Sells

Programming WPF by Chris Sells

4/5

A highly detailed and well written reference to WPF. Note that this second edition is still based on Visual Studio 2005 / .NET 3.0 so a little out of date now. I still found the book to be very useful and would recommend it both for picking up WPF basics and to refer back to for more advanced topics when needed.2/26/2010 2:00:00 AM

 

Professional C# 2008 by Christian Nagel

Professional C# 2008 by Christian Nagel

4/5

I'm in the process of upgrading to VS2008 and loved the 2005 version of this book so picked up the 2008 update. It's a broad language and framework reference, perfect for understanding what's available in .NET 3.5 and how to get started. My only complaint is that it could have used a "what's new" section or guide to separate out completely new technologies from those familiar from .NET 2.0. Not a big problem though, it's easy to skim through the old stuff and then pay attention when you reach something new. I'll probably pick up the 2010 version in 2015 or so ;)2/15/2010 2:00:00 AM

 

Links

- UK NHS urged to buy Fairtrade tools from BBC News | News Front Page | World Edition (Fair enough, but what about having developing countries pay to train doctors and nurses and then poaching them to work for the NHS?).

- Brown 'upset' by bullying claims from BBC News | News Front Page | World Edition (And when he finds those responsible he's going to turn purple, squint and twat them.).

- CBS runs free ad for "magic" energy box from Boing Boing (A slightly more skeptical take. Magic box plus natural gas...).

- French halal burger sparks appeal from BBC News | News Front Page | World Edition (So eat somewhere else. You're in France and not about to starve.).

- One inch equals $30,000 in online dating world from Boing Boing (I'm worth $2.2 million :)).

- Video: Mantis vs. Cursor from Boing Boing (OK, I need a Preying Mantis to entertain me like this while I work...).

- Toyota recalls 8,000 US vehicles from BBC News | News Front Page | World Edition (And they're not even real propellers. They're just the joke ones you can attach to your tow hitch.).

- Britain reveals how U.S. treated detainee from SFGate: Top News Stories (Miliband against the "principle of their disclosure by an English court against U.S. wishes"!).

- Mariposaaah!!! from Spots Unknown (Feels steeper walking up it.).

BlogEngine.NET most popular pages widget using Google Analytics

I finished off my BlogEngine.NET migration yesterday missing a couple of useful sections from the previous incarnation of this blog. The first is a list of the most popular posts based on Google Analytics data. I've just finished porting this from a UserControl to a widget for BlogEngine.NET. To use this just download and extract this zip file to your widgets directory:

MostPopularFromGA.zip (5.22 kb)

You can see the widget in action under the Most Popular heading to the left if you're reading this post on the blog.

More...

Tags: ,

Categories: .NET | C#

Migrating from Blogger to BlogEngine.NET

In January I got an email from Blogger announcing that they're killing FTP support. Apparently only 0.5% of Blogger blogs are published using FTP and it's a huge pain to support, mainly because many hosting providers restrict FTP access to certain IP addresses and if the Google servers running Blogger that moment aren't listed it's technical support time. 

Fair enough, but a bit painful for me as I have five blogs running on top of Blogger. I need FTP publishing as the templates I use end up running as ASP or ASP.NET pages. I Thought He Came With You is the first to move - if you're reading this post then it's up and running on BlogEngine.NET. This is an open source ASP.NET blogging platform. If it works out for this blog over the next month I'll start migrating the others. 

Getting up and running with BlogEngine.NET is easy enough - download the latest release and follow the getting started guide. I added the default install to a new Visual Studio web site project and was able to run it fine in the development server, no need to configure IIS. 

The challenge was moving posts and comments from Blogger into BlogEngine.NET. BlogEngine.NET happily imports and exports BlogML, Blogger spits out it's own Atom export format

More...

Tags: ,

Categories: .NET | C# | ASP.NET

Catfood.Shapefile.dll 1.10

I've just released v1.10 of my ESRI Shapefile Reader (Catfood.Shapefile.dll). This is a .NET 2.0 forward only parser for reading shapefile content.

Sharon Tickell was kind enough to report two bugs with suggested updates (10185 and 10186). These have both been fixed in 1.10.

While working on these fixes I also discovered that there are no 64-bit Jet drivers (since releasing the first version I've upgraded to a 64-bit box for development). This is an easy fix, just target any application using Catfood.Shapefile.dll at x86. I've updated the demo application accordingly.

Download Catfood.Shapefile.dll from Codeplex.

Categories: .NET | C# | shapefile

Ambient Orb Controller .NET Library

The Ambient Orb is an LED illuminated globe designed to display subtle information - stock market prices, weather, etc. Normally the Orb is controlled via the pager network but you can buy (or build) a developer module and connect the Orb via your serial port.

Ambient Orb

I've used my Orb via both pager and serial port for a number of applications. I've just released a library - Ambient Orb Controller - on CodePlex that supports both methods of control. I wrote the library to make it easier for me to gin up new Orb applications. If you use an Orb let me know what you come up with. Two of my favorites are using the Orb for continuous integration and as a music visualizer.

Categories: orb | .NET | C#

ESRI Shapefile Reader in .NET

I've just released a .NET library for parsing ESRI shapefiles - see ESRI Shapefile Reader on Codeplex. The library and source code are available under the Microsoft Public License.

A Shapefile is actually at least three files: a main file containing shape data (*.shp), an index file for locating shape records in the main file (*.shx) and a database of metadata for each shape (*.dbf) in dBASE format.

I ended up writing the library in order to convert Eric Muller's time zone shapefile into a format I could use with Catfood Earth. I found other libraries that could read shape data but not metadata, or provided a very thin .NET wrapper on top of unmanaged code and so I decided that a fully managed library could be useful.

The library - Catfood.Shapefile.dll - provides read-only, forward-only access to shapes and shape metadata. Currently all 2D shapes are supported: Null, Point, MultiPoint, PolyLine and Polygon. I might add additional types in the future, or if you have a pressing need it would be easy to extend the library by looking at an existing shape subclass and the shapefile specification (PDF).

See the Codeplex project for sample code and documentation.

Categories: .NET | C# | shapefile

Fastest image merge (alpha blend) in GDI+

I've been experimenting with the best way to merge two images in C#. That is, paint one image on top of another with some level of transparency as opposed to using one color as a transparency mask. I tried three candidates, all included below:

SimpleBlend is the naive approach using GetPixel and SetPixel to add the desired alpha value to the second image before painting it on top of the first.

MatrixBlend configures a ColorMatrix to specify the desired alpha and then paints the second image on to the first using the matrix.

ManualBlend locks and directly manipulates the image data. This uses pointers and so introduces unsafe code (it's possible to marshal the image data into a managed array but I wanted to look at the performance with raw access).

I tested each approach ten times with a couple of large JPEG images. The results are:

SimpleBlend: 17.69 seconds
MatrixBlend: 0.74 seconds
ManualBlend: 1.13 seconds



I expect ManualBlend could be optimized further but both this and MatrixBlend are an order of magnitude faster than the naive approach. I'll be using MatrixBlend as no unsafe code is required.

 


private static void SimpleBlend(string image1path, string image2path, byte alpha)
{
using (Bitmap image1 = (Bitmap)Bitmap.FromFile(image1path))
{
using (Bitmap image2 = (Bitmap)Bitmap.FromFile(image2path))
{
// update the alpha for each pixel of image 2
for (int x = 0; x < image2.Width; x++)
{
for (int y = 0; y < image2.Height; y++)
{
image2.SetPixel(x, y, Color.FromArgb(alpha, image2.GetPixel(x, y)));
}
}

// draw image 2 on image 1
using (Graphics g = Graphics.FromImage(image1))
{
g.CompositingMode = CompositingMode.SourceOver;
g.CompositingQuality = CompositingQuality.HighQuality;

g.DrawImageUnscaled(image2, 0, 0);
}
}
}
}

 


private static void MatrixBlend(string image1path, string image2path, byte alpha)
{
// for the matrix the range is 0.0 - 1.0
float alphaNorm = (float)alpha / 255.0F;
using (Bitmap image1 = (Bitmap)Bitmap.FromFile(image1path))
{
using (Bitmap image2 = (Bitmap)Bitmap.FromFile(image2path))
{
// just change the alpha
ColorMatrix matrix = new ColorMatrix(new float[][]{
new float[] {1F, 0, 0, 0, 0},
new float[] {0, 1F, 0, 0, 0},
new float[] {0, 0, 1F, 0, 0},
new float[] {0, 0, 0, alphaNorm, 0},
new float[] {0, 0, 0, 0, 1F}});

ImageAttributes imageAttributes = new ImageAttributes();
imageAttributes.SetColorMatrix(matrix);

using (Graphics g = Graphics.FromImage(image1))
{
g.CompositingMode = CompositingMode.SourceOver;
g.CompositingQuality = CompositingQuality.HighQuality;

g.DrawImage(image2,
new Rectangle(0, 0, image1.Width, image1.Height),
0,
0,
image2.Width,
image2.Height,
GraphicsUnit.Pixel,
imageAttributes);
}
}
}
}

 


private static void ManualBlend(string image1path, string image2path, byte alpha)
{
// percentage of destination and source image
float alphaDst = (float)alpha / 255.0F;
float alphaSrc = 1.0F - alphaDst;

using (Bitmap image1 = (Bitmap)Bitmap.FromFile(image1path))
{
Rectangle imageRect = new Rectangle(0, 0, image1.Width, image1.Height);
BitmapData image1Data = image1.LockBits(imageRect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

using (Bitmap image2 = (Bitmap)Bitmap.FromFile(image2path))
{
BitmapData image2Data = image2.LockBits(imageRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

unsafe
{
uint* image1Raw = (uint*)image1Data.Scan0.ToPointer();
uint* image2Raw = (uint*)image2Data.Scan0.ToPointer();
int stride = image1Data.Stride / sizeof(uint);
int currentPixel;
uint image1Pixel, image2Pixel;
uint srcRed, dstRed, finRed;
uint srcGreen, dstGreen, finGreen;
uint srcBlue, dstBlue, finBlue;

for (int x = 0; x < imageRect.Width; x++)
{
for (int y = 0; y < imageRect.Height; y++)
{
currentPixel = (y * stride) + x;
image1Pixel = image1Raw[currentPixel];
image2Pixel = image2Raw[currentPixel];

srcRed = (image1Pixel >> 16) & 0xFF;
srcGreen = (image1Pixel >> 8) & 0xFF;
srcBlue = image1Pixel & 0xFF;

dstRed = (image2Pixel >> 16) & 0xFF;
dstGreen = (image2Pixel >> 8) & 0xFF;
dstBlue = image2Pixel & 0xFF;

finRed = (uint)((alphaSrc * (float)srcRed) + (alphaDst * (float)dstRed));
finGreen = (uint)((alphaSrc * (float)srcGreen) + (alphaDst * (float)dstGreen));
finBlue = (uint)((alphaSrc * (float)srcBlue) + (alphaDst * (float)dstBlue));

image1Raw[currentPixel] = (uint)(finBlue | finGreen << 8 | finRed << 16 | 0xFF << 24);
}
}
}
image2.UnlockBits(image2Data);
}
image1.UnlockBits(image1Data);
}
}

Categories: .NET | C#

MessageInterceptor doesn't always...

I've been writing a play by text message version of battleships for Windows Mobile 6 using the MessageInterceptor class to receive messages. This works great on my AT&T Tilt but completely fails on my wife's Pantech device. The MessageInterceptor hooks up fine but never fires.

The 2.0 compact framework SmsAccount lets you send messages but unaccountably doesn't let you read them.

I avoided some unpleasant interop by grabbing the MAPIdotnet library. This implements a NewMessage event for MAPI stores, however as with MessageInterceptor the event hooks up OK but never fires on the damned Pantech.

MAPIdotnet does allow you to read the SMS inbox though, so the final answer is to fall back to looking for, processing and then deleting game related text messages on a timer. This is far from ideal as the game messages arrive and vibrate the phone before getting processed but at least it's now possible to play without buying a new phone.

To add to the frustration during development the Visual Studio 2005 toolbox lost all icons except for the pointer and a custom control that was part of the project. Resetting the toolbox didn't help, nor did restarting VS and the computer. The fix was to exit VS and then delete all the .tbd files from Microsoft\VisualStudio\8.0 in local application data. Sigh.

Categories: WinMo | C#

Launching a URL in the user's default browser

This has bitten me a few times. If you use Process.Start("url") it will work some of the time but you'll see a "The system cannot find the file specified" Win32Exception on some systems. Bummer.

Lots of people suggest looking up the HTTP handler in HKEY_CLASSES_ROOT but this is flawed as well - on my system for instance HTTP is registered to Firefox even though I'm actually using Chrome and I'd be unhappy waiting half an hour for Firefox to wake up and show the requested web page.

From XP there are a couple of registry settings tied to the current user's preferred browser.

First check HKEY_CURRENT_USER\Software\Clients\StartMenuInternet. This key will only exist if the user has overridden the system default browser - the default value is used to access the details (for me, it's chrome.exe).

If the user hasn't set a default then check HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet. The default value here is the system default browser (on my system it's FIREFOX.EXE).

There is a set of subkeys under HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet that contain details about each registered browser. The default value from StartMenuInternet (either HKCU or HKLM) is the subkey to look for. The path to my default browser is in this key:

HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet\chrome.exe\shell\open\command

Now I can Process.Start(path, url) to safely launch the default browser. You can fall back to Process.Start(url) if registry access fails for some reason, but be prepared for that Win32 exception.

Categories: .NET | Win32 | C#

Video timeout on XP and Vista (power management)

I'm updating a screensaver so that it stops work once the monitor switches off. This seemed like a really simple requirement but it took some time to find an API that works on both XP and Vista.

My first attempt was ReadPwrScheme(). The documentation suggests using a different method on Vista - it should say so more strongly because on Vista you get back some default information that bears no relationship to reality.

Next I tried CallNtPowerInformation(). This doesn't mention any alternatives but also doesn't work on Vista. I've added comments on both MSDN pages pointing to the answer.

GetCurrentPowerPolicies() is just the ticket - it returns a wealth of information including the video timeout on AC and battery power and works on both XP and Vista.

Pinvoke.net has all the structures required but not the actual function. I've just added the C# interop signature for GetCurrentPowerPolicies().

I can't believe how frustrating finding this information has been. If you've found this post I hope it saves you a couple of hours :).

Categories: Win32 | C#

 

CC | About | Search | Home | Validate