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: ,

12.21.2007

Silverlight is the ugly stepchild of WPF

Silverlight is the ugly stepchild of WPF (Windows Presentation Format). Nearly all of the things that are not yet implemented and/or I need/would like as tools for building Silverlight projects work in WPF in some way. WPF appears to have been designed to create the ultimate interactive kiosk. It allows developers to make visually pleasing interfaces for their applications easily. It appears to me that WPF is where Microsoft's focus lies, and Silverlight is them taking WPF technology and trying to force the square peg into the round hole of the web. Not that the hole will be round forever, but that's a different story. However, I think Microsoft has failed to provide some major features that are expected in well designed web experiences and RIAs these days.


  • More than Media - Rich Media Applications are not just media players. Silverlight, does a great job of being a cross-platform media player, but web developers have come to expect MUCH MORE, including Alpha Channel support and pre-compiled content. Silverlight isn't delivering these core elements, at least not in a useful way. And some of these still won't be included in the 2.0 release.

  • File size - Doing some tests, I took some XAML and created a basic, no interaction layout and the XAML file was Ten Times (10x) as large as the same layout in a SWF. 224k (Silverlight, xaml) vs 22k (flash, swf). Quick downloads and instantaneous user gratification is expected these days. If you're site is slow, or takes forever to download users just go elsewhere. You can't afford to have bloated files, especially if they have less functionality.

  • Slick Design at run-time - vector art is nice, but that's so 2004. The new design pallet is bitmap graphics and filters. You need to have gradient overlays with drop shadows, filter effects and pixel effects (especially blending modes) that can be manipluated at run-time. This falls back to the file size issue. Sure I can create all of these elements in another program, but then the user has to download them. If I can create them on the fly, then I don't need to pre-render them. Now I know you could do this in realtime using javascript and vector data, but the code to do that is big, and as a designer/developer, I'd rather just be able to call a filter function and be done.


Perhaps it's just a work-flow issue for me at this point. I can see how Silverlight has the potential to do many of the things I mention above. All of those things can be done easily in Flash. Right now, it takes me 3 times as long to do things using the Microsoft tools vs the Adobe tools. Granted I'm familiar with the Adobe tools, and I've put the time into learning them, but when Microsoft's marketing speech is, "we've integrated the work flow between designers and developers," I can't help thinking, "I'm a designer/developer and my work flow is more convoluted than ever using your tools."

I'm looking forward to Silverlight growing up and moving out of it's parents house. I don't want it to be the ugly stepchild anymore. Competition is good for the marketplace. If Silverlight can get some market share, it will push both Adobe and Microsoft to create better products, which is better for me.

Silverlight 2.0 should provide a lot of useful features, but until the ones I mentioned above are on par or better than Flash, Silverlight will remain inadequate and noncompetitive in the real world. The buzz will die down, just like it did with the Zune, and Vista...and what's left could be ugly. Integrated software and tools will only get Silverlight so far if the final delivery is inferior to it's competition. Adobe is working its butt off to integrate the crap out of Creative Suite. It's not there yet, but it's close. What's Microsoft doing to create a better overall experience for the user as compared to Flash?

Time will tell. Now I have to go and slap the ugly stepchild around a bit until it does what I want.

Labels: , ,