Skip to main content

Building Graphically Advanced Applications with the .NET Compact Framework 3.5

Authors

Marco Bodoira, Embedded Consultant, BEPS Engineering. http://www.bepseng.it
Giorgio Sardo, Technical Evangelist, Microsoft Corp. http://blogs.msdn.com/Giorgio

Expression Newsletter, subscribe now to get yours.

Summary

In this article you will learn to build a picture contacts browser using advanced rendering techniques offered by the .NET Compact Framework 3.5 and the Windows Mobile APIs

Introduction

Windows Mobile contains a default application to manage phone contacts. This application allows you to store and call phone numbers but does not offer other features, like the ability to browse the contacts by picture and call them just by clicking on their photos. In this article we will build this solution using some advanced techniques for rendering offered by the .NET Compact Framework 3.5 SP1 and Windows Mobile’s APIs.

By looking at the provided application source code, you will learn to:

  • Write custom controls
  • Use the double buffering
  • Add alpha channel transparency
  • Build custom a Message Box
  • Interact with the phone API
  • Much more…

Full source code of the application is available here: http://blogs.msdn.com/giorgio/archive/2008/11/03/building-graphically-advanced-applications-with-the-net-compact-framework-3-5-tutorial-published.aspx

Building a Picture Contact List for Windows Mobile

The Windows Mobile platform, thanks to its extended partner and community ecosystem, offers a lot of custom vendor implementations to browse your contact list; a few of these show contact pictures rather than showing only names.

This offers increased visual appeal, as well as the convenience of larger images instead of small written names.  This is useful, not only for visually impaired people, but also offers better readability in many conditions, such as in high brightness circumstances or “one hand only navigation”.

In this article we will not build a final end-user application. Instead, we will show how to use some advanced features of the Microsoft .NET Compact Framework to design and develop an “out-of-the-box” application, that allows users to browse contacts by picture, to call them with “one-click-only”, and to take and assign a picture to contacts without one.

Wireframing

Before starting the development process, it’s a good practice to draw a rough representation of the flow and screens of the application.

The proposed application is composed of the following forms:

  • 1: main form with the list of contact pictures in the device
  • 2: popup forms to ask for confirmation before calling or adding photos to contacts
  • 3,4: edit form that allows adding photos to contacts by directly accessing the camera
  • 5: popup form to provide help and guidance

The target of the application are adults, or general users with limited technical proficiency.

The solution will be designed for a generic device with Windows Mobile 6.0 Professional Edition (thus with touch screen). It will not be difficult however to migrate the application to Windows Mobile 5.0 (or higher) devices. We did the testing using the Microsoft Visual Studio 2008 emulator and - as physical devices – an HTC P3600 and an HTC Touch Dual.

The displacement of the buttons is dictated by standard design principles and by the need to make the application usable with only one hand. It should be noted that the layout shown is intended for an audience of right-handed people; however, for a real-world application, you should also consider left-handed people. Since the application run in full screen mode, we chose to place the close button in the top right corner - as in most Windows Mobile applications.

The main form (1) contains a list of contact pictures; as they would probably not fit into a single screen, the user can browse them scrolling vertically the.

Pressing on a contact, the user will be asked to confirm through a popup (2): If he answers affirmatively, the application willinitiate the calland close. Otherwise it will ignore the request and return to the main form.

From the main form you can move on to the second one by pressing the edit button at the bottom of the screen. As already mentioned, having the button in that position allow the user to easily press it by using the right thumb as represented in the following picture.

The editing form (3), allows the user to select a contact in the address book and add a picture from the camera to his profile. Like the main form, it has a list of contacts (this time represented by their names only).

Selecting the name of a contact, the camera will be accessed (4), giving the user the opportunity to take a picture and, once done, to confirm the association between the picture and the contact. Both the answers close the popup and return to the editing form.

The user can return to the main form with the back button; note that the button is located in the same position of the edit button, in order to give consistency to the overall form design.

Both forms offer a help button: as for the close button, a standard icon has been used. Although in this scenario the application is easy to use, it’s always a good practice to include some help for your solutions.

Finally note that all the popup messages have the default action set to cancel, in case the user click on the external opaque area.

Development

Requirements

To start developing this application, you will need:

  • Microsoft Visual Studio 2008
  • Microsoft Windows Mobile 6 Professional Software Development Kit (or an SDK for the available target device)
  • Optional: a Microsoft Windows Mobile 6 Professional device (you can use the Visual Studio emulator)

NOTE: If you use the emulator, although you will not receive any error, you will not be able to use the camera. Moreover the emulator has no built-in telephone contacts: in this case, we suggest you create some test contacts by un-commenting the method GenerateTestContacts() in the constructor of the MainForm.

        private void GenerateTestContacts()
        {
            Random rnd = new Random((int)DateTime.Now.Ticks);
            // Load temporary images from the folder "TestContacts"
            var files = newDirectoryInfo(Path.Combine(
                System.IO.Path.GetDirectoryName(System.Reflection. Assembly.GetExecutingAssembly().GetName().CodeBase)
                , "TestContacts")).GetFiles("*.jpg");
            // Create 100 test contacts
            for (int i = 0; i < 100; i++)
               PoomHelper.AddContact(
                   new Contact() { FirstName = string.Format("Test {0}", i) },
                    files[rnd.Next(0, files.Length)].FullName);
        }

