# Friday, March 13, 2009

.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

#    |
# Wednesday, April 02, 2008

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);

#    |
# Thursday, March 06, 2008

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

#    |
# Saturday, February 23, 2008

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.

#    |
# Tuesday, February 12, 2008

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.

#    |
# Wednesday, January 09, 2008

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");
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.

#    |
# Friday, November 23, 2007

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.

#    |
# Friday, September 21, 2007

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 - http://inthehand.com/content/Networking.aspx. A fully functionality Evaluation version is available to download - http://inthehand.com/files/folders/evals/entry4014.aspx.

#    |
# Tuesday, August 21, 2007

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.

#    |
# Friday, July 27, 2007

Multiline Button

On the newsgroup somebody asked how to have multiple lines of text on a .NETCF Button control. The native control supports this but the appropriate style is not set by default. The following code snippet shows how to enable this:-

private const int BS_MULTILINE = 0x00002000;
private const int GWL_STYLE = -16;

[System.Runtime.InteropServices.DllImport("coredll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

[System.Runtime.InteropServices.DllImport("coredll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

public static void MakeButtonMultiline(Button b)
{
    IntPtr hwnd = b.Handle;
    int currentStyle = GetWindowLong(hwnd, GWL_STYLE);
    int newStyle = SetWindowLong(hwnd, GWL_STYLE, currentStyle | BS_MULTILINE);
}

The usage is simple, just pass the specific Button control to MakeButtonMultiline:-

MakeButtonMultiline(button1);

Here is what the amended button looks like on the left (default appearance on the right)

The designer fully supports entering multiple lines for the Button Text property, just click the dropdown at the end of the field and it will pop up a window into which you can add linebreaks with your text.

#    |
# Tuesday, July 24, 2007

More Facebook Progress

I'm now a member of the CodePlex workspace for the Facebook Developer Toolkit. I've been working on porting across my modifications into the codebase. The .NETCF v2.0 version uses a project called Facebook.Compact but refers to the existing source files from the desktop project. Then some conditional compilation is used to hide a few unsupported features from .NETCF and implement some workarounds for missing functionality. This will be a familiar technique if you've been to Daniel's sessions (or read his blog posts on the subject). It's not quite working yet since my code made use of a couple of my own libraries for speed, so I'll need to implement a few of the features within those in the Facebook.Compact project.

#    |
# Friday, July 20, 2007

Facebook API and the Compact Framework

The Facebook API allows third-party web and desktop applications to interact with Facebook features. There is an excellent shared-source library for .NET to wrap the Facebook calls but currently it only supports the full framework. I did some work converting this source to compile and run on .NETCF v2.0. There are some example screens here of the login process, and pulling back information about our book group.

   

Since the login screen uses the same page as the desktop it's not a great fit on a Pocket PC screen, so that's an area for improvement.

#    |
# Monday, June 25, 2007

Guid.NewGuid Performance

João Paulo was investigating Guid performance when used as identifiers in a SQL Compact database and discovered that the performance of Guid.NewGuid() left a lot to be desired. The reason for this is that the function uses lowest-common-denominator support, using a random number generator and setting a couple of specific bits to conform to guid standards. Another method I've been recommending for some time is to use the native CoCreateGuid() function - see http://www.peterfoot.net/NeedAGUIDInAHurry.aspx. This method is supported in all devices running Windows Mobile 2003 and above, and in Windows CE 4.x. I've been using it in the InTheHand.Guid2 class in Mobile In The Hand (Will be renamed to GuidHelper in the next version). I did some tests creating 100,000 guids in a row with both methods. Guid.NewGuid() took 139 seconds, and GuidHelper.NewGuid() took a mere 9 seconds. As you can see that is quite a significant difference.

#    |
# Monday, May 14, 2007

Waiting for a Process

There have been numerous occasions where I've needed to write code to launch another process and wait for it to complete, usually taking some action based on the exit code. Therefore I've got a handy helper method to do this. It has changed a few times and is made much simpler in .NETCF v2.0 by taking advantage of the Process class. Most recently I used the code in one of the book chapters to show automatic installation of the Microsoft Message Queue (MSMQ) components onto a Windows Mobile device. The method is named ShellWait, as the name implies it launches a process and waits, the return value is the exit code from the process. If the application doesn't exist it returns -1 immediately.

[C#]

//helper function to launch a process and wait for the result code
private static int ShellWait(string app, string args)
{
   if (!File.Exists(app))
   {
      return -1;
   }


   Process p = Process.Start(app, args);
   p.WaitForExit();


   return p.ExitCode;
}

 

[VB]

Private Shared Function ShellWait(ByVal app As String, ByVal args As String) As Integer
   If Not File.Exists(app) Then
      Return -1
   End If

   Dim p As Process = Process.Start(app, args)
   p.WaitForExit()

   Return p.ExitCode
End Function

#    |
# Tuesday, May 01, 2007

New Sounds sample in Windows Mobile 6 SDK Refresh

The Windows Mobile 6 SDK Refresh is available today. It includes some documentation enhancements and new samples. One of these is called RingtoneManager and is a C# application which wraps all the Sound APIs for ringtone management and sound playback, the latter of which were introduced with Windows Mobile 6. This is great because it gives you all the P/Invokes etc you need to use this functionality yourself. However expect to see these Windows Mobile specific APIs in the next version of Mobile In The Hand.

#    |
# Monday, March 26, 2007

TomTom In The Hand 6.1

I've been a bit quiet over the past few weeks, on vacation and at the Microsoft MVP Summit. I've also been working on the TomTom In The Hand library and today have released a new version.

It turns out that TomTom SDK 6 shipped with a known bug that prevents you from passing negative co-ordinates into any of the methods (returned values were okay). At the moment I believe that our library is the only one which has a fix for this bug which was a major headache for developers. You can now use TomTom through this library wherever you reside in the world (assuming you have map coverage of course) without making any changes to your existing code.

This release also adds some new functionality - The RawGpsReceived event on the Navigator object allows you to receive NMEA data from TomTom which allows you to share this data if you are not already using a multiplexer such as the Windows Mobile 5.0 GPS service or Franson GPS Gate or similar.

#    |
# Monday, February 26, 2007

Programmatically Activating Speakerphone

Windows Mobile devices, both Smartphone and Pocket PC support Speakerphone functionality. When operating through the Phone application the end user can toggle the state, up until now there has been no documented way to achieve this through code. Last year I investigated the issue on behalf of one of my readers and failed on several attempts at simulating a press-and-hold of the green phone button. It turns out that the device issues a specific key constant to change the state, and this can be simulated through code. It also turns out that the constant is equivalent to VK_F16 (thats Keys.F16 for managed code). I've wrapped up the necessary P/Invoke into the following code:-

public sealed class SpeakerPhone
{
private SpeakerPhone() { }

/// <summary>
/// Toggles the SpeakerPhone state.
/// </summary>
public static void Toggle()
{
//keydown
NativeMethods.keybd_event((byte)Keys.F16, 0, 0, 0);
//keyup
NativeMethods.keybd_event((byte)Keys.F16, 0, NativeMethods.KEYEVENTF_KEYUP, 0);
}

internal static class NativeMethods
{
internal const int KEYEVENTF_KEYUP = 0x0002;


[System.Runtime.InteropServices.DllImport("coredll.dll")]
internal static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
}
}

 

Since this just toggles the state, you can't determine the current state at any particular time. This code has been tested on Windows Mobile 5.0 and beyond (It possibly works on Windows Mobile 2003 but I haven't tested), it doesn't work on the Windows Mobile 5.0 Emulators as Speakerphone isn't implemented. I was able to establish a call on speakerphone using the following code:

Microsoft.WindowsMobile.Telephony.Phone p = new Microsoft.WindowsMobile.Telephony.Phone();
p.Talk("01234567890");
SpeakerPhone.Toggle();

Once the call is ended the speakerphone state is restored on subsequent calls.

#    |
# Wednesday, February 21, 2007

Richard Jones is Blogging

Richard has just started blogging, starting with a sample for maximising screen space by creating a Vista style textbox with integral label, and a description of what he has been up to in the fight against "Monkey Code". I've subscribed to his RSS feed and added him to the blogroll.

#    |
# Wednesday, February 14, 2007

What's New For Managed Developers In Windows Mobile 6 (Part 2)

When I previously posted the list of additional system properties I was using the Windows Mobile 6 SDK Documentation as a reference. Well it turns out that there are even more new properties, you can view them using Object Browser in your project but they aren't included in the documentation. The other new properties are:-

  • CameraEnabled - This in addition to existing CameraPresent property
  • CellularSystemAvailable1xrtt
  • CellularSystemAvailableEdge
  • CellularSystemAvailableEvdo
  • CellularSystemAvailableEvdv
  • CellularSystemAvailableGprs
  • CellularSystemAvailableHsdpa
  • CellularSystemAvailableUmts
  • CellularSystemConnected1xrtt
  • CellularSystemConnectedEdge
  • CellularSystemConnectedEvdo
  • CellularSystemConnectedEvdv
  • CellularSystemConnectedGprs
  • CellularSystemConnectedHsdpa
  • CellularSystemConnectedUmts
  • ClamshellClosed
  • DeviceLocked
  • KeyLocked
  • LockStates - A combination of flags for Device, Key and Sim locks
  • SimLocked
  • PhoneTalkingCallStartTime

 

#    |
# Wednesday, January 10, 2007

SQL Server Compact Edition - Coming Tomorrow

Excellent news from the SQL Server Everywhere blog (those guys need to change the name of their blog again :-)). Tomorrow the runtimes and tools for SQL Server Compact Edition will be released to the web. It will replace the RC1 download so the link will remain the same:-

http://www.microsoft.com/downloads/details.aspx?FamilyID=85E0C3CE-3FA1-453A-8CE9-AF6CA20946C3&displaylang=en

 

#    |
# Thursday, November 30, 2006

Make Individual TreeView Nodes Bold

The full framework TreeView control supports setting a Font on a per-node basis, the Compact Framework control doesn't support this, however with a little interop magic you can mark individual nodes as Bold. Because the .NETCF v2.0 TreeView control exposes it's own window handle, and each TreeNode also exposes it's handle, we have all the raw data we need to format the node. First we need to define a structure and a couple of enumerations:-

internal struct TVITEM
{
public TVIF mask;
public IntPtr hItem;
public TVIS state;
public TVIS stateMask;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
string pszText;
int cchTextMax;
int iImage;
int iSelectedImage;
int cChildren;
int lParam;
}

[Flags()]
internal enum TVIF
{
TEXT =0x0001,
IMAGE =0x0002,
PARAM =0x0004,
STATE =0x0008,
HANDLE =0x0010,
SELECTEDIMAGE =0x0020,
CHILDREN =0x0040,
}

[Flags()]
internal enum TVIS
{
SELECTED =0x0002,
CUT =0x0004,
DROPHILITED =0x0008,
BOLD =0x0010,
EXPANDED =0x0020,
EXPANDEDONCE =0x0040,
EXPANDPARTIAL =0x0080,

OVERLAYMASK =0x0F00,
STATEIMAGEMASK =0xF000,
USERMASK =0xF000,
}

 

Then I've created a single static method which can set the bold state of any node:-

public static void SetNodeEmphasis(TreeNode n, bool bold)
{
//get the control and node handles
IntPtr hTreeview = n.TreeView.Handle;
IntPtr hNode = n.Handle;

//create a TVITEM struct
TVITEM t = new TVITEM();
t.hItem = hNode;
//mark only the handle and state members as valid
t.mask = TVIF.HANDLE | TVIF.STATE;
//set the state to bold if bold param was true
t.state = bold ? TVIS.BOLD : 0;
//set statemask to show we want to set the bold state
t.stateMask = TVIS.BOLD;

//pin the struct in memory
GCHandle hTVITEM = GCHandle.Alloc(t, GCHandleType.Pinned);
//create a TVM_SETITEM message with the handle of our pinned struct
Microsoft.WindowsCE.Forms.Message m = Microsoft.WindowsCE.Forms.Message.Create(hTreeview, 0x113F, IntPtr.Zero, hTVITEM.AddrOfPinnedObject());
//send the message to the treeview
Microsoft.WindowsCE.Forms.MessageWindow.SendMessage(ref m);
//free the pinned structure
hTVITEM.Free();
}

The method is easy to reuse as you only need to pass the TreeNode in, it will grab the handle of the parent control from the node itself. After applying the formatting to a couple of nodes you'll get something like this:-

 

#    |
# Wednesday, November 15, 2006

Using MessageInterceptor to launch an application on SMS

First things first a disclaimer, the following code is written for Mobile In The Hand (Professional Edition), it does apply equally to a Windows Mobile 5.0 project with the Microsoft.WindowsMobile managed APIs, you'll just need to change the namespaces and assembly references.

A normal MessageInterceptor is valid only for the lifetime of your application, once you shut down you'll no longer be able to respond to messages that match your rule. In many cases you'll want a specific message to launch your application and then process as normal. The IApplicationLauncher interface which MessageInterceptor implements contains methods to set this up. This allows the system to start your application, optionally with command line arguments of your choosing. This is useful so that you can tell when your app was called by an incoming SMS and when launched manually. The following code snippet is called in Form_Load, it checks for an existing registration, if not present it sets up all the required settings. The ApplicationLaunchId is a string which is unique to your application, if you try to register with an id which is already in use you'll receive an Exception.

if (InTheHand.WindowsMobile.PocketOutlook.MessageInterception.MessageInterceptor.IsApplicationLauncherEnabled("testapp"))
{
    mi = new InTheHand.WindowsMobile.PocketOutlook.MessageInterception.MessageInterceptor("testapp");
}
else
{
    mi = new InTheHand.WindowsMobile.PocketOutlook.MessageInterception.MessageInterceptor(InTheHand.WindowsMobile.PocketOutlook.MessageInterception.InterceptionAction.NotifyAndDelete);
    mi.MessageCondition = new InTheHand.WindowsMobile.PocketOutlook.MessageInterception.MessageCondition(InTheHand.WindowsMobile.PocketOutlook.MessageInterception.MessageProperty.Body, InTheHand.WindowsMobile.PocketOutlook.MessageInterception.MessagePropertyComparisonType.StartsWith, "test:", false);

    mi.EnableApplicationLauncher("testapp","\\Program Files\\InterceptorTest\\InterceptorTest.exe");
}

mi.MessageReceived += new InTheHand.WindowsMobile.PocketOutlook.MessageInterception.MessageInterceptorEventHandler(mi_MessageReceived);

Finally the event handler just displays the message body in a MessageBox:-

void mi_MessageReceived(object sender, InTheHand.WindowsMobile.PocketOutlook.MessageInterception.MessageInterceptorEventArgs e)
{
    MessageBox.Show(((InTheHand.WindowsMobile.PocketOutlook.SmsMessage)e.Message).Body, "Message");
}

Download the skeleton project: InterceptorTest.zip (11.08 KB)
#    |
# Wednesday, October 11, 2006

Bug in GAC Installation from VS2005 Device CAB Projects

I recently ran into a problem with a Smart Device CAB Project in Visual Studio 2005, which as it turns out is a known issue. You can build a CAB file which will register your .NETCF dlls into the GAC - the File System Editor has a standard folder called "Global Assembly Cache Folder" which you can put your files into. Behind the scenes this deploys the dlls to the windows folder and generates a .GAC text file with a list of paths to your dll(s). The problem is that the generated GAC file is a Unicode text file and doesn't work on devices prior to Windows Mobile 5.0. I'm assuming the same is true with generic CE 4.2 devices versus CE 5.0. In itself this seems bizarre since CE is fully Unicode based so shouldn't have any problem reading the file. It just so happens that when you are doing this the old fashioned way with notepad you get an ANSI text file which works just fine on all devices.

The workaround is simple, don't use the whizzy GAC support in the CAB project, place your dlls into the Windows Folder, and manually create a .GAC text file and place this in the Windows Folder also. The downside to this approach is that you must update your GAC file if you add or remove dlls from your setup project. I'd like to say thanks to fellow MVP Jan Yeh for helping to test the issue and to Manish Vasani from the Visual Studio for Devices team for following up with more details on the issue.

#    |
# Friday, September 22, 2006

SelectPictureDialog.LockDirectory property

If you refer to the original Windows Mobile 5.0 documentation (or the Intellisense) when using this component you'll notice it has a property called LockDirectory which is supposed to prevent the user from browsing outside of the folder you specified in InitialDirectory. To cut a long story short this property is not implemented and setting it will not affect the behaviour of the dialog. The online MSDN documentation has since been updated to indicate this.

When faced with this problem my first thought was to look at the native API which this component uses (GetOpenFileNameEx) and P/Invoke it since the documentation still indicates that there is a flag to achieve this behaviour. However as it turns out this too is unimplemented. It was a late change in Windows Mobile 5.0 and hence the SDK and documentation were innacurate.

#    |
# Monday, August 28, 2006

32feet.NET Reaches v2.0 Milestone

Although it took a lot longer than I originally anticipated I've finally put the finishing touches to v2.0 of the 32feet.NET library. v2.0 is a major re-write of the code so that the single codebase can be built into separate dlls for desktop or device. This was primarily to get around the bug in the desktop VB.NET compiler which couldn't cope with redirecting the device System.dll reference to the desktop equivalent. It has had the pleasant side-effect of making the footprint much smaller. The 4 previous dlls are now merged into the single InTheHand.Net.Personal.dll which range from 91kb for the .NETCF v1.0 version to 76kb for the desktop v2.0 version.

You can download the installer which includes the library, documentation and samples from the 32feet website. This release is the first release version to have the full source code available since the project was hosted at CodePlex. You can also use the CodePlex site to download other builds of the code and post bugs/feature requests. If you want to get involved in the project drop me a mail, or join the discussions on the 32feet site.

#    |
# Friday, August 25, 2006

Windows Mobile Context Menu Behaviour On Windows CE

Although many Windows CE devices include the aygshell.dll component which offers some functionality available in the Pocket PC shell, it's not directly taken advantage of by .NETCF. For example, when you add a ContextMenu to a control in a Pocket PC project you automatically get tap-and-hold behaviour on the control. Run the same code on an aygshell equipped CE device and nothing happens. Therefore I wrote the following helper class to allow you to hook up the context menus. Simply call HookAllControls(Me.Controls) from your code (e.g. in your form constructor after the call to InitializeComponent() ) or at any other stage if you are dynamically creating controls on your form. Now when you run your app you'll get the tap and hold circles and your context menu will be displayed. Obviously this only works on CE devices which have aygshell support. Just to mix it up a bit this sample is in VB.NET but you should find it easy to convert to C#.

Namespace InTheHand.Windows.Forms


Public Class ContextMenuHelper


Private Shared mousedelegate As System.Windows.Forms.MouseEventHandler = New System.Windows.Forms.MouseEventHandler(AddressOf ControlMouseDown)

Public Shared Sub HookAllControls(ByVal thecontrols As Control.ControlCollection)

'attach to the mousedown event on all controls with a context menu
For Each thiscontrol As Control In thecontrols

If Not thiscontrol.ContextMenu Is Nothing Then

AddHandler thiscontrol.MouseDown, mousedelegate

End If

HookAllControls(thiscontrol.Controls)
Next

End Sub


Private Shared Sub ControlMouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

Dim senderctrl As Control = CType(sender, Control)

'if theres no context menu do nothing
If Not senderctrl.ContextMenu Is Nothing Then

Dim shrgi As New SHRGINFO
shrgi.cbSize = 20
shrgi.hwndClient = senderctrl.Handle
shrgi.dwFlags = 3
shrgi.ptDownx = e.X
shrgi.ptDowny = e.Y
Dim result As Integer = SHRecognizeGesture(shrgi)
If result = 1000 Then

senderctrl.ContextMenu.Show(senderctrl, New System.Drawing.Point(e.X, e.Y))
End If
End If

End Sub

<System.Runtime.InteropServices.DllImport("aygshell.dll")> _
Private Shared Function SHRecognizeGesture(ByRef shrg As SHRGINFO) As Integer
End Function

Public Structure SHRGINFO
Public cbSize As Integer
Public hwndClient As IntPtr
Public ptDownx As Integer
Public ptDowny As Integer
Public dwFlags As Integer
End Structure

End Class

End Namespace

#    |
# Tuesday, June 06, 2006

Disable the Touch Screen

If you really need to disable the touch screen on a device, there is a method available, but you'll need to soft-reset the device to restore the functionality. You can call the TouchPanelDisable API, it's not documented in the Windows Mobile SDKs but you'll find it in the CE documentation, declaration is very simple:-

<System.Runtime.InteropServices.DllImport("touch")> _
Private Shared Sub TouchPanelDisable()
End Sub

 

or

[DllImport("touch")]

private static extern void TouchPanelDisable();

There is a possibility that the dll in which this function appears may be different on some devices, so you'll need to do some experimentation first.


#    |
# Thursday, June 01, 2006

SQL Mobile Access Sync Coming Soon

For a while the migration path from Pocket Access to SQL CE / SQL Mobile has been missing a key piece of functionality which many Pocket Access applications relied on - the Synchronisation functionality in ActiveSync which synchronised with an Access database on the PC.

Today we have some good news from the SQL Mobile Team - A tool called here "Sync with Access", which is due out in Beta form in August, will return this functionality for SQL Mobile (and the forthcoming SQL Everywhere Edition).

#    |
# Sunday, May 21, 2006

Take a Shortcut

There are a number of ways you can make use of Shortcuts within your project. You may create a shortcut to your application during your CAB file installation - either on the Start Menu or perhaps in the \Windows\Startup folder. VS2005 makes this easy because it has a nice file system graphical editor for CAB projects. Another way you can use shortcuts is within your code itself. There are two API functions to support this - SHCreateShortcut and SHGetShortcutTarget. By P/Invoking these from your .NETCF application you can create your own launcher applications which reuse the shortcuts setup for your Start Menu for example.

There are some caveats when using these functions though which you need to be aware of, the documentation has been revised since the Pocket PC 2003 SDK to warn you of this. To understand why let's have a quick look at the contents of an LNK file:-

34#"\My Documents\Templates\Memo.psw"

 

As you can see it's a very simple text format. The number indicates the length of the path, this is followed by the # symbol then the full path to the target. When the path contains a space it must be wrapped in quotes. So what were those caveats? Well whatever path you pass to SHCreateShortcut it doesn't add these quotes how you would expect - you end up with:-

34#"\My" Documents\Templates\Memo.psw

 

This path is invalid and the shortcut won't work. The solution is to wrap any path you pass into SHCreateShortcut with quotes to begin with. Even if the path doesn't contain spaces this will give you a valid shortcut.

The second caveat comes with the SHGetShortcutTarget API. When this reads the shortcut file it doesn't strip out the quotes if present, this means your returned path cannot be used as-is with any of the System.IO functionality. The solution to this one is very simple - perform a Trim() on the returned string passing in the " character - this will remove the leading and trailing quotes and leave you with a valid path. If your shortcuts are to executables and also have arguments specified you will need to split the quoted path from any following arguments.

To demonstrate both of these techniques I've attached a sample VB.NET project. It can create and list shortcuts and when you tap on an item it will launch the target document. For a true launcher application there are some additional steps, for example retrieving the Icon for the file, these are not included in this sample.

Shortcuts.zip (7.27 KB)
#    |
# Friday, February 17, 2006

Contact.WebPage

The Managed APIs in Windows Mobile 5.0 expose the Contact.WebPage as a Uri. The problem with this approach is that the user forms are free text and you can enter anything into this field. Probably 9 times out of 10 you'll enter an address such as

www.peterfoot.net

And because the managed API passes this to the Uri constructor and it has no http:// prefix it fails and returns null. However there is a solution to workaround the issue. You can access the Properties collection and access the property and it will be returned as a string. So for example you would use:-

[C#]
string webPage = session.Contacts.Items[0].Properties[Microsoft.WindowsMobile.PocketOutlook.ContactProperty.WebPage];

[VB]

Dim webPage As String = session.Contacts.Items(0).Properties(Microsoft.WindowsMobile.PocketOutlook.ContactProperty.WebPage)

If you then want to use a Uri with this value, check to see if it includes the http:// prefix and if not add your own e.g.

Uri contactsWebpage = new Uri("http://" + webPage);

 

#    |
# Monday, February 13, 2006

OpenNETCF.Windows.Forms.Control2 in SDF 2.0

In SDF v1 I wrote a class called ControlEx which would allow you to host a native windows control within a managed Control. This was the subject of an MSDN article (of which much of the concept applies here too). The implementation was rather convoluted to work around the limits of .NETCF v1.0, and the control was constructed with a Control, which hosted a MessageWindow with some of it's style bits altered which in turn hosted the native control. Luckily hosting controls is easier in NETCF v2.0 but unlike the desktop this functionality is still not built into the base Control class. Which is where Control2 enters the stage.

Like several other classes throughout the SDF the name has been changed to use the 2 suffix, but there are a few other changes I want to draw your attention to. First the inevitable disclaimer, what I'm going to describe won't work with the current Beta release, as I was building the sample code for this post I realised there were a few "nice" features lacking to add a bit more reusable functionality into the Control2 class itself. So lets proceed with how the architecture has changed, and then work through specifics with a sample.

The fundamental feature in .NETCF v2.0 which enables the new architecture is the ability to marshal a managed function as a function pointer to native code. Using this we are able to handle our wndproc in a managed method, this removes the need for the MessageWindow class. Control2 is derived from Control and when added to a form it hooks up a method to process its own windows messages. These are passed to a virtual WndProc method which can be overridden in a derived control to handle specific messages. After this is hooked up the CreateControl method is called, this takes the window class details returned from CreateParams and creates the window as a child of our Control2. This means than in it's simplest form you only need to override CreateParams with a valid class name to host your control.

However Control2 provides only basic functionality to interact with this class - for example automatically resizing when you resize the managed control, and getting/setting the control text. Beyond this you have two ways to interact with the control - add your own properties and methods to your Control2 derived class and from these send windows messages to the native control, and secondly add your own handlers for incoming messages from the control to create events.

For a basic example I've wrapped the CAPEDIT control which is part of WindowsMobile - this is simply a textbox which can Automatically Capitalize The First Letter Of Every Word. Because CAPEDIT is a common control it requires a call to InitCommonControlsEx - there is a static helper method in Control2 to help with this:-

Shared Sub New()

   Control2.InitCommonControls(&H2000)

End Sub

By the way as you've probably noticed, this and the rest of the example are in VB.NET, I would hope that it is self-explanitory enough for you to apply to C# as required.

Interestingly we don't need to worry about the constructor for the control at all, as we don't do anything special. Where the magic happens is in our override for the CreateParams property:-

Protected Overrides ReadOnly Property CreateParams() As OpenNETCF.Windows.Forms.CreateParams

   Get

      Dim cp As CreateParams = MyBase.CreateParams

      cp.ClassName = "CAPEDIT"

      Return cp

   End Get

End Property

And that's it, all we did was change the ClassName in this case. The other parameters such as size are already set for you based on the current size of your managed control.

So as I alluded to earlier, the example is a very simple class so there aren't any events to show you, just a couple of properties which are implemented like so:-

Private allcaps As Boolean = False

Public Property UpCaseAllWords() As Boolean

   Get

      Return allcaps

   End Get

   Set(ByVal value As Boolean)

      Dim val As IntPtr

      If (value) Then

         val = New IntPtr(-1)

      End If

      Dim m As Microsoft.WindowsCE.Forms.Message = Microsoft.WindowsCE.Forms.Message.Create(Me.childHandle, 1025, val, IntPtr.Zero)

      Microsoft.WindowsCE.Forms.MessageWindow.SendMessage(m)

      allcaps = value

   End Set

End Property

The magic value of 1025 was determined from the commctrl.h header file. I should proobably have created it as a const with the same name as the native implementation. One of the great things about VS2005 is that when you build a project with such a control in it, you'll get an automatic addition to your toolbar for it. We haven't added any designer support (outside the scope of this article) but you can set descriptions, categories and the toolbox icon for the control in the usual way. By default you'll get a rectangle with the name of the control which you can position on your form, in many cases this might be good enough. The sample project shows the control dropped on a form with a couple of checkboxes to toggle the properties. Also as a sanity check there is a button labelled Copy which copies the text value from the native control to a regular TextBox - remember we didn't write any code to do that, it's built into Control2 (well in a post-Beta release at least!). The standard behaviour of the CAPEDIT control is to have no border, but you can change this by setting the BorderStyle to BorderStyle.FixedSingle for a plain 1-pixel border.

Control2Example.zip (9.07 KB)

Wait what have I missed, oh yes there are two other useful properties - DesignMode allows you to check if your control is currently in a designer so you can for example not call device specific code, and ModifierKeys is a static property which gives you the current state of the Shift/Ctrl/Alt modifier keys, if your device has a "proper" keyboard.

Stop Press:-

Exhibit A - A CAPEDIT control in a managed app:-

#    |
# Saturday, January 28, 2006

OpenNETCF.IO in SDF 2.0

As well as the revolutionary changes in the SDF v2.0, some of which are simply only made possible by improvements in .NETCF v2.0, we have used this opportunity to make a number of evolutionary changes too. For example I'm going to take a quick trip through the file functionality in the OpenNETCF.IO namespace:-

DriveInfo - This is a new class which mimics functionality new in the desktop framework v2.0 and replaces previous separate classes for StorageCard and ObjectStore information. You can use it in two ways, use the constructor which takes a path and pass in the path of your storage device e.g. "\" or "\Storage Card" or you can use the static GetDrives() method which will return an array of all devices. A pleasant side-effect of this is that you can data-bind to this array of DriveInfo objects.

OpenNETCF.IO.DriveInfo[] di = OpenNETCF.IO.DriveInfo.GetDrives();
dataGrid1.DataSource = di;

File2 - To follow accepted naming behaviour we have stopped using Ex as a name suffix and so instead our classes which overlap existing classes in .NETCF have the 2 suffix. I have added some additional helper methods which are found on the desktop to quickly read/write whole files - ReadAllText / ReadAllLines and WriteAllText / WriteAllLines.

File2.WriteAllText(filename, textBox1.Text);

FileSystemWatcher - We've made some improvements here so that all the various event combinations are correctly raised. Also we have built in designer support for VS2005 so you can drop a FileSystemWatcher onto your form and hook up the events in the designer.

#    |
# Thursday, January 19, 2006

GetDeviceUniqueID For VB

To complement the C# version posted Here,  here is a working VB translation:-

<System.Runtime.InteropServices.DllImport("coredll.dll")> _
Private Shared Function GetDeviceUniqueID(ByVal appdata As Byte(), ByVal cbApplictionData As Integer, ByVal dwDeviceIDVersion As Integer, ByVal deviceIDOuput As Byte(), ByRef pcbDeviceIDOutput As Integer) As Integer
End Function

Private Function GetDeviceId(ByVal appData As String) As Byte()

Dim appDataBytes As Byte() = System.Text.Encoding.ASCII.GetBytes(appData)
Dim outputSize As Integer = 20
Dim output(19) As Byte

Dim result As Integer = GetDeviceUniqueID(appDataBytes, appDataBytes.Length, 1, output, outputSize)

Return output

End Function

#    |
# Sunday, January 08, 2006

Determine WM5.0 AKU Version Programmatically

The full build and AKU version of a device is shown on the Start > Settings > System > About screen, however what if you want to determine the version from your code. Well starting with Windows Mobile 5.0 there is now a registry key which holds the AKU version e.g.

RegistryKey kAku = Registry.LocalMachine.OpenSubKey("System\\Versions");

string akuVersion = kAku.GetValue("Aku", "");

kAku.Close();

This version will include a leading period so for example if the string is ".0.1.1" as on the current JasJar ROM the device has AKU 0.1, if it reads ".1.1.0" as on the current K-Jam ROM you have AKU 1.1. As far as I'm aware all shipping devices will have at least 0.1 as some fixes were implemented between RTM in May 2005 and the first shipping devices released later in the year. If your version is ".2.x.x" then you are a very lucky bunny indeed!

Whilst Windows Mobile 2003 had a similar concept of periodic AKU updates throughout it's lifetime this registry key is not available, nor is the AKU version displayed on the About dialog, only the Build number is displayed.

#    |
# Thursday, January 05, 2006

KeyboardPresent always returns false

This bug affects both managed and native developers working with the Windows Mobile 5.0 SDK.

Native

Due to an error in snapi.h the location of the registry key used to indicate if a hardware keyboard is present is incorrect:-

////////////////////////////////////////////////////////////////////////////////
// KeyboardPresent
// Gets a value indicating whether a keyboard is attached and enabled.
#define SN_KEYBOARDPRESENT_ROOT HKEY_LOCAL_MACHINE
#define SN_KEYBOARDPRESENT_PATH TEXT("Software\\Microsoft\\Shell")
#define SN_KEYBOARDPRESENT_VALUE TEXT("HasKeyboard")

The root key for this value should instead be HKEY_CURRENT_USER. Once you use this location you can correctly determine if there is a hardware keyboard (this is the same location as used on WM2003 Second Edition devices such as the HTC Blue Angel).

Managed

The SystemState class also uses the incorrect location to read this value so the property will always return false. The workaround here is to access the registry directly using either the Microsoft.Win32.RegistryKey in .NETCF v2.0 e.g.

RegistryKey keyboardKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Shell");

int dwHasKeyboard = keyboardKey.GetValue("HasKeyboard", 0);

keyboardKey.Close();

bool hasKeyboard = (dwHasKeyboard != 0);

#    |
# Wednesday, January 04, 2006

Bug in Microsoft.WindowsMobile.Telephone.Phone.Talk

Luis Cabrera has posted the details of a bug identified in the Talk method to the Windows Mobile Team blog. The workaround (see the original post) is to append a null character to the end of your dial string.

Note: this bug doesn't affect InTheHand.WindowsMobile.Telephony.Phone.Talk.

#    |
# Thursday, December 22, 2005

PocketOutlook Native <-> Managed Map

Windows Mobile 5.0 introduces a managed API which wraps both POOM and a subset of CEMAPI (enough to send an Email / Sms). The table below is designed to show how the managed objects map to the interfaces which will be familiar to seasoned POOM developers. It also shows those parts of POOM which are not available through the managed APIs:-

Native

Managed

IPOutlookApp

OutlookSession

· Logon

Automatically handled

· Logoff

Automatic – call Dispose on your OutlookSession when finished

· get_Version

Not Supported – Get OS version with System.Environment.OSVersion.Version

· GetDefaultFolder

Use strongly typed folder properties - Appointments, Contacts & Tasks

Infrared not supported

· CreateItem

Use default constructor for specific item type

· GetItemFromOid

Use constructor for item which accepts an ItemId e.g.

new Contact(new ItemId(oid)

· City Methods (Removed in Pocket PC 2002)

Obsolete

· ReceiveFromInfrared (Obsolete from Pocket PC 2002)

Obsolete

· get_OutlookCompatible

Obsolete

· GetTimeZoneFromIndex

Not Supported

IFolder

Folder – AppointmentFolder, ContactFolder, TaskFolder

Infrared not supported

· get_Items

Items

· get_DefaultItemType

N/A inferred from the Folder type

· get_Application

N/A

· AddItemToInfraredFolder

Not Supported

· SendToInfrared

Not Supported

· ReceiveFromInfrared

Not Supported

IPOutlookItemCollection

PimItemCollection – AppointmentCollection, ContactCollection, TaskCollection

· Add

Add

· get_Count

Count

· Find

Find (Requires a PropertyDescriptor)

· FindNext

Not Supported

· Item

· 1-based index

Default indexer – () VB or [] C#

0-based index

· Remove

RemoveAt - also implements Remove(PimItem)

· Restrict

Restrict

· Sort

Sort

· get_IncludeRecurrences

Not Supported

· put_IncludeRecurrences

Not Supported

IAppointment

Appointment

· ClearRecurrencePattern

Call Clear on the AppointmentRecurrence

· GetRecurrencePattern

RecurrencePattern

· get_* / put_*

Accessible by named properties or via Ids through the Properties collection

· Save

Update

· Send

Send

· Delete

Delete

· Cancel

Cancel

· Copy

Copy

· Display

ShowDialog

· get_Oid

ItemId

· get_BodyInk / put_BodyInk

BodyInk no longer supported on WM5.0

IContact

Contact

· get_* / put_*

Accessible by named properties or via Ids through the Properties collection

· Save

Update

· Delete

Delete

· Copy

Copy

· Display

ShowDialog

· get_Oid

ItemId

· get_BodyInk / put_BodyInk

BodyInk no longer supported on WM5.0

ITask

Task

· ClearRecurrencePattern

Call Clear on the TaskRecurrence

· GetRecurrencePattern

RecurrencePattern

· get_* / put_*

Accessible by named properties or via Ids through the Properties collection

· Save

Update

· Delete

Delete

· SkipRecurrence

Call Skip on the TaskRecurrence

· Copy

Copy

· Display

ShowDialog

· get_Oid

ItemId

· get_BodyInk / put_BodyInk

BodyInk no longer supported on WM5.0

IItem

New in WM5.0 supports access to custom properties etc Functionality is available via Appointment, Contact and Task types

IRecipients

RecipientCollection

Shared with the Email (MAPI) support

IRecipient

Recipient

Shared with the Email (MAPI) support

IRecurrencePattern

Recurrence – AppointmentRecurrence, TaskRecurrence

Properties follow same names as native equivalent. Managed types such as TimeSpan and DateTime are used as appropriate. Enums defined for Months, WeekOfMonth, DaysOfWeek

IExceptions

Not supported

IException

Not supported

ITimeZone

Not supported

#    |
# Monday, December 19, 2005

XmlSerialization of DateTime in .NETCF 2.0

Changes have been made to the DateTime type in v2.0 to help indicate whether a specific value represents a local time or universal time. What this can mean is that the behaviour of web services using DateTimes will change. This article has full details of the issue:-

http://blogs.msdn.com/mattavis/archive/2005/10/11/479782.aspx

The same approach is available under .NETCF v2.0 to request the old v1 behaviour - add a configuration file for your exe with the following content:-

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

   <system.xml.serialization>

      <dateTimeSerialization mode="Local" />

   </system.xml.serialization>

</configuration>

#    |
# Thursday, December 15, 2005

Issue with Microsoft.WindowsMobile.PocketOutlook.RecipientCollection.Add()

When you want to create a meeting request with managed POOM on WM5.0 you start by creating an Appointment and then add Recipient objects to it's Recipients collection. However what the documentation doesn't tell you is that you have to ensure that your Recipient has both the Name and Address properties. For example:-

Microsoft.WindowsMobile.PocketOutlook.Appointment ma = new Microsoft.WindowsMobile.PocketOutlook.Appointment();
ma.Subject = "Test 5";
ma.Recipients.Add(new Microsoft.WindowsMobile.PocketOutlook.Recipient("user@yourdomain.com"));

Will throw a Win32Exception with the text "Native method call failed". This isn't very descriptive but the reason it fails is due to how native POOM works - the IRecipients.Add method takes a name argument and since your Name property is empty this call fails. If you specify the name e.g.

ma.Recipients.Add(new Microsoft.WindowsMobile.PocketOutlook.Recipient("User","user@yourdomain.com"));

or even this if you only have an address:-

ma.Recipients.Add(new Microsoft.WindowsMobile.PocketOutlook.Recipient("user@yourdomain.com","user@yourdomain.com"));

Then you'll be okay.

#    |
# Thursday, November 24, 2005

VS2005 and File Alignment

One of the transparent benefits of building your projects with VS2005 is that the default File Alignment is now set at 512 bytes, rather than the 4096 bytes which was the default for device projects in VS2003. This means if you create a new project in both versions and add exactly the same code you should notice the output dll created by VS2005 is noticably smaller.

One thing you may not realise is that the default value used in a VS2003 project is stored within the C# project file, which means if you import a VS2003 C# Smart Device project to VS2005 it will still use the value 4096. You can change this from the project properties > Build tab > Advanced button and set it to 512.

#    |
# Tuesday, November 22, 2005

Divert system audio to a Bluetooth headset

In the Windows Mobile 5.0 audio gateway implementation there are a couple of control codes to turn on audio routing through the bluetooth headset/handsfree device. I've only tried this with a couple of devices and had mixed (That's a really bad audio pun sorry!) results but here's a library to allow you to try it yourself. In theory it may work on some 2003 Second Edition devices too. I'd be interested to hear your feedback.

To set audio routing just call

InTheHand.Net.Handsfree.AudioGateway.RouteAudioToHandsfree = true;

And set to false to return to normal audio use.

Once fully tested and documented this will make it into the 32Feet package.

InTheHand.Net.Handsfree.zip (2.54 KB)
#    |
# Tuesday, November 01, 2005

Bug in OpenNETCF.VisualBasic GetSetting

A fairly obvious bug managed to go unnoticed in the GetSetting method for about 18 months. The problem is fairly straight-forward - the method will never return a value if one is found (if not present it returns the default value you supply).

I've fixed it for the next version, but what are you options for working around the issue with current code:-

  • Use the RegistryKey directly instead - OpenNETCF.Win32.RegistryKey directly matches the .NET v2.0 version so any code you write against this is very portable.
  • Use the attached updated OpenNETCF.VisualBasic.dll. However in order for this method to work you will have to manually copy the dll to your program folder, and make sure your reference points to this version of the dll - 1.4.51101 OpenNETCF.VisualBasic.zip (3.61 KB)
  • Grab the updated code from the Vault and build the code into your own dll/executable and call that instead of the OpenNETCF.VisualBasic version.

It would be interesting to get some feedback on whether people are actually using this VB specific functionality, and if so how useful you find it, and what else you would like to see in future versions...

#    |
# Tuesday, October 18, 2005

Installing .NETCF 2.0 Runtimes

Marcus has posted some instructions on installing .NETCF v2.0 runtimes to a Windows Mobile 5.0 device. Of course you may wish to deploy to Pocket PC 2003 devices too, again it's a RAM install, and you can follow the same basic steps. There are a few points to note:-

  • You can still build an Autorun in .NETCF v1.0 code as all Pocket PC 2003 devices will have at least the RTM release of v1.0 in ROM. Autorun on devices with multiple card slots can be flaky this was improved in v5.0
  • The CAB file for Pocket PC 2003 is much larger (5.1mb) since Pocket PC 2003 doesn't support compressed CAB files. By default you'll find it here:-

C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\CompactFramework\2.0\v2.0\WindowsCE\wce400\armv4\NETCFv2.ppc.armv4.cab

  • The Autorun code will require modification because it relies on managed ConfigurationManager - you can either P/Invoke DMProcessConfigXML or use an available wrapper (if your device is a Phone Edition device) or OpenNETCF Registry wrapper - works for all PPC2003 devices.
  • You'll need to modify how the Autorun determines the path of the SD card on which the files are contained. One solution is to check for potential storage cards with this code:-

http://www.opennetcf.org/forums/topic.asp?TOPIC_ID=432

  • Place some token file on your SD card and check for it's existence on each returned path, then when you have your SD card folder you can programmatically install the cab file(s). Again I shouldn't need to give you any hints as to where to find a Process class for .NETCF v1.0
#    |
# Monday, October 17, 2005

Use IMessageFilter From a VB .NETCF Project

I posted this to the newsgroup earlier, but figured it was a useful thing to post for future reference. If you want to implement a custom IMessageFilter using OpenNETCF.Windows.Forms.ApplicationEx you have to be aware that VB.NET autogenerates a main proceedure for you if your project startup object is a form. Therefore it will use the Application.Run method and your filter will never be used. Instead you can implement a Sub Main as your startup object and use ApplicationEx:-

Public Shared Sub Main()

ApplicationEx.Run(New MyFormType())

End Sub

 

Then set your Startup object in project properties to your new Sub Main rather than the name of your form class.

#    |
# Thursday, September 15, 2005

SDF v1.4 Dlls

A request came up on the newsgroups for just the dlls for the SDF. This could be useful if you are using the VS2005 Beta. Of course if you don't know why you need these or what to do with them, then you can safely ignore this message and grab the package from http://www.opennetcf.org/download.asp?product=SmartDeviceFramework14

OpenNETCF.1.4.zip (479.38 KB)
#    |
# Tuesday, September 06, 2005

Useful new MessageWindow feature

Earlier in the Beta for Visual Studio 2005 I submitted a product suggestion to support a very common scenario with the MessageWindow control, and I was delighted to find that in the July CTP it has been implemented.

The MessageWindow class is provided as a mechanism to receive incoming windows messages and has become a key part of the .NETCF developers interoperability toolbox. .NETCF v2.0 extends the options we have available with new functionality such as support for passing callback functions into native code and COM interop. However there are still times when we will need the humble MessageWindow. One of the first tasks with using the MessageWindow is how to tell the sender where to send the messages. In some cases this involves passing the handle (HWND) of the MessageWindow in via a P/Invoke call, the other common way to identify a MessageWindow is by setting the text and using FindWindow.

This neatly brings me back to the new feature in question. In v1.0 you had to override the WndProc and add your own handler for WM_GETTEXT (and optionally WM_SETTEXT) in order for your MessageWindow to have a caption. .NETCF v2.0 adds the Text property making life that little bit easier. Just set the Text property to something uniquely identifiable for your application, then you can use FindWindow from your native code to get the handle (HWND) of the MessageWindow and start sending messages to it.

#    |
# Monday, September 05, 2005

One-handed Pocket PC Applications

Mark has posted the final version of his MSDN article on designing for stylus-free usage on Windows Mobile. This covers both what you get for free in .NETCF v2.0 for navigating around forms with the d-pad and also what you can do to make some of the other intrinsic controls behave. Mark's sample code includes wrappers around these "badly behaved" controls such as the DateTimePicker.

#    |
# Thursday, September 01, 2005

Service Packs and Fixes

In order to determine all the known issues with .NETCF v1.0 and which Service Pack contained the fix, you would need to look through the fix list for each of the Service Packs in turn. For ease of reference I copied the three fix lists from SP1,2 and 3 and categorised them into the following table. The "o"s indicated in which service pack the issued was resolved. Below it is a table showing which version is preinstalled on the various Windows Mobile devices which have had .NETCF in ROM.

  RTM SP1 SP2 SP3
Defects        
         
Improved code cache performance and memory utilization on ARM processors   o o o
Parsing of Numeric values is not working correctly on some locales (specially affects VB scenarios)   o o o
App would not launch properly if it were already running and showing MessageBox when the user navigated out to Home   o o o
Improved resource loading performance     o o
Minor GUI performance improvements     o o
Added support for new Smartphone languages: Finnish, Czech, Romanian, Slovakian, Norwegian, Hungarian, Polish, Turkish, Russian     o o
Transitions between managed and native code can cause memory leaks on ARM platforms       o
Stack corruption can occur on ARM platforms when local variables are created but never used       o
Invoking a multicast delegate from a catch handler throws a MissingMethodException on ARM platforms       o
Command line arguments containing double byte characters are truncated to a single byte.       o
Memory corruption can occur on devices that have the native security model enabled and both .NET CF V1 SP3 and a pre-release version of .NET CF V2 installed.       o
Deadlocks can occur when running under severe resource constraints.       o
Data Misalignment occurs on Decimal fields in MIPSIV devices.       o
         
Microsoft.WindowsCE.Forms        
InputPanel: EnabledChanged Event fires inspite of setting the enabled property to the same value.     o o
InputPanel: Setting the InputPanel.Enabled property when the form is closing throws an exception     o o
         
System
Double: conversion of 0.0F to a string and results in a memory leak     o o
String: Native exception while calling String.Intern()   o o o
Type: System.Type.GetType(string) fails to load types that reside on external assemblies if those assemblies are not already loaded   o o o
       
System.Data
DataRowCollection.Find Method Returning Incorrect Row   o o o
DataRowCollection.Find() method throws wrong exception     o o
DataSet: Improved performance of many data tasks, including populating DataSets, searching DataTables, DataSet.ReadXml() method when a schema is used, finding and indexing operations, setting DataSet.EnableConstraints property ">DataSet: Improved performance of many data tasks, including populating DataSets, searching DataTables, DataSet.ReadXml() method when a schema is used, finding and indexing operations, setting DataSet.EnableConstraints property      o o
DataSet: Data is missing or loaded incorrectly by DataSet.ReadXml() in some cases.       o
Fixed crash when SQLClient or SQLServerCe is installed     o o
       
System.IO
BinaryReader: BinaryReader.ReadBytes() returns less bytes than asked   o o o
       
System.Net
Improved network media sense / connection management experience   o o o
HttpClient: Authentication state handling errors in http client   o o o
HttpClient: Http client not using credentials from supplied proxy object   o o o
HttpWebRequest: Fixed erroneous parsing of HttpWebRequest response stream     o o
Socket: Force tear down of sockets after dialup disconnect   o o o
Socket: An uncatchable ObjectDisposedException is thrown when the server closes the socket connection.       o
       
System.Net.IrDA
IrDAClient.DiscoverDevices device names garbled     o o
       
System.Web.Services
Web services: Compatibility issues   o o o
Web services: Problem receiving empty arrays mixed with other data   o o o
Web services: InvalidOperationException when polymorphic type is returned and in the same namespace as the service   o o o
Web services: Not correctly handling the default values that VB creates for enums when using the DefaultValue attribute   o o o
Web services: After repeatedly canceling asynchronous web request, all web service calls fail     o o
Web services: An XmlException is thrown when deserializing a qualified name that has no prefix and there is no default namespace defined     o o
Web services: Incorrect handling of null headers in SOAP messa     o o
Web services: A NullReferenceException is thrown when a Web Method returns an empty array using the xsi:Nil attribute       o
Web services: Modifying the SoapClientMessage.ContentType property does not modify the Http requests ContentType header.       o
Web services: An ObjectDisposedException is thrown when a asynchronous web request is aborted before the response is received.       o
Web services: Any array containing one or more elements is not sent to the Web Service correctly.       o
Web services: An application may hang when invoking a Web Method that uses multiple XmlElementAttributes on a single argument, member or property.       o
WebRequest.Proxy doesn't allow spaces in the URL   o o o
       
System.Windows.Forms
Memory leak in the NumericUpDown, DomainUpDown, ComboBox and TextBox controls     o o
The Focus method does not work correctly for the NumericUpDown and DomainUpDown controls     o o
Auto scroll - scrollbars aren't removed until control is inside bounds of scrollbars   o o o
Auto scroll - with control sitting bottom left, should get both scrollbars when control moved over right edge   o o o
ContextMenu: Support raising context menus from assigned hardware key, Pocket PC     o o
ContextMenu: Fixed TreeView issues on Pocket PC 2003     o o
ContextMenu: Fixed side effects on controls like Scrollbar and Label     o o
ContextMenu: erroneous functionality when bound to ListBox     o o
ContextMenu: Showing a context menu on Pocket PC for a textbox unselects the selected text in the textbox     o o
ContextMenu: Empty ContextMenu on Pocket PC should not pop up     o o
Control: Added support for ForeColor &/or BackColor for Button, Checkbox, ComboBox, DomainUpDown, Label, Listbox, ListView, NumericUpDown, RadioButton, Trackbar, TreeView     o o
Control: If a focused control property is changed while the application is in the background it loses its focus   o o o
Control: Don't get GotFocus Event for first control in form   o o o
Control: Focus should move to the next control when the current control with the focus gets disabled   o o o
Control: Extend keyboard events to be enabled on all controls (Control.KeyUp, KeyDown, KeyPress)     o o
Control: Improved Control.Enabled and Control.Parent property changing performance     o o
Control: Native Exception occurs when using the get accessor for Control.Capture     o o
Control: Invoke on a disposed control hangs the application.       o
Form: ControlCollection Memory leak   o o o
Form: Improved performance of Controls property   o o o
Form: Tab support for Pocket PC based on Z-Order     o o
Form: does not get the focus when all controls are removed from the form     o o
Form: Navigation bar flickers when new form is being loaded     o o
Form: ObjectDisposedException occurs when DataBinding a control to a form shown via Show()     o o
Form: OK button eventually goes away when re-using recycled form for ShowDialog(     o o
Form: Scrollbars should go away when app 100% client sized control is returned back to 100% inside client area   o o o
ImageList: Unexpected exception while adding an image to an imagelist on an Hx4700 and hx4705       o
ListView control allows setting the text alignment of its first column to HorizontalAlignment.Center and HorizontalAlignment.Right   o o o
ListView: The Text property of a ListView column is reset to “” when removing the column from the ListView and then adding it back.     o o
ListViewItem.Checked property always returns false if the CheckBoxes property of the listview control is set to false   o o o
MainMenu: Support menu hotkeys on Pocket PC     o o
MainMenu: InputPanel Button disappears from MainMenu on Pocket PC 2002     o o
MainMenu: SIP button does not go away when the toolbar control is removed from a form that does not have a menu     o o
ProgressBar: Setting the Minimum and Maximum properties of a progressbar no longer crashes the application.       o
RadioButton: Native exception thrown while setting the Checked property to false   o o o
ScrollableControl: thumb in wrong position after setting AutoScrollPosition   o o o
ScrollableControl: throws not supported exception setting AutoScroll=false   o o o
TextBox: Application terminates with a first-chance exception in gwes.exe when typing quickly in a textbox   o o o
ToolBar: Tool Bar's on Windows Mobile 2003 SE no longer lose their images when removed from the form.       o
         
System.Xml
XmlQualifiedName objects are corrupted if the namespace of the data is the same as that of the service   o o o
XmlTextReader performance improvements     o o
         
         
Devices
Pocket PC 2003 o r r r
Smartphone 2003   o    
Pocket PC 2003 Second Edition     o r
Smartphone 2003 Second Edition     o  
Windows Mobile v5.0 Pocket PC       o
Windows Mobile v5.0 Smartphone       o
r = Available via RAM install        

#    |
# Sunday, August 21, 2005

Functionality in InTheHand.WindowsMobile.Forms

As has already been shown with some of the other libraries in WindowsMobile In The Hand, the object model is generally designed to follow the Windows Mobile 5.0 APIs. There are a few examples where new functionality is exposed which is not found in the WM 5.0 APIs, some of which was designed specifically to complement Windows Mobile 5.0.

In the case of the Forms assembly, none of the WM5.0 forms are supported, this is because functionality such as CameraCaptureDialog and SelectPicture dialog rely on new functionality in the underlying OS - prior to WM 5.0 each OEM implemented their own camera support.

However in WindowsMobile In The Hand, a few new pieces of forms related functionality are added:-

The MessageBox is designed to provide a softkey-enabled message box for Windows Mobile 5.0 Pocket PCs (although it can also be used on prior versions). When used in a Smartphone project it uses the standard compact framework implementation, on a Windows Mobile 5.0 Pocket PC it produces the following:-

It's been designed to follow the Smartphone experience so you can provide the same user experience on both platforms. It supports a full range of overrides for the Show method to specify buttons, icon etc. Here the MessageBoxIcon is used to draw a watermark image on the dialog, similar in spirit to the themed icons which are used on the Smartphone equivalent.

MobileDevice provides a few helper methods to reset the device, and get the platform type identifier e.g. PocketPC or Smartphone.

MobileKeys provides a mapping between the device specific key constants (as defined in winuserm.h) and the desktop key codes, so all of the members are of type System.Windows.Forms.Keys.

OpenFileDialog is built specifically for Windows Mobile 5.0 Smartphone and matches the System.Windows.Forms version available in Pocket PC projects. Again if used in a Pocket PC project it utilises the existing implementation in System.Windows.Forms. It will currently raise a NotSupportedException if used on a Smartphone 2003 device.

#    |
# Friday, August 19, 2005

Windows CE Services and Compact Framework

Neither .NETCF v1.0 or v2.0 will support runtime hosting, this means it's not possible to write a service in managed code which will run within the Services.exe process. However it is often useful to be able to query and manipulate other system services from managed code.

An example of this is where a system service needs to be stopped so that you can access some hardware - such as the OBEX listener service on Windows Mobile which opens the Infrared port. With this scenario in mind I set about wrapping some of the CE functionality for managing services, using the desktop framework as a model.

The resultant library - InTheHand.ServiceProcess.dll is designed as a subset of System.ServiceProcess.dll - this is the assembly which is added as a reference to your project when you create a windows service project with the desktop framework. The library includes a single class ServiceController which is created with the identifier of the service you which to attach to. Under Windows CE these services have an identifier in the form of a device name e.g. AAAN: where AAA is the prefix, often providing a clue as to the purpose of the service, and N is a numerical index. Returning to our example of OBEX the service is called OBX0:. If you don't know the name of a particular service you can either trawl through the registry under HKLM\Services, or better still call the ServiceController.GetServices static method. The final consideration is to ensure you close/dispose the ServiceController when you have finished working with it. Our OBEX shutdown code looks like this:-

ServiceController scObex = new ServiceController("OBX0:");
scObex.Stop();

while(scObex.Status!=ServiceControllerStatus.Stopped)
{
    System.Threading.Thread.Sleep(1000);
}

scObex.Close();

Notice that the WaitForStatus method isn't supported so in this case we periodically check the status while sleeping. If we weren't bothered when the service shutdown you could leave out this section, even when you call Close() to close our handle to the service it will continue with it's action and shutdown in it's  own time.

In terms of platform support, this services.exe model is supported on CE.NET 4.x and above so this includes Windows Mobile 2003 and above.

You can download the library here:-

http://www.inthehand.com/Services.aspx

#    |
# Saturday, August 13, 2005

Restricting Pim Item Collections

This applies equally to WindowsMobile In The Hand and the Windows Mobile 5.0 APIs. On the collection classes there exists a Restrict method which returns a subset of the collection matching your search query. You can use the resulting collection to databind or otherwise enumerate over.

The query language used is similar, but not the same, as SQL: if you imagine that what you are entering here is just the WHERE clause of a query you will not be far off. The key rules to follow are:-

  • Field names must match exactly - refer to the Properties of the Appointment, Contact and Task class for valid field names
  • Field names must be enclosed in square brackets e.g. [MobileTelephoneNumber]
  • You can combine multiple expressions with AND and OR
  • Supported operators are < (Less Than), <= (Less Than or Equal To), > (Greater Than), >= Greater Than or Equal To), = (Equals), <> (Not Equals)
  • Items without the property set will not be returned in a query. So if you set a query of [BusinessAddressCity] = "London" it would not return items without the business address city present even though these are not London.
  • You can use this knowledge to form a query to return all records where the property is set with [PropertyName] <> "" as all items with the property set will match this pattern.

You can return a full contact list for all items with a mobile number using this code:-

os = new OutlookSession();

PimItemCollection pic = os.Contacts.Items.Restrict("[MobileTelephoneNumber] <> \"\"");

listBox1.DataSource = pic;

listBox1.DisplayMember = "FileAs"

This example bind the collection to a control, the list will show the contact name only but you'll be able to retrieve the Contact object from the SelectedItem property of the list box to use it's other properties (e.g. the mobile number).

For Windows Mobile 5.0 you can use the new ChooseContactDialog which features a RequiredProperties property so you can easily setup the dialog to show only relevant items.

Update: Here is the VB equivalent:-

os = New OutlookSession
Dim pic As PimItemCollection = os.Contacts.Items.Restrict("[MobileTelephoneNumber] <> " & Chr(34) & Chr(34))
ListBox1.DataSource = pic
ListBox1.DisplayMember = "FileAs"

 

#    |
# Thursday, August 04, 2005

NDoc helper for Microsoft.WindowsCE.Forms

If you've tried documenting .NETCF libraries which make use of Compact Framework specific types you'll know that you have to do all sorts of workarounds and special builds to get an output which can successfully run through NDoc. This is because although the device specific assemblies such as Microsoft.WindowsCE.Forms are marked retargetable there isn't an equivalent in the desktop framework to retarget to.

One solution is aggressive conditional compilation to hide all hints of of these device classes. Another way which is cleaner and easier to deal with when you are regularly updating code and documentation is to build your own dummy classes into your NDoc configuration of your project. I've done this for documenting my own code as I often find myself using MessageWindows etc in my projects. Ratherthan everyone re-invent the wheel you can use the file (see link below) as-is. You will still be producing a separate dll for documentation purposes but the amount of code you have to hack around with is greatly reduced.

Simply add the attached cs or vb file to your project. Then when you build the project in Debug or Release configuration absolutely nothing is added into your dll which will reference Microsoft.WindowsCE.Forms normally. But when you do an NDoc build and define the NDOC conditional constant it will magically spring into life and create a local dummy copy of the whole Microsoft.WindowsCE.Forms namespace. Because of the way the compiler chooses which class to reference your local version will take preference over the official library, thus removing all dependency on the Microsoft.WindowsCE.Forms library.

Microsoft.WindowsCE.Forms.zip (1.27 KB)

For this to work in VB there are a couple of additional points, firstly make sure you don't have a Root Namespace configured (Project > Properties). You will also need VBCommenter to build the XML output used to feed Ndoc (Visual Studio 2005 will introduce built in XML comments generation for VB.NET projects).

Of course the same technique can be used for other device specific assemblies such as System.Data.SqlServerCe, although it contains a lot more types and so is less practical to do in this way. You can instead use this technique just with the individual types/methods you use...

#    |

Bluetooth Socket Options on Windows XP

Windows XP supports a much smaller number of socket options for Bluetooth than Windows CE, although it generally provides alternative ways to get/set those properties. The table below shows those that are supported on XP and how they relate to their Windows CE equivalent. Notice that the only one which behaves the same on both platforms is SO_BTH_ENCRYPT

Windows XP

Windows CE

#define SO_BTH_AUTHENTICATE 0x80000001  // optlen=sizeof(ULONG), optval = &(ULONG)TRUE/FALSE

#define SO_BTH_AUTHENTICATE                                    0x00000001    // optlen=0, optval ignored

#define SO_BTH_ENCRYPT      0x00000002  // optlen=sizeof(ULONG), optval = &(ULONG)TRUE/FALSE

#define SO_BTH_ENCRYPT                                               0x00000002    // optlen=sizeof(unsigned int), optval = &(unsigned int)TRUE/FALSE

#define SO_BTH_MTU          0x80000007  // optlen=sizeof(ULONG), optval = &mtu

 

#define SO_BTH_SET_MTU                                                0x00000006    // unconnected only! optlen=sizeof(unsigned int), optval = &mtu

#define SO_BTH_GET_MTU                                               0x00000007    // optlen=sizeof(unsigned int), optval = &mtu

#define SO_BTH_MTU_MAX      0x80000008  // optlen=sizeof(ULONG), optval = &max. mtu

 

#define SO_BTH_SET_MTU_MAX                                    0x00000008    // unconnected only! optlen=sizeof(unsigned int), optval = &max. mtu

#define SO_BTH_GET_MTU_MAX                                    0x00000009    // bound only! optlen=sizeof(unsigned int), optval = &max. mtu

#define SO_BTH_MTU_MIN      0x8000000a  // optlen=sizeof(ULONG), optval = &min. mtu

#define SO_BTH_SET_MTU_MIN                          0x0000000a    // unconnected only! optlen=sizeof(unsigned int), optval = &min. mtu

#define SO_BTH_GET_MTU_MIN                         0x0000000b    // bound only! optlen=sizeof(unsigned int), optval = &min. mtu

The current version of the Bluetooth.NET library doesn't include the XP versions in the BluetoothSocketOptionName enumeration, but I have added these for the next release.

#    |
# Monday, August 01, 2005

Comparing Windows Mobile APIs

To illustrate how the WindowsMobile In The Hand is a subset of the Windows Mobile 5.0 APIs I've modified this class diagram for the Windows Mobile 5.0 APIs to ghost out those which are not supported in WindowsMobile In The Hand on earlier devices. The key differences are in support for system state events and in the number of properties supported - there is no easy way to do events for these system properties without a lot of polling which is bad. Also it lacks many new properties on the PIM items (such as Photos for contacts) including the ability to add custom properties - this is based on a lot of work on the underlying POOM APIs which would not be feasable to replicate on older devices.

wm5vwmith1.jpg (679.87 KB)

In a future post we will look at what is added beyond the standard Windows Mobile 5.0 APIs.

#    |
# Monday, June 20, 2005

Retrieve IMEI Through TAPI

Earlier I posted to the newsgroup a description of using Alex Feinman's Tapi Wrapper to retrieve the IMEI of the phone device. When I checked again, the specific required method is not included in the wrapper, however as Alex has made the line handles accessible it's easy to tag functionality onto the library without re-inventing the wheel. I put together a VB example to P/Invoke the lineGetGeneralInfo method to retrieve information about the phone device. If you use this on a Smartphone device you may find it doesn't work - this is because many Smartphone devices require signing to access many of the TAPI methods. I tested this on a HTC Phone Edition device

TapiVBExample.zip (52.74 KB)

 

#    |
# Wednesday, June 01, 2005

No KnownColors In NETCF

A requested feature for NETCF is to retrieve a list of named colors. Fortunately this is easily done using reflection to read all the public statis properties of the Color class:-

System.Reflection.PropertyInfo[] colors = typeof(Color).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
Color[] allcolors = new Color[colors.Length];


for(int i = 0; i < colors.Length; i++)
{
    allcolors[i] = (Color)colors[i].GetValue(null,null);
}

comboBox1.DataSource = allcolors;

 

In this example the full list is assigned to a ComboBox for display purposes.

#    |
# Sunday, May 29, 2005

Compiled Documentation for OpenNETCF Libraries

With the release of the Smart Device Framework v1.3 the compiled help documentation was no longer included in the installer. I've built a standalone installer to install the full collection of documentation into your Visual Studio help. This release includes:-

  • OpenNETCF Smart Device Framework v1.3
  • OpenNETCF Application Blocks v1.0
  • OpenNETCF Desktop Communication
  • Microsoft.WindowsCE.Forms
  • The full package is approximately 5mb but once installed makes it much quicker to search than using the online version. It installs with either Visual Studio 2003 or Visual Studio 2005 Beta, Download it here.

    #    |
    # Saturday, May 28, 2005

    Using the Clipboard

    This is a very basic sample app to assist a thread in the newsgroup. Basically it shows a couple of approaches to working with the Clipboard, both using SDF v1.3.

    The first is the TextBoxEx class onto which I've added a ContextMenu with edit commands. The second is a plain TextBox and I've added buttons to call methods on the OpenNETCF.Windows.Forms.Clipboard class.

    In .NETCF v2.0 there will be basic functionality on the Clipboard class but it wont have the GetText and SetText shortcut methods. The OpenNETCF.Windows.Forms.Clipboard class follows the desktop v2.0 equivalent so should be fairly intuitive to use.

    The sample project was written and tested with a Pocket PC 2003. On brief testing with the 2002 emulator the context menu causes problems due to the way a tap and hold is handled and the control loses focus, thus the selection is removed, therefore no text is cut to the clipboard. I have yet to try on Pocket PC 2000/2002 device so I'd be interested in hearing if there are any problems encountered. It requires SDF v1.3 and I also recommend you are running the latest .NET Service Pack (SP3).

    ClipboardTest.zip (9.32 KB)
    #    |
    # Saturday, May 21, 2005

    SDF 1.3 Known Issues

    Firstly an apology to recent visitors to our website, we've just moved to a new server and are experiencing teething problems, so currently OpenNETCF forums and blogs are not working.

    This post is designed to highlight a few issues found with v1.3 and workarounds (if possible), I expect we will produce a refresh release shortly to resolve these:-

    • OpenNETCF.Configuration - in order to use these classes you'll need to replace the \windows\config\machine.config file with an amended version which correctly references the v1.3 runtimes (http://www.peterfoot.net/OpenNETCFConfigurationV13Workaround.aspx)
    • OpenNETCF.VisualBasic - This assembly is unusable in the compact framework as it references the desktop version of mscorlib.dll. No current workaround (other than using the functionality from elsewhere in the SDF since all of the methods here are wrappers to other parts of the SDF
    • OpenNETCF.WindowsCE.Forms - It appears this assembly is not correctly registered in the GAC on devices, this will cause a TypeLoadException when you reference a class from this library. To workaround this you can manually copy the assembly to your program folder on the device e.g. over activesync or add to your project as "Content" file
    • All assemblies appear as "Smart Device Framework" in the add reference dialog. If you scroll across (you may need to extend the columns) to the path you'll be able to determine the name of each assembly.
    • IDE Plugins for v1.3 may not correctly install on your machine. You may find the custom menu items don't do anything when clicked. You can still access all of the SDF and Application Blocks functionality by manually adding references to your project through the Add Reference dialog
    • (Update) Integrated help is not included in the v1.3 installer. However I've built a standalone installer with compiled help for all our libraries.

    Please use our bug submission tool if you encounter other errors, and try to give as much detail as possible. We will try and make arrangements for a refresh release shortly to overcome these issues, thanks for your patience.

    #    |
    # Friday, May 20, 2005

    ADOCE In The Hand v1.7 Completed

    The ADOCE wrapper is the first of our libraries to be updated with full support for Visual Studio 2005 Beta, integrating both the libraries and the help content.

    The main update is the v1.7 version of the COM Interop library which now has functionality for translating domain specific HResults into particular exception types, previously any ADO errors would result in a cryptic error code. I've also added some functionality to upsize databases from Pocket Access to Sql Server CE (.sdf).

    The v1.7 interop library shipped with the WindowsMobile community preview and will be used with the upcoming update of PocketOutlook In The Hand along with some further cool Windows Mobile stuff...

    #    |
    # Thursday, May 19, 2005

    OpenNETCF.Configuration v1.3 Workaround

    As I suspect many of you will be doing too, I'm recompiling one of our apps against the latest v1.3 release of the SDF. There is a minor bug in this release when using the OpenNETCF.Configuration classes due to the machine.config file which is installed with the SDF containing references to the v1.2 assemblies. The workaround is luckily quite straight-forward, simply replace your \windows\config\machine.config with an updated file referencing the v1.3 versions. You can use the version attached below:-

    machine.config.zip (1.72 KB)
    #    |
    # Monday, May 16, 2005

    SDF v1.3 for Visual Studio 2005

    So, I've heard a few requests for VS2005 support for the SDF. The reason we don't have this fully integrated into VS2005 yet is because the extensibility model is significantly changed from VS2003, and since it's a Beta product is still changing. Therefore we'll have a fully integrated installer nearer to the release of VS2005.

    In the mean time you can pull the dlls off of a machine with VS2003 and SDF v1.3 installed, or grab them here in a zip file. These are the exact same dlls as you'll get in the v1.3 setup. Just to set your expectations you wont get automatic deployment of the SDF cab files (these are included in the zip for manual deployment). You also won't get the full designer experience - if you use any of our forms controls you'll have to add it through code.

    If you encounter any issues using this version from within VS2005, be sure to file a bug report, and make sure you tell us what version of the .NETCF you are targetting (1 or 2) and what platform type (Pocket PC 2003, Windows Mobile 5.0 Smartphone etc) and which version of VS2005, though I wouldn't recommend using anything prior to Beta 2 now it is available.

    #    |
    # Sunday, May 15, 2005

    Windows Mobile Managed APIs Diagram

    During his session at MEDC, Robert Levy handed out copies of a cool class library diagram for the new Windows Mobile 5.0 managed APIs, thanks to Robert for allowing me to post the diagram here - simply print to a large sheet of paper and enjoy :)


    WM5APIs.gif (242.62 KB)

    #    |
    # Tuesday, May 10, 2005

    Windows Mobile 5.0 Managed APIs

    The much anticipated update to Windows Mobile has been announced by Bill Gates this morning. This new platform will be the first platform from Microsoft to include device specific managed APIs in ROM (separate from the .NET Compact Framework itself). These allow access to configuration, telephony, pocket outlook etc from managed code.

    But what about existing devices? To add to our existing PocketOutlook library we have produced a WindowsMobile suite which includes a large proportion of WindowsMobile 5.0 APIs for previous versions. More details are available here.

    As well as supporting older generations of Windows Mobile, the suite also supports Windows Mobile 5.0, and one library in particular InTheHand.WindowsMobile.Gps provides a managed wrapper around the native GPS API in Windows Mobile 5.0

    In due time the PocketOutlook library v1.7 will be released with an object model more closely aligned to Windows Mobile 5.0 APIs.

    #    |
    # Monday, May 02, 2005

    Emulate Screen Taps

    You can simulate user activity on your touch-screen device by using the mouse_event API to send the system screen taps. There are a number of reasons you might want to do this from testing your application through to automating some third-party application, the following is example code to send a tap (and release) to any screen co-ordinate:-

    [DllImport("coredll")]
    private static extern void mouse_event(MOUSEEVENTF dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

    [Flags()]
    private enum MOUSEEVENTF
    {
    MOVE = 0x1, /* mouse move */
    LEFTDOWN = 0x2, /* left button down */
    LEFTUP = 0x4, /*left button up */
    RIGHTDOWN = 0x8, /*right button down */
    RIGHTUP = 0x10, /*right button up */
    MIDDLEDOWN = 0x20, /*middle button down */
    MIDDLEUP = 0x40, /* middle button up */
    WHEEL = 0x800, /*wheel button rolled */
    VIRTUALDESK = 0x4000, /* map to entrire virtual desktop */
    ABSOLUTE = 0x8000, /* absolute move */
    TOUCH = 0x100000, /* absolute move */
    }

    public void SendTap(int x, int y)
    {
    mouse_event(MOUSEEVENTF.LEFTDOWN | MOUSEEVENTF.ABSOLUTE, (int)((65535 / Screen.PrimaryScreen.Bounds.Width) * x), (int)((65535 / Screen.PrimaryScreen.Bounds.Height) * y), 0, 0);
    mouse_event(MOUSEEVENTF.LEFTUP, 0, 0, 0, 0);
    }

     

    The mouse_event method is fairly straight-forward, one thing to notice is that it doesn't accept screen co-ordinates but rather a value from 0 to FFFF in each direction, where FFFF, FFFF is the bottom right corner.


    #    |
    # Monday, April 18, 2005

    .NETCF v2.0 Beta 2 Redistribuable Package

    I'm sure I don't need to mention that Microsoft recently released Beta 2 of their Visual Studio 2005 tools. Alongside this release a redistributable version of the .NETCF v2.0 runtime is available so that you can download to your devices and test code you can download the package here.

    Ilya Tumanov posted some useful information on the release on the newsgroup:-

    "Visual Studio 2005 download is not required; installation of NETCF V2 Beta
    2 won't break existing VS 2003 and/or NETCF V1.
    It also works side by side with CF V1 on device (in ROM or RAM).

    If you're planning to install VS 2005 Beta 2 later on, you would have to
    uninstall NETCF V2 prior to VS installation.

    We would appreciate if you try your CF V1 application(s) under V2 and
    report incompatibilities so we could fix them.

    Here's how to run existing V1 applications under V2:

    1. Install V2 on to the device (via Active Sync or copy CAB file to the
    device and click on it).
    2. Create a configuration file named <App_Name>.exe.config as follows:

    <configuration>
    <startup>
    <supportedRuntime version="v2.0.5056"/>
    </startup>
    </configuration>

    To try application without V1 compatibility enabled, the following section
    can be added:

    <runtime>
      <compatibilityversion major="2" minor="0"/>
      </runtime>

    To run V2 application in V1 compatibility mode (for example if V2 app uses
    V1 component), section can be changed as follows:

    <runtime>
      <compatibilityversion major="1" minor="0"/>
      </runtime>

    3. Copy configuration file to the application folder.
    4. Run application as usual.

    Please report problems with installation and/or compatibility to this NG.
    For CAB problems, please attach CAB log file "Microsoft .NET CF
    2.0.LOG.TXT" which can be found in device's root folder. Thanks."

    Even if you are not currently evaluating the Visual Studio 2005 tools, I would recommend downloading these runtimes and testing your existing code - there are a number of cases where behaviour has changed in v2.0 but as you can see above you can run an app with v1.0 compiled code in compatibility mode.

    #    |
    # Friday, April 15, 2005

    The great Media Player 10 Automation Challenge!

    Media Player 10 is the first device version to have an automation model. Previous versions could be controlled via some undocumented windows messages but that was about it. The Media Player 10 Mobile object model is COM based, so you can't use it directly from .NETCF v1.0. I set about creating a wrapper months ago but it got left due to lack of time. However I've decided there is enough functionality available in it now for it to function. I've not had time to create a sample application, so your challenge if you choose to accept it (and I'll be honest there isn't a prize!) is to create something using the assembly.

    Because theres no support for hooking com events with a sink interface the wrapper exposes no events, also because there isn't ActiveX hosting support you won't get any UI - so this is useful for audio content only. The other big limitation is that you must have Media Player 10 on your device.

    Other than that feel free to have a play and see what fun you can have with it, any issues suggestions or cool creations you build with it please drop me an email or post a comment.

    Download InTheHand.MediaPlayer.zip

    #    |
    # Monday, April 04, 2005

    Time to turn out the lights...

    Time to provide a little balance to the previous piece on SetPowerRequirement for Smartphone which looked at the scenario of ensuring the backlight remained on. You might also want to manually turn off the backlight (or another peripherial) to save power. You can do this with SetDevicePower. You pass in the identifier of the hardware device ("BKL1:" being the backlight on most devices), and a power state - thus the backlight can be powered off with the following:-

    SetDevicePower("BKL1:", POWER_NAME, DevicePowerState.D4);

    POWER_NAME is passed in to the flags argument to indicate that the first argument represents a device name. The Power states run from D0 full power to D4 power off. And without further ado, the P/Invoke:- 

    public enum DevicePowerState : int
    {
    Unspecified = -1,
    D0 = 0, // Full On: full power, full functionality
    D1, // Low Power On: fully functional at low power/performance
    D2, // Standby: partially powered with automatic wake
    D3, // Sleep: partially powered with device initiated wake
    D4, // Off: unpowered
    }

    private const int POWER_NAME = 0x00000001;

    [DllImport("coredll")]
    private static extern int SetDevicePower(
    string pvDevice,
    int dwDeviceFlags,
    DevicePowerState DeviceState);

    #    |
    # Friday, March 04, 2005

    Control and Component Designers Part Four - Events

    This is a quick addendum to part three. In that section we looked at un-hiding some properties in the standard controls which were implemented in .NETCF SP2. As well as adding Fore and Back colour support, SP2 introduced support for a few more events which were declared in the original classes but never fired. Specifically these include the keyboard events KeyDown, KeyUp and KeyPress. Just like the colour properties these can be added to our design time assembly so that we can hook these events from the designer.

    [Browsable(true),
    Category("Key"),
    Description("Occurs when a key is first pressed.")]
    public new event KeyEventHandler KeyDown;

    [Browsable(true),
    Category("Key"),
    Description("Occurs after a user is finished pressing a key.")]
    public new event KeyPressEventHandler KeyPress;

    [Browsable(true),
    Category("Key"),
    Description("Occurs when a key is released.")]
    public new event KeyEventHandler KeyUp;

    We declare the events "new" so that they will replace the base class implementation, but as this is design time only, the code generated hooks the events that already exist in the Control class. The category and description attributes improve the grouping in the property pane.

    The last event item to cover is the DefaultEventAttribute which can be applied to a class. In our PictureBoxEx class we inherit from the standard PictureBox (Thanks to Sergey Bogdanov for submitting the code). Because I have now added a Click event to the designer (In SP2 the PictureBox supports the Click event) we can make this the default event for the class, so that when you double click on the control in the designer it will automatically rig up a handler for you and drop you into the appropriate place in the code. This makes a little more sense that the PictureBox for which the default event is ParentChanged.

    #if DESIGN
        [DefaultEvent("Click")]
        public class PictureBoxEx : System.Windows.Forms.PictureBox
    #else    
        public class PictureBoxEx : System.Windows.Forms.PictureBox, OpenNETCF.Windows.Forms.IWin32Window
    #endif

    Part 1 | Part 2 | Part 3 | Part 4

    #    |

    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.

    #    |
    # Wednesday, March 02, 2005

    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. \bin\Designer 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 \bin\Designer\ 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 Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Designer

    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 16x16 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

    #    |
    # Tuesday, March 01, 2005

    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

     

    #    |
    # Wednesday, February 23, 2005

    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.

    #    |
    # Friday, February 18, 2005

    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.

    #    |
    # Wednesday, February 09, 2005

    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.

    #    |
    # Monday, February 07, 2005

    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

     

    #    |
    # Sunday, February 06, 2005

    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.

    #    |
    # Thursday, February 03, 2005

    Potted history (and glimpse into the future) of the .NET Compact Framework

    Mike Zintel has posted a description of how the .NET Compact Framework got to where it is today, and where the team are headed in v2.0 and beyond.

    Key lessons learned by the team were in performance, interop and a few bloopers like the infamous DateTimePicker - the control which should never have been left out. The good news is that all these areas are receiving attention for v2.0.

    A focus for v3.0 will be managing transient networks - being able to seamlessly use a connection as and when available, based on emerging WS-* standards. We will see some improvements in this area before v3.0 as the Windows Mobile team have already announced the Notifications Broker for their next version which will support events on key system changes, however this won't be available to other Windows CE based platforms. The problems faced are not just in choosing and activating the most appropriate connection, but handling situations where the connection is lost part way through a process, a real problem when your devices are constantly on the move, in and out of network coverage.

    My personal wishlist for v3.0 would add more support for location and context awareness, so that apps can be a little more smart to react to changes not just in network connectivity but also changing usage profiles such as sound and appearance for different locations and times.

    Once you've read Mike's article you can check out some of his wonderful photographs too at http://www.zintel.net/.

     

    #    |
    # Tuesday, January 25, 2005

    More details on Generics and Reflection for .NETCF v2.0

    Nazim Lala from the .NET Compact Framework team has posted further details on the generics support in .NETCF v2.0 specifically the Reflection functionality available and how it differs from the full framework implementation.
    #    |
    # Saturday, January 15, 2005

    Bluetooth Build 50115

    I've posted an updated build of the Bluetooth library here. It adds full support for the desktop, improved class-of-device and other properties.

    The sample app is now supplied in Pocket Pc, Smartphone and Desktop versions which all talk to each other.

    #    |
    # Wednesday, January 05, 2005

    .NETCF Service Pack 3 is out - Go Get It!

    .NETCF SP3 Redistributable can be downloaded from here:-

    http://www.microsoft.com/downloads/details.aspx?amp;displaylang=en&familyid=a5a02311-194b-4c00-b445-f92bec03032f&displaylang=en

    List of fixes grabbed from the above page:-

    Fixed Issues:
    - Transitions between managed and native code can cause memory leaks on ARM platforms.
    - A NullReferenceException is thrown when a Web Method returns an empty array using the xsi:Nil attribute.
    - Modifying the SoapClientMessage.ContentType property does not modify the Http requests ContentType header.
    - Stack corruption can occur on SH, MIPS and x86 platforms when local variables are created but never used.
    - Invoking a multicase delegate from a catch handler throws a MissingMethodException on SH, MIPS and x86 platforms.
    - Command line arguments containing double byte characters are truncated to a single byte.
    - An ObjectDisposedException is thrown when a asynchronous web request is aborted before the response is received.
    - Invoke on a disposed control hangs the application.
    - Any array containing one or more elements is not sent to the Web Service correctly.
    - An application may hang when invoking a Web Method that uses multiple XmlElementAttributes on a single argument, member or property.
    - Memory corruption can occur on devices that have the native security model enabled and both .NET CF V1 SP3 and a pre-release version of .NET CF V2 installed.
    - Deadlocks can occur when running under severe resource constraints.
    - Tool Bar's on Windows Mobile 2003 SE no longer lose their images when removed from the form.
    - An uncatchable ObjectDisposedException is thrown when the server closes the socket connection.
    - Setting the Minimum and Maximum properties of a progressbar no longer crashes the application.
    - Unexpected exception while adding an image to an imagelist on an Hx4700 and hx4705.
    - Data Misalignment occurs on Decimal fields in MIPSIV devices.

    #    |
    # Tuesday, January 04, 2005

    GetEntryAssembly for .NETCF

    If your application contains multiple levels of DLL files, you may want to determine the name and path of the original calling executable. On the desktop you can use Assembly.GetEntryAssembly() but this is not available in the Compact Framework. I have added an equivalent to the SDF code to work in just the same way, using Platform Invoke. It uses the GetModuleFileName API which when passed IntPtr.Zero for the module handle, returns the path of the calling exe. Assembly.LoadFrom is then used to return the Assembly object corresponding to this path. Since the exe is already loaded this will not increase the overhead of your application. From the returned Assembly object you can determine the Path, Version etc as required.

    The full code for AssemblyEx is available in the online Source Browser, and will be built into a future SDF release.

    #    |
    # Friday, December 24, 2004

    Rudolph the Bluetoothed Reindeer

    I've uploaded a new release of the Bluetooth library which adds the key feature of hosting services over bluetooth. This now allows two-way communications between devices and to demonstrate how this works I've included a sample Bluetooth Chat application. This registers a custom bluetooth profile and listens for incoming connections, and creates outgoing connections using this service identifier to other devices. In this way it only communicates with other devices exposing this service and wont interfere with any other applications using Bluetooth.

    Thanks go out to Wei-Meng Lee for giving permission to base the sample on his previous IrDA chat application available with this MSDN article. The Bluetooth version works in a very similar way, with the exception of doing a device discovery when it first loads. An enhancement yet to be added is the ability to periodically discover in a background thread. From the app screen select the target device which must also be running the software and Bluetooth must be Discoverable. Then type your message and click send and it will appear onscreen on the other device. In the below example I had a brief conversation with Santa who was half-way up a chimney at the time - such is the versatility of Bluetooth :)

    Bluetooth Chat

    The ZIP file below includes the Bluetooth library project and compiled output, and the BTChat sample project. As I get time to do more work on the library I'll post some other examples, and include versions for other platforms e.g. Smartphone and XP.

    Known issues:-

    • Hosting services doesn't yet work on XP (some of the structures are slightly different so this requires a little more work)
    • BluetoothClient.RemoteDeviceName doesn't work so you can't retrieve the device name from an open connection (Device names work correctly during discovery on both Windows CE and XP)
    • BluetoothSerialPort (For emulating a COM port) is not fully tested and probably doesn't work - SerialPortProfile connections work great using sockets (BluetoothClient).

    Requirements:-

    • SDF v1.2
    • Windows CE Device or Windows XP computer using the Microsoft Bluetooth stack (Sorry but Widcomm is not supported).

    Download:-

    Downloads

     

    If you have any comments or questions please drop me an email. For now all that remains is for me to wish you a Very Merry Christmas!

    #    |
    # Wednesday, December 15, 2004

    New in .NETCF v2.0

    Jono posted a link to a new section in the online Beta documentation at MSDN which describes in some detail whats new in v2.0 of the Compact Framework. This includes new framework features and a list by namespace of the new classes introduced in v2.0.

     

    #    |
    # Thursday, December 09, 2004

    Online Bluetooth code updated

    There were some recent enquries on the OpenNETCF Forums about the current Bluetooth code. It seems I had refreshed the website with some development code which would only work if a couple of items were commented out. This is because these classes (Sdp related) are still under development and require COM interop and are currently built against InTheHand.Interop.dll which does COM interop with no native DLL required, and is used in my PocketOutlook and ADOCE products.

    So I've updated the code online and attached a .zip of the project below which will build successfully against the v1.2 SDF (and the compiled dll is included in the bin folder). Documentation is in the online library at http://32feet.net/library/

    I'm working on a sample application to accompany the library, but it's been tested with a Bluetooth GPS unit and a Jabra headset successfully (Before you ask it only uses the control functionality of the headset, not the audio stream). But you can programmatically make the headset ring and capture the event when the user presses the answer button. Not terribly exciting but an interesting start, I guess I need some more unusual Bluetooth devices to test against.

    What isn't working in this release is the ability to host a service and allow other devices to discover it, since this requires some of the ongoing Sdp work. Once this is in place you will be able to do data transfer between devices which is when the fun will really begin!

    Also bear in mind this is designed to work only with devices with the Microsoft Bluetooth stack, for example HTC Phone Edition devices and most Smartphone 2003 models.

    Downloads

    #    |
    # Saturday, December 04, 2004

    Forms Anywhere built around OpenNETCF Smart Device Framework

    Via Jono's Blog:-

    'Forms Anywhere is an attempt to provide a development platform for data capture using the Pocket PC. It handles all data collection tasks from creation to capture, all that is needed on the back end is the code to integrate your application.'

    The code for Jim Lavin's Forms Anywhere is available in a GotDotNet workspace. The project uses OpenNETCF's Smart Device Framework for missing controls such as the DateTimePicker and the Desktop Communications library to implement desktop synchronisation. An impressive project, well worth a look.

    #    |

    Using OpenNETCF.Phone.Sms

    Dag König has posted an example to his blog showing how to add Sms sending to your application using the OpenNETCF.Phone.Sms class and just 4 lines of code - check it out.

    #    |
    # Wednesday, December 01, 2004

    New version of .NETCF GDI+ Library

    XcrossOne Studio have just released a new v1.2 release of their incredible looking GDI+ library for .NETCF. A key change in this release is a switch to a Shared Source license, similar to what we use with our OpenNETCF projects.

    This means that you are no longer restricted to releasing any works using the code in source form, this should have a dramatic effect on the number of people able to use the library. You can achieve some pretty impressive visuals, as demonstrated in the large gallery of samples on the site. This latest version adds the ability to combine raster images and anti-aliased text with the vector based drawing.

    #    |
    # Saturday, November 27, 2004

    CLS Compliant WaitForSingleObject

    Maartens recent blog post highlighted an issue with the current SDF implementation of Core.WaitForSingleObject when used from VB.NET since this method was not CLS Compliant and used unsigned integer types for both parameters and return type. Because of the values used by this function its very easy to convert it to be CLS compliant, so from the next release you'll be able to call it just as easily from both C# and VB. The method only accepts a timeout value up to 0x7fffffff which incidently is the maximum positive value for an Int32. The exception to this is a special constant passed when you want to wait indefinately on a handle - 0xffffffff which just happens to be -1 when interpreted as a signed integer. The same transformations are posible on the Wait enumeration which is the return type for the method. The amended code is already up on the online source browser. Therefore to wait with a 1s timeout on a handle in a loop you can now do this from VB:-

    While WaitForSingleObject(myWin32Event, 1000) <> Wait.Object

                'do stuff here

    End While

    #    |
    # Monday, November 22, 2004

    Toggle Bluetooth on an iPaq device

    We can already enable and disable Bluetooth on devices equipped with Microsoft's Bluetooth stack. In the case of iPaq devices, which use the Widcomm stack, it is possible to toggle the radio state using an API provided in HP's iPAQUtil.dll. This can be P/Invoked from a .NETCF project like so:-

    [DllImport("iPAQUtil.dll", SetLastError=true)]

    public static extern bool iPAQSetBlueToothRadio(ref int lpdwValue);

    Which you can then call with:-

    int val = 0;

    iPAQSetBlueToothRadio(ref val);

    Where val is either 0 to disable Bluetooth, or 1 to enable it. Tested on an iPaq 2210 but should work on any other iPaq device with Bluetooth.

    Update:-

    The following should also work for devices with WiFi built in:-

    [DllImport("iPAQUtil.dll", SetLastError=true)]

    public static extern bool iPAQSetWLANRadio(ref int lpdwValue);

    But I've not been able to test this myself.
    #    |
    # Friday, November 19, 2004

    From the Mobility Road Show

    Thom Robbins posts some Powerpoint slides and code from the recent Mobility Road Shows. Check out "Mobility and Visual Studio 2005" for a good overview of NETCF 2.0 development features.

    #    |
    # Saturday, November 13, 2004

    Hosting a Native Windows Control - The desktop approach

    As a follow on to my recent article, I have compared and contrasted the System.Windows.Forms.Control classes in desktop and compact frameworks.
    #    |
    # Tuesday, November 09, 2004

    Hosting a Native Windows Control - Live on MSDN

    My latest .NETCF article is now live in the MSDN library. This is an update of the control hosting article previously published here at OpenNETCF.org. The process has been simplified so that there is now a standard base class (ControlEx) which does most of the hard work for you, the process of hosting a control is therefore much closer to the desktop experience. The article contains a sample using the WebBrowser control, which shows not only setting properties and calling methods for the control, but also reacting to notifications from the native control.

    #    |
    # Tuesday, November 02, 2004

    Open All Hours

    Sometimes you want to ensure that the system will not automatically close down your application when it goes into the background. You can achieve this by handling the Closing event of your main form, the event arguments passed to your handler will allow you to Cancel the close. Therefore you can set a boolean member to ensure that the operation only succeeds once you decide it's okay to close:-

    bool keepopen = true;

    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)

    {

       if(keepopen)

       {

          e.Cancel = true;

       }

    }

     

    Then based on some pre-determined action in your program you can set keepopen to false and the form will close down.

    #    |

    The Naked Emulator

    If you want to display the standard Pocket PC emulator without the regular skin, so just the screen itself is shown you can modify a couple of the settings files and skin bitmaps. For the default Pocket PC 2002 emulator you'll find the files here by default:-

    C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\ConnectionManager\Bin\Images\PocketPC\2002\1033

    Make a backup before you alter anything!

    Then replace the ppc2002.xml file with this one. Finally add this image to the folder which is the null skin, necessary in order that the emulator window is sized correctly. The finished result should look like this:-

     

    Naked Emulator
    #    |
    # Friday, October 29, 2004

    Great Installation advice on the Smartphone Developer newsgroup

    Lars Peter recently posted this excellent post on the microsoft.public.smartphone.developer newsgroup.

    In the post Lars describes using Nullsoft Installer (NSIS) to build a desktop installation package to include multiple cab file installations. This is ideal for those scenarios when you want to deploy more than just one application cab file, for example OpenNETCF's Smart Device Framework, Sql Ce or the .NETCF runtimes themselves.

    Lars' post includes a sample install script, which you can pass a number of cab files for installation. You can also download the sample script from Lars' server.

    Nice one Lars!

    #    |
    # Wednesday, October 20, 2004

    Need a GUID in a hurry?

    There may be times in your application you need to generate a new unique Guid. The System.Guid class in .NETCF v1.0 doesn't have the NewGuid method which is what you would normally use on the desktop. There are a couple of proposed alternatives, either generating one yourself by following the standards for Guids - using a few P/Invokes to Crypto API methods to get random numbers, using the GuidEx class which uses the same technique or indirectly using SqlCe to create a new identity value.

    An easier way in many cases is to use one of the COM subsystem API methods as this involves only a single P/Invoke call. The only caveat to this is that not all CE based systems have full COM support - there are three varieties Minimal COM, Full COM and DCOM support. Minimal COM doesn't support Guid generation. However in my brief experimentation with Platform Builder it would appear that among .NETCF's prerequisites is COM support so this should in theory be supported by any CE device on which .NETCF is supported. It is certainly supported on all Windows Mobile devices:-

    namespace InTheHand

    {

          ///

          /// Helper class for generating a globally unique identifier (GUID).

          ///

          /// "System.Guid"/>

          public sealed class ComGuid

          {

                private ComGuid(){}

     

                ///

                /// Initializes a new instance of the "System.Guid"/> class.

                ///

                /// A new "System.Guid"/> object

                public static Guid NewGuid()

                {

                      Guid val = Guid.Empty;

     

                      int hresult = 0;

     

                      hresult = CoCreateGuid(ref val);

     

                      if(hresult != 0)

                      {

                            throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error(), "Error creating new Guid");

                      }

     

                      return val;

                }

     

                [DllImport("ole32.dll", SetLastError=true)]

                private static extern int CoCreateGuid(ref Guid pguid );

          }

    }

     

    #    |
    # Thursday, October 14, 2004

    Create a Top-Most form

    The following code can be used to force your form to the top of the z-order. Use this functionality with care since it's bad practice to hog the topmost position which could obscure other important functionality.

    private void Form1_Load(object sender, System.EventArgs e)

    {

          //get handle

          this.Capture = true;

          IntPtr hwnd = OpenNETCF.Win32.Win32Window.GetCapture();

          this.Capture = false;

     

          //set foreground

          OpenNETCF.Win32.Win32Window.SetWindowPos(hwnd, Win32Window.SetWindowPosZOrder.HWND_TOPMOST, 0, 0, 0, 0, Win32Window.SetWindowPosFlags.SWP_NOMOVE | Win32Window.SetWindowPosFlags.SWP_NOSIZE | Win32Window.SetWindowPosFlags.SWP_SHOWWINDOW);

     

    }

    Note that this code cannot be placed in the form constructor, since the native form has yet to be created so a valid window handle won't be returned. Here the code is placed into the Form_Load method.

    In .NETCF 2.0 you can set the TopMost property of your form which removes the need for any of this interop (Thanks Daniel Moth for correcting this).

    #    |
    # Wednesday, October 13, 2004

    .NETCF Chat Tomorrow

    As part of a regular series of .NETCF technical chats there will be an MVP hosted chat tomorrow (14th October) on any aspect of .NET Compact Framework and Smart Device programming. 10-11am PDT, 17-18 GMT

    Add a reminder to your calendar

    More details, and details of other technical chats, here at MSDN.

    #    |
    # Saturday, October 09, 2004

    Bring a .NETCF Form to the foreground

    Sometimes calling BringToFront for your form is not enough to bring your app to the foreground. You can P/Invoke SetForegroundWindow which will activate your app and bring the window to the front of the Z-Order:-

    C#

    public void SetForegroundWindow()
    {
        this.Capture = true;
        IntPtr hwnd = OpenNETCF.Win32.Win32Window.GetCapture();
        this.Capture = false;
        OpenNETCF.Win32.Win32Window.SetForegroundWindow(hwnd);
    }

    or VB

    Public Sub SetForegroundWindow
        Me.Capture = True
        Dim hwnd As IntPtr = OpenNETCF.Win32.Win32Window.GetCapture()
        Me.Capture = False
        OpenNETCF.Win32.Win32Window.SetForegroundWindow(hwnd)
    End Sub

    #    |
    # Thursday, October 07, 2004

    Fixing ComboBox bugs...

    The standard ComboBox in NETCF has a couple of "issues", however it's possible to workaround them with a bit of tweaking. I rolled together a number of these fixes into a ComboBoxEx class. Heres the code (C#), I hope this (with a few more missing features) will be in the next SDF build with designer support like our other controls:-

    namespace OpenNETCF.Windows.Forms

    {

          /// <summary>

          /// Extended ComboBox control.

          /// </summary>

          public class ComboBoxEx : ComboBox, IWin32Window

          {

                //windows messages

                private const int WM_SETREDRAW = 0x0b;

                private const int CB_SETCURSEL = 0x014E;

                private const int CB_DELETESTRING = 0x0144;

                private const int CB_INSERTSTRING = 0x014A;

     

                //native window handle

                private IntPtr m_handle;

     

                //databound collection

                private IBindingList thebindinglist = null;

     

                //is display updatable?

                private bool m_updatable = true;

     

                /// <summary>

                /// Gets the window handle that the control is bound to.

                /// </summary>

                public IntPtr Handle

                {

                      get

                      {

                            if(m_handle == IntPtr.Zero)

                            {

                                  this.Capture = true;

                                  m_handle = Win32Window.GetCapture();

                                  this.Capture = false;

                            }

     

                            return m_handle;

                      }

                }

     

                // Redraw code courtesy of Alex Feinman - http://blog.opennetcf.org/afeinman/PermaLink,guid,9305a1d9-e24e-4310-89e2-f80808076a37.aspx

     

                /// <summary>

                /// Maintains performance when items are added to the <see cref="ComboBoxEx"/> one at a time.

                /// </summary>

                public void BeginUpdate()

                {

                      m_updatable = false;

     

                      Win32Window.SendMessage(this.Handle, WM_SETREDRAW, 0, 0);

                }

     

                /// <summary>

                /// Resumes painting the <see cref="ComboBoxEx"/> control after painting is suspended by the <see cref="BeginUpdate"/> method.

                /// </summary>

                public void EndUpdate()

                {

                      m_updatable = true;

                      Win32Window.SendMessage(this.Handle, WM_SETREDRAW, 1, 0);

                }

     

                //ComboBox doesn't support ItemChanges in a datasource implementing IBindingList

                //The following workaround forces the list to update if an item is changed

     

                //data source has changed

                protected override void OnDataSourceChanged(EventArgs e)

                {

                      //remove event handler

                      if(thebindinglist != null)

                      {

                            thebindinglist.ListChanged-= new ListChangedEventHandler(ComboBoxEx_ListChanged);

                            //reset our handle to the bound data

                            thebindinglist = null;

                      }

     

                      //get the underlying ibindinglist (if there is one)

                      if(this.DataSource is IListSource)

                      {

                            IList thelist = ((IListSource)this.DataSource).GetList();

                            if(thelist is IBindingList)

                            {

                                  thebindinglist = (IBindingList)thelist;

                            }

                      }

                      else if(this.DataSource is IBindingList)

                      {

                            thebindinglist = (IBindingList)this.DataSource;

                      }

                     

                      if(thebindinglist != null)

                      {

                            //hook up event for data changed

                            thebindinglist.ListChanged+=new ListChangedEventHandler(ComboBoxEx_ListChanged);

                      }

                     

                      base.OnDataSourceChanged (e);

                }

     

                //called when a change occurs in the bound collection

                private void ComboBoxEx_ListChanged(object sender, ListChangedEventArgs e)

                {

                      if(m_updatable)

                      {

                            if (e.ListChangedType == ListChangedType.ItemChanged)

                            {

                                  //update the item

     

                                  //delete old item

                                  Win32Window.SendMessage(this.Handle, CB_DELETESTRING, e.NewIndex, 0);

                                  //get display text for new item

                                  string newval = this.GetItemText(this.Items[e.NewIndex]);

                                  //marshal to native memory

                                  IntPtr pString = MarshalEx.StringToHGlobalUni(newval);

                                  //send message to native control

                                  Win32Window.SendMessage(this.Handle, CB_INSERTSTRING, e.NewIndex, pString);

                                  //free native memory

                                  MarshalEx.FreeHGlobal(pString);

                            }

                      }

                }

     

                /// <summary>

                /// Get or Set the selected index in collection.

                /// </summary>

                /// <remarks>Overridden to overcome issue with setting value to -1 (http://support.microsoft.com/default.aspx?scid=kb;en-us;327244)</remarks>

                public override int SelectedIndex

                {

                      get

                      {

                            return base.SelectedIndex;

                      }

                      set

                      {

                            if(value == -1)

                            {

                                  Win32Window.SendMessage(this.Handle, CB_SETCURSEL, -1, 0);

                            }

                            else

                            {

                                  base.SelectedIndex = value;

                            }

                      }

                }

     

          }

    }

     

    So whats in the above code? Well it integrates Alex Feinman's recent tip to implement Begin/EndUpdate methods to suspend redrawing when populating the control.

    Secondly if works around a bug in the DataBinding support for ComboBox. If you make an edit to an existing item in the bound collection the combo wont normally update (It does correctly react to additions and deletions).

    Thirdly it overcomes a known issue with resetting the selected index property (by assigning -1) which normally has to be done twice to take effect - details in this KB article - Thanks to Tim Wilson for posting this KB on the newsgroup.

    As a Bonus I've added a Handle property so you can get at the native control handle - which in conjunction with Win32Window methods allows you to tweak other aspects of the control.

    UPDATE: Changed the databinding code to update a single item via P/Invoke rather than refreshing the list. Changed the SelectedIndex to set via P/Invoke - avoids raising the SelectedIndexChanged event.

    #    |
    # Saturday, October 02, 2004

    Some new OpenNETCF code

    I've uploaded to our online source browser some of the new code which will feature in the next Smart Device Framework release. This includes a new library for WindowsCE specific functionality, designed to match the new functionality available in the Microsoft.WindowsCE.Forms assembly in the .NET Compact Framework v2.0 which is currently in Beta with Visual Studio 2005.

    For Smartphone developers this includes the InputModeEditor which allows you to set a specific input mode for an edit control. Therefore when the control receives focus, the required input mode is automatically selected for the user - useful for numeric only fields or a field where you want to capture some form of text but know that T9 would be inappropriate.

    For Pocket PC 2003 Second Edition the SystemSettings class allows you to easily change the screen orientation with a single statement:-

    SystemSettings.ScreenOrientation = ScreenOrientation.Angle90;

    There are also some changes to existing classes - specifically the RegistryKey has had a number of useful changes:-

    • ToString now matches the behaviour on the full .NET Framework (In the current release there is a subtle difference in the format of the string returned)
    • CreateSubKey allows you to create volatile registry keys on supported Windows CE 5.0 systems.
    • GetValue now correctly returns DWORD values as an Int32 rather than UInt32, this is now consistent with the desktop and makes life a lot easier.
    • We have a full implementation of GetValueKind and the RegistryValueKind enumeration - this functionality is part of the full .NET Framework v2.0 Beta but we are making it available now for .NETCF v1.0

    All of this code is currently available in the source tree which you can browse online. Object model documentation has also been updated in the online library - which now exceeds 6000 individual pages. Expect to see all this code built into the next binary release.

    #    |
    # Friday, September 17, 2004

    New Visual Studio 2005 edition announced

    One of the stumbling blocks to getting into .NETCF development today is that the only supported tool for development is Visual Studio 2003 Professional or higher.

    Microsoft announced today at VSLive a new addition to the Visual Studio family in the 2005 version - Visual Studio Standard Edition. This will be a significantly cheaper version of Visual Studio but will include the full device development experience with both VB.NET and C# for managed code and C++ for native code.

    A more detailed comparison of the editions is available here:-

    http://lab.msdn.microsoft.com/vs2005/productinfo/productline/default.aspx

    The full press release can be viewed here:-

    http://www.microsoft.com/presspass/press/2004/sep04/09-13VSLiveOrlandoPR.asp

    #    |
    # Thursday, September 09, 2004

    Keep your Smartphone backlight on

    If your application involves displaying screen content you probably have come across the issue where the screen backlight turns off after a few seconds of no keypresses. You can override this behaviour in your application using a couple of underdocumented API Power-Management functions. Here is a VB.NET snippet for .NETCF to keep the backlight on:-

    Namespace OpenNETCF.WindowsCE.Forms

     

    Public Class Backlight

     

    'ensure the power requirement is released

    Protected Overrides Sub Finalize()

    Release()

    End Sub

    'handle to the power requirement

    Private handle As IntPtr

     

    Private Enum PowerState

    PwrDeviceUnspecified = -1

    'full on

    D0 = 0

    'low power

    D1 = 1

    'standby

    D2 = 2

    'sleep

    D3 = 3

    'off

    D4 = 4

    PwrDeviceMaximum = 5

    End Enum

     

    'keep the backlight lit

    Public Sub Activate()

    'request full power

    handle = SetPowerRequirement("BKL1:", PowerState.D0, 1, IntPtr.Zero, 0)

    End Sub

     

    'release power requirement

    Public Sub Release()

    If handle.ToInt32() <> 0 Then

    Dim result As Integer

    result = ReleasePowerRequirement(handle)

    handle = IntPtr.Zero

    End If

    End Sub

    Private Declare Function SetPowerRequirement Lib "coredll.dll" (ByVal pvDevice As String, ByVal DeviceState As PowerState, ByVal DeviceFlags As Integer, ByVal pvSystemState As IntPtr, ByVal StateFlags As Integer) As IntPtr

    Private Declare Function ReleasePowerRequirement Lib "coredll.dll" (ByVal handle As IntPtr) As Integer

    End Class

    End Namespace

    Thanks to Paul O'Brien from MoDaCo for inspiring and helping test the code.

    #    |
    # Thursday, August 12, 2004

    Upcoming Smart Device Chat

    There is a smart device programming chat starting in about 45 minutes from now:-

    MVP chat: .NET Compact Framework and Smart Device Programming
    You know them from the newsgroups! You love them for their immense knowledge! Please join these amazing Microsoft MVPs in this live chat regarding the .NET Compact Framework and the Smart Device Programming features of VS.NET. The .NET Compact Framework is a subset of the .NET Framework designed to allow .NET developer to target smart devices. The Smart Device Programming features of VS.NET allow embedded developers to target devices running the .NETCF.

    August 12, 2004
    10:00 - 11:00 A.M. Pacific time
    1:00 - 2:00 P.M. Eastern time
    17:00 - 18:00 GMT


    Event Reminders


    OutlookAdd to Outlook Calendar
    FriendTell a Friend

    #    |
    # Wednesday, August 11, 2004

    Casey posts detailed .NETCF v2.0 base class library changes

    The poster announced in the previous post gives a fairly high-level view of API changes between versions of the .NET Compact Framework. Casey Chesnut has posted a very detailed member-by-member comparison of v1 and v2 of the Compact Framework. This includes some exciting stats of the number of types, methods and properties supported in the base class libraries, and a complete alphabetical list of types.

    #    |
    # Saturday, July 31, 2004

    New .NET Compact Framework poster available for download

    Its been a bit of a moving target but I've finally released a current version of the .NET Compact Framework Versions poster. The aim is to show a fairly detailed view of the functionality available in .NET Compact Framework v1.0, that which is expected in v2.0, and the functionality available in the next version of Windows Mobile. This is contrasted against the functionality available now in the OpenNETCF Smart Device Framework v1.2.

    The poster is divided into two main sections, the functionality which is unique to the Smart Device Framework is down the righthand side in the blue section. The increasing functionality in the .NET Compact Framework from v1.0, v2.0 and functionality specific to future Windows Mobile devices is arranged down the left in increasing intensities of green.

    A number of our Smart Device Framework classes are not wholly unique and either extend those available in the Compact Framework v1.0, or directly match those which will form a part of the Compact Framework v2.0. These are shown on the diagram in Blue - To avoid naming conflicts these have the "Ex" prefix on their name, and our root namespace is "OpenNETCF" as apposed to "System" or "Microsoft".

    All of the future functionality is subject to change since these are based on functionality which has been announced and things may be added, removed or re-architected between now and the Compact Framework v2.0 (and future Windows Mobile) being released. Therefore it is likely that this diagram will be periodically updated to keep it accurate. Of course it is likely that during this time the Smart Device Framework may gain additional functionality too, so this just represents a current snapshot of the functionality available to developers. It is worth noting that the Compact Framework has a growing community of third-party controls and components which are not included on this diagram, many of these also add functionality to the v1.0 framework which either pre-empts v2.0 or future Windows Mobile specific functionality, or adds whole new functionality than that show on this diagram. There is a section in the Wiki which lists some of these (and you are welcome to contribute to the wiki)

    .NET Compact Framework Versions Poster .NET Compact Framework Versions (PDF 422kb)
    Compares the functionality available in the .NET Compact Framework v1.0, v2.0, Windows Mobile v.Next and the OpenNETCF Smart Device Framework.
    Since .NET Compact Framework v2.0 and Windows Mobile v.Next are not yet released these details are subject to change and are based on recent public announcements and the functionality available in Visual Studio 2005 Beta 1.

    #    |
    # Tuesday, July 20, 2004

    Using the Smart Device Framework?

    If you are using the Smart Device Framework in your software then why not take up Neil's offer of free publicity in an upcoming webcast.

    Chris and Neil will be giving a webcast next Wednesday, and you can submit your Logo or Screenshots of your app to Neil for a quick showcase of all the cool things people are doing with OpenNETCF code. Full details here:-

    http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032254427&Culture=en-US

    #    |
    # Sunday, July 18, 2004

    NDoc with Visual Studio 2005 Beta1

    I saw this post by Steve and realised that I hadn't tried NDoc with Whidbey B1 yet. I was able to get it to work flawlessly, though perhaps my particular configuration is unusual.

    I'm running inside a Virtual PC image, into this I added an absolute bare-bones installation of XP Pro, I've applied SP2 RC2 but no other updates - at this moment it doesn't have the .NET Framework v1,1 installed. Next I installed Whidbey Beta1 with pretty much all the options including the MSDN documentation. I built a very simple C# Pocket PC project, usual hello world stuff, added the configuration option to build xml documentation and built the project.

    I then went off to the NDoc website to download the v1.3 Beta installer. However this checks for .NET v1.1 and won't install without it. Getting worried that installing v1.1 after v2.0 B1 might cause problems I promptly backed out. My alternative was to share a folder on the host PC and copy across NDoc 1.3 Beta from there. The program loaded flawlessly against the v2.0 Beta1 framework. I then had no problems documenting my .NETCF v2.0 project. So I guess this is the key, if NDoc is running against the v1.1 framework it will choke when faced with a v2.0 assembly, but I don't intend to check this theory just yet (It's taken long enough to get this virtual machine set up just the way I want it!

    The solution should be to add a config file for NDoc which includes the following XML to prefer the v2.0 framework:-

    <configuration>
       <startup>
          <supportedRuntime version="v2.0.40607" />
       </startup>
    </configuration>

    Save this file as:- c:\program files\NDoc 1.3\bin\net\1.1\NdocGui.exe.config You may need to adjust this path depending on where you installed NDoc.

    The next step will to be to test with some more complex projects (like the Smart Device Framework).

    #    |
    # Wednesday, July 14, 2004

    Write cool .NETCF Code and win prizes

    Chris has announced our Coding Competition on his blog. This is a chance to win some cool prizes including a Smartphone Dev Kit, Visual Studio, Pocket PC, Compact Framework books and more!

    Looking forward to seeing the cool entries we are anticipating!

    #    |
    # Thursday, July 08, 2004

    .NET Compact Framework / Visual Studio for Devices Chat starts soon

    This months chat with the Visual Studio for Devices team is due to start in just under half an hour, logon here and bring your tricky questions for the product team members.

    Full details along with other online chats are listed at MSDN.

    #    |
    # Friday, June 18, 2004

    Automatic Capitalisation Of Words In A Text Box

    A question arose recently on the newsgroup of how to automatically capitalise the first letter of a word in a text box, e.g. by activating the shift key on the soft keyboard. Since there is no API for the SIP to do this the workaround is to simulate a mouse click over the position of the Shift key in the soft keyboard.

    An alternative method is to handle the TextChanged event on the TextBox and add some logic to capitalise words as the text is entered. The advantage here is that it is not dependent on a specific SIP being in use:-

    private void textBox1_TextChanged(object sender, System.EventArgs e)

    {

      //start with true as the first character should always be upper case

      bool makeUpper = true;

      //get the current text as a char array

      char[] oldText = textBox1.Text.ToCharArray();

      //create a new char array the same size for the new text

      char[] newText = new char[oldText.Length];

      //for each char

      for(int iChar = 0; iChar < oldText.Length; iChar++)

      {

        if(makeUpper)

        {

          //make the character upper-case and reset the flag

          newText[iChar] = Char.ToUpper(oldText[iChar]);

          makeUpper = false;

        }

        else

        {

          //copy the character as-is

          newText[iChar] = oldText[iChar];

        }

        //if it's a space the next character should be upper-case

        if(oldText[iChar] == ' ')

        {

          makeUpper = true;

        }

      }

      //assign the new value

      textBox1.Text = new String(newText);

      //position the cursor at the end of the text

      textBox1.SelectionStart = textBox1.Text.Length;

    }

    #    |
    # Sunday, June 13, 2004

    Vibration and Pocket PC devices

    A number of Pocket PC devices support Vibration as an alert method, most (but not all) are Phone Edition devices. The Vibrate class in the OpenNETCF.Notification library is specific to Smartphone devices only.


    However the good news is that the Vibrate functionality is implemented as a notification Led so you can control the vibration using the Led class. One of the peculiarities of the NLed API is that the collection of Leds may contain gaps, for example some devices contain a notification Led at position 0 and a vibration device at position 5. There is no way to programmatically determine the index of the vibration device, you can only determine the overall count of devices. Also the vibration device can only be turned on or off so the Blink setting behaves exactly as On would.


    On the HTC Himalaya the vibration device is implemented at index 1 and the following code can be used to turn on and off the vibration:-


    OpenNETCF.Notification.Led l = new OpenNETCF.Notification.Led();


    //turn on vibration


    l.SetLedStatus(1, OpenNETCF.Notification.Led.LedState.On);


    //turn off vibration


    l.SetLedStatus(1, OpenNETCF.Notification.Led.LedState.Off);

    #    |
    # Saturday, June 12, 2004

    Vibration and Pocket PC devices

    A number of Pocket PC devices support Vibration as an alert method, most (but not all) are Phone Edition devices. The Vibrate class in the OpenNETCF.Notification library is specific to Smartphone devices only.

    However the good news is that the Vibrate functionality is implemented as a notification Led so you can control the vibration using the Led class. One of the peculiarities of the NLed API is that the collection of Leds may contain gaps, for example some devices contain a notification Led at position 0 and a vibration device at position 5. There is no way to programmatically determine the index of the vibration device, you can only determine the overall count of devices. Also the vibration device can only be turned on or off so the Blink setting behaves exactly as On would.

    On the HTC Himalaya the vibration device is implemented at index 1 and the following code can be used to turn on and off the vibration:-

    OpenNETCF.Notification.Led l = new OpenNETCF.Notification.Led();

    //turn on vibration

    l.SetLedStatus(1, OpenNETCF.Notification.Led.LedState.On);

    //turn off vibration

    l.SetLedStatus(1, OpenNETCF.Notification.Led.LedState.Off);

     

    I'll be updating the documentation to make this clearer as currently the Vibrate class is incorrectly listed as supported on Smartphone and Pocket PC Phone Edition.

    #    |
    # Thursday, June 10, 2004

    Smart Device Programming chat starts soon!

    I intended to post this slightly more in advance but have been travelling around all this week, please excuse me :-)

    Chat Date: June 10th
    10:00am - 11:00am Pacific Time
    1:00pm - 2:00pm P.M. Eastern time
    17:00 - 18:00 GMT/BST

    Description: You know them from the newsgroups! You love them for their
    immense knowledge! Please join these amazing Microsoft MVPs in this live
    chat regarding the .NET Compact Framework and the Smart Device Programming
    features of VS.NET. The .NET Compact Framework is a subset of the .NET
    Framework designed to allow .NET developer to target smart devices. The
    Smart Device Programming features of VS.NET allow embedded developers to
    target devices running the Compact Framework.

    To join this chat, please visit:
    http://communities2.microsoft.com/home/chatroom.aspx?siteid=34000070

    #    |
    # Saturday, May 22, 2004

    Want to know more about OpenNETCF.Security.Cryptography?

    As Sam points out, the OpenNETCF.Security.Cryptography library was donated to the OpenNETCF codebase by fellow MVP Casey Chesnut. So a good source of information about how the library is built is Casey's original article on the subject.

    The library is designed in such a way that it follows the object model of the System.Security.Cryptography namespace in the full framework. A background on the Cryptographic services in .NET can be found here in the MSDN library.

     

    #    |
    # Friday, May 21, 2004

    Friday Fun: Automating Windows Media Player from .NETCF

    Windows Media Player for Pocket PC (and Smartphone) doesn't have a true object model like it's desktop cousin, so the ability to use it from your own code is limited. However there is an undocumented method of sending commands to Windows Media Player via a specific series of Windows Messages. These are actually hidden away in the Registry under the curiously named section "Pendant Bus".

    Therefore I put together a simple dll which creates an instance of Media Player if one is not already running, and sends messages to it, to allow you to play, pause, move back and forward through the playlist or adjust the volume. The code requires the Smart Device Framework which is used to P/Invoke a couple of Windows methods e.g. SendMessage. A typical method looks like:-

    /// <summary>
    

    /// Skips to the next track in the playlist. /// </summary> public void NextTrack() { Win32Window.SendMessage(hwnd, 32972, IntPtr.Zero, 0);

    }

    There are some limitations in the code I've posted here - it doesn't start the player with a specific file queued up (this would require a very simple overload to the constructor).

    There are currently no events and it is not possible to get information back from the player such as track name, elapsed time etc. I'm still investigating whether such information is output in any way which can be captured. This code should work with all Windows Mobile 2003 devices (inc Smartphone) and possibly earlier Pocket PCs but these have not been tested yet.

    Download the full code project with Pocket PC sample application here.

    #    |
    # Wednesday, May 19, 2004

    Smart Device Framework v1.1 Release Notes

    I thought it would be a good idea to compile a set of release notes for v1.1! You can view the resulting document here:-

    http://www.opennetcf.org/PermaLink.aspx?guid=a8b2c046-b9fd-4b0b-bd21-f0d03f6bec55

    The document lists the new items in this release. I haven't compiled the more subtle changes to existing classes (new methods, bug fixes etc). These are available by looking through the ChangeLogs for the individual assemblies via the installed Source Code shipped with the package or via the online SourceBrowse interface.

    Importantly also I've documented a number of known issues with this release. For many there is a workaround which is described, for other issues you can be assured they have been logged and will receive attention for the next release. If you encounter an issue which is not listed here please submit it either to the Forums or via our Submissions email address.

    #    |
    # Friday, May 14, 2004

    .NET Compact Framework drum machine...

    Spotted this on Seth Demsey's blog:-

    The article by Ianier Munoz shows how a desktop drum-machine sample was converted to the .NET Compact Framework. Calls to managed Direct Sound were replaced with P/Invokes to the WaveOut APIs. Check it out!

    http://www.microsoft.com/belux/nl/msdn/community/columns/munoz/cfrhythm.mspx

    #    |
    # Wednesday, May 12, 2004

    Upcoming .NET Compact Framework Chat: 13th May 2004

    Coming up tomorrow, the latest MSDN web chat with the .NETCF and Visual Studio for Devices team. Below are the details from MSDN:-

     

    Smart Device Programming with Visual Studio .NET 2003
    So what's that 'Smart Device Application' project type is all about? Please join the members of the .NET Compact Framework and Visual Studio product groups in this live chat regarding the .NET Compact Framework and the Smart Device Programming features of VS.NET. Please come prepared to ask the tough questions!

    May 13, 2004
    10:00 - 11:00 A.M. Pacific time
    1:00 - 2:00 P.M. Eastern time
    17:00 - 18:00 GMT


    Event Reminders


    OutlookAdd to Outlook Calendar
    FriendTell a Friend
    #    |
    # Monday, May 10, 2004

    Three ways to deploy the OpenNETCF.org Smart Device Framework

    1. The simplest method is to deploy the entire Smart Device Framework using the CAB files provided. When you deploy a project including a reference to an OpenNETCF dll this will occur automatically. The device gets the whole framework installed into the Global Assembly Cache (GAC) and an entry in the remove programs applet in control panel.

    2. An alternative is to deploy only those dlls which you use in your project within your own custom CAB file. Be aware that there are dependencies between the libraries so if you use OpenNETCF.Windows.Forms, then you need OpenNETCF.Drawing.dll and OpenNETCF.dll also. I think some kind of dependency diagram would be useful to illustrate all the dlls in the SDF, I'll follow up with this in a later thread.

    3. The third method (which is the most flexible and more complex) is to cherry-pick the classes you use from our source code and either build your own dll, or place it directly in your exe. If you are a VB.NET developer you'll need to use a dll project since most of our code is in C#. As with method 2 you need to take care to include any dependencies of the class(es) you use, if they are not present in your project (or referenced) then you'll get build errors. We don't have a definitive reference of dependencies for each class, however I'm sure it's something we can eventually phase into our documentation. In many cases related classes are contained in the sale code file - e.g. Registry and RegistryKey.

    #    |
    # Saturday, May 08, 2004

    P/Invoke Add-in for Visual Studio

    The site at www.pinvoke.net is a rapidly expanding Wiki solely devoted to P/Invoke definitions for .NET. This now includes Compact Framework P/Invokes for coredll, aygshell, rapi etc.

    To accompany this resource there is a Visual Studio plugin which gives you a right click option while editing code to insert a ready-made P/Invoke definition. If the one you want isn't available then you are encouraged to add the definition to the library.

    You can download the add-in from GotDotNet:-

    http://www.gotdotnet.com/Community/UserSamples/Download.aspx?SampleGuid=75122F62-5459-4364-B9BA-7B5E6A4754FE

    The downside to the www.pinvoke.net site is that it only displays correctly in Internet Explorer.

    For the Compact Framework specific wiki check out http://wiki.opennetcf.org

     

    #    |
    # Friday, April 30, 2004

    P/Invoke Wiki Update

    Chris has setup a Wiki for OpenNETCF, I've added a few topics to sample how P/Invokes may be presented. There will be a lot more work to do to get the template just right but I wanted to ensure the following was included for each entry by default:-

    • C# definition
    • VB definition
    • Equivalent managed functionality. This will point to the .NETCF class you can use to avoid P/Invoking in the first place or the OpenNETCF class which implements the P/Invoke.
    • Link to full description in SDK. Microsoft have placed online in the MSDN library the CE.NET 4.2, Pocket PC and Smartphone SDKs which describe the functions and their arguments and usage.

    Because of the nature of a Wiki there is an opportunity to easy tag additional information on, for example Samples or articles which directly apply to the function.

    #    |

    Understanding AcceptChanges and DataAdapter.Update

    Bill Ryan from KnowDotNet and Devbuzz has posted an article clearly describing the issues around DataSets which arise commonly on the newsgroups and discussion forums.

    http://msmvps.com/williamryan/posts/5679.aspx

    These include "Why does calling AcceptChanges followed by DataAdaptor.Update do nothing to the database" and "why doesn't calling Remove on a row doesn't remove the row from the database".

     

    #    |
    # Thursday, April 29, 2004

    Strongly-typed DataSets

    Chris Craft has written how to get around the lack of support for Strongly-typed DataSet's in the IDE for Smart Device projects.

    http://www.cjcraft.com/Blog/PermaLink.aspx?guid=23fc2044-c854-4358-a0b8-8460f2c56d49

    It requires some tweaking of code but is an interesting proposal. Chris plans a full article on the topic, to be released as and when he has time to complete it.

    #    |
    # Tuesday, April 06, 2004

    Reboot a device

    This blog entry (courtesy of Robert Levy) shows how to programatically reset a device:-

    http://blogs.msdn.com/windowsmobile/archive/2004/04/01/105878.aspx

    Here is the VB.NET equivalent:-

    Declare Function KernelIoControl Lib "coredll.dll" (ByVal dwIoControlCode As Integer, ByVal lpInBuf As IntPtr, ByVal nInBufSize As Integer, ByVal lpOutBuf As IntPtr, ByVal nOutBufSize As Integer, ByVal lpBytesReturned As Integer) As Integer

    Declare Sub SetCleanRebootFlag Lib "coredll.dll" ()

     

    Public Sub HardReset()

    Dim IOCTL_HAL_REBOOT As Integer = &H101003C

    Dim bytesReturned As Integer = 0

    SetCleanRebootFlag()

    KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, IntPtr.Zero, 0, bytesReturned)

    End Sub

     

    To perform only a soft-reset exclude the call to SetCleanRebootFlag (Thank's to Alex Feinman for highlighting this in a recent newsgroup post)

    #    |
    # Friday, April 02, 2004

    All about RAPI

    If you are writing a desktop application to talk to your device-side software, chances are you'll need to work with the Remote API (RAPI). This article by Larry Roof describes RAPI and uses OpenNETCF's Communication library to copy files, launch programs and query settings on the device.

    #    |
    # Saturday, March 20, 2004

    Smartphone files article gone live

    Thanks to Geoff Schwab for the heads up. My article on working with files covering Storage Cards and File Dialogs is now up in the MSDN library.

    #    |
    # Friday, March 19, 2004

    Free space on Storage Cards

    You can determine the total size of a Storage Card and available free bytes using the GetDiskFreeSpaceEx API function. Below is a "mini-wrapper" around the function which returns a structure with the three return values. You'll notice in this example I'm marshalling longs (64bit Integers), values greater than 32bit cannot be marshalled by value but can be marshalled by reference as in this case. The DiskFreeSpace struct contains three long members to hold the accessible free bytes, total bytes and total free bytes.

    public static DiskFreeSpace GetDiskFreeSpace(string directoryName)
    {
        DiskFreeSpace result = new DiskFreeSpace();
    
        if(!GetDiskFreeSpaceEx(directoryName, ref result.FreeBytesAvailable,
            ref result.TotalBytes, ref result.TotalFreeBytes))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), "Error retrieving free disk space");
        }
        return result;
    }
    
    
    public struct DiskFreeSpace
    {
        public long FreeBytesAvailable;
        
        public long TotalBytes;
        
        public long TotalFreeBytes;
    }
    
    [DllImport("coredll")]
    private static extern bool GetDiskFreeSpaceEx(string directoryName,
        ref long freeBytesAvailable,
        ref long totalBytes,
        ref long totalFreeBytes);

     

    Or if you prefer Visual Basic:-

    Public Function GetDiskFreeSpace(ByRef directoryName As String) As DiskFreeSpace

        Dim result As New DiskFreeSpace

        If GetDiskFreeSpaceEx(directoryName, result.FreeBytesAvailable, result.TotalBytes, result.TotalFreeBytes) = False Then

            Throw New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error(), "Error retrieving free disk space")

        End If

        Return result

    End Function

    Public Structure DiskFreeSpace

        Public FreeBytesAvailable As Long

        Public TotalBytes As Long

        Public TotalFreeBytes As Long

    End Structure

    Private Declare Function GetDiskFreeSpaceEx Lib "coredll.dll" (ByVal directoryName As String, ByRef freeBytesAvailable As Long, ByRef totalBytes As Long, ByRef totalFreeBytes As Long)

    #    |
    # Thursday, February 19, 2004

    Microsoft Mobile Dev Con just over a month away

    Kevin Lisota has just posted about his excitement for the upcoming MDC in San Francisco. It's shaping up to be a really interesting event and of course OpenNETCF will be providing an exciting session:-

    "CLI345 - Developing Real-world Smart Device Applications with Visual Studio .NET 2003, .NET Compact Framework and OpenNETCF SmartDevice Framework
    The .NET Compact Framework is a powerful tool for a mobile developer. To fully utilize its potential in a real-world application, a developer needs access to the native API and intrinsic Windows CE controls. OpenNETCF SmartDevice framework is designed to address these needs."
     
    There will also be a number of worldwide events to follow offering MDC content nearer to you.


    #    |
    # Saturday, January 31, 2004

    .NET Compact Framework Poster

    To celebrate the upcoming release of a full featured developer poster detailing the .NET Compact Framework class hierarchy, Jon Wells is holding a giveaway for a "Poster and Coaster". This consists of the poster and a CD-Rom full of goodies from the MSDN mobility website. There is an image of the poster available here on Jon's blog.

    #    |

    Multiple icons in .NETCF projects

    A discussion came up on the newsgroup regarding using a system tray icon from within .NETCF code and how the icons are handled. The way this is done (including in OpenNETCF's NotifyIcon control) is to use the icon of the calling assembly using the native LoadIcon function.

    The tray icon needs to be a 16x16 icon, however to look right in the Programs screen the application needs a 32x32 icon too. There is some confusion of how to handle multiple icons within a .NETCF application. Adding multiple icons through embedded resources does not make these icons accessible from native functions such as LoadIcon because .NETCF does not store these icons as Portable Executable (PE) resources, instead using the .NET method with manifests. Therefore in the normal build process the only PE icon to be built into the executable will be that which is specified in the ApplicationIcon property in the project properties:-

    The icon file in this case was created using Visual Studios icon editor, this contains two icons: 32x32 256 color and 16x16 256 color. You can download the sample .ico here. To illustrate which is used they contain merely a number with their size (32 and 16 respectively).

    In the Start Menu / Programs the 32 icon is used to display a correctly sized icon. When the NotifyIcon is created it automatically uses the 16x16 sized image.

     

    One final note about the application icon is that .NETCF executables all store their application icon with the resource identifier 32512. so a native handle to the icon of the currently executing application can be got using

            IntPtr hIcon = LoadIcon(GetModuleHandle(null), "#32512");
        

    LoadIcon is within Coredll.dll and you'll find the P/Invoke details in the OpenNETCF Smart Device Framework source. When you have finished with the handle you should call DestroyIcon to free up resources used.

    Sample Icon

    #    |

    .NETCF Performance

    Alex recently posted a link in his blog to a presentation discussing the architecture of the .NET Compact Framework which has some interesting details on which parts are ported from the full framework and which are ground-up re-writes specifically for the Compact Framework. One of the other interesting items is the performance statistics which show the difference between the Tech Preview (doesn't that seem like a long time ago now) and "Today" (which represents when this presentation was given in 2001).  It would be very interesting to see how the release and the subsequent two service packs have made further progress on these figures.

     

    #    |
    # Friday, December 19, 2003

    Cache Bonus

    On the newsgroups recently there were some enquiries about accessing the browser cache from .NETCF code. This is possible in devices running CE.NET 4.0 and above using the FindFirstUrlCacheEntry function and related functions. I put together a very sketchy demo class here:-

    http://www.opennetcf.org/public/cache.zip

    Its far from complete but illustrates a few techniques required. Firstly the size of buffer required is dynamic, to get around this we query the function first to retrieve the required buffer size and then allocate a byte array large enough to store the data. The data about each entry is extracted from the byte array using the BitConverter helper class and converted to .NET friendly types. I hope to complete this at some point into a complete wrapper around the WinInet Cache model and hopefully it will appear as an OpenNETCF library in 2004.

    #    |
    # Friday, December 05, 2003

    Help in .NETCF Applications

    I'm often asked where the best place to provide access to help files is within .NETCF applications - You cannot use the Start > Help menu so must choose an alternative, here are a few suggestions...
    #    |