SDF Sample: Showing the Entire String Contents of a ComboBox DropdownList#

Following Chris' SDF Samples (here, here and here) here is another little tip that reminded me we had this functionality in the Smart Device Framework while talking to a customer facing this issue.

Problem
I have a combobox with the following items in the list:

  1. Red
  2. Green
  3. A very dark and drab Gray

When you run your application you get something like this:

Your users call your helpdesk (and if you are like us the developers are the help desk :)) and complain they can't see the last colour option.

Solution
[Tested using Windows Mobile 5 emulator and Smart Device Framework 2.1]

Two possible solutions to this.  First, manually extend the ComboBox via the Visual Studio designer.  This is fine, but what happens if you create forms dynamically (as many of our customer do).

Second solution is found in OpenNETCF.Windows.Forms.ComboBox2 class and the DropDownWidth property.  Setting this property you get this:

Now if you have a dynamic form you can use this helper method to dynamically size the DropDownWidth.

private void AutoSizeDropDownWidth(OpenNETCF.Windows.Forms.ComboBox2 comboBox)
{
    int margin = 10;
    using (Graphics g = this.CreateGraphics())
    {
        SizeF size = SizeF.Empty ;
        int largestWidth = comboBox.Width + margin;
        for (int x = 0; x < comboBox.Items.Count; x++)
        {
            size = g.MeasureString(this.comboBox21.Items[x].ToString(), this.comboBox21.Font);
            largestWidth = ((int)size.Width>largestWidth ? (int)size.Width + margin: largestWidth );
        }
        comboBox.DropDownWidth = largestWidth;
    }
}


Wednesday, April 25, 2007 4:04:26 PM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  | 

 

MEDC 2007 - OpenNETCF Will Be There#

Mobile Embedded Developer Conference 2007 is fast approaching and runs from April 30 to May 3.  We (Chris and I) will be doing two sessions:


Panel Discussion with .NET Compact Framework Team, OpenNETCF's Smart Device Framework Team and Other Industry Insiders
Speaker(s):
Mark Arteaga
Do you have pressing questions about the .NET Compact Framework? Do you use OpenNETCF's Smart Device Framework and have specific questions? Do you have general questions on Windows Mobile and Windows Embedded CE development? Come to this session where members of the Compact Framework Team, OpenNETCF's Smart Device Framework team and other industry developers will be part of a panel answering questions from general coding to architecting mobile software, even covering .NET Micro Framework.

The panel will have Amit Chopra (Visual Studio for Devices), Richard Greenberg and Scott Holden (Compact Framework), Daniel Moth, Chris Tacke, Andy Wigley, Alex Yakhnin, Neil Cowburn and Peter Foot

Compact Framework Memory Management
Speaker(s):
Chris Tacke
In this session we'll explain how the .NET Compact Framework manages memory and how memory management relates to your application. We explore the garbage collector in the .NET Compact Framework, which provides a high-speed allocation service with good use of memory and no long-term fragmentation problems. By understanding how the garbage collector works, where memory is allocated for managed objects in the system memory, and how the operating system itself handles memory, you can make informed decisions about application architecture.

If you still haven't registered Derek Snyder (content owner for MEDC2007) has an RSVP code saving you $500 on the  registration fee (Hurry only until April 13)!  What are you waiting for go register and see you in Vegas!


Thursday, April 12, 2007 2:31:51 PM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  | 

 

Why is Vista Using So Much Memory?#

So I've been running Vista on a new Dell XPS machine for about a week and things have been going well.  I found this SideBar gadget just to see how my machine was doing.  Everything looked good but the screen shot below was taken when the device just started up.  I'm thinking 53% of memory! C'mon! 

So a little bit of searching and I found this great explanation as to why it's doing what it's doing.  If you are like me and thinking "why did I upgrade Vista is such a memory hog" think again.  Vista using all the memory is actually good thing!  Now I'm actually thinking why is there only 53% memory usage :)


Saturday, April 07, 2007 1:11:50 AM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  | 

 

Trapping Cut,Copy,Paste and Clear Using Compact Framework and Smart Device Framework 2.1#

As I mentioned in a previous post, this week we released Smart Device Framework 2.1.  A new feature in the product that we added to support an new upcoming control (that is currently in the final stages of development before we release a beta) are new Cut, Copy, Paste and Clear events for the OpenNETCF.Windows.Forms.TextBox2 class.