The final project will look as follows; in the next session we will go through the most relevant parts of the application.

Getting Started

The first step is to create a new project for smart devices in C#. From Visual Studio 2008, create a new project (selecting .NET Framework 3.5 from the command bar):

File -> New Project…

After pressing OK, you will see the following form, which asks for you to choose the target platform, the version of the .NET Compact Framework and the type of application to build. In our case you should choose the parameters outlined in the following image.

The project wizard will automatically create a project with a main form. You can run the project by hitting F5 and selecting a target device (the emulator by default). As the emulator loads, the .NET Compact Framework 3.5 and the application will be deployed; once the deployment is completed, the application starts in debug mode, and the following blank form will be shown inside the emulator:

Full-Screen Applications

By default the forms in Windows Mobile are full screen, having the top bar of the window that gives key device information (time, volume, signal strength) and a lower bar to access the application menu and to show an onscreen keyboard. To remove the bar at the bottom, you need to delete the MainMenu component from the form designer of Visual Studio.

To remove the top bar instead you must set two properties of the form class: FormBorderStyle and WindowState. They can be changed by mean of the properties panel in the form designer or by writing the following two lines of code:

this .FormBorderStyle = FormBorderStyle.None;
this .WindowState = FormWindowState.Maximized;

Writing Custom Controls

The convenience of having custom controls is that they can be used as normal controls. Where convenient, we adhered to this philosophy throughout the project; e.g. the message box, the picture button and the sliding list are real controls, ready to be reuse in external projects.

Custom Image Button

The button ImageButton inherits from Control and allows you to display an image with the behaviors of a button. To customize the control we perform the override of these methods:

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //Do nothing
        }
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            if (isPressed)
                e.Graphics.DrawImage(imagePressed, 0, 0);
            else
                e.Graphics.DrawImage(image, 0, 0);
        }

To change the image of the button when it is pressed, we override OnMouseDown and OnMouseUp event methods and we set a Boolean defining which image to draw:

        protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
        {
            isPressed = true;
            this.Invalidate();
            base.OnMouseDown(e);
        }
        protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
        {
            isPressed = false;
            this.Invalidate();
            base.OnMouseUp(e);
        }

Finally, in order to use this custom control within a form, we can use the following:

            ImageButton customButton = new ImageButton(bitmap, bitmapPressed, transparentColor);
            customButton.Size = new Size(200,50);
            customButton.Location = newPoint(0,0);
            customButton.Click += new EventHandler(customButton_Click);

Custom MessageBox, AlphaBlend and Image Trasparency

The MessageBox is a full screen form exploiting alpha blending and image transparency. The alpha blending is obtained from a PInvoke call to the AlphaBlend API, which is available starting from Windows CE version 5.0.

        [DllImport("coredll.dll")]
        extern publicstatic Int32 AlphaBlend(IntPtr hdcDest, Int32 xDest, Int32 yDest, Int32 cxDest, Int32 cyDest, IntPtr hdcSrc, Int32 xSrc, Int32 ySrc, Int32 cxSrc, Int32 cySrc, BlendFunction blendFunction);

The function is wrapped by the managed method DrawApha, which can be called as follows:

Drawing .DrawAlpha(e.Graphics, background, 180, 0, 0);

NOTE: the image “background” will be drawn with a transparency of 70% (=180/255).

As for the ImageButton, the customized message box has OnPaintBackground and OnPaint methods overridden, drawing a picture completely black semitransparent. After painting the background image, the solid background image of the message box is drawn using the technique of image transparency offered by the Compact Framework. First you must create an instance of the class ImageAttributes:

                  transparency = new ImageAttributes

Then you have to decide what color to make transparent, in this case we are using the Black:

            transparency.SetColorKey(transparentColor, transparentColor);

NOTE: in .NET Framework, you can select a range of colors ranging from the first and the second parameter of the SetColorKey function. In the .NET Compact Framework instaed this is not possible, and the two parameters need to be equal.

Finally you can  draw the image using the following overload method of Graphics.DrawImage:

            e.Graphics.DrawImage(background, rectangle, 0, 0, background.Width, background.Height, GraphicsUnit.Pixel, transparency);

In the case of our application, the final result is a background image with the edges rounded, while the rest of the screen is darker.

 

Custom Sliding List Control

The main component of this application is the sliding list control. With this item, you can scroll through the list with simple gestures. We created two implementations of the sliding list control: the first displays images, the second displays text only.

