Between the Lines
5Feb/100

Attaching to WndProc in WPF

WPF, like any other UI program, has an inner loop that continually runs in order to update the state of the application and render the UI.  One part of this loop is a call to the function WndProc, which is the function through which Windows communicates the messages your window is receiving (be it input or system notifications).

WPF hides this function from you (presumably to make things easier) and instead just fires events off for anything [it thinks] you'll ever need.  Sometimes, however, it is useful to attach to this loop in order to address messages that don't have a related WPF event, such as messages sent by other applications.

Here's how you do it.

In your window's SourceInitialized event, create an HwndSource object from your window's handle. Use the AddHook method to attach an event handler to all of your window's events using the supplied function.

private void Window_SourceInitialized(object sender, EventArgs e)
{
    IntPtr windowHandle = (new WindowInteropHelper(this)).Handle;
    HwndSource src = HwndSource.FromHwnd(windowHandle);
    src.AddHook(new HwndSourceHook(WndProc));
}

As its always good practice to define the methods you reference, be sure to define WndProc and, hopefully, do something useful with it. Its parameters describe the message by giving you its ID, as well as the parameters sent along with it. For some more on windows messages, check out my earlier post regarding emulating those messages. If your desired message has been captured and handled, be sure to set handled to true.

private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    // address the messages you are receiving using msg, wParam, lParam
    if (msg == WM_LOOK_FOR_DROIDS)
    {
        if (wParam == DROIDS_IM_LOOKING_FOR)
        {
            CaptureDroids(lParam);
            handled = true;
        }
        else
        {
            AskToMoveAlong(lParam);
        }
    }
    return IntPtr.Zero;
}

Lastly, be sure to remove the hook when your window is closing.

private void Window_Closed(object sender, EventArgs e)
{
    IntPtr windowHandle = (new WindowInteropHelper(this)).Handle;
    HwndSource src = HwndSource.FromHwnd(windowHandle);
    src.RemoveHook(new HwndSourceHook(this.WndProc));
}

Easy as pie. If you're feeling nostalgic and don't want to use events, you can implement your entire application in the WndProc method (other than the rendering, which WPF also hides from you). I wouldn't recommend it, though...

Related posts:

  1. Sending Commands/Events to Another Application
  2. Windows 7 Multitouch Using WPF 3.5
  3. Introduction to Threads
  4. Introduction to the Windows Presentation Foundation (WPF)
  5. Multithreading in WPF
11Oct/090

Multithreading in WPF

If you're unfamiliar with multithreading, be sure to check out my previous entries on the topic.

In WPF, creating a thread is as easy as it is with C#. You can find an example on that here.  Alternatively, you could use the BackgroundWorker, which basically will create a thread and will give you a generalized, simplified interface in which to interact with it for a common threading task: doing an extra task in the background (such as downloading or progress bar updating).

In an earlier post, I used a mysterious method to enable responsiveness in the UI while loading a bunch of content (in that case, images).

This mystical object is called The Dispatcher.

THE DISPATCHER

No, this isn't an edge-of-your-seat thrill ride movie that smacks explosions, swords, and alien guts into your M&M-filled mouth. It is an object used to manage the work for threads within WPF.  It maintains a queue of work items that are requested of any given thread, based on their order and priority.  This is the object you want to get to know if you're going to be playing with your UI on a separate thread.

As mentioned previously, UI objects can't be accessed outside of the threads that created them.  You can, however, use a separate thread to determine what changes you'll be making and to what objects you will make them, then use their thread to actually apply that change.  In order to do this, use the object's dispatcher to schedule the work on their queue.

For example, take a look at the code for loading images mentioned above:

private void LoadImage(string fname)
{
	// instantiate and initialize the image source
	BitmapImage bmi = new BitmapImage();
	bmi.BeginInit();
	bmi.UriSource = new Uri(fname, UriKind.Relative);
	bmi.EndInit();
 
	bmi.Freeze();		// freeze the image source, used to move it across the thread
 
	// this method tells the separate thread to run the following method to run on the UI thread
	// the (ThreadStart)delegate(){ } notation is a shorthand for creating a method and a delegate for that method
	TheImage.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (ThreadStart)delegate ()
	{
		TheImage.Source = bmi;
	});
}

