Click here to Skip to main content
6,822,123 members and growing! (16,182 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » Windows Presentation Foundation » Controls     Beginner License: The Code Project Open License (CPOL)

WPF : A Simple Color Picker With Preview

By Sacha Barber

WPF : A Simple Color Picker With Preview
C# (C#3.0), .NET (.NET3.0, .NET3.5), WPF, Architect, Dev, Design
Revision:5 (See All)
Posted:2 Feb 2009
Updated:4 Jan 2010
Views:26,678
Bookmarked:60 times
Unedited contribution
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
40 votes for this article.
Popularity: 7.75 Rating: 4.84 out of 5

1

2

3
5 votes, 12.5%
4
35 votes, 87.5%
5

 

Contents

Introduction

Yesterday I posted an article about creating a WPF Graph and when I post a new article I always have a look at the new articles, including those awaiting public status. Yesterday someone publised a WPF color picker, that looked really cool. The only problem was the code was not attached to that article and the article text gave you no clue as to how the damn thing worked. I joked to a fellow code project author that I just may have to try and write a color picker for WPF, as this article sparked my interest a bit.

As luck would have it, I woke up today (Monday) and tried to get into work (I work in London and live 50 mile aways), but was faced with the worst snow storm in the UK for some time. No trains/buses/taxis we on, so guess what I did. That's right, I wrote a color picker.

This article is it.

It is very simple actually. I should point out before I start that I did borrow an idea or 2 from other exellent sources from the www. So I would like to start by having a special thanks section.

Special Thanks Goes Out To

 

The Code

So how does it all work. Well it is actually so simple you probably would think "Ha, is that it". Well yep, this next section explains all that is inviolved which aint that much. Simplicity is good.

There is a WPF Window called ColorDialog which holds the actual ColorPicker control. Here is the XAML:

<Window x:Class="WPFColorPickerLib.ColorDialog"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFColorPickerLib"
    Icon="Images/ColorSwatchSquare.png"
    Title="Pick Color" Height="370" 
    KeyDown="Window_KeyDown"
    Width="520" WindowStartupLocation="CenterOwner">
    
    <local:ColorPicker x:Name="colorPicker"/>
        
</Window>

This ColorDialog window is the one you can use from your own code. The ColorDialog window exposes a single property which is really just the value of the currently selected color within the contained ColorPicker control.

Here is the code behind for the ColorDialog window:

public partial class ColorDialog : Window
{
    #region Ctor
    public ColorDialog()
    {
        InitializeComponent();
    }
    #endregion

    #region Public Properties
    public Color SelectedColor
    {
        get { return colorPicker.SelectedColor; }
    }
    #endregion

    #region Private Methods
    /// <summary>
    /// Closes the dialog on Enter key pressed
    /// </summary>
    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            this.Close();
        }
    }

    /// <summary>
    /// User is happy with choice
    /// </summary>
    private void btnOk_Click(object sender, RoutedEventArgs e)
    {
        DialogResult = true;
    }

    /// <summary>
    /// User is not happy with choice
    /// </summary>
    private void btnCancel_Click(object sender, RoutedEventArgs e)
    {
        DialogResult = false;
    }
    #endregion
}

And here is how you could use it from your own WPF code to set a Color:

private void btnPickColor_Click(object sender, RoutedEventArgs e)
{
    ColorDialog colorDialog = new ColorDialog();
    colorDialog.Owner = this;
    if ((bool)colorDialog.ShowDialog())
    {
        RectColorPicked.Fill = new SolidColorBrush(colorDialog.SelectedColor);
    }
}

The actual ColorPicker control works as follows:

There are a number of static swatch images

That the user may pick from using the image buttons provided at the top of the ColorPicker control. The user is then able to use the mouse to move around the image, and also adjust the Alpha value using the slider. The SelectedColor is worked out based on where the mouse is in relationship to the current static swatch image. Basically a single pixel under the mouse is retrieved from the current static swatch image, and this is made into a 1*1 byte array, and then the values within this 1*1 byte array are used to create a Color, taking into account the current Alpha slider value.