The number of pixels to translate vertically the panel is continuously calculated by the difference between the coordinates from the events MouseDown, MouseMove and MouseUp: the location of each item of the list is updated and the image is redrawn on the screen. To simulate an inertial behavior, we followed the method suggested by Fredrik Bornander on CodeProject.com (customized accordingly).

To make the sliding panel movements flicker-free, we had to implement a double buffering mechanism: we created an image serving as a buffer, on this image we performed all the drawing operations and finally we draw the resulting image to screen. To summarize the key points:

  • in theInitialize_Graphics we created the Bitmap and Graphics objects that we subsequently use as buffers to draw in:            // Initialize "writeable memory bitmap"
                doubleBuffer = new Bitmap(this.Width, this.Height);
             graphics = Graphics.FromImage(doubleBuffer);
  • to draw pictures, strings and shapes on doubleBuffer throughgraphics we used the methods:graphics.DrawImage(Resources.XPressed, …
    graphics.FillRectangle(brushPressed, rectangle);
    graphics.DrawString(name, font, brush, textRectangle);

  • inside the OnPaint overriden method finally we performed the real onscreen drawing:e.Graphics.DrawImage(doubleBuffer, 0, 0);

The operation of filling the list with images can take a long time: we made the loading operation asynchronous, placing the data binding method inside a background thread separated from the graphic thread:

  publicoverridevoid LoadData()
        {
            // Load contacts with a profile picture asynchronously
            System.Threading.Thread asyncLoading = new System.Threading.Thread(delegate()
            {
               var contacts = PoomHelper.GetContactsWithPicture();
               ...
            });
            asyncLoading.IsBackground = true;
            asyncLoading.Start();
        }

From the background thread we also want to update the UI as soon as we add a new contact to the buffer. In order to do so, we implemented a delegate and we call the Invalidate method on our custom control, such as:

               foreach (Contact contact in contacts)
                {
                   IListControlItem contactGui = new PictureContact(contact);
                    ....
                    Invoke(new CustomInvalidateDelegate(CustomInvalidate));
                }

The Invoke method will invalidate the screen area through theCustomInvalidateDelegate delegate, thus forcing a repaint.

        protected delegate voidCustomInvalidateDelegate();
        protected void CustomInvalidate()
        {
            this.Invalidate();
        }

Each item of the list will follow his behaviours, as defined in the specialized ISlidingListItem class.

Helpers

In order to access some of the device API, we created a set of static helper classes.

DrawingHelper: allow us to perform some low-level graphic operation.

PoomHelper: using the OutlookSession object, we can do almost any operation with our phone contacts, using managed code.

PhoneHelper: give us the ability to call a contact from withitin the application.

CameraHelper: using the CameraCaptureDialog class we can open the custom camera dialog form developed by the phone vendor.

Conclusion

In this article our goal was to demonstrate how you can create graphically appealing applications with the Microsoft.NET Compact Framework 3.5 SP1 and the Windows Mobile APIs , without recurring to any C++ or GDI code. The application provided is meant to be a starting example and it can be further improved.

We would like to give a short list of helpful tips to follow when working with the Microsoft .NET Compact Framework:

  • When you override the OnPaint or OnPaintBackground methods, avoid creating new objects inside their body: if you frequently use an object throughout the life of an instance of a control, define it at a global level and create it inside the constructor to improve performance.
  • Give feedbacks to the user: update graphics as soon as possible, move the code that takes a long time in a secondary thread and whenever it is possible, invoke graphic’s update methods.
  • Don’t forget to include some kind of help or suggestion inside your application.
  • Follow the best practices discussed in the previous article.

Author Biography

Marco Bodoira, Software Engineer, is an Embedded Consultant in BEPS, Certified on Microsoft Windows CE 6.0. BEPS Engineering, an Italian Windows Embedded Silver Partner, offers its customers products, system buildings, consultancy, applications for embedded system solutions and training on Windows CE. Email: marco.bodoira@bepseng.it Website: http://www.bepseng.it

Giorgio Sardo is a Technical Evangelist for Microsoft Corporation, specialized on web technologies.
Blog: http://blogs.msdn.com/Giorgio

References

Mobile Best Practices
http://expression.microsoft.com/en-us/cc964299.aspx

.NET Framework Developer's Guide: How to: Draw Images with Transparency
http://msdn.microsoft.com/en-us/library/ms172507.aspx

.NET Framework Developer's Guide: How to: Draw Images Off-Screen
http://msdn.microsoft.com/en-us/library/ms172506.aspx

.NET Framework Developer's Guide: How to: Set a Background Image on a Form
http://msdn.microsoft.com/en-us/library/ms172529.aspx

AlphaBlend API function
http://blogs.msdn.com/b/chrislorton/archive/2006/04/07/570649.aspx
http://msdn.microsoft.com/en-us/library/aa452850.aspx (for windows CE 5.0)

Inertial Behavior
http://www.codeproject.com/KB/list/SmoothListBox.aspx

This article appeared in the November Expression Newsletter, subscribe nowto get yours.