This method creates the BitmampImage object on a separate thread, leaving the main thread free for user input, and freezes it so that it can be used on another thread.  It then uses TheImage's Dispatcher to modify TheImage on its own thread by calling its dispatcher's BeginInvoke method.

There are two ways to invoke using the dispatcher: BeginInvoke() and Invoke().  BeginInvoke() will queue the work for the dispatcher and continue the separate thread's execution.  It puts in the request for the UI thread to execute the delegate, then continues on it merry way for its own execution.  This is useful when your separate thread does not rely on what it is requesting the UI thread to do.

The Invoke() method will wait until the delegate is executed and returns.  If you are modifying anything that you need or if the modification must be done before continuing in the separate thread, you should go with this one.

The Dispatcher is something you'll get pretty cozy with if you plan on changing your UI elements from a separate thread.  If you're just doing a progress bar or something else that is rather predictable, you can skip it by using the BackgroundWorker's ReportProgress method and ProgressChanged event.  Just be sure to give it some time if you are calling the dispatcher often.

In case you didn't notice all of my linking to previous posts, you may want to check out the rest of my posts on multithreading.

Related posts:

  1. Just a Bit: Loading Images Asynchronously in WPF
  2. Introduction to Threads
  3. Threading Complexities
  4. Windows 7 Multitouch Using WPF 3.5
  5. Introduction to the Windows Presentation Foundation (WPF)
13Sep/091

Threading Complexities

As I explained previously, threads are like workers with separate to-do lists that share the same tools and materials and perform tasks at the same time. There are a couple of tough situations that these coworkers will often find themselves in, however, and you need to make sure that their employer has the proper processes to provide solutions.  Yes, I am going to run this metaphor straight into the ground.

First, you need to know what "concurrent" means to a computer.  Dictionary.com defines it as "occurring or existing simultaneously or side by side".  Your computer, however, defines it as "switching between the tasks fast enough so that nobody notices that they aren't occurring simultaneously".  So, when I say that your employees are working at the same time, I actually mean that they are working one at a time but switching between who is working fast enough that the boss doesn't realize they're taking breaks.  The CPU is constantly juggling which thread gets to execute, based on priority and (usually) the order by which they come.  This same kind of exercise is happening with all of the processes that are currently running.

If you don't notice, why should you care?  Well, there is a delay when switching between threads (or processes) called a context switch.  During a context switch, the CPU must save the state of the currently active thread, choose the next thread to give time to, restore that thread's state, and continue its execution.  What this boils down to is that there is cost a  associate with multithreading.  You need to be aware of this cost, otherwise you may find your application running slower with multiple threads.  The reason is that your threads are unbalanced - that they are switching back and forth so much that the time it takes to do all of the context switching is greater than the time you save running two tasks simultaneously!

I ran into an example of this recently when attempting to improve the responsiveness of an application.  I was trying to do things on a separate thread to keep things smooth in the UI for the user; however I had to perform a task on a set of elements on the original thread (more on that later).  This forced me to call back to the original thread so often that the experience ended up being even worse.  I'll explain more detail about how that works in WPF in a future post, but here's the basic idea in pseudocode:

create a new thread to perform a CPU-intensive task; run:
   foreach object in somelist
      call back to original thread with the following task:
         perform an action on object

Because I went back to the original thread so often and so quickly, the CPU was spending most of its time context switching.  In order to fix it, I added one line:

create a new thread to perform a CPU-intensive task; run:
   foreach object in somelist
      call back to original thread with the following task:
         perform an action on object
      sleep for x amount of time

I added a sleep command in the separate thread.  This gave the main thread time to perform the task on the object, redraw, and settle in a little before I gave it another task.  This added a visual delay to the action on-screen (since there is x amount of time between each object being acted upon), but that was acceptable in this case to give the user a smooth experience.

Secondly, there is a key part of this metaphor that you have to consider: each worker is sharing resources.  This is good - it means that each thread can access the data it needs while executing; however, it comes with a caveat: you have to ensure no thread is changing that data while another thread is trying to access it.