The following diagram may help to explain it a little better.

One of the nice things about this control is the Preview, which is simply using a WPF InkPresenter control and showing some strokes on it. And the nice checker background is easily ahcieved in WPF using a DrawingBrush.

In essence that is how it works, so probably time for some code.

Here is the entire XAML for the ColorPicker control.

<UserControl x:Class="WPFColorPickerLib.ColorPicker"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="340" Width="510">


    <UserControl.Resources>
        <DrawingBrush x:Key="CheckerboardBrush" 
        Stretch="None" TileMode="Tile" AlignmentX="Left" AlignmentY="Top" 
        Viewport="0,0,10,10" ViewportUnits="Absolute">
            <DrawingBrush.Drawing>
                <DrawingGroup>
                    <GeometryDrawing Brush="sc# 1,1,1">
                        <GeometryDrawing.Geometry>
                            <RectangleGeometry Rect="0,0,10,10" />
                        </GeometryDrawing.Geometry>
                    </GeometryDrawing>
                    <GeometryDrawing Brush="sc# 0.5,0.5,0.5">
                        <GeometryDrawing.Geometry>
                            <RectangleGeometry Rect="0,0,5,5" />
                        </GeometryDrawing.Geometry>
                    </GeometryDrawing>
                    <GeometryDrawing Brush="sc# 0.5,0.5,0.5">
                        <GeometryDrawing.Geometry>
                            <RectangleGeometry Rect="5,5,5,5" />
                        </GeometryDrawing.Geometry>
                    </GeometryDrawing>
                </DrawingGroup>
            </DrawingBrush.Drawing>
        </DrawingBrush>
    </UserControl.Resources>

    
    <Grid Background="White">

        <Grid.RowDefinitions>
            <RowDefinition Height="35"/>
            <RowDefinition Height="230"/>
            <RowDefinition Height="70"/>
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Height="35" 
                    HorizontalAlignment="Stretch" Orientation="Horizontal" 
                    Background="Black">
            <Label Content="Pick swatch type" Foreground="White" FontWeight="Bold" 
                   VerticalAlignment="Center"/>
            <Image x:Name="ImgSqaure1" Height="20" Width="20" 
                   Source="Images/ColorSwatchSquare.png" Margin="45,0,0,0" 
                   ToolTip="Square swatch1" 
                   MouseLeftButtonDown="Swatch_MouseLeftButtonDown"/>
            <Image x:Name="ImgSqaure2" Height="20" Width="20" 
                   Source="Images/ColorSwatchSquare2.png" Margin="5,0,0,0" 
                   ToolTip="Square swatch2" 
                   MouseLeftButtonDown="Swatch_MouseLeftButtonDown"/>
            <Image x:Name="ImgCircle1" Height="20" Width="20" 
                   Source="Images/ColorSwatchCircle.png" Margin="5,0,0,0" 
                   ToolTip="Circle swatch1" 
                   MouseLeftButtonDown="Swatch_MouseLeftButtonDown"/>
        </StackPanel>

        <Grid Grid.Row="1" Height="230" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="170"/>
                <ColumnDefinition Width="170"/>
                <ColumnDefinition Width="170"/>
            </Grid.ColumnDefinitions>

            <!-- Colorbox, Column1-->
            <Grid Grid.Column="0" Grid.Row="0" Margin="10,30,0,0" >

                <Border BorderBrush="Black" BorderThickness="2" 
                    HorizontalAlignment="Center" VerticalAlignment="Top"
                        Background="White"
                        Width="154" Height="154">
                </Border>
              
                
                
                <Image x:Name="ColorImage" Width="150" Height="150" 
                       HorizontalAlignment="Center"
                       VerticalAlignment="Top" Margin="2"
                       Source="Images/ColorSwatchSquare.png"/>

                <Canvas x:Name="CanvImage" Width="150" Height="150" 
                       HorizontalAlignment="Center"
                       Background="Transparent"
                       VerticalAlignment="Top" Margin="2"
                       MouseDown="CanvImage_MouseDown"
                       MouseUp="CanvImage_MouseUp"
                       MouseMove="CanvImage_MouseMove">
                    <Ellipse x:Name="ellipsePixel" Width="10" 
                       Height="10" Stroke="Black" Fill="White" 
                       Canvas.Left="0" Canvas.Top="0"/> 
                    
                </Canvas>


            </Grid>

            <!-- Preview, Column1-->
            <StackPanel Grid.Column="1" Orientation="Vertical" >
                <Label Content="Preview" Margin="5,0,0,0" HorizontalAlignment="Left" 
                       Foreground="Black" FontWeight="Bold" VerticalAlignment="Center"/>

                <Border Margin="4,5,10,0" Width="154" Height="154" 
                        HorizontalAlignment="Left" BorderBrush="Black" BorderThickness="2"
                        Background="{StaticResource CheckerboardBrush}">
                    <InkPresenter Name="previewPresenter" Margin="0" Width="150" Height="150"
                        Strokes="AOcBAxdIEESAgYAERYQBGwIAJAFGhAEbAgAkAQUBOBkgMgkA9P8CAekiOkU
						zCQD4nwIBWiA6RTgIAP4DAAAAgH8RAACAPx8JEQAAAAAAAPA/CpYBNIfm3uajgcQgUU
						iUkjUelEal0KkUBh0HichlM1mtJotZp9JodDl8jk8ZgcBiUOjUYl08m0+l0+lFCjksjE
						SAh+kg6auNwaEwSBQiEQyLRKTRiVSiUSSORyLQ6JQSBIPFYnKZTL5fOZfMZXL4/H47DY
						LBYHFoJLIpEo9GgIP3OB5PlxLCJiZmU1MISSi4SJiS74+D4+4o" />
                </Border>

            </StackPanel>

            <!-- TextBoxes, Column2-->
            <StackPanel Grid.Column="2" Orientation="Vertical" >

                <StackPanel Orientation="Horizontal" Margin="0,30,0,0">
                    <Label Content="A" Margin="5,0,0,0" HorizontalAlignment="Left" 
                            Foreground="Black" FontWeight="Bold" VerticalAlignment="Center"/>
                    <Border CornerRadius="5" BorderBrush="Black" Background="LightGray" 
                            BorderThickness="2" Width="50" Height="30">
                        <TextBox x:Name="txtAlpha" BorderThickness="0" Background="LightGray" 
                            BorderBrush="Transparent" Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                    <Border CornerRadius="5" BorderBrush="Black" Background="LightGray" 
                            BorderThickness="2" Margin="10,0,0,0" Width="50" Height="30">
                        <TextBox x:Name="txtAlphaHex" BorderThickness="0" 
                            Background="LightGray" BorderBrush="Transparent"
                            Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                </StackPanel>

                <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                    <Label Content="R" Margin="5,0,0,0" HorizontalAlignment="Left" 
                            Foreground="Black" FontWeight="Bold" VerticalAlignment="Center"/>
                    <Border CornerRadius="5" BorderBrush="Black" Background="LightGray" 
                            BorderThickness="2" Width="50" Height="30">
                        <TextBox x:Name="txtRed" BorderThickness="0" Background="LightGray" 
                            BorderBrush="Transparent" Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                    <Border CornerRadius="5" BorderBrush="Black" Background="LightGray" 
                            BorderThickness="2" Margin="10,0,0,0" Width="50" Height="30">
                        <TextBox x:Name="txtRedHex" BorderThickness="0" Background="LightGray" 
                            BorderBrush="Transparent" Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                </StackPanel>

                <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                    <Label Content="G" Margin="5,0,0,0" HorizontalAlignment="Left" 
                            Foreground="Black" FontWeight="Bold" 
                            VerticalAlignment="Center"/>
                    <Border CornerRadius="5" BorderBrush="Black" Background="LightGray" 
                            BorderThickness="2" Width="50" Height="30">
                        <TextBox x:Name="txtGreen" BorderThickness="0" 
                            Background="LightGray" BorderBrush="Transparent" 
                            Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                    <Border CornerRadius="5" BorderBrush="Black" Background="LightGray"
                            BorderThickness="2" Margin="10,0,0,0" Width="50" Height="30">
                        <TextBox x:Name="txtGreenHex" BorderThickness="0"
                            Background="LightGray" BorderBrush="Transparent" 
                            Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                </StackPanel>

                <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                    <Label Content="B" Margin="5,0,0,0" HorizontalAlignment="Left" 
                           Foreground="Black" FontWeight="Bold" 
                           VerticalAlignment="Center"/>
                    <Border CornerRadius="5" BorderBrush="Black" Background="LightGray" 
                           BorderThickness="2" Width="50" Height="30">
                        <TextBox x:Name="txtBlue" BorderThickness="0" Background="LightGray" 
                           BorderBrush="Transparent" Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                    <Border CornerRadius="5" BorderBrush="Black" Background="LightGray" 
                            BorderThickness="2" Margin="10,0,0,0" Width="50" Height="30">
                        <TextBox x:Name="txtBlueHex" BorderThickness="0" 
                            Background="LightGray" BorderBrush="Transparent" 
                            Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                </StackPanel>

                <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                    <Border CornerRadius="5" Margin="22,0,0,0" Background="LightGray" 
                            BorderBrush="Black" BorderThickness="2" Width="112" Height="30">
                        <TextBox x:Name="txtAll" BorderThickness="0" Background="LightGray" 
                            BorderBrush="Transparent" Margin="5,1,5,1" IsReadOnly="True"/>
                    </Border>
                </StackPanel>
                
            </StackPanel>
            
        </Grid>

        <!--AlphaSlider-->
        <Border x:Name="AlphaBorder" Grid.Row="2" Grid.ColumnSpan="2" 
                BorderBrush="Black" Height="60"
                BorderThickness="2" CornerRadius="5" Margin="10,5,10,5">
            <Slider x:Name="AlphaSlider" Orientation="Horizontal" 
                Minimum="0" Maximum="255" 
                SmallChange="1" LargeChange="25"
                VerticalAlignment="Center" Margin="5" 
                Value="255"
                ValueChanged="AlphaSlider_ValueChanged"/>

        </Border>

    </Grid>
