Category: NETCF

  • Happy Birthday .NET

    Happy Birthday .NET

    .NET is 20 years old this month. I can remember when I first encountered .NET and C# and found it a great step forward from Visual Basic and the C++ and Java I had learned at university. However, what really changed things for me was due to some very chance encounters I had ended up working with mobile phones (remember WAP browsers?) and in the process had come across the Pocket PC. I began working with embedded Visual Basic (eVB) and I found I could create applications that you could carry around in your pocket. I bought myself a chunky Compaq iPaq with an add on sleeve for a Compact Flash memory card – plenty of space for an app or three.

    When the .NET Compact Framework Beta came around this was a game changer – a subset of the .NET Framework with the same Visual Studio tools including a drag and drop designer for the subset of WinForms and an “emulator”. Because .NETCF code was retargetable you could use your .NETCF dll on the desktop and share code across platforms.

    Happy 20th Birthday .NET!

    Of course the Compact Framework didn’t hit RTM until later in 2002 but I was soon hooked. Although v1.0 was very basic (the base class library was quite small and there was no COM interop) the ability to interop with native code via P/Invoke meant it was possible to add functionality using a C++ wrapper. My first commercial library for .NET CF was an interop layer for ADOCE – the COM based data API around the built-in “Pocket Access” database engine. This replicated the ADO.NET System.Data APIs with the built-in database rather than adding the more complex SQLCE database engine saving a few megabytes of space and making use of ActiveSync’s Pocket Access sync engine. I went on to create a library around Pocket Outlook to access Calendar, Contacts and Tasks (and later Email) in a similar way. It wasn’t until several years later with Windows Mobile 5.0 that Microsoft provided a .NET API for this functionality.

    The first Microsoft Mobility Developer Conference after the release of .NETCF 1.0 was in March 2003 in New Orleans and was closely followed by the European version at Disneyland Paris of all places. The event continued annually for a number of years, morphing into the Mobile and Embedded Developer Conference (MEDC) covering .NETCF, Windows CE, Pocket PC, Windows Mobile and the .NET Framework’s even smaller relation – the .NET Micro Framework.

    Microsoft Mobility Developer Conference 2003 Post-Conference DVD
    Microsoft MDC 2003

    The .NET Compact Framework got me into being an MVP too. I created a number of open source libraries, one of these (32feet.NET) has continued forward to this day adding in functionality and modernising (but still supporting Infrared data transfer!). Many others were part of a suite created by a group of like-minded MVPs called OpenNETCF. We created APIs to fill in many of the gaps in the .NET Compact Framework as well as add functionality relevant to mobile developers.

    OpenNETCF members at the MVP Summit 2004.
    OpenNETCF – MVP Summit 2004

    I had the opportunity to write a book, The Microsoft Mobile Development Handbook, with two fellow MVPs – Daniel Moth and Andy Wigley. It was released in 2007 and covered all aspects of developing mobile apps using .NET.

    Peter Foot, Daniel Moth and Andy Wigley at Tech Ed 2007 Barcelona

    The .NET Compact Framework continued along for some time behind the scenes – it was used in Windows Phone (Versions 7 and 8 were based on Windows CE) although because of the stricter sandbox you couldn’t access the underlying APIs as before. Windows Phone 8.1 was re-worked to use the desktop OS and introduced the strange world of two different app models – Silverlight from Windows Phone 7 and the Windows 8 (WinRT) model which has developed into what we see in Windows 10 and 11 today.

    In order to build for Android and iOS, we had Xamarin using the Mono framework to provide a comparable .NET runtime. Again we have the ability to share .NET code across multiple platforms and with Xamarin Forms/MAUI and Uno we have the ability to share UI too.

    While a lot has changed in the last 20 years, the ability to create apps across mobile and desktop platforms is still recognisable even though what we have now is much more powerful. I still believe that having had to design code for tiny processors, dodgy networks and limited pixels has been immensely helpful in how to approach any mobile development today.

    There will be a live broadcast on 14th February to celebrate the special occasion.

  • .NETCF 3.5 Breaking Changes

    I came across this useful list of breaking changes in the .NETCF 3.5 runtime and thought I’d blog it here before I lose the URL:-

    http://msdn.microsoft.com/en-us/netframework/bb986636.aspx

  • Antialisasing and .NETCF

    On the newsgroup, a developer asked if it was possible to use antialiasing on a Label font. By default on Windows Mobile the text does not use antialiasing unless you turn on the global ClearType option under Settings > System > Screen > ClearType. The platform has the capability to smooth fonts, we just need an easy way to specify the quality from our code. The System.Drawing.Font class doesn’t support this directly, but Microsoft.WindowsCE.Forms contains a wrapper for the native LOGFONT structure in the LogFont class. There is a static method on the Font class of FromLogFont(object o) which when passed a Microsoft.WindowsCE.Forms.LogFont will draw the font with the specified options. The following code shows setting three labels with default quality, antialiasing and cleartype, the following screen grab shows the result from my device screen:-Microsoft.WindowsCE.Forms.LogFont lf = new Microsoft.WindowsCE.Forms.LogFont();lf.FaceName = “Tahoma”;


    lf.Height = 48;


    lf.Quality = Microsoft.WindowsCE.Forms.LogFontQuality.Default;


    label1.Font = Font.FromLogFont(lf);


    Microsoft.WindowsCE.Forms.LogFont lf2 = new Microsoft.WindowsCE.Forms.LogFont();


    lf2.FaceName = “Tahoma”;


    lf2.Height = 48;


    lf2.Quality = Microsoft.WindowsCE.Forms.LogFontQuality.AntiAliased;


    label2.Font = Font.FromLogFont(lf2);


    Microsoft.WindowsCE.Forms.LogFont lf3 = new Microsoft.WindowsCE.Forms.LogFont();lf3.FaceName = “Tahoma”;


    lf3.Height = 48;


    lf3.Quality = Microsoft.WindowsCE.Forms.LogFontQuality.ClearType;


    label3.Font = Font.FromLogFont(lf3);


  • Exception Messages on .NETCF v3.5

    Martijn Hoogendoorn provides a description of how to avoid the message:-


    An error message is available for this exception but cannot be displayed because these messages are optional and are not currently installed on this device. Please install ‘NETCFv35.Messages.EN.wm.cab’ for Windows Mobile 5.0 and above or  ‘NETCFv35.Messages.EN.cab’ for other platforms. Restart the application to see the message.


    Even if you have installed the cab file with message resources. A useful link:-


    http://blogs.msdn.com/martijnh/archive/2008/01/03/fixing-exception-messages-on-the-net-compact-framework-3-5.aspx

  • How To: Get System Power State Name and Flags

    A question came up on our forums and so I investigated writing a wrapper for the GetSystemPowerState API function. This allows you to retrieve the power state name, and also a bitmask of flags – Is the backlight on, is the device password protected etc. This is the result in VB.NET. We will add it to the wish list for the next version of the library.


    <DllImport(“coredll.dll”)> _
    Public Shared Function GetSystemPowerState(ByVal pBuffer As System.Text.StringBuilder, ByVal Length As Integer, ByRef pFlags As PowerState) As Integer
    End Function

    <Flags()> _
    Public Enum PowerState
    [On] = &H10000 ‘// on state
    Off = &H20000 ‘ // no power, full off
    Critical = &H40000 ‘// critical off
    Boot = &H80000 ‘ // boot state
    Idle = &H100000 ‘ // idle state
    Suspend = &H200000 ‘ // suspend state
    Unattended = &H400000 ‘ // Unattended state.
    Reset = &H800000 ‘ // reset state
    UserIdle = &H1000000 ‘ // user idle state
    BackLightOn = &H2000000 ‘ // device screen backlight on
    Password = &H10000000 ‘ // This state is password protected.
    End Enum


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim sb As New System.Text.StringBuilder(260)
    Dim flags As PowerState = 0
    Dim ret As Integer = GetSystemPowerState(sb, sb.Capacity, flags)

    TextBox1.Text = sb.ToString()
    TextBox2.Text = flags.ToString()
    End Sub


    The last method is just a very simple example of calling the function and displaying the result.

  • How To: Programmatically Scroll Controls

    A number of controls within .NETCF have built in ScrollBars. Occasionally you may want to operate these programmatically on behalf of the user. When you do this you want both the control to scroll and the scrollbars to correctly reflect the current position. Faced with this requirement I found a solution in the WM_VSCROLL (and equivalent HSCROLL) message. You can send this message to the native handle of your control along with a number of present constants to offer hands-free scrolling. Along the way I discovered that to work you must have the handle of the native control which implements the scroll bars. In the case of the WebBrowser this is a grand-child of the outer managed control so we have to use the native GetWindow API call to get down to the right HWND. I wrapped this up in a class I’ve called ScrollBarHelper which allows the user to move left, right, up and down. The code for the class is:-


    /// <summary>
    /// Helper class to programmatically operate scrollbars.
    /// </summary>
    public class ScrollBarHelper
    {
      private IntPtr handle;


      public ScrollBarHelper(Control c)
      {
        if (c is WebBrowser)
        {
          //special case for complex control
          //get the inner IE control
          IntPtr hInternetExplorer = NativeMethods.GetWindow(c.Handle, NativeMethods.GW.CHILD);
          //get the first child (status bar)
          IntPtr hStatus = NativeMethods.GetWindow(hInternetExplorer, NativeMethods.GW.CHILD);
          //get the html body area
          handle = NativeMethods.GetWindow(hStatus, NativeMethods.GW.HWNDNEXT);
        }
        else
        {
          handle = c.Handle;
        }
      }



    public void LineRight()
    {
      SendMessage(NativeMethods.WM_HSCROLL, NativeMethods.SB_LINEDOWN);
    }
    public void LineLeft()
    {
      SendMessage(NativeMethods.WM_HSCROLL, NativeMethods.SB_LINEUP);
    }

    public void PageRight()
    {
      SendMessage(NativeMethods.WM_HSCROLL, NativeMethods.SB_PAGEDOWN);
    }
    public void PageLeft()
    {
      SendMessage(NativeMethods.WM_HSCROLL, NativeMethods.SB_PAGEUP);
    }

    public void LineDown()
    {
      SendMessage(NativeMethods.WM_VSCROLL, NativeMethods.SB_LINEDOWN);
    }
    public void LineUp()
    {
      SendMessage(NativeMethods.WM_VSCROLL, NativeMethods.SB_LINEUP);
    }

    public void PageDown()
    {
      SendMessage(NativeMethods.WM_VSCROLL, NativeMethods.SB_PAGEDOWN);
    }
    public void PageUp()
    {
      SendMessage(NativeMethods.WM_VSCROLL, NativeMethods.SB_PAGEUP);
    }

    private void SendMessage(int msg, int value)
    {
      Microsoft.WindowsCE.Forms.Message m = Microsoft.WindowsCE.Forms.Message.Create(handle, msg, (IntPtr)value, handle);
      Microsoft.WindowsCE.Forms.MessageWindow.PostMessage(ref m);
    }

    [DllImport(“coredll.dll”)]
    internal static extern IntPtr GetWindow(IntPtr hWnd, GW uCmd);

    internal enum GW : int
    {
      HWNDFIRST = 0,
      HWNDLAST = 1,
      HWNDNEXT = 2,
      HWNDPREV = 3,
      OWNER = 4,
      CHILD = 5,
    }

    //scrollbar messages
    internal const int WM_HSCROLL = 0x0114;
    internal const int WM_VSCROLL = 0x0115;

    //constants for scrollbar actions
    internal const int SB_LINEUP = 0;
    internal const int SB_LINEDOWN = 1;
    internal const int SB_PAGEUP = 2;
    internal const int SB_PAGEDOWN = 3;

    }


    In order to use the control you create a new instance passing it the control of your choice. Then call methods to scroll the control e.g.


    private ScrollBarHelper wsbh;
    private ScrollBarHelper tsbh;

    private void Form1_Load(object sender, EventArgs e)
    {
      wsbh = new ScrollBarHelper(webBrowser1);
      tsbh = new ScrollBarHelper(textBox1);
    }


    private void button1_Click(object sender, EventArgs e)
    {
      tsbh.PageUp();
    }


    The control contains methods to Scroll via single lines or pages at a time, I didn’t get around to looking at setting the explicit value of the scrollbar control, but this should be possible also – refer to the documentation for WM_VSCROLL for how to pass the value.

  • HttpWebRequest Exceptions under .NETCF

    While testing code using HttpWebRequest it can be observed in the debug output that a number of exceptions are thrown within the GetResponse call of a HttpWebRequest. If you run exactly the same code on the desktop you don’t see this behaviour. For reference the following is a simple example which displays the issue:-


    System.Net.WebRequest request = System.Net.WebRequest.Create(http://www.microsoft.com&#8221;);
    System.Net.WebResponse webResponse = request.GetResponse();
    webResponse.Close();


    Since the exceptions are caught it doesn’t stop the code from running but I considered it annoying enough to investigate and try to find the cause. Here is the typical output during the call to GetResponse:-


    A first chance exception of type ‘System.IO.IOException’ occurred in mscorlib.dll
    A first chance exception of type ‘System.UriFormatException’ occurred in System.dll
    The thread 0x577c6eaa has exited with code 0 (0x0).
    The thread 0xaf16af8a has exited with code 0 (0x0).
    A first chance exception of type ‘System.UriFormatException’ occurred in System.dll
    The thread 0x577c6eaa has exited with code 0 (0x0).
    The thread 0xaf16af8a has exited with code 0 (0x0).
    The thread 0xaf399a02 has exited with code 0 (0x0).


    I eventually tracked it down to an issue with WebProxy. It occurs if you do not specify a Proxy or use the system proxy:-


    request.Proxy = System.Net.GlobalProxySelection.Select;


    If you won’t be using a proxy you can set the Proxy property to an empty WebProxy:-


    request.Proxy = System.Net.GlobalProxySelection.GetEmptyWebProxy();


    After making this change you’ll see the method progress without any exceptions – you’ll just see the 5 thread exit notifications in the output. Whether or not this makes a noticeable difference to performance I have yet to discover but it does indicate an underlying issue since the desktop has no such problem.

  • Determine Platform – .NETCF 3.5 and earlier

    One of the new features in v3.5 of the Compact Framework is the ability to easily detect the platform you are running on from Smartphone (Standard Edition), PocketPC (Classic or Professional Editions) or WinCEGeneric (Everything else). The code is very straight-forward:-


    using Microsoft.WindowsCE.Forms;

    if(SystemSettings.Platform == WinCEPlatform.Smartphone)
    {
       //do something smartphone specific…
    }

     


    In the latest (v3.0) version of Mobile In The Hand I’ve implemented a matching property, so for the above code sample you’d just change the using statement to use InTheHand.WindowsCE.Forms and the code would work the same way. This is available in both the .NETCF v1.0 and v2.0 builds of the library.

  • New Networking Component

    In The Hand Ltd today released Networking In The Hand, a developer library for the .NET Compact Framework 2.0 and 3.5 Beta. This library adds additional networking functionality not found in in the Compact Framework while matching the object model used in the full .NET framework to make it easy to share your code between platforms. Functionality includes:-




    • InTheHand.Net.WebClient – Provides helper methods for working with information upload and download over HTTP and FTP transports, and any other WebRequest based implementations.


    • InTheHand.Net.FtpWebRequest – Provides a complete desktop compatible implementation of the WebRequest pattern for FTP.


    • InTheHand.Net.WebRequestMethods – Provides a reference of all the HTTP and FTP methods (GET/POST etc)


    • InTheHand.Net.NetworkInformation.Ping – Perform a Ping and determine network availability and performance.


    • InTheHand.Net.NetworkInformation.IPGlobalProperties – Retrieve a wide range of networking statistics to measure traffic and help identify faults.

    The library is licensed on a per-developer basis with no additional royalties required to distribute the runtime with your applications. Full details on the product can be found on the product details page – https://inthehand.com/content/Networking.aspx. A fully functionality Evaluation version is available to download – https://inthehand.com/wp-content/uploads/folders/evals/entry4014.aspx.

  • System.Media.SoundPlayer versus the PlaySound API

    In .NETCF v3.5 there is a new namespace – System.Media which brings audio support to the Compact Framework. Previously the common way to add sounds to your application was to use the PlaySound API (either P/Invoking yourself or using one of many wrappers). Now that the framework itself has built-in support, which matches the desktop .NET v2.0 framework it makes sense to standardise on the SoundPlayer component.


    There are some differences in behaviour which you’ll need to be aware of. When you specify a filename this doesn’t simply call through to the native APIs passing the filename, the file is first loaded into memory and then the WaveOut APIs are used to play it. This means that if you simply create a new SoundPlayer and call Play the file will not be loaded, the Play method will have to first load the file contents, and then play the sound. This will create a noticable delay before the sound is heard. The class allows you to load the file at any time prior to calling play – you can use either Load or LoadAsync to do this. Once the file is loaded the Play method will be able to immediately begin playing the file. Exactly where you call the Load/LoadAsync method will depend on your application design. Keeping a large audio file cached will tie up valuable memory, you should dispose of the SoundPlayer instance once you have finished with it.