Welcome to MSDN Blogs Sign in | Join | Help

Ivo Manolov's Blog

Windows Presentation Foundation (WPF) and Win32 Programming
WPF Application Quality Guide v.0.3 Released!

On Friday, we released the third preliminary version of the "WPF Application Quality Guide", adding a section 3 new sections: a suggested reading roadmap, a section on globalization and localization testing and a section on manual testing and record and replay.

The guide is available here. You can also download it as a Word document.

As always, please send us suggestions both on the content and on the organization of the document. You can post feedback directly here or send it to wpftbest@microsoft.com.

Posted Sunday, September 28, 2008 8:52 PM by ivom | 8 Comments

Filed under: ,

Jobs in the WPF Team

We (the WPF test team) are looking for several engineers, so I wanted to use the blog to point to the available positions in the team and give you a brief outline of the opportunities and responsibilities associated with each position.

 

Software Development Engineer in Test

(see official job posting)

As a SDET on the team you'll be responsible for ensuring the high quality of the WPF platform, by being the first and most critical customer of the platform, by being the first application developer using the new features introduced in WPF.

An accomplished SDET on our team is...

  • a world-class CS engineer;
  • an expert application developer, passionate about UI;
  • a feature expert, with deep knowledge of specific parts of the WPF stack (e.g. Controls, Application Model, Graphics, etc.);
  • fundamentals expert, with deep knowledge of software fundamentals such as security, performance & scalability, globalization/localization, accessibility, etc;
  • passionate about code quality, passionate and capable code and design reviewer;
  • striving on living on the absolute leading edge (and sometimes bleeding edge :) ) of the WPF technology;
  • a capable problem solver and having great sensitivity and zeal for discovering and fixing quality issues in the platform;
  • an effective team player.

We are currently looking for both junior and senior SDETs. You don't have to be all of the above in order to apply. You just have to be passionate, smart and willing to learn.

 

Software Architect

(see official job posting)

We are also looking for several software architects. Software architects are senior individual contributors with broad technical knowledge and experience, who are interested in having broad influence rather than being deep area experts.

A successful software architect on the team is:

  • an experienced software engineer with broad knowledge and appreciation of advanced software design and development techniques;
  • a passionate "code librarian", driving high code quality, as well as proper architectural layering, componentization and reuse across the organization;
  • a fundamentals champion and driver;
  • a technical leader and mentor;
  • an effective design and code reviewer;
  • very friendly and approachable. Willing to be randomized by folks asking for technical guidance and advice.

The Software Architects work closely with the managers and with other senior individual contributors on the team to form a coherent technical vision and strategy, matched with a pragmatic execution plan.

 

If you think you have what it takes to be successful in one of the best teams at Microsoft and you feel you are ready for a change, drop me a line. We offer working on the most advanced UI platform shipped by Microsoft to date, working alongside some of best and brightest engineering brains in the industry, a supportive and friendly team and practically limitless career growth opportunities.

Posted Tuesday, May 20, 2008 7:30 PM by ivom | 11 Comments

Filed under: , , ,

WPF Application Quality Guide v.0.2 Released!

Today we are releasing the second preliminary version of the "WPF Application Quality Guide", targeted at WPF application and component developers and QA professionals. Check out the document here or download the DOC version here.

This second revision of the document has a lot of new content, so be sure to check it out.  We have expanded our section on UI element discovery and have added new sections on general principles of WPF, general principles of software testing, visual verification testing, media testing, animation and transition testing, performance and scalability testing, security testing, data binding and interop. We have also added a section on tools that you can use to develop, debug and test WPF applications and components.

Let us know what you think about the content and the organization of the document. Can you easily find what you are looking for? Are there other topics that you'd like us to include in future revisions? We are looking forward to your feedback, which you can send to wpftbest@microsoft.com or directly to me.

Posted Thursday, May 08, 2008 1:05 PM by ivom | 3 Comments

Filed under: ,

First Media Center PC