You are probably thinking "who cares what do I need that for?!"  Think of a TextBox where you have sensitive information for example a Social Insurance Number, Drivers License Number or Credit Card Number say in a mobile data collection or mobile billing application.  You could have a scrupulous person doing a "Copy" (CTRL-C using the input panel) and pasting (CTRL-V again with the input panel) that information into a webpage opened using Internet Explorer Mobile and emailing that to themselves at the end of the day.  It may be difficult to do on a 240x320 screen but it can be done (and has happened in one of my first projects I worked on).

So using a more lighthearted example, let's take a look at creating a NumericTextBox.  There are two ways to implement this control.  The first one is to modify the window style of a TextBox using the following.

private void SetNumeric()
{
    int style = OpenNETCF.Win32.Win32Window.GetWindowLong(this.Handle, OpenNETCF.Win32.GWL.STYLE);
    style |= (int)OpenNETCF.Win32.ES.NUMBER;
    OpenNETCF.Win32.Win32Window.SetWindowLong(this.Handle, OpenNETCF.Win32.GWL.STYLE, style);
}

The problem with this was it *only* accepted numbers.  There are some cases where you need a decimal place, but by modifying the TextBox style to ES_NUMBER, all you get is the ability to enter numbers.

The second option is to create your own control and override the OnKeyPress method and enter your custom logic. There are plenty of samples for creating a control like this but there is a great one here on MSDN specifically for the Compact Framework

One major flaw with this implementation is a user could always paste text into the TextBox and have no control over what is displayed.  Using OpenNETCF.Windows.Forms.TextBox2.Paste event allows you to 'clean' the pasted text of any unwanted characters.  Here are the new events exposed by TextBox2:

// Summary:
//     Occurs when a WM_CLEAR message is sent to the textbox
public event CancelEventHandler Clearing;
//
// Summary:
//     Occurs when a WM_COPY message is sent to the textbox
public event CancelEventHandler Copying;
//
// Summary:
//     Occurs when a WM_CUT message is sent to the textbox
public event CancelEventHandler Cutting;
//
// Summary:
// Occurs when a WM_PASTE message is sent to the textbox
public event CancelEventHandler Pasting;

 

All events use the CancelEventHandler Delegate which allows you to cancel the whole operation and not allow the WM_* message to flow to the underlying native control.  Let's take a look at implementing this new functionality for the NumericTextBox. 

Here is the sample form we will be using to test the new functionality:

We have three ways to set text into the NumericTextBox:

  1. Using CTRL-C and CTRL-V keys via the Input Panel
  2. Sending a WM_COPY message to the lower TextBox and then a WM_PASTE to the NumericTextBox
  3. Setting the Text property of the NumericTextBox

First we have the OnKeyDown event.  Here we check to see if a CTRL key is pressed:

//Added this to allow for CTRL keys to be pressed
protected override void OnKeyDown(KeyEventArgs e)
{
    base.OnKeyDown(e);

    if ((e.Modifiers & (Keys.Control | Keys.Alt)) != 0)
    {
        // Let the edit control handle control and alt key combinations
        m_isCtrlKey = true;
    }
}

Next we have the OnKeyPressed event.  Here we validate the text being entered:

// Restricts the entry of characters to digits (including hex), the negative sign,
// the decimal point, and editing keystrokes (backspace).
protected override void OnKeyPress(KeyPressEventArgs e)
{
    base.OnKeyPress(e);
   
    if (!m_isCtrlKey)
    {
        if (!ValidateKey(e.KeyChar))
        {
            e.Handled = true;
            OpenNETCF.Media.SystemSounds.Beep.Play();
        }
    }
    else
        m_isCtrlKey = false;
}

Here is our logic to only allow numeric characters and/or decimals, spaces etc.

 

/// <summary>
/// This was originally in OnKeyPress in the MSDN sample but moved 
/// here so we can use in the Paste() method /// </summary> /// <param name="key"></param> /// <returns></returns> private bool ValidateKey(char key) { NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat; string decimalSeparator = numberFormatInfo.NumberDecimalSeparator; string groupSeparator = numberFormatInfo.NumberGroupSeparator; string negativeSign = numberFormatInfo.NegativeSign; string keyInput = key.ToString(); bool ret = false; if (Char.IsDigit(key)) { // Digits are OK ret = true; } else if (keyInput.Equals(decimalSeparator) || keyInput.Equals(groupSeparator) || keyInput.Equals(negativeSign)) { // Decimal separator is OK ret = true; } else if (key == '\b') { // Backspace key is OK ret = true; } //else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0) //{ // // Let the edit control handle control and alt key combinations //} else if (this.allowSpace && key == ' ') { ret = true; } return ret; } private string CleanString(string value) { if (value == null) return ""; StringBuilder sb = new StringBuilder(); for (int x = 0; x < value.Length; x++) { if (ValidateKey(value[x])) { sb.Append(value[x]); } } return sb.ToString(); }