</UserControl>

And here is all the C# code behind for the ColorPicker control.

public partial class ColorPicker : UserControl
{
    #region Data
    private DrawingAttributes drawingAttributes = new DrawingAttributes();
    private Color selectedColor = Colors.Transparent;
    private Boolean IsMouseDown = false;
    #endregion

    #region Ctor
    public ColorPicker()
    {
        InitializeComponent();
        this.Loaded += new RoutedEventHandler(ColorPicker_Loaded);
    }
    #endregion

    #region Public Properties
    /// <summary>
    /// gets or privately sets the selected
    /// Color. When the Color is set 
    /// the CreateAlphaLinearBrush()/UpdateTextBoxes()
    /// and UpdateInk() methods are called
    /// </summary>
    public Color SelectedColor
    {
        get { return selectedColor; }
        private set
        {
            if (selectedColor != value)
            {
                selectedColor = value;
                CreateAlphaLinearBrush();
                UpdateTextBoxes();
                UpdateInk();
            }
        }
    }
    #endregion

    #region Private Methods
    /// <summary>
    /// Start with a default Color of black
    /// </summary>
    private void ColorPicker_Loaded(object sender, RoutedEventArgs e)
    {
        SelectedColor = Colors.Black;
    }

    /// <summary>
    /// Creates a new LinearGradientBrush background for the
    /// Alpha area slider. This is based on the current color
    /// </summary>
    private void CreateAlphaLinearBrush()
    {
        Color startColor = Color.FromArgb(
                (byte)0,
                SelectedColor.R, 
                SelectedColor.G, 
                SelectedColor.B);

        Color endColor = Color.FromArgb(
                (byte)255,
                SelectedColor.R, 
                SelectedColor.G, 
                SelectedColor.B);

        LinearGradientBrush alphaBrush = 
            new LinearGradientBrush(startColor, endColor, 
                new Point(0, 0), new Point(1, 0));

        AlphaBorder.Background = alphaBrush;
    }