Imagine if we have two workers sharing a drill.  Worker One is going to use it to screw a shelf to a wall, while Worker Two is going to drill a hole for the next shelf.  Now, imagine that Worker One has placed the screw where he wants it and is about to pull the trigger on the drill when a context switch occurs.  Worker One freezes, and Worker Two grabs the drill.  He pulls out the Phillips head bit that Worker One was using and replaces it with a drill bit.  Like an episode of Seinfeld, the worst thing happens at the worst possible time: another context switch.  Worker one takes the drill back and uses the drill bit on his screw, damaging the screw and quite possibly his hand.  This is called a race condition: multiple independent algorithms are dependent on a single shared resource, thus making the timing of each access of that resource critical to the success of each algorithm.

This means you have to be weary of using your global variables or the members of your class in a thread.  You must be certain that you aren't changing something that your other thread is depending on.  The common way to handle this is by using mutual exclusion (or mutex) algorithms.  The basic concept is that, when using a variable that is common to other threads, you must ensure that the variable is not currently in use by another thread, often via queues or access flags.  Take a look at the previous link for a list of well-known algorithms with examples.  There is a wealth of knowledge related to solving race conditions, and I'm not even going to attempt to address it all.

If you take a close look at the pseudo code above, you'll notice that I'm using a single thread to perform all actions on the set of objects, thus avoiding race conditions (as only one thread accesses them at a time).  This isn't by my own design, however; this is a restriction given to UI elements in most, if not all, languages.  Because of their nature, UI elements aren't thread safe.  They can be accessed by you, the graphics engine, or even the user.  Because of the amount of overhead required to allow UI elements to work in threads, they are restricted to being accessed only by the thread that created them.  Above, since I cannot access the UI elements in my worker thread, I have to call back to the thread that created the object and tell it to do the modifications I need.  This makes moving work to separate threads in a UI-heavy application complicated at times, but you get used to it pretty quickly.

So, it doesn't sound near as simple as it did in my first post; however, don't let this scare you away from using multithreading.  Once you get the hang of it, it is really quite simple to use.  Besides, you'll need to be familiar with it before digging your hands into any serious user-oriented application.

Related posts:

  1. Introduction to Threads
  2. Multithreading in WPF
  3. Just a Bit: Loading Images Asynchronously in WPF
  4. Introduction to the Windows Presentation Foundation (WPF)
  5. Windows 7 Multitouch Using WPF 3.5
6Sep/090

Just a Bit: Make Your WPF Application Resolution and DPI Independent

We've all seen it. Lower your resolution to 800x600? The application's UI is giant, hard to navigate, and ugly. Bring it up to 1920x1200? Now, you can't see it. Here's an easy way to make your application's content size relative to your window's size (which will lead it to size independently of the resolution or DPI).

All you have to do is surround your content in a Viewbox, with a uniform Stretch (to ensure the aspect ratio is maintained). You may need to specify a particular size for your content, in order to ensure proper aspect ratio and distance for your elements.

<Viewbox Stretch="Uniform">
    <Grid Width="800" Height="600">
        <!-- Content -->
    </Grid>
</Viewbox>

Related posts:

  1. Sending Commands/Events to Another Application
  2. Introduction to Threads
  3. Threading Complexities
  4. Multithreading in WPF
  5. Introduction to the Windows Presentation Foundation (WPF)
30Aug/090

Introduction to Threads

Threading is a pretty core concept, but I felt it might be necessary to give it a brief explanation before moving on to some WPF-specific concerns for threads.  If you are already familiar with threads, these aren't the droids you're looking for.

If you think about the flow of a simple application that does not use multithreading, you'll find that you can basically draw a line on a sheet of paper and label the events of the process as a straight line of consecutive actions:

simple_console_eventsThis method is often very stifling to the developer, as it limits what you can do.  At times, you want another action to be able to perform simultaneously.  A classic case is to allow a user to cancel an action.  In this case, the user is allowed to interact with the process while it is busy.  That is, the line of execution cannot be drawn so straight:

Threaded ExecutionYou can perform this (seemingly) concurrent operation by using threads.  Threads are similar to processes in that they are a set of instructions for the computer to perform; however, processes and threads differ in that separate threads share resources under the same process, while processes are independent of each other.  You can think of separate threads as workers who share materials and tools, but have separate instructions to perform at the same time.

Every application has at least one thread: the main thread of execution.  This is represented by the green line above; it is the thread that starts the application and is the top of the family tree of the cute little baby threads that are spawned during your application's execution.  When you have an action that you wish to perform concurrently with the main thread, you create a new thread, give it a set of tasks, and start its execution.  In C#, simply instantiate a Thread object using a delegate and start it.

Thread worker = new Thread(delegate()
   {
      // actions to perform on separate thread
   });
worker.Start();

A delegate is a reference type to a function that serves to give the thread an action to perform. So, if you think of a thread as a worker separate from the main thread, you can think of a delegate as that worker's to-do list.

In C#, there is also a Delegate class. This class is used as a base for derived delegates - you can use this if you want to have a custom delegate, which is useful for defining to-do lists that have specific requirements. For example, events use custom delegates in order to ensure that the event handler has the proper information when it reacts to the event. So, if you want to create a MouseDown event handler, you must define a handler that accepts the sender of the event, as well as information regarding the mouse's state.

Seems simple enough, right?  Well, things can actually get quite complicated.  I'll address some complexities of multithreading in another post.

Related posts:

  1. Threading Complexities
  2. Multithreading in WPF
  3. Introduction to the Windows Presentation Foundation (WPF)
  4. Just a Bit: Loading Images Asynchronously in WPF
  5. Sending Commands/Events to Another Application
5Feb/095

Windows 7 Multitouch Using WPF 3.5

Finally!  Another post about programming!  I know!  And Windows 7, too!  That ever sure is topical!  This one is for all of you developers running the Win7 beta on the HP TouchSmart (moneyhat go).

Win7 is supposed to woo and wow you with fixing Vista's many shortcomings new features like multi-touch support.  If you're curious on how it all works, I'd suggest you watch this great PDC 2008 video on the subject.  Windows will give you everything you need to fancify your touch application, once you've set it up to do so.  They'll tell you how to get multi-touch working in unmanaged code.  There's also some examples out there showing how to use interop to use this method in C#.  We've bridged the gap from unamanaged to managed code - what am I still writing this post for?

Well, WPF is a bit different.  Not only is native multi-touch not present in WPF right now (look forward to .NET 4.0 some time after Win7 releases), but you actually can't use interop to support multi-touch in your applications.  Yeah, I know.  Something's amiss when interop fails.

Actually, it is just that WPF doesn't accept the WM_Touch messages that are sent to windows when the user touches the screen.  Since you don't get this notification, you can't capture information regarding Win7 gestures or raw data using interop.

Hold on!  Don't run to make your shiny, new, and intuitive application in C++ just yet.

As Anson Tao alludes to in the Q&A session after the presentation in the video above, you can recieve the raw data from stylus events in WPF 3.5 SP1, which is already released.  However, you have to do just a tad bit of fidgeting to get it working.

Here's an application that will show you how to access this information. It just moves two rectangles to the two points you touch on the window.

I'll start with the simple XAML:

 

Now, the business logic:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Diagnostics;
 
namespace MultitouchTest
{
    public partial class Window1 : Window
    {
        #region Class Variables
 
        private int Touch1ID = 0;    // id for first touch contact
        private int Touch2ID = 0;    // id for second touch contact
 
        #endregion
 
        #region P/Invoke
 
        // just a little interop.  it's different this time!
        [DllImport("user32.dll")]
        public static extern bool SetProp(IntPtr hWnd, string lpString, IntPtr hData);
 
        #endregion
 
        #region Constructors/Initialization
 
