Sunday, August 20, 2006

So, this is a little off-topic compared to some of the other posts I have done lately, but it was something new to me and I thought I'd share it for information... and as a means of helping me remember it later!

At home, I have been using both Microsoft Digital Image Library 2006 and Picasa to manage my digital pictures because I like features in both. Microsoft's product provides some nice editing features and tagging while I've been using Picasa's export as a webpage in an XML format for mine and my wife's blog. One of the hassles between the two, though, is that they store captions for images differently. I was having to manually copy and paste captions between both programs, which is huge time waster. Because I wanted to continue using Digital Image Library, I decided to write a program to export the gallery. (I know there are programs out there that can do this for me... I've got the programmers' disease!)

To write this program correctly, I wanted to still be able to pull out information like the captions I had set for each picture. I ended up digging around a little bit researching the different implementations for storing metadata in the files and it would appear that Microsoft's implementation seems more standard than that of Picasa. In fact, some digging in one of my pictures using a hex editor shows the proprietary <picasastamp> enclosing a <caption> tag. At least that means it will be easier to pull the caption out.

Probably one of the best places to start for researching this is the MSDN how to: Read Image Metadata. It details the PropertyItem that you can get off of the System.Drawing.Image class. There is actually a collection of PropertyItem objects from the PropertyItems collection. Basically, you can loop through the collection and inspect each item's Id property until you find the one you are looking for. That's the easy part. The hard part is figuring out which Id you're interested in because they don't have user-friendly names like "Caption" or "Title" - they're in hex. Thanks to this sort of random post, I was able to find out that the captions I was looking for were 0x9c9b.

So, without further ado, here's a very simple GetCaption method that will return the caption/title based on an Image passed to you:

public static string GetCaption(Image img)
{
    if (img == null) 
        throw new ArgumentNullException("img");

    Encoding enc = Encoding.UTF8;

    foreach (PropertyItem prop in img.PropertyItems)
    {
        if (prop.Id == 0x9c9b)
        {
            return enc.GetString(prop.Value).Replace("\0", "").Trim();
        }
    }

    return string.Empty;
}

Let me know what you think!

If you're interested in more about the PropertyItem class, check out these pages - they've got some nice information on them as well.

- http://www.codeproject.com/cs/media/photoproperties.asp
- http://www.pixvillage.com/blogs/devblog/archive/2005/03/27/176.aspx

posted on Sunday, August 20, 2006 8:21:59 PM (Central Standard Time, UTC-06:00)  #    Comments [2]
 Friday, August 18, 2006
This post is just as much for me as it is to share...

I was attempting to create a automatically resizing GroupBox control that would let users drop controls on it and it would grow as the controls dropped. I also wanted to offer a FlowLayoutPanel-like ability so that it would slide controls that were lower up if higher controls were hidden. Doesn't sound too bad and we would use it enough that it made sense to encapsulate it in a custom control. I started looking into inheriting from GroupBox and adding a FlowLayoutPanel to it's control collection. Then I hooked into the ControlAdded event for the GroupBox so that I could move the control from the GroupBox to the FlowLayoutPanel. I'm just walking you through the steps in my thinking process here... this apparently isn't how it should be done, because though it worked if controls were added at run-time, it gave me a weird designer error that said "'child' is not a child control of this parent" (like these guys did).

What research I came up with looked like I would have to create my own custom designer to support code like this, that would also include code serialization into InitializeComponent. Yay. A little more research brought me this link, though. It details how to drop controls onto a UserControl at design time. It is a slightly different approach, but it provided what I needed. Basically, the solution also involves using a ControlDesigner, but the code seems much less involved than if I were handling code serialization.

Here's a code snippet to give you an idea of what I did:
<Designer(GetType(AutoResizeGroupBoxDesigner))> _
Public Class AutoResizeGroupBox
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property FlowPanel() As FlowLayoutPanel
Get
' Where _flowPanel has already been added to the designer
Return _flowPanel
End Get
End Property

' code snipped...

End Class