A PC that holds all of your media (music, photos, home videos, movies), allows you to pause, record and play back live TV and looks like a regular consumer electronics device? Sure! It's called a Media Center PC (or Home Theater PC, or HTPC) and I felt it was a high time to assemble one.

The last time I assembled a PC was about 15 years ago as an undergrad student and, boy, those were simpler, purer times. It quickly became apparent that I would spend weeks figuring out what components to use in the PC, given the myriad of motherboards, CPU sockets, etc, etc, etc, so I looked for help on the web, and I came across this great article by Loyd Case.

So I just went ahead and duplicated the cheapest PC configuration recommended by Loyd. Here's what I ended up with:

 

Component Model Notes Price
Motherboard Gigabyte GA-MA69GM-S2H   $86
CPU AMD Athlon 64 X2   $116
CPU Cooler Scythe Ninja Mini To replace the original cooler that came with the CPU $31
Graphics ATI Radeon X1250 Internal with HDMI Integrated on the motherboard n/a
Audio Integrated HD audio Integrated on the motherboard n/a
Memory 2GB Kingston ValueRAM (KVR800D2N5K22G)   $56
Hard Drive Western Digital WD7500AYYS 750GB   $201
Optical Drive Lite-On LH-20A1 DVD Burner   $36
Case & PSU Antec Fusion Black 430   $150
TV Tuner ATI TV Wonder HD 650 PCI-express The package includes a MC remote control.

Note:
There are two problems with this tuner:
a. I couldn't actually get this tuner to receive any over-the-air TV programming, although I tried several different antennas. I have as a result ordered a Hauppauge tuner.
b. The remote that comes with the tuner is a RC5 remote, so it does not work with the integrated RC6 infrared receiver in the Antec box. So I ended up getting another remote (a RC6 one) from a friend, which worked beautifully. See below for pointers to a RC6 remote.
$130
Total   $805

 

Putting together the PC took an evening. I installed Windows Vista Ultimate (a smooth uneventful installation, as long as you have a USB keyboard and a USB mouse handy), connected the PC to the Internet, to my TV signal source and to my TV and fired up Windows Media Center. The configuration I ended up with is:

 

Media Center Setup

 

The integrated graphics card on the motherboard conveniently provides HDMI output, so that's what I used to connect the TV to the Media Center PC. You will notice that I have not connected an audio system. I am just using the speakers of my TV (via the same HDMI cable), which frankly are good enough for us.

It took me about 2 days to rip all of my CDs (I used Windows Media Player to do that) and transfer all of my videos and pictures to the PC.

 

MCE Works Beautifully!

The Windows Media Center included with Windows Vista is an excellent piece of software and works perfectly for me with the above PC config (see the few gotchas I had to deal with). It has it all -- beautiful UI, an excellent set of discoverable features, a natural navigation model. It's just a great example of consumer software. We as a company should advertise it better...

Here are a few screen-shots:

 

MCE TV Program Guide

TV Channel Guide

The TV channel guide is updated through Internet. This snapshot shows the channel guide superimposed on top of the currently displayed channel (NBC)

 

MCE Recorded TV

Recorded TV

Shows you representative frames from TV shows you have recorded. Notice that the currently played content is shown in a small PIP pane at the bottom left corner.

 

MCE Picture Library

Picture Library

Browsing a large number of digital pictures is very easy. We have about 3000 pictures in our library and I have not noticed any degradation in performance or performance issues, when browsing through them. Importing your new pictures is always very easy - you just connect your camera via a USB cable and you get prompted to import the pictures.

 

 MCE Music Library

Music Library

You can sort by various criteria (album, artists, etc) and you get optimized lists that help you quickly find what you are looking for. Notice how the CD art gets automatically loaded for any recognized album. This feature works very well even for fairly old and/or apocryphal CDs.

 

A Few Gotchas