        public Window1()
        {
            InitializeComponent();
 
            // here's the first thing you need to do.  upon window load, you want to set the tablet
            // property to receive multi-touch data.  you need to the window loaded to ensure the handle is created.
            this.Loaded += new RoutedEventHandler(
               delegate(object sender, RoutedEventArgs args)
               {
                   var source = new WindowInteropHelper(this);
 
                   SetProp(source.Handle,
                       "MicrosoftTabletPenServiceProperty", new IntPtr(0x01000000));
 
               });
 
            // then, simply subscribe to the stylus events like normal.  you'll get an event for each contact.
            // so, when you move both fingers, you get a StylusMove event for each individual finger
            this.StylusDown += new StylusDownEventHandler(Window1_StylusDown);
            this.StylusMove += new StylusEventHandler(Window1_StylusMove);
            this.StylusUp += new StylusEventHandler(Window1_StylusUp);
        }
 
        #endregion
 
        #region Touch Events
 
        void Window1_StylusDown(object sender, StylusDownEventArgs e)
        {
            Point p = e.GetPosition(this);   // get the location for this contact
 
            // attribute an id with a touch point
            if (Touch1ID == 0)
            {
                Touch1ID = e.StylusDevice.Id;
                // move the rectangle to the given location
                Touch1.SetValue(Canvas.LeftProperty, p.X - Touch1.Width / 2);
                Touch1.SetValue(Canvas.TopProperty, p.Y - Touch1.Height / 2);
            }
            else if (Touch2ID == 0)
            {
                Touch2ID = e.StylusDevice.Id;
                // move the rectangle to the given location
                Touch2.SetValue(Canvas.LeftProperty, p.X - Touch2.Width / 2);
                Touch2.SetValue(Canvas.TopProperty, p.Y - Touch2.Height / 2);
            }
        }
 
        void Window1_StylusMove(object sender, StylusEventArgs e)
        {
            Point p = e.GetPosition(this);
           // determine which contact this belongs to
            if (Touch1ID == e.StylusDevice.Id)
            {
                // move the rectangle to the given location
                Touch1.SetValue(Canvas.LeftProperty, p.X - Touch1.Width / 2);
                Touch1.SetValue(Canvas.TopProperty, p.Y - Touch1.Height / 2);
            }
            else if (Touch2ID == e.StylusDevice.Id)
            {
                // move the rectangle to the given location
                Touch2.SetValue(Canvas.LeftProperty, p.X - Touch2.Width / 2);
                Touch2.SetValue(Canvas.TopProperty, p.Y - Touch2.Height / 2);
            }
        }
 
        void  Window1_StylusUp(object sender, StylusEventArgs e)
        {
             // reinitialize touch id and hide the rectangle
 	     if (e.StylusDevice.Id == Touch1ID)
            {
                Touch1.SetValue(Canvas.LeftProperty, -Touch1.Width);
                Touch1ID = 0;
            }
            else if (e.StylusDevice.Id == Touch2ID)
            {
                Touch2.SetValue(Canvas.LeftProperty, -Touch2.Width);
                Touch2ID = 0;
            }
        }
 
        #endregion
    }
}

Related posts:

  1. Introduction to the Windows Presentation Foundation (WPF)
  2. Attaching to WndProc in WPF
  3. The New HP TouchSmart PCs
27Oct/080

Just a Bit: Loading Images Asynchronously in WPF

Multithreading using WPF is a little tricky at first (I'm planning a more thorough post on that later), but the basic thing you need to know is that you can't access WPF elements outside of the UI thread, because they aren't thread safe.  There are some things you can do to speed loading up, however.  Here's a method for loading images on a separate thread:

private void LoadImage(string fname)
{
	// instantiate and initialize the image source
	BitmapImage bmi = new BitmapImage();
	bmi.BeginInit();
	bmi.UriSource = new Uri(fname, UriKind.Relative);
	bmi.EndInit();
 
	bmi.Freeze();		// freeze the image source, used to move it across the thread
 
	// this method tells the separate thread to run the following method to run on the UI thread
	// the (ThreadStart)delegate(){ } notation is a shorthand for creating a method and a delegate for that method
	TheImage.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (ThreadStart)delegate ()
	{
		TheImage.Source = bmi;
	});
}

The meat of the method is the BitmapImage.Freeze method - this is specifically useful for loading images.  The Dispatcher.BeginInvoke is also important, but I'll leave more explanation on that for the threading post.