    /// <summary>
    /// apply the new Swatch image based on user requested swatch
    /// </summary>
    private void Swatch_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Image img = (sender as Image);
        ColorImage.Source = img.Source;
    }


    /// <summary>
    /// Simply grab a 1*1 pixel from the current color image, and
    /// use that and copy the new 1*1 image pixels to a byte array and
    /// then construct a Color from that.
    /// </summary>
    private void CanvImage_MouseMove(object sender, MouseEventArgs e)
    {
        if (!IsMouseDown)
            return;

        try
        {
            CroppedBitmap cb = new CroppedBitmap(ColorImage.Source as BitmapSource,
                new Int32Rect((int)Mouse.GetPosition(CanvImage).X,
                    (int)Mouse.GetPosition(CanvImage).Y, 1, 1));

            byte[] pixels = new byte[4];

            try
            {
                cb.CopyPixels(pixels, 4, 0);
            }
            catch (Exception ex)
            {
                //Ooops
            }

            //Ok now, so update the mouse cursor position and the SelectedColor
            ellipsePixel.SetValue(Canvas.LeftProperty,(double)(Mouse.GetPosition(CanvImage).X-5));
            ellipsePixel.SetValue(Canvas.TopProperty, (double)(Mouse.GetPosition(CanvImage).Y-5));
            CanvImage.InvalidateVisual();
            SelectedColor = Color.FromArgb((byte)AlphaSlider.Value, pixels[2], pixels[1], pixels[0]);
        }
        catch (Exception exc)
        {
            //not much we can do
        }
    }

    /// <summary>
    /// Update text box values based on SelectedColor
    /// </summary>
    private void UpdateTextBoxes()
    {
        txtAlpha.Text = SelectedColor.A.ToString();
        txtAlphaHex.Text = SelectedColor.A.ToString("X");
        txtRed.Text = SelectedColor.R.ToString();
        txtRedHex.Text = SelectedColor.R.ToString("X");
        txtGreen.Text = SelectedColor.G.ToString();
        txtGreenHex.Text = SelectedColor.G.ToString("X");
        txtBlue.Text = SelectedColor.B.ToString();
        txtBlueHex.Text = SelectedColor.B.ToString("X");
        txtAll.Text = String.Format("#{0}{1}{2}{3}",
                txtAlphaHex.Text, txtRedHex.Text, 
                txtGreenHex.Text, txtBlueHex.Text);
    }

    /// <summary>
    /// Updates Ink stroked based on SelectedColor
    /// </summary>
    private void UpdateInk()
    {
        drawingAttributes.Color = SelectedColor;
        drawingAttributes.StylusTip = StylusTip.Ellipse;
        drawingAttributes.Width = 5;

        // Update DA on previewPresenter
        foreach (Stroke s in previewPresenter.Strokes)
        {
            s.DrawingAttributes = drawingAttributes;
        }
    }

    /// <summary>
    /// Update SelectedColor Aplha based on Slider value
    /// </summary>
    private void AlphaSlider_ValueChanged(object sender, 
        RoutedPropertyChangedEventArgs<double> e)
    {
        SelectedColor = 
            Color.FromArgb(
                (byte)AlphaSlider.Value,
                SelectedColor.R, 
                SelectedColor.G, 
                SelectedColor.B);
    }

    /// <summary>
    /// Change IsMouseDown state
    /// </summary>
    private void CanvImage_MouseDown(object sender, MouseButtonEventArgs e)
    {
        IsMouseDown = true;
    }

    /// <summary>
    /// Change IsMouseDown state
    /// </summary>
    private void CanvImage_MouseUp(object sender, MouseButtonEventArgs e)
    {
        IsMouseDown = false;
    }
    #endregion

}

 