Public Class AutoResizeGroupBoxDesigner
Inherits ControlDesigner
Public Overrides Sub Initialize(ByVal component As System.ComponentModel.IComponent)
MyBase.Initialize(component)
Dim autoGroupBox As AutoResizeGroupBox = DirectCast(component, AutoResizeGroupBox)
EnableDesignMode(autoGroupBox.FlowPanel, "FlowPanel")
End Sub
End Class
posted on Friday, August 18, 2006 6:58:52 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Wednesday, August 16, 2006

I'm sorry... I've been bad about posting lately. So bad in fact, that I've only posted once this month! But you know what? I've got a good excuse... I was in Alaska on vacation! So there!

I plan on putting pictures on mine and my wife's blog soon if anyone is interested in seeing what Alaska looks like. It is a lot cooler there, which was a huge plus over the 100+ (Fahrenheit) temperature here.

Anyway, I wanted to also say that I've been a del.icio.us junkie lately, too. I didn't know until fairly recently that you could subscribe to OTHER users' bookmarks and see what they're watching. That feature is downright cool. It gives you a glimpse of what other people find interesting and it is even faster than watching blog posts, because people tend to bookmark things before posting about them. I do. My del.icio.us page is at http://del.icio.us/drmohundro if anyone is interested in checking it out. The RSS feed is at the bottom.

Does anyone else use del.icio.us regularly? If so, leave your del.icio.us IDs!

