Discorax's House of w00t

A collection of technology lessons learned though doing. Sharing of code samples, tips and tricks for web design and development. Written by an interactive designer/developer for other designer/developers.

9.14.2009

Getting and using the pixels of your Visual in WPF

Have you ever wanted to get the Bitmap Data (pixels) of a Visual (Canvas, Grid, etc) in WPF or Silverlight from memory and without having to add it to the root visual. After doing a lot of trial and error here is a quick piece of code and a sample project that can help you accomplish exactly that.

There are plenty of cool ways to extend this project including some cool transition and other code based animations. Just let your imagination go wild!

First, create a new WPF Application in Visual Studio or [download a sample project]. In your Window1.xaml give the Grid an x:Name value. You'll use this to add your elements later on.


Now lets add a new Page to our project. We're going to alter the Page to extend a Canvas rather than a Page for no other reason then when I'm creating animations I prefer to work with a Canvas. We are going to put some visuals onto our canvas. In the sample it's a blue square with a red circle next to it and a little bit of text below it. It could be any UIElement including another Canvas/Grid, Images, Text anything.

In our Window1.xaml code behind we're going to create an instance of our Canvas1 and call the methods to have WPF Measure, Arrange, and UpdateLayout in memory. We need to call these methods in order for WPF to figure out where all the pixels are positioned in our visual to return accurate Bitmap Data. These methods are called automatically when you add a Visual to WPF using the Visual.Children.Add() method.

The CreateBitmapSourceFromVisual function was taken from a project on CodePlex, unfortunately I can't recall the link. I'll add it here if I run across it again. That function takes a Visual and returns a BitmapSource object with the pixel data. It automatically updates the dots per inch (DPI) to 96, which is required for WPF to render properly).

Here is the code behind from our root Window.





You can run the sample project and you will see the visual we created in Canvas1. We used the BitmapSource object of the Canvas1 as the Source of our Image. Note: we never added Canvas1 to the root visual, we simply created it in the code behind and retrieved the pixel data from that visual to use as on our Image. I leave it to you to play with this technology to create cool WPF/Silverlight animations.

[Download Source Code] as Visual Studio Project.

Labels: , ,

12.01.2008

Building Custom Events in C#

The more I learn Object Oriented Programing techniques the more I value the ability to have my classes listen to each other. I've been working in C# a lot recently for a WPF project. At various points throughout the development process I've found a need to have different events cause effects among objects and classes. .NET has a great list of events built into many of their classes especially the UIElements and Controls. What I want to do is put together some code snippets on how to build a custom event for your object and hopefully to help some new C# programmers better understand how events work and how powerful they can be.



What in the world does that do you ask...well lets break it down.

The first part of this example is based on a WPF Application template from Visual Studio 2008. It includes all the using statements, the namespace deceleration and the Window1 class. The reason I included all this is so that you can download the Project file and poke around.

Inside the Window1 constructor we're going to create an instance of our EventBroadcasterClass so that we can use it to send out our custom event.



The EventBroadcasterClass has a public event myEvent and a Method to broadcast it, MyEventMethod. The constructor method then creates a new CustomEventHandler Object myEventHandler and adds it's Handle method as a listener to the EventBroadcasterClass myEvent event.

You can pass a variety of data through events (although it's not always the best approach). In this case we set up a new CustomEventArgs object and added some text to it. "Text from EventBroadcasterClass" will be used by our CustomEventHandler later on. Here is the whole EventBroadcasterClass.



The CustomEventHandler is very simple. It has a string property and a Handle method. As you can see the Handle method takes two arguments. object sender is where the event was broadcast from, in this case it's the EventBroadcasterClass, and a CustomEventArgs object. This is where the string value we set in our broadcaster is held. To access it we just have to set our string property to the CustomEventArgs public property MyString. Then all we do is write it out to the Console for demonstration purposes. Here is the CustomEventHandler Class



The final piece of this puzzle is the CustomEventArgs. This Class just hold the arguments we pass between events and listeners. You can fill this object will anything, although it can really hurt performance if you pass too much data in event args. The constructor method sets a private property and the public MyString property which has a get to return the value set when the CustomEventArgs object is created. Directly below we see a public delegate CustomEvent. This delegate is used to relay your event to any object that is listening.




It took me some time to put all these pieces together, but now that I have I can build Classes that are always aware of what others are doing, which can have some very cool effects. I hope this little summary will help others get up to speed quickly building Custom Events in C#.

Download the Source Code

Labels: ,

10.09.2008

Access WPF Storyboard in XAML from code-behind (C#)

At more than one time working with WPF I've wanted to create a generic Storyboard using Blend because it saves me time and gives me a nice time line type layout to create/tweak my Storyboard. What happens is when you save the Storyboard it's added to the Windows.Resources collection the XAML. In Silverlight you can access these Storyboard resources directly using their x:Name value. In WPF, however, you need to do it slightly differently.


  • First, You need to specify x:Key for each Storyboard

  • Storyboards must be found using TryFindResource:

    Storyboard myStoryboard = (Storyboard)TryFindResource("myStoryboard");

  • TryFindResource will only work if the Storyboard is in the Window.Resources section of the XAML and you're in the code-behind of that XAML

  • Once you have the reference to the Storyboard contained in a variable you can call the various Storyboard methods on it. To run it, use the Begin method:

    myStoryboard.Begin();



Here is a quick code snippet to help you out.



Here is the XAML:

Labels: , ,

9.19.2008

WPF Full screen accross multiple monitors

I've been working on a cool instillation project for Microsoft and one of the things I need to do is have my application go full screen across multiple monitors. By default, if you maximize your application window inside Windows it fills the Primary Screen or Active screen but it doesn't go across all monitors. You have to manually drag the application window across to have it show up on more than one monitor. What if you wanted to make a screen saver for multiple monitors? Doing some internet searching I pieced together this little solution. Here is a code snippet that maximizes your WPF app window across all monitors in multi-mon setups. It also adds a listener for the ESC key to close the window down. Hope this helps people find this solution faster in the future.



Then in your XAML make sure you don't have any values set so the code behind can do it's thing.

Labels: ,