Category: NETCF

  • Building the Latest SDF v1.3 Source

    We get a lot of requests asking for the very latest code for the SDF since tons of exciting stuff has been added (and many issues resolved) since our v1.2 release last year specifically from users starting to work with the VS2005 betas and community previews and would like to use the SDF with these new tools. Firstly just a reminder that the SourceBrowser no longer contains a current record of the source code, which is now maintained in the Vault (Username: guest, Password: guest). From the vault you can see all the latest source files as they are checked in.


    If you need a build which you can use with VS2005 Beta you can download from:-


    http://www.peterfoot.net/files/OpenNETCF.SDF.1.3.50302.zip


    And now the big disclaimer on this build, it’s not a final v1.3 release, it’s not signed with a key pair and so cannot be installed in the GAC on devices, there is no installer, no help content. This should not be used for release purposes (just like VS2005 itself of course) and we offer no support for this build.


    Update: v1.3 is now released, see this post for instructions for using the v1.3 release version in VS2005.


    Please remember if you have any product requests, bug reports etc whether you are using the current tools or VS2005 please post them to our new bug submission page, we are grateful for any feedback to help us make v1.3 our best release yet.

  • Control and Component Designers Part Three – Extending Existing Controls

    Using these techniques it’s possible to extend existing controls and add attributes to improve their designer experience. To illustrate this I’ve taken the example of the ComboBoxEx control. This extends the ComboBox control by overriding runtime behaviour to overcome a data binding issue, and adds BeginUpdate and EndUpdate methods to improve performance when filling the list of items.


    The designer experience for the control inherits the behaviour of the ComboBox control. Since the ComboBox’s own designer excludes some designer support which the control now implements as of Service Pack 2 such as Fore and Back Colors we can add these to our designer and have the designer insert the code to set the colour. The following block of code implements these properties in the design version of the control:-


    #if DESIGN


    [Browsable(true),

    EditorBrowsable(EditorBrowsableState.Always),

    DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

    public new System.Drawing.Color ForeColor

    {

    get

    {

    return base.ForeColor;

    }

    set

    {

    base.ForeColor = value;

    }

    }


    [Browsable(true),

    DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

    public new System.Drawing.Color BackColor

    {

    get

    {

    return base.BackColor;

    }

    set

    {

    base.BackColor = value;

    }

    }

    #endif


    Once built we have a combobox with color support, and because the forms designer in Visual Studio uses a standard ComboBox for drawing it already supports drawing itself with the specified colour.



     


    Part 1 | Part 2 | Part 3 | Part 4

  • Control and Component Designers Part Two – Hanging the Decorations

    How the designer interprets your components is from a mixture of reflection to actually see what properties you expose, but also attributes which allow you to override this behaviour.


    The first attributes which are required for any component to appear in the toolbox are:-


    #if DESIGN

    [ToolboxItemFilter(“NETCF”,ToolboxItemFilterType.Require),

    ToolboxItemFilter(“System.CF.Windows.Forms”, ToolboxItemFilterType.Custom)]

    #endif



    This ensures that the component only appears on the device controls toolbar and not within a desktop project. We wrap this in an if DESIGN block so that the attribute is not added to the runtime control (because the CF assemblies don’t include this attribute). The ToolboxItemFilterAttribute can be found in the System.ComponentModel namespace.


    If you build the libraries now you should be able to add these components to your toolbox. Open a new device project and open a form in the designer, right click the toolbox and select “Add/Remove Items…” then browse to the output of your project e.g. binDesigner once you have added the file and closed the dialog you should have some new entries in your toolbox:-


    In order for the properties pane to work correctly we need to do some further decorating. For most properties you’ll be dealing with fundamental types which visual studio can display automatically. It is a good practise to specify the default values for these fields, in this way if you set the properties to the default it won’t generate code to assign to the property, also the property pane displays non-default values in bold so you can quickly see which have been set to a specific value. The DefaultValueAttribute accepts an object, for example in the case of the ProcessStartInfo the FileName default is an empty string


    #if DESIGN
            [DefaultValue(“”), RecommendedAsConfigurable(true)]
    #endif
            public string FileName


    Some properties will have no meaning at design time such as the Handle property of the Process, using the BrowsableAttribute with a value of false will hide the property


    #if DESIGN

    [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

    #endif

    public IntPtr Handle


    The DesignerSerializationVisibility attribute ensures that this property is excluded from the data serialized to describe your component.


    If you have a property which is of type Object then the designer will have no idea what is valid to assign to this and it will appear greyed out. Some of our components and controls now include a Tag property which allows you to tag an object of any type which may contain supporting data. On the desktop this is exposed as a string, so we do the same in our designer support. At runtime you can still assign any object to this property. We also apply the BindableAttribute which tells the designer that this property may be used in data binding.


    #if DESIGN

    [Bindable(true), DefaultValue((string) null), TypeConverter(typeof(StringConverter))]

    #endif

    public object Tag

     


    Some properties will use other classes which themselves contain multiple properties. A good example is the ProcessStartInfo which is used with the Process class. In order to allow the designer to display this correctly as a nested object we apply the TypeConverterAttribute and give it a value of ExpandableObjectConverter, this allows the designer to populate the property pane with the various properties contained within it.


    #if DESIGN

    [TypeConverter(typeof(ExpandableObjectConverter))]

    #endif

    public sealed class ProcessStartInfo


    We apply the same selection of properties to define the default values for the properties within this class. Now the property pane takes on a logical nested appearance and we can setup all of these properties at design time:-


    To ensure these properties are written out in our code by the designer we need to add the DesignerSerializationVisibilityAttribute:-


    #if DESIGN

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

    #endif

    public ProcessStartInfo StartInfo


    Optionally you can specify categories and descriptions for properties and events. Depending on the user’s preferences the property pane may be shown by category or alphabetically. By default properties are added to the “Misc” category. The grey box below the actual property list will show a short description as defined by the DescriptionAttribute as used here in the BackgroundWorker class.


    #if DESIGN

    [Category(“Asynchronous”),

    Description(“Event handler to run on a different thread when the operation begins.”)]

    #endif

    public event DoWorkEventHandler DoWork;


    Part 1 | Part 2 | Part 3 | Part 4

  • Control and Component Designers Part One – Building for Design Time

    Introduction


    When developing desktop .NET forms projects the toolbox contains a number of components you can drag across to your form and setup via the designer. A component in this case is any class which inherits from System.ComponentModel.Component. Visual Studio generates the appropriate code for you, in just the same way as forms controls except your components sit in a tray below your form.


    Over the past few versions of the SDF we have steadily built up a number of components which directly match those available on the desktop, so I decided it would be great to offer exactly the same designer experience.


    There are two key points to design time controls, firstly they are compiled against the full .NET framework (since that is what Visual Studio’s form designer uses), secondly they include a number of special attributes to setup the correct behaviour of the component and the properties window.


    Setting Up the Build Process


    There are two ways to build your designer assembly, either via the command line usually by building a batch file to call the C# compiler with your code files (That’s correct no VB.NET design time controls at this stage) this article was probably the first to describe this process and is still just as relevant today. The other way is to create a desktop Class Library project type and insert your existing code files.


    This is the approach I took this time as I’ve used command line build before and fancied a change. I started with a Solution which contains all the affected SDF assemblies – OpenNETCF, OpenNETCF.Drawing, OpenNETCF.Windows.Forms and OpenNETCF.WindowsCE.Forms. OpenNETCF.Drawing exposes no designable types but is used by the two forms assemblies. Within this solution file I created 5 new desktop Class Library projects – OpenNETCF.CF, OpenNETCF.CF.Drawing, OpenNETCF.CF.Windows.Forms and OpenNETCF.CF.WindowsCE.Forms, I then removed these new projects from the solution and moved the project files (.csproj) into the respective folder with their device equivalent (note that device projects have the .csdproj extension). I then opened each of the runtime projects in a text editor and copied all the entries into the design time projects. Finally back in Visual Studio I add these new desktop projects into the same solution. Next in order to allow both sets of files to build side-by-side I create a new configuration for the project called “Designer”. Then in my default “Debug” configuration for the entire solution I set the design time projects (OpenNETCF.CF.*) to use the Designer configuration and all the runtime projects to use the Debug configuration.


    Next I go into the project properties for each of the design time libraries and set the output folder to binDesigner and set a conditional compilation constant for “DESIGN”. We have already used this constant for previous versions when adding designer support to the controls so this already makes much of the libraries “designer safe”.


    These OpenNETCF libraries include dependencies to each other so OpenNETCF.CF.Drawing requires a reference to OpenNETCF.CF, OpenNETCF.CF.Windows.Forms requires a reference to both these and so on. These references are easily added with the Add Reference dialog and switching to the Projects pane. Next each of the design time projects needs a couple of standard references to the .NETCF designer assemblies:-



    • System.CF.Design
    • System.CF.Drawing
    • System.CF.Windows.Forms

    Additionally a reference to Microsoft.CF.WindowsCE.Forms was required in OpenNETCF.CF.WindowsCE.Forms since InputPanelEx derives from InputPanel. All of these designer assemblies is found within the Visual Studio installation e.g.


    C:Program FilesMicrosoft Visual Studio .NET 2003CompactFrameworkSDKv1.0.5000Windows CEDesigner


    The advantage of going through all these hoops is that both the design time and runtime projects point to exactly the same source code and you can build both assemblies from within your visual studio solution.


     


    Designer Support


    For each component or control which is exposed to the toolbox an image is required. This should be a 16×16 bitmap with the name of the control including full namespace e.g.


    OpenNETCF.Diagnostics.Process.bmp


    This is added to the design time project as an Embedded Resource in the root of the project (otherwise folder names are added to the resource name). We could try building the solution now, and will probably come across errors.


    A quick way to simplify the process is to remove any code files which are not required by any of your designable components, alternatively you could exclude entire files or code blocks from the design time build process by encapsulating them in if blocks using the compilation constant we setup e.g.


    #if !DESIGN

    public class NativeStuffWeDontNeedAtDesignTime

    {

    }

    #endif


    Concentrating on our components you can actually be quite ruthless with this conditional compilation as long as you expose the public properties which will be displayed in the properties window in the designer. Once you have successfully built the whole solution you’ll have a full set of runtime and design time assemblies, however they are not ready just yet as with all new builds they need decorating before we can move in…


    Part 1 | Part 2 | Part 3 | Part 4

  • Determine Current GSM Network

    This VB.NET code will work on Smartphone and Pocket PC Phone devices and return details of the current GSM operator (though it probably works on CDMA also). It relies on Alex Feinman’s excellent TAPI wrapper whish you can download here. Using the library we create a line object which we pass the handle of (line.hline) into lineGetCurrentOperator, one of the ExTAPI functions. For simplicity the structure is just passed as one big byte array then the strings are copied out from it and have trailing nulls chopped off.


    ‘gets the textual representation of the operator
    Public Function GetCurrentOperator(ByVal line As OpenNETCF.TAPI.Line) As Operator
    Dim result As Integer
    Dim nullindex As Integer

    ‘stores operator details
    Dim lo As New Operator

    Dim buff(140) As Byte

    ‘copy LINEOPERATOR_USEFIRSTAVAILABLEINDEX to struct
    BitConverter.GetBytes(-1).CopyTo(buff, 0)

    ‘call tapi method
    result = lineGetCurrentOperator(line.hLine, buff)

    If result < 0 Then
    ‘error encountered
    Throw New System.Runtime.InteropServices.ExternalException(“TAPI Error getting operator: “ + result.ToString())
    End If

    ‘index
    lo.Index = BitConverter.ToInt32(buff, 0)
    ‘get status
    lo.Status = BitConverter.ToInt32(buff, 4)
    ‘get valid fields
    lo.ValidFields = CType(BitConverter.ToInt32(buff, 8), OperatorFormat)



    ‘long name
    If (lo.ValidFields And OperatorFormat.AlphaLong) = OperatorFormat.AlphaLong Then
    lo.LongName = System.Text.Encoding.Unicode.GetString(buff, 12, 64)
    nullindex = lo.LongName.IndexOf(Chr(0))
    If nullindex > -1 Then
    lo.LongName = lo.LongName.Substring(0, nullindex)
    End If
    End If


    ‘copy short name
    If (lo.ValidFields And OperatorFormat.AlphaShort) = OperatorFormat.AlphaShort Then
    lo.ShortName = System.Text.Encoding.Unicode.GetString(buff, 76, 32)
    nullindex = lo.ShortName.IndexOf(Chr(0))
    If nullindex > -1 Then
    lo.ShortName = lo.ShortName.Substring(0, nullindex)
    End If
    End If

    ‘copy num name
    If (lo.ValidFields And OperatorFormat.Numeric) = OperatorFormat.Numeric Then
    lo.NumName = System.Text.Encoding.Unicode.GetString(buff, 108, 32)
    nullindex = lo.NumName.IndexOf(Chr(0))
    If nullindex > -1 Then
    lo.NumName = lo.NumName.Substring(0, nullindex)
    End If
    End If

    Return lo

    End Function

    Declare Function lineGetCurrentOperator Lib “cellcore.dll” (ByVal hLine As IntPtr, ByVal operator As Byte()) As Integer

    Public Class Operator

       Public Index As Integer
       Public ValidFields As OperatorFormat
       Public Status As Integer
       Public LongName As String
       Public ShortName As String
       Public NumName As String

    End Class

    _
    Public Enum OperatorFormat
       None = &H0
       AlphaShort = &H1
       AlphaLong = &H2
       Numeric = &H4
    End Enum


     

  • FolderBrowserDialog for Windows CE

    To follow up from a recent enquiry on the newsgroup, neither .NETCF v1.0 or v2.0 include the FolderBrowserDialog component. The main reason for this is that this functionality is not implemented in all flavours of Windows CE, for example Windows Mobile (Pocket PC / Smartphone) doesn’t include support for this dialog. If your device does support this shell feature then here is a simple wrapper I wrote which wraps the SHBrowseForFolder API in a FolderBrowserDialog class, which mimics the desktop equivelent. The code is packaged with a quick three line demonstration using the dialog. This works on the CE.NET 4.1 Emulator shipped with Visual Studio 2003.


    Download InTheHand.Windows.Forms.FolderBrowserDialog.zip


    If your platform is unsupported the control will throw a PlatformNotSupportedException when you call ShowDialog(). If you want to create this kind of functionality on Windows Mobile then a good starting point is the code accompanying this article at MSDN.

  • Bluetooth Remote Control

    Mike Hall posted a link on his blog to a channel9 interview with Anil Dhawan from the Windows Mobile team discussing Bluetooth programming, which I recommend you check out. Anil gave a demo of a native code application to remote control PowerPoint on a desktop PC. This inspired me to put some finishing touches to a test application I built for the Bluetooth .NETCF library – It is by no means finished but it works (with the wind blowing in the right direction!).


    There are two components, on the Smartphone an application which you first select Search from the menu and it will do a lookup of local discoverable devices, then select one and select the Connect menu option. Once connected any d-pad or number keys are captured and sent over bluetooth. As I said it was an unfinished project, key items missing are:-



    • Store desktop address in the registry so we only have to search once

    • More intuitive interface 🙂

    • Support for key mapping – map the device keys to application specific commands e.g. for media player etc

    On the desktop a simple listener which listens on a custom service, incoming data is received as keycodes which are broadcast on the system using the SendKeys.Send method.


    On an unrelated note, thanks to Sergey Bogdanov who has contributed an implementation of the SendKeys class to be included in the upcoming SDF v1.3 release.


    With the listener application running and the Smartphone client connected you can automate (within reason) whatever app has the focus. It works great for Powerpoint browsing between slides using the d-pad on the phone. The usual disclaimer applies – this works only with the Microsoft Bluetooth stack on both device and desktop, I tested with an Orange SPV C500.


    The two projects are available to download here.

  • Patterns & Practices Survey

    Announced on Jono’s blog the Patterns & Practices team are looking at what guidance they can provide for device development. They have now setup a formal online survey to capture your wishes and needs, so I recommend you stop by and add your thoughts:-


    Fill in the survey


    Personally I’d like to see some kind of Power Management application block and accompanying guidelines produced, along with the obvious choice of a port of the Smart Client Offline block.

  • Upcoming .NETCF Chat

    Tomorrow the .NETCF MVPs will be hosting a developer chat at MSDN. Start time is 10am PST (6pm GMT). As usual any questions related to .NETCF, Smart Device Development or OpenNETCF are welcome. Full details along with other upcoming chats on a whole raft of topics can be found at:-


    http://msdn.microsoft.com/chats


     

  • Bluetooth Library (February Edition)

    Not a huge amount of change since last months release but I just wanted to post the latest update. The download includes the same Chat application samples along with the complete solution for the library itself.


    Downloads


    The main changes in this release are:-



    • BluetoothRadio class which handles the radio state on a single or multiple radio device. Multiple radios are only supported on XP, Windows CE supports a single radio device.
    • BluetoothSecurity class which has a couple of methods to automate the pairing (bonding) process between devices. Using SetPin and RevokePin you can specify the PIN to use with a particular remote device. Using PairRequest you can force the device to intiate a connection and bond with the remote device with the specified PIN code. Currently the BluetoothSecurity class is built for Windows CE only, in a future update this functionality will be extended to run on the desktop too.
    • General housekeeping – P/Invokes have been moved into a single NativeMethods class and a few new ones added, though not all are used by the library yet.

    Online documentation for this build can be browsed here.