# Monday, August 25, 2008

Get the name of your executing .exe

The Compact Framework doesn't support Assembly.GetEntryAssembly to determine the launching .exe. You can instead P/Invoke the native GetModuleFileName function like so:-

byte[] buffer = new byte[MAX_PATH * 2];

int chars = GetModuleFileName(IntPtr.Zero, buffer, MAX_PATH);

if (chars > 0)

{

string assemblyPath = System.Text.Encoding.Unicode.GetString(buffer, 0, chars * 2);

}

Where MAX_PATH is defined in the Windows CE headers as 260. The P/Invoke declaration for GetModuleFileName looks like this:-

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

private static extern int GetModuleFileName(IntPtr hModule, byte[] lpFilename, int nSize);

The function expects a HMODULE - a handle to a native module. However passing IntPtr.Zero here indicates we want the module which created the process which is our .exe. This code will always return the path of the calling .exe regardless of if it is in a utility dll, or even a GAC assembly located in the \Windows folder.

#    Comments [2] |
# Wednesday, August 13, 2008

Home and Visiting Clocks in Professional Edition

In Professional Edition (Pocket PC) devices the Clock control panel allows you to set a home timezone and a visiting zone and lets you toggle between them. If you need to retrieve the current settings they are stored in the registry in a key called HKEY_LOCAL_MACHINE\Software\Microsoft\Clock in a binary value called "AppInfo". Here is breakdown of that data:-

00,00,00,00,31,00,00,00,55,00,00,00,00,00,00,00,01,00,00,00,80,01,00,00,be,00,00,00,00,00,00,00,00,00,00,00

The first 4 bytes contains an integer which is 1 if in the home zone, and 0 if visiting.

The next 4 bytes always seems to be 0x31

The next 4 bytes are the index into the timezone collection of the home zone (In this example 85 GMT)

The next 4 bytes are unused

The next 4 bytes indicate whether to use DST (In this example 1 true)

The next 4 bytes are always 0x180

The next 4 bytes are the index into the timezone collection of the visiting zone (in this example 190 - New Delhi)

The next 4 bytes are unused

The next 4 bytes indicate whether to use DST in visiting zone (In this example 0 false)

I suspect that the unused values may be connected to the old Cities feature which was originally in the control panel but removed with PPC2003. You may be wondering how to get the timezone information at the specified indexes - in Windows Mobile they are not all stored in the registry as on other Windows CE flavours. They are accessible through POOM - IPOutlookApp.GetTimeZoneFromIndex, or in managed code in Mobile In The Hand.

#    Comments [0] |
# Thursday, August 07, 2008

SQL Compact 3.5 SP1 RTM

To coincide with the RTM release of SQL Server 2008 the SQL Compact Team have delivered Service Pack 1 for v3.5. This includes Entity Framework support and a native 64bit version. Steve Lasker has the details:-

http://blogs.msdn.com/stevelasker/archive/2008/08/07/sql-server-compact-3-5-sp1-released.aspx

Meanwhile SQL Server 2008 RTM is available already online for both MSDN and TechNet subscribers.

#    Comments [0] |
# Friday, August 01, 2008

APPA Mundi Awarded Microsoft Certified Partner Status

APPA Mundi has received Certified Partner status within the Microsoft Partner Program along with the Mobility Solutions competency. This achievement showcases APPA Mundi’s expertise in creating mobile solutions based on Microsoft technologies.

Read Full Press Release

Microsoft Certified Partner - Mobility Solutions

One of the reasons I have been busy lately and not blogging as feverishly as in previous months is that I have been, with my three MVP colleagues, busy building up our company - APPA Mundi Ltd. We all have a long history of working with Windows Mobile and we have combined forces to offer consulting, development and training services. You can read more about us and what we do on our website.

#    Comments [0] |
# Friday, June 20, 2008

Using RemoteWipe

With Windows Mobile 5.0 AKU2.0 (Messaging & Security Feature Pack) a new feature was implemented called RemoteWipe. This allowed an administrator to remotely wipe a device if it may have got lost and was designed to remove all sensitive data from the device and return it to a fresh state. It was only with Windows Mobile 6 that the details of the implementation were added to the SDK documentation. Like most other administration and device management features RemoteWipe is implemented as a Configuration Service Provider, this allows it to be activated either via remote or local means. For example you could build a mechanism into your software where you wish to wipe the device, perhaps after an extended number of failed password entries etc. Whether you can call the CSP will depend on the particular security policy on the device, however if possible you can initiate a wipe locally with either DMProcessConfigXML or the managed ConfigurationManager e.g.