Overall, setting up a media center PC has been a breeze. The problems that I hit were:

  • Set-up:
    • HDMI audio kept getting disabled. To fix this, open up Control Panel > Sound, open up the "Realtek HDMI Output" playback device, disable the device, log off, log on and re-enable the device:

   Audio Woes    Audio Woes 1

    • The integrated IR receiver in the Antec case did not work with remote that came with the TV tuner card. Apparently, the IR receiver is set up to recognize RC6 codes, and my remote was issuing RC5 codes, so I had to use the USB IR receiver that came with the remote (that works just fine -- you just have to be comfortable with the external receiver). Alternatively, get a MS MCE remote (e.g. this one). I approached the Antec support team with questions around this -- they were very responsive.
    • The volume knob on the Antec case did not work initially. To fix the problem, I had to download and install the latest version of the iMon utility (from here) and uninstall the VFD utility which came on the CD with the Antec case, and which I had previously installed. iMon is just a souped-up version of VFD. 
    • The channel guide browsing performance tended to degrade noticeably if I had tuned to a channel before I hit the guide. To fix this, I had to switch to the "High performance" power plan (in Control  Panel > Power Options)
  • HD channels:
    • You cannot get HD channels through you cable provider (see [5] below), so I recommend giving up cable TV (yeah, you'll have to fight your Nip/Tuck addition) and switching to a combination of over-the-Internet NetFlix and a TV antenna.

 

MCE Hardware Accessories and Software Add-Ins

You may consider getting a few hardware accessories:

Accessory Model Notes Price
Wireless keyboard /mouse Microsoft Wireless Entertainment Desktop 7000 A very slick, but somewhat expensive piece. Cheaper alternatives are the ZV1-00004 IR keyboard or the ZV7-00009 IR keyboard, both for $40. $120
Antenna TBD Over-the-air TV broadcasts are free and (in the US) of higher quality than what you can get through a cable TV provider (you can't get HDTV cable content even though you have an HDTV tuner - see [2] below). I have personally disconnected my cable and switched to an antenna (see [5] below). TBD
MCE Remote Microsoft A9O-00007 WinXP Media Center Infrared Remote Control As discussed above, if you want to use the IR receiver integrated in the Antec case, you'd need to have a RC6 remote.  $39

I also recommend installing the following software (in suggested priority order):

Software Notes Price
My NetFlix MC add-in, which allows you to manage your NetFlix queue and watch streamed NetFlix movies (for as little as $8.99/month - Patrick Danino, one of our test architects, pointed me to this great deal) from within Media Center. Works great! Free
FFDShow Codecs You may need these codecs to be able to watch video files. Free
ShowGallery hack You can rip your DVDs to your drive and have MCE display them in a nifty DVD library. Check out this article by Max Zuckerman for a walk-through of how to do it. Free
DVR MS Toolbox Allows you (among other things) to automatically remove commercials from recorded TV. By the way http://TheGreenButton.com provides a wealth of MCE information (big thanks to Gilman Wong - our dev manager, who is also a big MCE aficionado - for pointing me to it) Free

 

Pearls of MCE Wisdom

Here are a few articles that I'd recommend to any Media Center enthusiast:

[1] Build a Windows Vista Home Theater PC is the excellent article by Loyd Case I used to build our media center PC.

[2] Planning Your Media Center PC: Choosing Your TV Source provides the best description of the different sources of TV signal I have come across.

[3] Review: Antec Fusion Black 430 provides a good review of the Antec PC case.

[4] This post explains how to play CD+G karaoke files in MCE (ok, I admit, I have a few of those lying around...)

[5] All About HDTV Antennas walks you through choosing an HDTV antenna. AntennaWeb.org shows the available over-the-air channels in your ZIP code.

Posted Wednesday, March 12, 2008 3:39 AM by ivom | 5 Comments

Filed under: ,

WPF Application Quality Guide v.0.1 Released!

I am happy to announce that we have just released the first preliminary version of the "WPF Application Quality Guide". This document is targeted at WPF application developers and QA professionals.

This document is a first of its kind, so we intend to iterate on it rapidly, modifying the content based on comments from you -- the WPF developer community. In its first preliminary version the document contains a table of (planned) contents as well as a few sections, giving you a taste of what to expect in future revisions.

Check out the document here or download a DOC version of it here. And most importantly -- let us know what you think. Too little detail? Too much detail? Do we have the right sections? Should we add / remove anything from the planned content?

Posted Thursday, January 31, 2008 5:57 PM by ivom | 3 Comments

Filed under: ,

"Starter Kit" Released!

I am delighted to broadcast that earlier today our team released the "Syndicated Client Experiences (SCE) Starter Kit and Reader SDK", affectionately known as "Starter Kit".

The "Starter Kit" is a generalized application skeleton, that allows you as a developer to create reader applications similar to the popular NY Times Reader (#25 in PC World's list of 100  Best Products of 2007). The Kit combines the power of WPF with standardized communication protocols (RSS) to deliver a superior occasionally connected reading experience.

A few existing applications, based on the Starter Kit:

Check it out. The Kit comes with complete source code.

Posted Wednesday, January 16, 2008 2:15 PM by ivom | 6 Comments

Filed under:

WPF Application List

A couple of months ago I met with a few interns as part of a small networking event held at the Microsoft company museum. I wanted to show them a particularly cool WPF XBAP developed by an external company, but I could not remember the correct URL and I couldn't find the right WPF app list out there that had a pointer to that application... So I decided to start my own shiny WPF application list, which I will evolve with time. I am also providing pointers to the existing app lists out there that I am aware of.

WPF is getting great adoption, so I am pretty sure that very soon all of these lists will become meaningless, crushed by the sheer number of available applications. Until then...

Application Type / Deployment Notes
Asahiyama Zoo XBAP The portal of one of the largest zoos in Japan.
Cine.View Standalone Desktop Netflix application.
Da.Code Standalone  
Denounce Standalone Blog and podcast reader.
Daily Mail eReader Standalone Newsreader application from Daily Mail (one of the largest British newspapers).
Disney Hong Kong Vista Sidebar Gadget & Standalone A Windows Vista sidebar gadget and a standalone application presenting Hong Kong Disneyland.
Family.Show Standalone A fully functional sample WPF genealogy application, developed by Vertigo Software in collaboration with Microsoft. The complete source code of the application is available for download and modification.
Flotzam Standalone A mash-up of Facebook, Flickr, Twitter and blogs, created by Karsten Januszewski (developer) and Tim Aidlin (designer).
Forbes.com Reader Standalone Newsreader application from Forbes.
Metaliq Standalone Snowboarding data visualization.
MSDN Reader Standalone The MSDN Reader allows you to browse through MSDN Magazine articles like never before. Read through articles, view figures and code snippets in an intuitive and easy-to-use experience. The MSDN Reader is based on the SCE Starter Kit & Reader SDK (see below).

The complete source code for the reader is also provided for you here.
NoteScraps Standalone Virtual sticky notes.
Nostalgia Standalone Flickr photo browser application.
PoshConsole Standalone A PowerShell console with UI written in WPF. Available on CodePlex.
Quixotry XBAP A game similar to Scrabble.
RIPT Standalone An excellent scrapbook application, allowing you to record URLs, documents, etc. in a "pile" of related stuff.
RSS Reader Standalone RSS feed reader
Sawdust XBAP A 3D workbench application.
SCE Starter Kit & Reader SDK Standalone The "Starter Kit" is two things: a) a generic template for a Reader application (see "Times Reader" below) and b) a one-stop synchronization service for Reader applications.

The "Starter Kit" comes with complete source code that will allow you to quickly develop and deploy rich desktop applications similar to the NY Times Reader.
StickySpaces Standalone Virtual sticky notes.
ThoughtEx.NET Standalone Idea mapping application.
Times Reader Standalone One of the top 25 products in PC World's list of 100 Best Products of 2007, the New York Times Reader is a unique reading experience that showcases the power of WPF. This is the original WPF killer application.
Tripogo XBAP A slick travel booking web site.
UniveRSS Standalone A demo 3D RSS feed reader created and published as part of the "The Panel" program by Microsoft EMEA (Europe, Middle East and Africa). Complete source code and documentation available.
Valil's Chess XBAP, Standalone A chess game developed by Valentin Iliescu
Windows Vista Magazine XBAP Newsreader application from
Yahoo Messenger Standalone A WPF version of Yahoo's popular IM client.
Zurich Airport XBAP A fascinating web application showing live data from the Zurich Airport. 

 

Existing Lists

 

Posted Friday, January 04, 2008 1:55 PM by ivom | 3 Comments

Filed under:

WPF and XAML in 10 Minutes

A couple of our evangelists (Karsten and Jaime) published an excellent paper on WPF and XAML, which is probably the most dense publication on WPF I have seen to date. A great overview of the WPF-XAML tandem in 32 quick pages. Check it out here.

Posted Monday, December 10, 2007 11:47 PM by ivom | 2 Comments

Filed under: ,

What's New in WPF 3.5?

The first version of WPF was released as part of .NET Framework 3.0 in November 2006. On 11/16/2007, we released the second version of WPF, as part of .NET Framework 3.5 (code-named Orcas). We call this WPF 3.5.

WPF 3.5 has a number of exciting new features and a number of product fixes and improvements, quite a few of them reported and suggested by our customers.

For a full list of the new features in .NET Framework 3.5, check out this article on MSDN and this article on WindowsClient.net. Below is a summary of changes and additions in WPF 3.5. Some of the items below are large features, others are small incremental changes.

 

WPF 3.5 Feature Notes
WPF Add-Ins The "Application Model" team responded to a common request by our customers and delivered a new WPF add-in model (based on the new add-in model in .NET 3.5) that allows developers to create visual add-ins.
Improved Cookie Support Support for session cookies and attaching cookies to resource requests.
Firefox Plugin Now, you can run your XBAPs in Firefox.
Improvements to XAML Intellisense  
RichTextBox hyperlink integration  
RichTextBox.EnableEmbeddedElements  
Expose text selection on DocumentViewer  
Support for Indic text Support for 15 Indic scripts
Dlinq, Xlinq suport  
FreezableCollection<T> additions  
Improved debuggability in Data Support for IDataErrorInfo, support for trace levels, etc.
ClickOnce file associations  
VerboseTextChanged  
Newly exposed Setters in Controls  
Transition effects in page transitions  
IME fixes Multiple fixes to enable proper IME (input method editor)
Serialization of custom TextElements  
UIElement3D UIElement3D extends the 3D feature set in WPF, adding support for input, focus and eventing. Check out this post for more.
Performance Improvements Layered windows performance improvements;
Animation smoothing work; Data binding improvements (faster binding from a XML source, improved Blend cold start-up by 11%!); Incremental improvements to cold start, runtime and working set; Incremental improvements to battery life
Expose InteropBitmap.Invalidate()  
BitmapImage.DecodeFailed event  
BitmapImage.BitmapCacheOption New BitmapImage cache behavior
HwndTarget.SetRenderingModel() A new API to allow a developer to force SW rendering for a given window.
PackUri support for SoundPlayerAction  

Posted Saturday, December 08, 2007 8:21 PM by ivom | 3 Comments

Filed under: ,

WPF-Win32 Interop Part 2: Hosting Win32 Controls (ListBox) in WPF Windows

Introduction

This article describes hosting of a Win32 user control in a WPF window. It is supplemented by the following two projects, which show working examples of the material presented in the document:

  • Win32ControlInWpfWindow_CompositeWin32Messages
  • Win32ControlInWpfWindow_SimpleWin32Messages

The only difference between the two projects is the Win32ListBoxHost.cs file. The differences between the two versions of the file are related to the material covered in the “Simple” Messages vs “Composite” Messages section below. You can view the differences between the two versions of the file by using a utility such as WinDiff.exe, which is shipped with the Windows SDK.

This article is based on the material available on the WPF/Win32 interoperability portal on MSDN.

 

Hosting of a Win32 Control in a WPF Window

In traditional Win32 programming, user controls (buttons, listboxes, etc.) are instantiated through a call to the CreateWindow or CreateWindowEx APIs. Every control has a unique (per session) identifier of type HWND[1] and is recognized as a separate window (albeit a child window) by the window manager of the OS. What this means is that the window manager of the OS has the ability to do hit-testing[2] of the user control without the assistance of the parent window and is thus capable of sending window messages (e.g. WM_LBUTTONDOWN, etc.) directly to the user control. These window messages are typically intercepted and processed by the message loop of the parent window, but can also be processed by the user control.

In WPF programming user controls are not separate windows with separate HWNDs. Hit-testing is accomplished by the Visual layer in the WPF stack. Thus the window manager of the OS sends messages only to the top-level WPF window.

Hosting of a Win32 user control in a WPF window is accomplished using the following steps:

  1. Create a class deriving from HwndHost;
  2. In the HwndHost-derived class implement 3 methods declared in HwndHost (BuildWindowCore, DestroyWindowCore and WndProc):

 

class MyHost : HwndHost

{

  // Public adapter interface goes here

 

  protected override HandleRef BuildWindowCore(HandleRef hwndParent)

  {

    // PInvoke to CreateWindow(Ex)...

    return new HandleRef(this, hwnd);

  }

 

  protected override void DestroyWindowCore(HandleRef hwnd)

  {

    // PInvoke to DestroyWindow

  }

 

  protected override IntPtr WndProc(

    IntPtr hwnd,

    int msg,

    IntPrt wparam,

    IntPtr lparam,

    ref bool handled)

  {

    // Handle incoming messages here.

    // The incoming messages are typically delegated

    // to the hosted control.

  }

}

 

 

You use the BuildWindowCore to instantiate the Win32 user control you want to host. This is typically done through a call to the CreateWindow / CreateWindowEx API. Similarly, in DestroyWindowCore you destroy your Win32 user control, typically by a call to the DestroyWindow API.

The WndProc method allows you to handle incoming window messages.

  1. In your HwndHost-derived class (MyHost in this particular example), declare an adapter interface[3] to allow communication with the hosted Win32 control. In order to ensure reusability of the host class in different WPF applications, you should strive to avoid any Win32 idiosyncrasies in the interface. Instead, the adapter interface should conform to the .NET coding and style guidelines and should hide the fact that there is an underlying Win32 control.

For example, if your HwndHost-derived class is wrapping a Win32 listbox, then it probably makes sense to expose basic listbox methods such as:

·         AddItem

·         DeleteItem

·         SelectedItemIndex {get; set}

·         SelectedItemText {get;}

·         SelectionChanged event  (see the “Communicating Win32 Events to the WPF Window” section later in this document)

 

Conversely, it is not a good idea to expose a method such as SendMessage, wrapping the Win32 SendMessage API.

  1. In the XAML file declaring the UI of your WPF window, add a declaration for your HwndHost class:

 

<Window

  x:Class="Win32ControlInWpfWindow.MainWindow"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:custom="clr-namespace:Win32ControlInWpfWindow;assembly="

  Title="Win32 Control in a WPF Window"

  Height="500" Width="600"

  >

 

  <StackPanel>

    <Button Click="ButtonAddItemOnClick">Add Item</Button>

    <custom:Win32ListBoxHost x:Name="listbox" Width="100" Height="100"/>

  </StackPanel>

 

</Window>

 

 

Note how the XAML file above defines the name space for your HwndHost-derived class (the “custom” namespace) and the assembly where the class is implemented. In this particular case the “assembly=” directive points to nothing, which indicates that the host class is implemented in the same assembly as the one of the MainWindow class.

 

“Simple” Messages vs “Composite” Messages

In a traditional Win32 application, you display a number of Win32 user controls in a top-level Win32 window. The top-level window is typically handling all window messages resulting from interaction of the user with the controls through a top-level WindowProc.

As the user interacts with the controls on the window, the top-level WindowProc receives both “simple” messages (e.g. WM_LBUTTONDOWN, etc.) that are generated by the OS window manager as well as “composite” messages (e.g. WM_COMMAND, etc.) that are generated by the user controls and sent as notifications to the parent window[4].

These “composite” notifications present a problem in the WPF hosting case, because there is no parent window WindowProc to process them[5]. As a result, in the code below would not really work as expected:

 

class MyHost : HwndHost

{

  protected override HandleRef BuildWindowCore(HandleRef hwndParent)

  {

    _hwndListBox = CreateWindowEx(

        0, "listbox", "",

        WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | WS_BORDER,

        0, 0,

        (int)Width, (int)Height,

        hwndParent.Handle,

        IntPtr.Zero,

        IntPtr.Zero,

        0);

 

    return new HandleRef(this, _hwndListBox);

  }

 

  protected override IntPtr WndProc(

    IntPtr hwnd,

    int msg,

    IntPrt wparam,

    IntPtr lparam,

    ref bool handled)

  {

    switch (msg)

    {

      case WM_COMMAND:

        // This code-path will never get hit as the listbox control will

        // never receive the WM_COMMAND message that it posts to its parent

        break;

 

      case WM_LBUTTONDOWN:

        // This code-path will get hit as the listbox control will

        // be receiving the message from the OS window manager

        break;

    }

  }

 

  ...

}

 

In most cases handling “simple” messages in the WndProc method is sufficient, although it may be somewhat cumbersome.

There are, however, cases in which you would want to receive “composite” messages. To achieve this, you need to create an artificial parent HWND, so that you can receive the “composite” notifications, generated by the hosted child windows.  In other words you end up with the following general structure:

clip_image002[6]

This is achieved as follows:

class MyHost : HwndHost

{

  protected override HandleRef BuildWindowCore(HandleRef hwndParent)

  {

    _hwndListBoxParent = CreateWindowEx(

      0, "static", "",

      WS_CHILD,

      0, 0,

      (int)Width, (int)Height,

      hwndParent.Handle,

      IntPtr.Zero,

      IntPtr.Zero,

      0);

 

    _hwndListBox = CreateWindowEx(

      0, "listbox", "",

      WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | WS_BORDER,

      0, 0,

      (int)Width, (int)Height,

      _hwndListBoxParent,

      IntPtr.Zero,

      IntPtr.Zero,

      0);

 

      return new HandleRef(this, _hwndListBoxParent);

  }

  ...

 

  Private IntPtr _hwndListBoxParent = null;

  Private IntPtr _hwndListBox = null;

}

 

 

Communicating Win32 Events to the WPF Window

With the code above we can capture and process the window messages sent to the hosted Win32 user control. We do that in the WndProc method.

In addition to that we need to be able to inform interested WPF elements of the fact that we have received a certain event. For example, a hosted Win32 button may need to inform a WPF textbox that is has been clicked, a hosted Win32 listbox may need to inform a WPF textbox that the selection in the listbox has been changed, etc. The traditional way to do expose that capability in .NET is through events.

So we declare a public event and a protected event handler as follows:

 

class MyHost : HwndHost

{

  ...

 

  public event EventHandler SelectionChanged;

 

  protected void OnSelectionChanged(EventArgs args)

  {

    EventHandler handler = SelectionChanged;

    if (handler != null)

    {

      handler(this, args);

    }

  }

 

  ...

}

 

 

This allows the users of the class to write code such as:

 

class Test

{

  public static void Main()

  {

    ...

    myHost.SelectionChanged += MySelectionChangedHandler;

    ...

  }

 

  public void MySelectionChangedHandler(EventArgs args)

  {

    // This method gets called whenever someone changes the selection in the Win32

    // control (which is presumably a listbox) hosted in MyHost.

  }

 

  ...

}

 

 

Adding Tab and Accelerators Support for the Hosted Win32 Control

One current problem that you will see in the application is that keyboard navigation does not work well with the Win32 control. Keyboard navigation has several aspects:

a)       Enabling tabbing into and out of the hosted Win32 control (listbox)

