Switch On The Code RSS Button - Click to Subscribe
Aug
21

WPF Tutorial - Using Splash Screens in SP1

Splash screens - everyone loves them, right? Actually, I'm not a big fan of them, but sometimes they are a necessary evil - especially in the world of WPF. A cold start up of a WPF application can be, well, slow - mostly because there are a lot of common WPF dlls that need to be loaded. Once they are loaded for the first time after bootup, WPF apps generally start pretty fast, but that first WPF app after a reboot can crunch away at your hard drive for quite a few seconds.

Adding a splash screen for WPF in the pre .NET 3.5 SP1 world was a huge pain. You had to pull in a couple native methods and essentially create your own window, and on top of all that there was a special build step that had to be executed. Really, we should have written a tutorial about that here at SOTC a long time ago. But now, it's so easy, it's almost not worth a tutorial (but I'm going to write it up anyway, cause hey, you never know).


Adding a splash screen for a WPF app has been turned into a three step process now that SP1 is out . The first step is to make the splash screen image. Break out Photoshop and do your worst! For the sample app here today, I just took a screen shot of the webpage and cropped out the top logo, so the splash screen image is going to look like this:


Ok, you have an image now? Good. Add it as an item to your WPF project. In our case, it is a png called SOTCSplash.png:


And now for the final, horribly complicated step. Select that newly added image, go to the item properties, and for the Build Action property choose "SplashScreen":


Your done! That is all that you need to do now to create a splash screen for a WPF app. In the case of our example, the app looks like this when starting up:


The splash screen even does a nice automatic fade out.

Now, if you want a little more control over the splash screen, you can choose not to use that build action, and instead use the new SplashScreen class that comes in SP1. This is more complicated than the build action, but much less complicated than the old way. First, we have to add a Main method to App.xaml.cs. Generally, Visual Studio creates a main method automatically, but we don't want that to happen anymore, because we will be putting special code in that method. To do this, change the "Build Action" for App.xaml from "Application Definition" to "Page".

Now, in App.xaml.cs, we add a main method. The standard base main method for WPF looks something like this:

/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
public static void Main()
{
  app.InitializeComponent();
  app.Run();
}

Now we want to add the splash screen to that. First, we need to set the build action for the image to "Resource", so that we can reference it. Then we add a couple lines to the main method:

/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
public static void Main()
{
  SplashScreen splashScreen = new SplashScreen("SOTCSplash.png");
  splashScreen.Show(true);
  app.InitializeComponent();
  app.Run();
}

That will give the exact same behavior as using that "SplashScreen" build action from before. If we want to customize it a bit, we can do something like this:

/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
public static void Main()
{
  SplashScreen splashScreen = new SplashScreen("SOTCSplash.png");
  splashScreen.Show(false);
  SplashScreenTest.App app = new SplashScreenTest.App();
  app.InitializeComponent();
  splashScreen.Close(TimeSpan.FromMilliseconds(1000));
  app.Run();
}

The boolean passed into the splash screen Show function determines if the splash screen will close automatically (true is automatic, false is manual). If we choose false, we have to remember to call Close at some point, but we also get the ability to say how long it takes for the splash screen to fade out. In this case, we are saying the fade out should take 1000 milliseconds (instead of the default 300).

And that is about it for the new stuff on splash screens that came with SP1 for .NET 3.5 and VS2008. You can check out the new SplashScreen class at MSDN, and you can download the sample project we built today here. And just to leave on an amusing note here - Microsoft went to all this work to make splash screens easy in SP1, but their own User Experience Guidelines for Vista recommend against using splash screens in the first place.



Posted in WPF, All Tutorials by The Tallest | No Comments »

Aug
20

XAML Tutorial - Changing Text Color on Mouse Over

I received a comment on an old Silverlight 1.1 post a while ago asking how to change the foreground of text when the user has moused over it. I could have pasted the solution as a reply in the comment, but I felt it deserved its very own tutorial.

Silverlight is getting pretty close to supporting everything WPF can, so I went ahead and implemented a solution using WPF instead of Silverlight. When the final Silverlight 2 is released, the code should port very easily to the new environment.


Let's start the tutorial with a simple Windows application and a resource we're going to use as our mouse-over color.

<Window x:Class="MouseOverTutorial.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">

  <Window.Resources>
    <SolidColorBrush x:Key="mouseOverColor"
                     Color="Red" />

  </Window.Resources>
    <Grid>
  </Grid>
</Window>

This is basically exactly what Visual Studio generates for you when you create a new application. The only exception is that I added a SolidColorBrush as a resource. The next thing we need in this application is some text.

<Window x:Class="MouseOverTutorial.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">

  <Window.Resources>
    <SolidColorBrush x:Key="mouseOverColor"
                     Color="Red" />

  </Window.Resources>
    <Grid>
      <Label HorizontalAlignment="Center"
             VerticalAlignment="Center"
             Content="My Text"
             FontSize="20"
             FontWeight="bold" />

  </Grid>
</Window>

Now we've actually got some text to change when the mouse enters it. You might have noticed I went with a Label instead of a TextBlock. This is because I decided to use a ControlTemplate to control the colors, and TextBlocks don't support ControlTemplates. Let's take a look at this ControlTemplate now.

<Style x:Key="myStyle" TargetType="Label">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Label">
        <ControlTemplate.Triggers>
          <Trigger Property="IsMouseOver"
                   Value="True">

            <Setter Property="Foreground"
                    Value="{StaticResource mouseOverColor}" />

          </Trigger>
        </ControlTemplate.Triggers>
        <ContentPresenter />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

I put everything inside a style so I could easily apply it to more than one Label. The most important piece here is the property trigger. Whenever IsMouseOver is true, the foreground of my Label will be set to the SolidColorBrush in my Window's resources. When the property is false, it will revert back to its default color. If you want the mouse-out color to be something other than black, you'll have to add another property trigger to handle that.

The ContentPresenter tag is required when you're using a ControlTemplate. It simply notifies the template where the Label's content is supposed to go. There's no limit to what visuals you can put inside the template, so if you wanted the text to be inside a blue ellipse, you could simple do something like this:

<Grid>
  <Ellipse Fill="Blue" />
  <ContentPresenter />
</Grid>

But the ins and outs of ControlTemplates are beyond the scope of this tutorial. Now that the style is written, all that's left to do is apply it to the Label.

<Label HorizontalAlignment="Center"
       VerticalAlignment="Center"
       Content="My Text"
       FontSize="20"
       FontWeight="bold"
       Style="{StaticResource myStyle}" />

Now if you were launch this application you'd get something that looks like the picture below. The image on the left is with the mouse outside of the Label and the image on the right is when the mouse enters the Label.



And here's the code in its entirety:

<Window x:Class="MouseOverTutorial.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">

  <Window.Resources>
    <SolidColorBrush x:Key="mouseOverColor"
                     Color="Red" />

    <Style x:Key="myStyle" TargetType="Label">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Label">
            <ControlTemplate.Triggers>
              <Trigger Property="IsMouseOver"
                       Value="True">

                <Setter Property="Foreground"
                     Value="{StaticResource mouseOverColor}" />

              </Trigger>
            </ControlTemplate.Triggers>
            <ContentPresenter />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>
  <Grid>
    <Label HorizontalAlignment="Center"
           VerticalAlignment="Center"
           Content="My Text"
           FontSize="20"
           FontWeight="bold"
           Style="{StaticResource myStyle}" />

  </Grid>
</Window>

So there you have it, you've just learned how to use ControlTemplates to change the foreground color of text when the user mouses over it.



Posted in XAML, All Tutorials by The Reddest | No Comments »