(PS - this post comes to you from Windows Live Writer... too bad it doesn't work through my corporate proxy, either...)

posted on Wednesday, August 16, 2006 9:38:24 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Wednesday, August 02, 2006
wikiality (wi-ki-al-i-ty) - the process of creating "reality" (see reality) by making something up on Wikipedia enough that more and more people agree with you.

It looks like Stephen Colbert from the Colbert Report on Comedy Central had some fun with Wikipedia recently. Check it out.
posted on Wednesday, August 02, 2006 12:37:32 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Wednesday, July 26, 2006

Recently, I've been experimenting with different console colors in PowerShell, primarily because the light gray on black is sort of boring (lame excuse, I know). I've been using Console and I had set the foreground color to green in the options. The only problem with doing this is that programs that output other colors, such as the error messages from MSBuild, are not displayed. I like seeing the color difference because the red text really jumps out at me and says that I have an error.

This got me curious about whether or not I could set a different color in PowerShell, instead of in Console. I stumbled across this TechNet article from way back when PowerShell was still MSH. Basically, you use the -foregroundcolor or -backgroundcolor switch against Write-Host to alter the color of the text you're outputting. That's certainly userful information if you're writing cmdlets, but I wanted to change the default color for the entire session.

If you've worked with .NET console applications, you may have seen System.Console.ForegroundColor. Well, this is available from PowerShell as well! .NET shell integration is great! So now, my PowerShell profile has a brand new line in it:

[System.Console]::ForegroundColor = [System.ConsoleColor]::Green

By doing this, whenever an application, cmdlet, function or whatever changes the default output color, like MSBuild does, you'll be able to see it. As a side note, I really like the PowerShell profile idea. Though options dialogs tend to be more user friendly, the PowerShell profile (try 'notepad $profile') is far more powerful and customizable.

posted on Wednesday, July 26, 2006 12:00:28 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, July 20, 2006
Like many other users of Visual Studio 2005, I've occasionally received the WSoD (White Screen of Death) while using the designer. And like a typical user, I blamed it on Visual Studio. That's what users do, right? They blame the program, because the user is always right. The same behavior that frustrates me to no end when users enter invalid data into MY program and then blame MY program (of course, if my UI were better, it wouldn't be as difficult to use, but that is another story). Anyway, my frustrations with VS2005 crashing and the WSoD's were in fact a problem with the user - me.

In one of my forms, I had some background threading work that was started when the form loaded. Like a good programmer, I had wrapped this threading work in a check against Me.DesignMode to ensure that it wouldn't try to do this work while in the designer. What I didn't know at the time is that the DesignMode property isn't set until AFTER the constructor fires. I checked around with some guys at work and I discovered that I wasn't the first one to discover this. They had already put a check against Application.ExecutablePath to see if it was devenv.exe. If it is, then we're in DesignMode. Simple as that!

So, all of my VS crashes and weird WSoD's have now been tracked back to my OWN code. HOWEVER, I would like to say that it would have been nice if Visual Studio had given me a better message to inform me that my designer code was trying to run background threads or something - in much the same way that my own code should work better and give my users better messages.

Ah, the joys of user interaction.

Note: This fixed the problem suggested after sending error reports that link to this hotfix (http://support.microsoft.com/?kbid=915038). If you're running into this, check and double-check the code in your UI constructors, INCLUDING base class constructors!
posted on Thursday, July 20, 2006 10:22:10 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, July 18, 2006
Earlier today, Mark Russinovich announced that Microsoft had acquired Winternals and Sysinternals. In other words, some of the best administration tools available will be moving to Microsoft. Not only that, but by having Mark on board at Microsoft, they will have a great developer working with them. I think that this is a great move as far as bringing Mark on board. As far as acquiring Winternals and Sysinternals, I'm excited about that as well, so long as the products continue to be supported by Microsoft. I'm quite confident they will, too, because I know that Microsoft uses a lot of their tools as well (i.e. Process Explorer, RegMon, FileMon, etc).

Congratulations and I look forward to hearing more!
posted on Tuesday, July 18, 2006 11:11:58 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, July 13, 2006

Yesterday, I downloaded the Developer Productivity Tools video from the Wrox website that Scott Hanselman did for one of his presentations with a user group. He had a lot of great resources in the video but the command prompt tips he had were new to me. I've done some work with the console, but I've only recently been using it more, particularly with PowerShell coming along.

Scott's tip about customizing your prompt (from c:\dir\> to whatever) was really cool (also posted here). I knew that the prompt could be customized, but at the time I saw someone do it, I didn't have a good grasp of environment variables so it didn't really make sense what was going on, but Scott's video and his post have helped out a lot. They also prompted me to want to do the same with my PowerShell prompt!

The PROMPT environment variable trick doesn't work for the PowerShell prompt, but after a little digging around with Google, I discovered this post from Lee Holmes about the prompt function. If you have a function named prompt declared, PowerShell will use the value returned by that function to alter the display of your prompt. Here's my prompt function, which I have saved in PowerShell profile so that it will load every time (mine is located here C:\Documents and Settings\David\My Documents\PSConfiguration\Microsoft.PowerShell_profile.ps1)

# Initialize custom prompt
function prompt
{
   "PS " + (get-location).Path + [System.Environment]::NewLine + ">".PadLeft((get-location -stack).Count + 1, "+")
}

The only thing I haven't figured out yet is how to get a visual indication of how far in the stack you are (by using pushd and popd). Once I figure that out, I'll have a PowerShell prompt customized just like my cmd prompt!

UPDATE: I did some more research and discovered get-location -stack which will return everything on the pushd/popd stack. I've updated my prompt function accordingly. Now it matches my cmd prompt in every way!

posted on Thursday, July 13, 2006 12:00:39 PM (Central Standard Time, UTC-06:00)  #    Comments [0]

Last night, Cara and I were driving back from church during a thunderstorm. The entire time, I kept wishing that I had my digital camera with me, because the lightning was amazing! The storm was almost past just as the sun was going down, so the entire sky was almost golden in color. There was also a full rainbow all the way across the sky. While all of this was going on, the lightning was filling the sky, shooting from cloud to cloud. (side note - I'm not a writer, so if my descriptive writing skills are lacking, I apologize)

Well, today at work, I notice a post on digg about "incredible pictures" and "the moment lightning shared the sky with a rainbow." Hmm... that's interesting. But surely it couldn't be Fort Smith, Arkansas, now could it? But it is! Check out the digg post here.

The actual website with pictures is here at Daily Mail. The craziest part of all is that this Daily Mail site is apparently a British site! Be sure to check out the pictures.

posted on Thursday, July 13, 2006 11:24:56 AM (Central Standard Time, UTC-06:00)  #    Comments [0]