b)       Enabling keyboard navigation within the hosted Win32 control (e.g. moving the selection in the listbox)

c)       Supporting access keys

In order to achieve a) and b), your HwndHost-derived class needs to implement two methods of the IKeyboardInputSink interface: TabInto and TranslateAccelerator.

The TabInto method gives you (as the name suggests) tabbing into the Win32 listbox (by pressing either Tab or Shift+Tab). In this particular case, the implementation of TabInto is trivial because we only have a single Win32 control:

 

class Win32ListBoxHost : HwndHost, IKeyboardInputSink

{

  ...

 

  bool IKeyboardInputSink.TabInto(TraversalRequest request)

  {

    if (request.FocusNavigationDirection == FocusNavigationDirection.Next)

    {

      NativeMethods.SetFocus(_hwndListBox);

    }

    else

    {

      NativeMethods.SetFocus(_hwndListBox);

    }

 

    return true;

  }

 

  ...

}

 

 

The TranslateAccelerator method gets called whenever the OS sends keyboard messages (WM_KEYDOWN or WM_SYSKEYDOWN) to the application. We use the method to intercept pressing of the up and down arrow so that we can change the selected item in the hosted Win32 listbox:

 

class Win32ListBoxHost : HwndHost, IKeyboardInputSink

{

  ...

       

  bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers)

  {

    bool isHandled = false;

 

    if (msg.message == NativeMethods.WM_KEYDOWN)

    {

      if (msg.wParam == (IntPtr)NativeMethods.VK_UP)

      {

        if (this.SelectedItemIndex > 0)  { this.SelectedItemIndex--; }

        else                             { this.SelectedItemIndex = 0; }

 

        isHandled = true;

      }

 

      if (msg.wParam == (IntPtr)NativeMethods.VK_DOWN)

      {

        this.SelectedItemIndex++;

        isHandled = true;

      }

    }

    return isHandled;

  }

}

 

The only thing that remains is supporting access keys (also known as mnemonics). In order to do that, you need to provide an implementation for the IKeyboardInputSink.OnMnemonic method.

 

Conclusion

The attached projects demonstrate the final solution for hosting a Win32 listbox in a WPF window. The final interface of the HwndHost-derived Win32 listbox container class is:

class Win32ListBoxHost : HwndHost, IKeyboardInputSink

{

  public void AddItem(string item);

  public void DeleteItem(int itemIndex);

  public int SelectedItemIndex { get; set; }

  public string SelectedItemText { get; }

  public event EventHandler SelectionChanged;

 

  protected override HandlerRef BuildWindowCore(HandleRef hwndParent);

  protected override void DestroyWindowCore(HandleRef hwnd);

  protected virtual void OnSelectionChanged(EventArgs args);

  protected override IntPtr WndProc(IntPtr hwnd, int message,

                                    IntPtr wParam, IntPtr lParam, ref bool handled);

 

  bool IKeyboardInputSink.TabInto(TraversalRequest request);

  bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers);

}

 

For demonstration purposes only, I have included both a project that only uses “simple” (aka “raw”) window messages only and one that uses composite window messages. The only differences between the two projects are in the Win32ListBoxHost.cs file. In most real-world situations, you will end up using “composite” window messages – otherwise you would have to re-implement parts of the business logic of the component you are hosting, which is obviously undesirable.

 



[1] A handle to a window

[2] Hit-testing is the act of determining whether the position of the mouse coincides with the control representation on the screen

[3] “Adapter” in this context refers to the Adapter design pattern

[4] The notion of “simple” and “composite” messages is not something that is defined by the OS API or documentation. It is introduced in this text only as a way to illustrate the need for a parent HWND in order to be able to handle certain window messages. Instead, I could have used “OS generated” and “control generated” messages, etc.