Related posts:

  1. Multithreading in WPF
  2. Introduction to Threads
  3. Threading Complexities
  4. Introduction to the Windows Presentation Foundation (WPF)
  5. Windows 7 Multitouch Using WPF 3.5
30Sep/080

Introduction to the Windows Presentation Foundation (WPF)

WPF is a graphical subsystem to the .NET framework.  It is essentially used to make UI programming easier by separating the UI from the business logic.  By doing this, it is easy to maintain and allows designers to easily change the UI without futzing with too much programming.  This, of course, makes it easier for the programmers because they don't have to convert the design elements into application assets.  How does this all fit together?  I'll go through a sample application in order to show how one might use the strengths of WPF to make application development a breeze.

For our example, I'll pretend I'm making a browser application.  To keep it nice and simple, I'm only interested in the controls.  Being an expert graphic artist, I've crafted a stunning visual masterpiece:

Design

In order to create this amazing experience, all I had to do was drag-and-drop and edit the details using Visual Studio 2008's design view:

For designers, Visual Studio 2008 will make it much easier.  However, it could still be a little daunting.  With WPF, the entire UI is laid out using XAML, which is an XML-based language that describes the layout, properties, and actions of the UI elements (I'll go over this in more detail later).  Because of this, any program can be made to more easily lay out the elements of your window in the way the designers need (here's some examples) - all it has to do is output the result in XML-based XAML.

The best part for the programmer is that he doesn't have to take the bitmaps created by the designer in photoshop, break them apart, and create buttons.  All he has to do is add the XAML and add the code behind the elements (aka business logic).  Oh, and say the design completely changes?  While the XAML changes, the business logic remains the same - no need to change things on the back end (yeah, that's how it should be).  This makes maintaining the application marginally better - major UI revisions could leave all of the business logic exactly the same.  Though you should probably considering adding some features if all your doing is adding a new coat of paint.

Programming

"But Andrew," says the imaginary, whiney, no-designing programmer that presumably exists in my subconscious.  "What does all of this mean to me!?"  Well, imaginary programmer, maybe this blog isn't JUST FOR YOU.  Maybe you should just go read man pages for the rest of the day...or you can just read the rest of this post, since it is for you.  I'd say the best idea would be to stop existing in my imagination and quit telling me to start fires.

XAML