System.Xml.XmlDocument cd = new System.Xml.XmlDocument(); cd.LoadXml("<wap-provisioningdoc><characteristic type=\"RemoteWipe\"><parm name=\"doWipe\" value=\"1\"/></characteristic></wap-provisioningdoc>");

System.Xml.XmlDocument xd = ConfigurationManager.ProcessConfiguration(cd, true);

Of course you use this code snippet at your own risk, if it works successfully it will wipe data from your device and return to factory fresh condition!

More details about the service provider here:-

http://msdn.microsoft.com/en-us/library/bb737595.aspx

#    Comments [0] |
# Tuesday, June 10, 2008

Session Materials from Tech-Ed

I've posted a number of links relevant to the session I gave last week on our Tech-Ed page here. This includes the sample code which is an additional selection of samples than those which appear in the 32feet.NET package itself. The session covered the latest v2.3 release of the library and development continues on the next version based on your feedback.

One of the items of feedback I got for the session was the confusion between Personal Area Networking as a concept and the Bluetooth PAN Profile (Which supports Network Access Point, Group Networking and PAN User). Windows Mobile supports a limited subset of this profile to support the Internet Sharing application which was added in Windows Mobile 5.0 AKU3 but is often documented as a new feature in Windows Mobile 6. There is no exposed API to programmatically interact with the BT PAN profile, however there is an API for Internet Sharing which can be used to start/stop a sharing connection. I'm investigating the best way to add this to a future version of the library.

#    Comments [0] |
# Friday, May 16, 2008

Chinese Translation of Microsoft Mobile Development Handbook now available

 

I just got word from David Chang that the Chinese translation of our book is now complete. You can order it from Amazon.cn here:-

http://www.amazon.cn/mn/detailApp?pageletid=newpromote&prodid=bkbk820876

#    Comments [0] |
# Wednesday, April 30, 2008

New Mobile Development Team Blog

Amit Chopra's Visual Studio for Devices team has grown to include Silverlight Mobile and .NETCF and the team have a new blog to cover all these areas. I'm looking forward to some great content from the team:-

http://blogs.msdn.com/mobiledev/

#    Comments [0] |
# Tuesday, April 08, 2008

Disable Windows Mobile 6.1 Threaded SMS View

There may be an occasion where you want to restore the original chronological view for the SMS Inbox rather than the new threaded view. One example is where a system programmatically moves or inserts SMS messages into the system because these are not visible in the threaded view (even though the count of unread messages increases). There is a simple registry fix to turn off threading and restore the "classic" view. From the registry editor of your choice browse the device registry for the key:

[HKEY_CURRENT_USER\Software\Microsoft\Inbox\Settings]

Under this add a new DWORD value called "SMSInboxThreadingDisabled" and set it to 1. Close the tmail.exe application or soft-reset the device and the regular message view will be used. Set this registry value back to 0 or delete it to restore the default threaded view.

#    Comments [0] |
# 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);

#    Comments [0] |

New Windows Mobile 6.1 Screen Resolutions

The release of Windows Mobile 6.1 brings a number of improvements for users but retains the same SDK and libraries as 6. The devices ship with .NETCF 2.0 SP2 in ROM. 

This release adds additional screen resolutions to both the Professional (touchscreen) and Standard (non-touchscreen) editions. For Standard edition these are all 131 dpi and consist of 320x320 square and 400x240 and 440x240 landscape. For Professional there are 240x400 and 480x800 portrait screens. Once again these additional screen sizes emphasize the importance of making sure your app dynamically adjusts to make best use of screen space, for example using the Windows Mobile Line of Business Accelerator 2008.

 

The images (currently US English only although localised versions should follow) are available to download here:-

http://www.microsoft.com/downloads/details.aspx?FamilyID=3D6F581E-C093-4B15-AB0C-A2CE5BFFDB47&displaylang=en

#    Comments [0] |
# 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

#    Comments [0] |
# 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.

#    Comments [0] |
# Thursday, February 21, 2008

Tech-Ed 2008

I was delighted to find out this week that my session on Personal Area Networking was selected for Tech-Ed Developers this year. The session will cover a range of networking topics including of course Bluetooth. There will be a selection of demos which will support audience participation. It looks like I'll be in good company too, the Windows Mobile track will have a wide range of topics which will enable you to build compelling applications with the latest tools and technologies. You can search the session list here.

#    Comments [1] |
# 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.

#    Comments [0] |