The ValidateKey() method is taken from the MSDN sample.  CleanString() method is used by our overridden Text property and our OnPaste override.

public override string Text
{
    get
    {
        return base.Text;
    }
    set
    {
        value = CleanString(value);
        base.Text = value;
    }
}

protected override void OnPaste(System.ComponentModel.CancelEventArgs e)
{
    //When something is pasted in we need to verify that they are numeric
    string pasted = Clipboard2.GetText();

    //Insert the char where the cursor currently is
    this.Text = this.Text.Insert(this.SelectionStart, CleanString(pasted));

    //Optional. Clear the clipboard so it can't be used anymore
    Clipboard2.Clear();

    //Optional. Prevent any event handlers from being called
    e.Cancel = true;

    //Call the base
    base.OnPaste(e);
}

The Text override property is straight forward.  OnPaste is the new virtual method available in TextBox2:

protected virtual void OnPaste(CancelEventArgs e);

By overriding OnPaste, we now have the ability to get what has been copied into the clipboard using OpenNETCF.Windows.Forms.Clipboard2 and inserting the 'cleaned' text into our new NumericTextBox.

Now we have a nice simple way to stop unwanted characters from being pasted into our TextBox2 control and a nice clean way to know when a Clear, Cutting or Copying operation is being done within our control.

Download the full source for the NumericTextBox here and remember you need the Smart Device Framework 2.1 (either Community Edition or Extensions for Visual Studio) for this sample to work.

Enjoy!


Saturday, April 07, 2007 12:53:31 AM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  | 

 

Smart Device Framework 2.1 Released#

We have been fairly busy here with consulting work, product development, website upgrades, new online store etc etc.  As I hinted at earlier we were in the process of releasing v2.1 of the Smart Device Framework. 

This week we finally released Smart Device Framework 2.1.  Although it's a minor release and have cleared all bugs in our bugzilla database we have added some new features.  Nick Randolph decided to take the new release for a spin and talks about his experience here. Even though we have just released v2.1, Chris is already talking about v2.2 features here and here!  Thanks to Neil, the Smart Device Framework Extensions for Visual Studio has a much cleaner install, more integration with Visual Studio and start menu shortcuts to the help, source, samples etc.  As usual, we still offer the Smart Device Framework Community Edition free of charge.

For a list of new changes to the library see here.  One big change we did is separate the OpenNETCF.WindowsCE.Messaging into it's own assembly OpenNETCF.WindowsCE.Messaging.dll from OpenNETCF.WindowsCE.dll.

We have also reintroduced support for the OpenNETCF.Windows.Forms.Signature control.  Unfortunately it slipped through the cracks with the 2.0 release (mainly my fault as I was responsible for OpenNETCF.Windows.Forms namespace) but it is now back in the 2.1 release with design time support. 

For OpenNETCF.Windows.Forms.OwnerDrawnList we added a DrawMode property to keep it in line with the desktop framework.  If you use the ListBox2 or SmartList and have some custom drawing code you may want to test your code if you are going to use Smart Device Framework 2.1.

Another cool feature we added to OpenNETCF.Windows.Forms.TextBox2 was the ability to be notified when a Cut, Copy, Paste or Clear event is sent to the TextBox.  I have a seperate post on that so if you are interested in that stay tuned :)

If you are a current customer of either the Extension or Community Edition, our online store now has the ability to accept product reviews. Let us know what you like, don't like and want to see in the next version.  We are already adding features to v2.2 but are always interested in what our customers and the community want to see. 


Friday, April 06, 2007 11:21:21 PM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  | 

 

Toronto CodeCamp 2007 Followup#

This year Toronto CodeCamp went off without a hitch.  We had about 300 people show up (out of 600 registered) so not a bad turnout considering the weather was nice and it was a Saturday.  Suprisingly I got a lot of interest in my session and was assigned the biggest room available and I would say about 60-70 people showed up.  A lot better turn out than last year were I probably got about 20-25 people!

Thanks to Chris Dufour for putting everything together and managing to get over $300,000 in prizes to give to the attendees!

As for my session here are the slide decks.