I'll start with XAML, since it's the basis behind WPF (and I've already introduced it to you).  Like I mentioned earlier, Extensible Application Markup Language (XAML, typically pronounced 'zammel') is based on XML.  This makes laying out an application as easy as setting up your first Geocities webpage.  Like XML, it has the main tags (like <Window> or <Button>) with properties that define the tag.  Here's the XAML for the browser control window:

 
<Window x:Class="WPFIntroduction.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Browser Controls" Height="121.38" Width="775" Keyboard.KeyDown="Window_KeyDown">
    <Grid>
        <Button Height="48" HorizontalAlignment="Left" Margin="32.844,18.564,0,0" Name="BtnBack" VerticalAlignment="Top" Width="50" Click="BtnBack_Click">
            <Image Source="Images\back.png" />
        </Button>
        <Button Height="48" HorizontalAlignment="Left" Margin="102.816,18.564,0,0" Name="BtnForward" VerticalAlignment="Top" Width="50" Click="BtnForward_Click">
            <Image Source="Images\forward.png" />
        </Button>
        <Button Height="48" HorizontalAlignment="Left" Margin="172.788,18.564,0,0" Name="BtnHome" VerticalAlignment="Top" Width="50" Click="BtnHome_Click">
            <Image Source="Images\home.png" />
        </Button>
        <Button Height="48" HorizontalAlignment="Left" Margin="242.76,18.564,0,0" Name="BtnStop" VerticalAlignment="Top" Width="50" Click="BtnStop_Click">
            <Image Source="Images\stop.png" />
        </Button>
        <TextBox Height="38.164" Margin="309.876,23.24,79.254,0" Name="AddressBar" VerticalAlignment="Top" />
        <Button Height="48" HorizontalAlignment="Right" Margin="0,18.564,12.138,0" Name="BtnRefresh" VerticalAlignment="Top" Width="50" Click="BtnRefresh_Click">
            <Image Source="Images\refresh.png" />
        </Button>
    </Grid>
</Window>

Notice the XAML namespaces defined in the root element - these are required for XAML files. These are the namespaces used in defining the various XAML elements.

You might be wondering just how the XAML text gets converted into a user interface. The XAML is actually converted into code. You might notice above that all of the tags in the XAML are actually control classes. Window, Button, and Image are all classes, and WPF actually instantiates objects of these classes at runtime. So, for each Button tag, we have a Button object. The object names are as defined: BtnBack, BtnForward, etc.  You can actually reference these objects in your code - and no need to instantiate or set them up in the constructor.

Business Logic

Now, this isn't entirely automatic.  You do have to include a call to a method, namely InitiataiteComponent(), to create the UI elements contained in the XAML.  Where do you call this method?  Well, each XAML window has a file that contains the code behind the XAML.  The Window created by the XAML is actually an inherited class.  In our case, the new class is Window1.  In this class' constructor, the call to InitializeComponent() is called.  This class also houses the business logic, or the code behind the application.

This is also the best place to add event handlers for your application.  Since I'm not making a full browser, we'll just stick with dialog boxes when buttons are clicked.  Here's the whole class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace WPFIntroduction
{
    ///
    /// Interaction logic for Window1.xaml
    ///
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
 
        private void BtnBack_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Back button clicked");
        }
 
        private void BtnForward_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Forward button clicked");
        }
 
        private void BtnHome_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Home button clicked");
        }
 
        private void BtnStop_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Stop button clicked");
        }
 
        private void BtnRefresh_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Refresh button clicked");
        }
 
        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter &amp;&amp; AddressBar.IsFocused)
                MessageBox.Show("New address entered");
        }
    }
}

Notice in the Window_KeyDown event, I reference the AddressBar object.

This is all pretty standard, so no need to really explain anything here - it's simply some simple event handlers.  So, you have a basic WPF application to reference when creating your own WPF application.  While this, obviously, won't get you to be able to create a brand new application in its entirety, it'll give you a start to the mentality behind WPF.  I use this quite a bit, so don't be surprised if I go into more in-depth examples in the future.  In the meantime, check out MSDN's resources on WPF...or feel free to ask questions. Lord knows I could have left plenty of details out.

Related posts:

  1. Windows 7 Multitouch Using WPF 3.5
  2. Introduction to Threads
  3. Attaching to WndProc in WPF
  4. Just a Bit: Loading Images Asynchronously in WPF
  5. Sending Commands/Events to Another Application
Tagged as: , , , No Comments
18Sep/080

Just a Bit: Copying Text to the Clipboard

A bit is the difference between true and false

So when working on this blog sometimes I spend a little too much time getting code together. I'm sure I'll get better, faster, and care less about what it looks like over time.

Until then, I'll use these 'Just a Bit' posts. The idea being that I post a tiny bit of code that I found useful recently. Sure, about 400,000,000 pages can be found elsewhere with this information, but they don't have clever wordplay in their titles!

So, the first "Just a Bit" is using .NET to add text to the Windows clipboard.  First, put together a string using the StringBuilder class - the reason for this is that any formatting characters ('\n', '\t', etc.) won't necessarily translate correctly onto the clipboard correctly if you simply put them into a string.  Finally use the System.Windows.Clipboard static method SetDataObject to copy the text to the clipboard.

// build the string, with new lines between entries
StringBuilder clipStr = new StringBuilder();
foreach (string itm in TheItemCollection.Items)
{
	clipStr.Append(itm);
	clipStr.Append("\n");
}
// copy to clipboard, clear the box, and notify user
Clipboard.SetDataObject(clipStr.ToString(), true);

Enjoy that one.

Related posts:

  1. Multithreading in WPF
  2. Attaching to WndProc in WPF
  3. Sending Commands/Events to Another Application
  4. Just a Bit: Loading Images Asynchronously in WPF