Archive for the ‘Software’ category

ProgressStream: A Stream with Read and Write events

January 19th, 2010

In my experience with WCF I’ve implemented several solutions that leverage the message streaming capabilities present in the framework. Specifically in a client/server scenario when either side needs to transfer a file to the other side it is really convenient to be able to just pass a FileStream to a WCF service call and have the server read bytes from it and write them to disk as it pleases.

However, in this exact scenario, while the server can monitor and control how the bytes are read from the stream and track the progress, the client has no inherent way of determining how much of the file has been read across the network by the server. It would be really useful if the client could track this upload progress and display a progress bar or percentage to the user.

Well, I’ve created one of probably many possible solutions to this dilemma. I’ve written a class that inherits from Stream and exposes some events that are raised when bytes are read or written to/from the stream. These events provide information for how many bytes were read from the stream, what the current position is in the stream, and what the stream’s total length is.

The ProgressStream, as I call it, accepts any Stream object and encapsulates it, forwarding all regular stream calls to the underlying object. With this you can use the ProgressStream in conjunction with any other stream in .Net and leverage the added functionality.

Well enough explanation, here’s the code:

ProgressStream.cs (C#)
ProgressStream.vb (VB.Net)

And here’s a simple example in C# of how to use it:

using System;
using System.IO;
using CGS;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var test = File.OpenRead(@"C:\Test\Test.doc");
 
            var pStream = new ProgressStream(test);
            pStream.BytesRead += 
                new ProgressStreamReportDelegate(pStream_BytesRead);
 
            int bSize = 4320;
            byte[] buffer = new byte[bSize];
            while (pStream.Read(buffer, 0, bSize) > 0) { }
 
            Console.ReadKey();
        }
 
        static void pStream_BytesRead(object sender, 
                                      ProgressStreamReportEventArgs args)
        {
            Console.WriteLine(
                string.Format("{2} bytes moved | {0} of {1} total", 
                    args.StreamPosition, 
                    args.StreamLength, 
                    args.BytesMoved
                )
           );
        }
    }
}

WPF: Simple Vista Image Viewer

September 25th, 2009

Preview of WPF Image Viewer

Download source code – 72.2 KB
Download sample app – 67.8 KB

What does it do?

This lightweight WPF UserControl will display a single image in a manner similar to the Windows Photo Gallery. It doesn’t manage more than one image in a gallery or slideshow fashion however, but it does:

  • Zoom In/Out both with the mouse and with a slider control
  • Pan the image with the mouse
  • Rotate the image clockwise or counter-clockwise 90 degrees
  • Keep the image fully visible in the display area when not in zoom mode

How can I use it?

You can use this image viewer in any WPF application with little effort since it’s built as a WPF UserControl. By leveraging the WPF Interoperability in WinForms it’s possible to use this in a Windows Forms application as well, see the article here for instructions on accomplishing that.

To get started using the control, download the source project from the above link. You can play around with the sample application to see an example of how to use the image viewer. The sample program simply provides a Window for the control and sets the path for the image to display; the control does all the rest.

To use the control in your own application you simply need to include the necessary source files in your own project or solution (CgsImageViewer.xaml(.cs), PanAndZoom.cs, and the images for the buttons). Once you’ve got them, you’ll begin by inserting the viewer into your XAML, like so:

<Window x:Class="ImageViewer.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:iv="clr-namespace:ImageViewer"
    Title="Image Viewer Sample" Height="418" Width="410">
    <Grid>
        <iv:CgsImageViewer x:Name="cgsImageViewer" />
    </Grid>
</Window>

This is just placing the image viewer in a window and giving it a name. Now to load up an image all that you need to do is provide a path to the image or a BitmapImage object. You can do this in the business code or in the XAML by means of a data binding. Here’s an example of setting the image in the business code:

cgsImageViewer.CurrentImagePath = @"c:\test images\cat-plans-your-doom.jpg";

That’s all you really need to know to use the image viewer. Continue on for some extra info.

Class Members you might want to know about:

  •  CurrentImage – Gets or sets the current BitmapImage used by the viewer.
  •  CurrentImagePath – Gets or sets a string representing the Uri to load an image from.
  •  ZoomLevel – Gets or sets a double representing the percentage to zoom.
  •  ScaleToFit – Resizes the image to fit within the visible bounds.
  •  RotateLeft – Rotates the image 90 degrees to the left and scales it to fit.
  •  RotateRight – Rotates the image 90 degrees to the right and scales it to fit.

(Note: The code for panning and zooming was found here)

A little background and explanation:

I wrote this control in a grand total of about two days, which included testing. It was written for use in a WPF project I’m currently working on where users needed to be able to preview graphic files inside the program. I decided to make something that could be re-used and would provide simple viewing capabilities.

So here you go. If you’ve used it and like it why not leave a comment or trackback. If you find any bugs or have some ideas to improve on it let me know. I’m always looking to make things better!

WPF: CheckBox as GroupBox Header

August 7th, 2009

This is a followup post to the one I wrote on Enabling Controls with a CheckBox. In that post we created some XAML that would enable/disable controls in the GUI based on the IsChecked property of a checkbox.

Here’s an enhancement to that:

Checkbox as header for Groupbox

So what we’re doing is giving the controls on our dialog a nice visual grouping letting the user know that they’re associated. The GroupBox element has long existed to fulfill this need. However, with this little XAML change it also doubles as a sort of access control for the items it contains.

Here’s the XAML:

<GroupBox Padding="5" HorizontalAlignment="Stretch">
    <GroupBox.Header>
        <CheckBox x:Name="chkEnableBackup">Run Backup Sets</CheckBox>
    </GroupBox.Header>
 
    <StackPanel IsEnabled="{Binding ElementName=chkEnableBackup, Path=IsChecked}">
        <StackPanel Orientation="Horizontal">
            <Label Margin="12,0,0,0">Run backup every</Label>
            <ComboBox Width="70" SelectedIndex="0">
                <ComboBoxItem>Minute</ComboBoxItem>
                <ComboBoxItem>Hour</ComboBoxItem>
                <ComboBoxItem>Day</ComboBoxItem>
            </ComboBox>
        </StackPanel>
        <StackPanel Margin="12,10,0,0">
            <Label>Path to Backup:</Label>
            <TextBox Width="200" Margin="5,0,0,0"/>
        </StackPanel>
    </StackPanel>
</GroupBox>

So all we’ve done here is add the CheckBox to the <GroupBox.Header> element of the GroupBox. Pretty slick!

This little technique is complete UI Candy and in my opinion illustrates one of the many powerful features of WPF: the ability to customize the GUI in any way you want, down to any level!

WPF: Creating a Pop Up Button Style

August 7th, 2009

So I’ve been getting pretty fancy with my GUI development, and today I wanted to design a button that would appear as just flat text until you hovered over it with the mouse, at which point it would “pop up” and look like an actual button.

Regular Button'Flat' Button

The following solution only works when run on a system with a Windows Vista/7 theme enabled, such as Aero or Basic. It will not work when run with the Windows Classic theme.

The ‘Flat’ Pop Up Button was achieved by simply setting the background and border to transparent. Here’s the XAML:

<Button Content="Click Me!" Background="Transparent" BorderBrush="Transparent"/>

The next step was to make it so that when the mouse hovers over the button it “pops up” visually and looks like your standard button. At first I tried several methods for accomplishing this using triggers to set the style of the button which were all turning out to be pretty messy since I’m not the best graphical designer.

But silly me, I didn’t realize that in this case I didn’t have to do anything special at all! I could just leave the button as it is in the XAML above and the baked in triggers for the Button would still kick in and change the appearance when the mouse hovered over it.

Here’s what that looks like:

Pop Up Button

It looks pretty cool in spots where you want a nice, Aero style button, but if the user isn’t interacting with it you don’t want all those pixels distracting from the clean whiteness that is your polished application.

WPF: Setting a Type Specific Property Value

August 7th, 2009

While XAML in WPF is probably the most powerful GUI development architecture I’ve ever used and by far my favorite, there’s still a few little tasks here and there that I just scratch my head trying to figure out.

This is probably due to my limited knowledge of XAML and how to use it properly, so until I get it all mastered I’m forced to use lines of DuctTape to get some of the results I want.

Here’s my most recent hack job. If you look at the XAML below you’ll notice that I’m making use of the Tag property of the button. This is just an example, but in real life there’s actually quite a few valuable uses for Tag.

<Button Content="Am I the right button?" Tag="False" Click="Button_Click" />
<Button Content="Am I the right button?" Tag="True" Click="Button_Click" />
<Button Content="Am I the right button?" Tag="False" Click="Button_Click" />

So in this example the user needs to click the right button. The right button is indicated by its tag property. In this case the second button is the one that works, right?

Which button is it?

Not exactly.

The code to handle this situation would look something like ths:

private void Button_Click(object sender, RoutedEventArgs e)
{
    var sourceBtn = sender as Button;
 
    bool isRight = (bool)sourceBtn.Tag;
}

Since Tag is defined as an object and I’m binding it to “False” in my XAML I thought this code would work out just fine, but it doesn’t.

The problem is Tag gets populated with a string instead of a boolean. That’s interesting, after all why shouldn’t it? How is XAML supposed to know that what I wanted to set to Tag is the boolean value False? It doesn’t.

So I had to write my XAML in such a way that it knew without a doubt that I was using a boolean value.

The first thing in accomplishing this was to include the System namespace in my XAML file, like so:

xmlns:system="clr-namespace:System;assembly=mscorlib"

Then I could declare my Tag property full out giving it a system:Boolean for its value.

<Button Content="Am I the right button?" Click="Button_Click">
	<Button.Tag>
		<system:Boolean>False</system:Boolean>
	</Button.Tag>
</Button>
<Button Content="Am I the right button?" Click="Button_Click">
	<Button.Tag>
		<system:Boolean>True</system:Boolean>
	</Button.Tag>
</Button>
<Button Content="Am I the right button?" Click="Button_Click">
	<Button.Tag>
		<system:Boolean>False</system:Boolean>
	</Button.Tag>
</Button>

And that’s it, it works! Yay!

But man, it really is ugly. Does anyone know of a cleaner, better way to accomplish the same thing? I would love to learn something new!