Saturday, October 26, 2013

Getting the icon for the user’s default browser in C#

In my last post I showed how to get hold of the associated icon for a file. Now, say you want to get hold of the icon for the user’s default browser, you may think you can just grab the icon for HTML files and that’ll do the job. Whilst that will work for some users, it won’t work for all of them. The application used to open HTML files does not need to be the same application that is used to open websites. For example changing your default browser to Chrome won’t change the default application for HTML files to Chrome. So here’s an extension to that previous code to get the icon for the default browser. It won’t work for XP since the way default applications are handled has changed but it should work with all later OSes.

    private static string GetDefaultBrowserPath()
    {
      const string userChoice = @"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice";
      using (RegistryKey userChoiceKey = Registry.CurrentUser.OpenSubKey(userChoice))
      {
        if (userChoiceKey != null)
        {
          object progIdValue = userChoiceKey.GetValue("Progid");
          if (progIdValue != null)
          {
            string progId = progIdValue.ToString();
            const string exeSuffix = ".exe";
            string progIdPath = progId + @"\shell\open\command";
            using (RegistryKey pathKey = Registry.ClassesRoot.OpenSubKey(progIdPath))
            {
              if (pathKey != null)
              {
                string path = pathKey.GetValue(null).ToString().ToLower().Replace("\"", "");
                if (!path.EndsWith(exeSuffix))
                {
                  path = path.Substring(0, path.LastIndexOf(exeSuffix, StringComparison.Ordinal) + exeSuffix.Length);
                }
                return path;
              }
            }
          }
        }
      }

      return null;
    }

    public static Icon GetDefaultBrowserLargeIcon()
    {
      string browserPath = GetDefaultBrowserPath();

      if (!string.IsNullOrEmpty(browserPath))
        return GetLargeIcon(browserPath);

      // last chance (probably XP), just grab the icon for HTML files
      return GetLargeIcon("test.html");
    }

    public static Icon GetDefaultBrowserSmallIcon()
    {
      string browserPath = GetDefaultBrowserPath();

      if (!string.IsNullOrEmpty(browserPath))
        return GetSmallIcon(browserPath);

      // last chance (probably XP), just grab the icon for HTML files
      return GetSmallIcon("test.html");
    }

Getting the associated icon for a file in C#

Sometimes it’s useful to display an icon for a file in an application and probably the best icon to display is whatever the operating system uses. The Windows API provides the SHGetFileInfo function for this purpose, so here’s a little wrapper around it. All the methods take a file name parameter, but the file doesn’t need to actually exist.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace TestIcons
{
  public static class ImageUtilities
  {
    [StructLayout(LayoutKind.Sequential)]
    struct SHFILEINFO
    {
      public IntPtr hIcon;
      public IntPtr iIcon;
      public uint dwAttributes;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
      public string szDisplayName;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
      public string szTypeName;
    };

    static class Win32
    {
      internal const uint SHGFI_ICON = 0x100;
      internal const uint SHGFI_LARGEICON = 0x0; // 'Large icon
      internal const uint SHGFI_SMALLICON = 0x1; // 'Small icon
      internal const uint SHGFI_USEFILEATTRIBUTES = 0x10;
      internal const uint SHGFI_LINKOVERLAY = 0x8000;

      [DllImport("shell32.dll")]
      public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

      [DllImport("User32.dll")]
      public static extern int DestroyIcon(IntPtr hIcon);
    }

    public static Icon GetSmallIcon(string fileName)
    {
      return GetIcon(fileName, Win32.SHGFI_SMALLICON);
    }

    public static Icon GetSmallOverlayIcon(string fileName)
    {
      return GetIcon(fileName, Win32.SHGFI_SMALLICON | Win32.SHGFI_LINKOVERLAY);
    }

    public static Icon GetLargeIcon(string fileName)
    {
      return GetIcon(fileName, Win32.SHGFI_LARGEICON);
    }

    private static Icon GetIcon(string fileName, uint flags)
    {
      SHFILEINFO shinfo = new SHFILEINFO();
      IntPtr hImgSmall = Win32.SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo),
        Win32.SHGFI_ICON | Win32.SHGFI_USEFILEATTRIBUTES | flags);

      if (hImgSmall == IntPtr.Zero)
        return null;

      Icon icon = (Icon)Icon.FromHandle(shinfo.hIcon).Clone();
      Win32.DestroyIcon(shinfo.hIcon);
      return icon;
    }
  }
}

Monday, October 21, 2013

None of our politicians have a clue

So we have a Labour party who are talking about a cost of living crisis. Good on them. Until you hear their main policy, which seems to be fixing the cost of energy. I’m pretty sure the talk of the lights going out are completely alarmist, but I doubt trying to fix prices is going to work, the fact is fossil fuel costs go up and down and no politician can stop that happening.

But Ed is missing the point a little anyway. For most people, energy is a big cost but it’s generally outweighed by something else, housing. We hear a lot about energy price rises, but not so much about rises in rent. And if house prices go up, that’s a good thing apparently? As a home owner, I don’t get it. If I want to move up the ladder, higher prices mean I need a bigger mortgage to move anywhere. First time buyers presumably don’t want higher prices. As a parent, I don’t want housing to be completely unaffordable for my child when she gets to an age when she wants her own place. Yes, there are people who gain from house price rises, but I’m pretty sure they are outnumbered by people who would actually gain from falling prices.

But enough of the Labour party, what have the Conservatives got to offer? Oh yes, Help To Buy, the scheme that seems most people are a little concerned about. Apparently it may cause a new housing bubble. What the ….? We haven’t escaped the last bubble yet. We are still number one in the housing bubble stakes. What George seems to have missed is that the problem with our housing market is not a demand problem, there’s plenty of demand. The problem is not enough houses are being built and the ones that are being built cost too much!

So what’s the solution? First, the British need to get over their obsession with house prices and realise houses are a place to live, not pay for their retirement. Second, we need to radically change our planning laws, so we can build a lot more houses. Third, the government needs to start building some council houses.

The sad thing is none of this looks likely to happen. No political party is going to say “We will build houses in your back yard and let other people do the same and the price of your property will then fall, but in the long run it will be good for the country”

Friday, October 18, 2013

Our dog really hates cats

WP_000063Eyes and nose removed, most internal organs gone. Fortunately it wasn’t a real cat, just a toy.

Sunday, October 13, 2013

Postcode populations

doogal.co.uk has some exciting new postcode data (depending on your definition of exciting…). I’m in the process* of importing population data for each active postcode in England and Wales. This includes the estimated population and number of households and comes from the ONS website based on the Census of 2011, which I’ve just realised only covers England and Wales. Scottish data is a separate download and will be my next task. Northern Ireland doesn’t seem to provide population data per postcode.

The data appears on the information page for each postcode and will become part of the CSV downloads once the import is complete. I could aggregate this data up to postcode district and sector level, so let me know if that would be useful to you.

* A database of 2.5 million postcodes can take some time to update!