All Demo code can be downloaded here.  In this zip you will find

  • "Demo1" - Basic intro to device development and the environment
  • "CodeSharing" - Sharing business logic with the desktop and device. (For an entire 75 minute session on this instead of 15mins check out Daniel Moth's session at this year's MEDC.)
  • "SqlCompactEdition" - Contains a SqlDesktop and SqlDevice that both access the same Sql Server 2005 Compact Edition database file. (NOTE: the SqlDevice project references the SDF file in the BIN\Debug directory of SqlDesktop.  So run SqlDesktop first, make changes and save, then run SqlDevice to see the changes)
  • "RPMSample" - sample to show RPM and the various numbers it shows.  NOTE: If you want to have RPM working in Vista make sure you install Compact Framework SP2 on your machine (thanks to Steven Pratchner for letting me know :-) )  Also take a look at my previous entry on RPM and various resources.

Comments or questions?  Just contact me via my blog and thanks to all that attended code camp and my session!


Friday, April 06, 2007 10:37:49 PM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  | 

 

Disposable SolidBrush for Compact Framework 1.0#

I've been working on a Compact Framework 1.0 project for a customer and doing some custom control work (yes CF1.0 even though CF3.5 is coming).  I've done a lot of custom controls using Compact Framework 2.0 and have gotten used to the new methods/properties available so going back to 1.0 takes a little bit of getting used to.

That said, I was using a SolidBrush and in CF1.0 it does not implement IDisposable whereas in CF2.0 it does.  At first I ended up with code like this.

SolidBrush brush = new SolidBrush(Color.Black);
//Drawing code here
brush.Dispose();

This will work, but when you have a lot of brushes you are creating it also starts creating a lot of code.  You are probably thinking why not just use the using statment since SolidBrush has a Dispose() method like this.

using (SolidBrush brush = new SolidBrush(Color.Black))
     //Drawing code here

Although in CF1.0 SolidBrush does have a Dispose() method, it does not implement IDisposable so using the using statement is out.  So how do you overcome this?  I created a 'wrapper' to the SolidBrush.  Here is an implementation:

public class SolidBrush2 : IDisposable
{
    private SolidBrush brush;

    public SolidBrush2(Color color)
    {
        this.brush = new SolidBrush(color);
    } 

    public SolidBrush Brush
    {
        get
        {
            return brush;
        }
    }

    #region IDisposable Members

    public void Dispose()
    {
        brush.Dispose();
    }

    #endregion
}

 

You'll notice a few things.  First, our SolidBrush2 class implements IDisposable. Second, we have a private SolidBrush variable that holds the actual SolidBrush object used for drawing.  With this class we can now use using like this:

using (SolidBrush2 brush = new SolidBrush2(Color.Black))
    //Drawing code here

So we eliminated the manual calling of Dispose() by using the using statement (for another example of using statement see here).  Great, but I still wasn't happy.  With the SolidBrush2 implementation we would still have code like this:

using (SolidBrush2 brush = new SolidBrush2(Color.Black))
    e.Graphics.DrawString("Test", this.Font, brush.Brush, 1, 1);

Notice the brush.Brush in the DrawString() method?  If the customer would ever update to CF2.0 (which I'm trying to get them to do) there will be a lot of code to change. If this does happen, first SolidBrush2 would be changed to SolidBrush. Then all the brush.Brush statements would have to be changed to just brush.  This means grunt work for me and wasted money for the customer (since they would pay me for the grunt work). 

implicit operator to the resuce!!  By adding an implicit operator to our SolidBrush2 class we can return the internal SolidBrush member variable.

public static implicit operator SolidBrush(SolidBrush2 sb2)
{
    return sb2.Brush;
}

And when using our SolidBrush2 in a using statement we can get rid of the '.Brush' like so:

using (SolidBrush2 brush = new SolidBrush2(Color.Black))
    e.Graphics.DrawString("Test", this.Font, brush, 1, 1);

The results, cleaner code, less grunt work for me if the customer decides to upgrade CF2.0, and saved money for the customer since all I would have to do is a Find&Replace on SolidBrush2 to SolidBrush.

Here is the final SolidBrush2 implementation:

public class SolidBrush2 : IDisposable
{
    private SolidBrush brush;

    public SolidBrush2(Color color)
    {
        this.brush = new SolidBrush(color);
    }

    public static implicit operator SolidBrush(SolidBrush2 sb2)
    {
        return sb2.Brush;
    }

    public SolidBrush Brush
    {
        get
        {
            return brush;
        }
    }

    #region IDisposable Members

    public void Dispose()
    {
        brush.Dispose();
    }

    #endregion
}
Enjoy!
Friday, April 06, 2007 10:12:21 AM (Eastern Daylight Time, UTC-04:00) #    Comments [0]  | 

 

All content © 2008, Mark Arteaga
Related Sites
Archives
Sitemap
Disclaimer

Powered by: newtelligence dasBlog 1.9.7174.0

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

Send mail to the author(s) E-mail

Theme design by Jelle Druyts