[
Advertise | Submit Code | About us | Contact us | Link us
]
Go!
Membership Services
Login
Register

Home
C# General

General

C# Language

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting
C# Windows Forms

General

Combo and List boxes

Miscellaneous Controls

Button Controls

Edit Controls
Cutting Edge

ASP.NET 2.0

Visual Studio 2005

Windows Longhorn

SQL Server 2005
C# Multimedia and GDI+

General

DirectX

GDI+

Audio
Internet & Web

General

Images and multimedia

Database

Utilities

Security

ASP.NET Controls

Design and Architecture

Webservices
.NET

General

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting

ADO.NET

XML.NET

Tools

Enterprise

IDE
Visual Basic .NET

VB.NET General

VB.NET Controls
General Reading

.NET Books Review

Product Showcase

Book Chapters

Business Design & Strategy
Community

Discuss

Job Board

Discussion

CodeXchange
DeveloperLand

Advertise

Submit Code

About us

Contact us

Link us
Miscellaneous

Favorite Links

Downloads

Programming Sites

Top Stories
Regular Expressions

E-Mail

Date/Time
Home > Visual Basic .NET > VB.NET General
Intercepting the ENTER and ESC keys in custom, drop-down UITypeEditors.
Posted by on Thursday, January 20, 2005 (EST)

This article and the accompanying source code shows you how to intercept the ENTER and ESC keys in your own UITypeEditor implementation. Intercepting the keys is essential for emulating the behavior of the .NET Framework's built-in, drop-down editors.

This article has been viewed: 4,925 times
Technology: VB.NET General.

resimage.zip (83.25 KB)

When developing Windows Forms controls it is often useful to provide your own, drop-down type editors for some of the control's properties. Custom type editors provide for richer design-time experience and they might be the deciding factor whether your users like your controls or not.

If you decide to create your own drop-down type editor, it should, presumably, follow the same behavioral pattern exposed by the built-in drop-down editors. Let's take the Anchor property as an example. A typical design-time user interaction with the property is as follows:

  • The user selects the Anchor property in the property grid and clicks the down-arrow button to the right of the property's cell.
  • A nice graphical control is dropped down allowing the user to either click the edges by the mouse or use the arrow keys to highlight an edge and the SPACEBAR key to select / deselect it.
  • The user presses the ENTER key or clicks outside of the drop-down control for accepting the changes. In order to cancel the changes, the user presses the ESC key.
Pretty intuitive!

So what does it take to replicate the above-mentioned behavior?

In order to explore the implementation choices, let's build a ResourceImageEditor type editor that allows for picking an image file from the file system (just like the built-in ImageEditor class) or picking an image resource from an assembly's manifest. With regards to user experience, the ResourceImageEditor should behave like the built-in type editors. Here are our requirements in a nutshell:

  1. When the user selects a property in the property grid, the grid should display a down-arrow button indicating that the property will be edited with a drop-down UI.
  2. When the down-arrow button is clicked, a list of all image resources from the current assembly should be displayed.
  3. When the user selects an image resource item, the image will be loaded from the assembly.
  4. To allow for selecting an image file, the last item in the drop-down list will be labeled as "Browse...". When the user clicks the "Browse..." item, the "classic" open file dialog will be displayed and the user will be able to pick an image file from the file system.
  5. The drop-down list will allow the user to select an item by single-clicking it with the mouse, or by using the arrow keys to highlight an item and pressing the ENTER key to actually select it. The drop-down selection will be also accepted by clicking off of the list. The drop-down selection will be canceled by pressing the ESC key.
The ResourceImageEditor is a type editor so it should derive (directly or indirectly) from the System.Drawing.Design.UITypeEditor class. I've decided to inherit from the built-in System.Drawing.Design.ImageEditor, because it already implements the image file selection functionality specified in the fourth requirement above. That is, the ImageEditor.EditValue implementation displays a file open dialog allowing the user to select an image file from the file system. Invoking this functionality from within my derived class is then a simple call to MyBase.EditValue.

In order satisfy the first requirement (displaying the down-arrow button in the property grid), I've had to override the GetEditStyle method to return the appropriate constant from the UITypeEditorEditStyle enumeration:

Public Overloads Overrides Function GetEditStyle( _
  ByVal context As ITypeDescriptorContext) As UITypeEditorEditStyle
 
  Return UITypeEditorEditStyle.DropDown
End Function
To display the list of image resources, I've had to enumerate all resources in a given assembly and display only the image resources in the list. To keep things simple, I've decided to employ a simple convention - when a resource name ends with a valid image file extension (.bmp, .jpg, .gif...), it is considered an image resource and it will be included in the drop-down list. The collection of image resource names is used to populate the drop-down ListBox control as described later. When the user selects an image resource name in the list box, the image should be loaded from the given assembly's manifest. This is implemented within the LoadResourceImage method:
Private Function LoadResourceImage(ByVal resourceName As String) As Image
  Debug.Assert(Not resourceName Is Nothing)
  Dim ImageStream As System.IO.Stream = _
    Me.ResourceAssembly.GetManifestResourceStream(resourceName)
  Return System.Drawing.Bitmap.FromStream(ImageStream)