So What Do You Think ?

I would just like to ask, if you liked the article please vote for it, and leave some comments, as it lets me know if the article was at the right level or not, and whether it contained what people need to know.

More News

One of the readers of this article, a one Mark Treadwell, has taken this idea further and enhanced this Dialog to allow the Dialog to also show a selected Color on ShowDialog() and also done various other enhancements. You can read more about this over at Marks blog post at http://geekswithblogs.net/mtreadwell/archive/2010/01/03/137314.aspx, and here is a link to his source code : Marcs better ColorPicker

A few people have asked for this, but I have been too busy, so thanks Marc

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sacha Barber


Member
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Occupation: Software Developer (Senior)
Location: United Kingdom United Kingdom

Other popular Windows Presentation Foundation articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 41 (Total in Forum: 41) (Refresh)FirstPrevNext
Generalhi PingroupSarafuddin7:21 18 Jan '10  
GeneralRe: hi PinmvpSacha Barber7:23 18 Jan '10  
GeneralRe: hi PingroupSarafuddin7:26 18 Jan '10  
GeneralShould have been called 'WPF: Beautiful Color Picker' PinmemberTheArchitectmc6:58 4 Jan '10  
GeneralRe: Should have been called 'WPF: Beautiful Color Picker' PinmvpSacha Barber7:02 4 Jan '10  
GeneralGood Stuff PinsupporterMark Treadwell2:56 3 Jan '10  
GeneralRe: Good Stuff PinmvpSacha Barber4:38 3 Jan '10  
GeneralRe: Good Stuff PinsupporterMark Treadwell5:15 3 Jan '10  
GeneralRe: Good Stuff PinmvpSacha Barber10:42 3 Jan '10  
GeneralRe: Good Stuff PinmvpSacha Barber6:33 4 Jan '10  
GeneralCool! But I miss a SetIntialColor() Method Pinmemberbanjoji1:05 1 Jul '09  
GeneralRe: Cool! But I miss a SetIntialColor() Method PinmvpSacha Barber6:34 4 Jan '10  
GeneralOn Lee Brimelow code PinmemberOleg V. Polikarpotchkin18:50 30 May '09  
Generalthanks Pinmemberahmad35820:30 20 Mar '09  
GeneralRe: thanks PinmvpSacha Barber22:45 20 Mar '09  
GeneralLicense Pinmemberclemi18:09 10 Feb '09  
GeneralRe: License PinmvpSacha Barber22:48 10 Feb '09  
GeneralCool PinmemberMember 41635242:16 10 Feb '09  
GeneralRe: Cool PinmvpSacha Barber2:29 10 Feb '09  
GeneralFantastic Control PinmvpAbhijit Jana4:22 3 Feb '09  
GeneralRe: Fantastic Control PinmvpSacha Barber4:37 3 Feb '09  
GeneralAwesome!! PinmemberDr.Luiji1:58 3 Feb '09  
GeneralRe: Awesome!! PinmvpSacha Barber2:00 3 Feb '09  
GeneralEven in a snow storm PinmemberDaniel Vaughan9:16 2 Feb '09  
GeneralRe: Even in a snow storm PinmvpSacha Barber11:19 2 Feb '09  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.

PermaLink | Privacy | Terms of Use
Last Updated: 4 Jan 2010
Editor:
Copyright 2009 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2010
Web09 | Advertise on the Code Project