End Function
The drop-down user interface is implemented by dynamically creating and populating a ListBox control inside the overridden EditValue method. The editor also handles the Click and KeyDown events generated by the ListBox, which is necessary to intercept the ENTER and ESC keys. Here is pseudocode illustrating the logic inside the EditValue method:
Public Overloads Overrides Function EditValue(...)
  ' Store the context information for use in the drop-down ListBox event handlers.
  ' Create and fill the ListBox with the names of the available image resources.
  ' Add our special "Browse..." item.
  ' Wire the ListBox events.
  ' Display the ListBox in a drop-down window.
End Function
That's it.

I've written the ResourceImageEditor code.

I've created a sample MyPictureBox (derived from System.Windows.Forms.PictureBox) overriding the Image property as to have the ResourceImageEditor specified as the property's type editor.

I've compiled the code, placed the MyPictureBox control onto a form and invoked the drop-down user interface...

The mouse interface worked well. However, when I've selected an item with the keyboard and then pressed the ENTER key, the drop-down list disappeared, but my selection has been lost (i.e. the previously selected image hasn't changed). I've quickly discovered that when the ENTER key is pressed, the ListBox doesn't generate the KeyDown event.

The property grid has apparently "stolen" the ENTER and ESC keys before the ListBox control could get a chance to process them. Or did it?

To make a long story short, the solution that worked was to employ the ProcessDialogKey method. The method is called during message preprocessing to handle dialog characters, such as TAB, RETURN, ESCAPE and also the arrow keys. The method is declared within the System.Windows.Forms.Control class in such a way that it simply delegates the call to the control's parent (if any). I've "subclassed" the ListBox control and I've overridden the ProcessDialogKey method to intercept the ENTER key like this:

Protected Overrides Function ProcessDialogKey(ByVal keyData As Keys) As Boolean
  If keyData = System.Windows.Forms.Keys.Return Then
    RaiseEvent EnterPressed(Me, EventArgs.Empty)
    Return True  ' True means we've processed the key
  Else
    Return MyBase.ProcessDialogKey(keyData)
  End If
End Function
Instead of generating the KeyDown event from within the ProcessDialogKey implementation, I've decided that a more straightforward approach would be to generate a new, distinguished event - the EnterPressed event. The ResourceImageEditor.EditValue implementation has been changed to handle this event (instead of the KeyDown) event and everything finally worked correctly.

You can use this technique to intercept the ENTER key in any Control-derived class that you use for implementing the drop-down UI inside your type editor.

Top Go to Table of Contents

About Palo Mraz

Click here if you want to know more about .

Other articles that may interest you

  • Write a Word Add-In – Part 0
  • Write a Word Add-In – Part I
  • Lengthy Operations on Single Thread in .NET Application
  • Learning Draughts
  • Exceptions and Performance
  • Average Rating :

    Discussion Forums
    Got a programming related question? Hopefully someone has the answer... Want to help out other developers? Visit our discussion forums.

    Sponsored by:

    New Articles

  • Exceptions and Performance
    Almost every time exceptions are mentioned in mailing lists and newsgroups, people say they're really expensive.Let's examine that claim, shall we?

  • Creating multilingual websites - Part 1
    Extend the existing globalization capabilities of .NET to create flexible and powerful multilingual web sites. First, create a custom ResourceManager, and then create custom localized-capable server controls to easily deploy multilingual functionality.

  • Parameter passing in C#
    Many people have become fairly confused about how parameters are passed in C#, particularly with regard to reference types. This page should help to clear up some of that confusion

  • Most Popular Articles

  • LDAP, IIS and WinNT Directory Services
    This article explains how to use .NET Directory Services to retrieve and search directory objects, create new directory objects and edit or delete existing directory objects. Describes Active Directory Application Mode (ADAM) and how to use the IIS, WinNT and LDAP directory (ADSI) provider.

  • An in-depth look at WMI and instrumentation, Part II
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article is the second part of a two-part series.

  • An in-depth look at WMI and instrumentation, Part I
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article provides an in-depth look at WMI and MOM 2005

  • New Books

  • Murach's ASP.NET 2.0 Upgrader's Guide: VB Edition
    What’s new and how to use it! That’s what this book delivers if you’re a VB developer who’s interested in upgrading from ASP.NET 1.x to ASP.NET 2.0.

  • C# in easy steps
    Learn to program with Microsoft’s premier programming language. No previous programming knowledge is assumed. With numerous easy-to-follow examples, this title explains the essentials of object-oriented programming with C#.

  • Murach's ASP.NET web programming with VB.NET
    Murach's ASP.NET web programming with VB.NET by Doug Lowe and Anne Prince is a in depth training and reference book for ASP.NET programming using VB.NET. The book builds upon Murach's previous books and covers more advanced concepts for programming ASP.NET pages.

  • Got Code?

    if you have any article , source code , or anything else you'd like to share with this community that you think others might find useful, please submit it here and we will gladly make it available on this site. submit@developerland.com.
    Partners

    All articles are copyrighted by their individual authors unless otherwise specified , everything else Copyright ©2004-2006 DeveloperLand