How to Vibrate a Smartphone / Windows Mobile Standard device in .NETCF

The Vibrate API is only available in the Windows Mobile Standard or Smartphone platform. This has been so since Smartphone 2002. Calling Vibrate() will cause the device to vibrate, and VibrateStop() will stop it.

Here’s a simple managed wrapper for the Vibrate API

public class Vibrate
{
    [DllImport("aygshell.dll")]
    static extern int Vibrate(int cvn, IntPtr rgvn, bool fRepeat, uint dwTimeout);
 
    [DllImport("aygshell.dll")]
    static extern int VibrateStop();
 
    const uint INFINITE = 0xffffffff;
 
    public static bool Play()
    {
        VibratePlay(0, IntPtr.Zero, true, INFINITE);
    }
 
    public static void Stop()
    {
        VibrateStop();
    }
}

For more information on the Vibrate API, you might want to check the MSDN Documentation out.



How to switch on/off the speaker phone in .NETCF

A few years back, I stumbled upon this article while trying to find a solution on how to switch on/off the speaker phone. It uses a DLL found in Windows Mobile 5 (and higher) devices called ossvcs.dll. This library exposes some pretty neat API’s for controlling communication related features in the device (like controlling the wireless/bluetooth radio and other cool stuff).

Here’s a quick way for switching the speaker on/off in .NETCF

DllImport("ossvcs.dll", EntryPoint = "#218")]        
static extern int SetSpeakerMode(uint mode);
 
void EnableSpeakerPhone()
{
    SetSpeakerMode(1);
}
 
void DisableSpeakerPhone()
{
    SetSpeakerMode(0);
}

Unfortunately, ossvcs.dll is not documented and might not exist in the future. But for now, it pretty much works in all devices I’ve tried



How to enumerate storage cards in .NETCF

In Windows Mobile, external storage cards are usually represented as the '\SD Card' or '\Storage Card' folder, this varies from device to device. A simple way to enumerate the external storage cards is to check all directories under the root directory that have the temporary attribute flag set.

Here’s a quick way to do so in .NETCF:

public static List<string> GetStorageCards()
{
    var list = new List<string>();
    var root = new DirectoryInfo("\\");
    foreach (DirectoryInfo directory in root.GetDirectories()) 
    {
        if (FileAttributes.Temporary == (directory.Attributes & FileAttributes.Temporary))
            list.Add(directory.Name);
    }
    return list;
}



How to send keyboard events in .NETCF

I’ve seen some people ask how to how to send keyboard events in .NET Compact Framework in the community. Although the operation is pretty simple, I’ll share a code snippet anyway.

const int KEYEVENTF_KEYPRESS = 0x0000;
const int KEYEVENTF_KEYUP = 0x0002;
 
[DllImport("coredll.dll")]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
 
void SendKey(Keys key)
{
    keybd_event((byte) key, 0, KEYEVENTF_KEYPRESS, 0);
    keybd_event((byte) key, 0, KEYEVENTF_KEYUP, 0);
}

The code above will send the keyboard event to currently focused window or control



Generic Bordered Control Base for .NETCF

For quite some time I’ve been using Google Chrome as my browser. The behavior of some of the controls are similar with Safari (probably because they use the same rendering engine). Anyway, I really liked the way that a border is drawn around the control whenever it receives focus. This inspired me to create a generic base control that draws a border around any control you use it for. The code I use is pretty much the same with my previous article, Extending the TextBox Control in .NETCF.

To accomplish this I created an abstract control that takes a generic parameter of type Control and has a default constructor. You might notice that in my override Font I check whether the control is in design time or run time. If in design time, we need to create a new Font object for the setter using the values passed. If we directly use the value passed the designer will crash, and at times Visual Studio will crash.

Here’s how it can look like:

And here’s the code for the base control:

[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class BorderedControlBase<T> : Control
    where T : Control, new()
{
    protected T innerControl;
 
    protected BorderedControlBase()
    {
        innerControl = new T();
        innerControl.GotFocus += delegate { OnGotFocus(EventArgs.Empty); };
        innerControl.LostFocus += delegate { OnLostFocus(EventArgs.Empty); };
        innerControl.TextChanged += delegate { OnTextChanged(EventArgs.Empty); };
        Controls.Add(innerControl);
    }
 
    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);
        innerControl.Bounds = new Rectangle(1, 1, ClientSize.Width - 2, ClientSize.Height - 2);
        Height = innerControl.Height + 2;
    }
 
    protected override void OnParentChanged(EventArgs e)
    {
        base.OnParentChanged(e);
        Invalidate();
    }
 
    protected override void OnGotFocus(EventArgs e)
    {
        base.OnGotFocus(e);
        Invalidate();
        innerControl.Focus();
    }
 
    protected override void OnLostFocus(EventArgs e)
    {
        base.OnLostFocus(e);
        Invalidate();
    }
 
    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.Clear(innerControl.Focused ? SystemColors.Highlight : BackColor);
    }
 
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        if (Environment.OSVersion.Platform != PlatformID.WinCE)
            base.OnPaint(e);
    }
 
    public override Font Font
    {
        get { return base.Font; }
        set
        {
            if (Environment.OSVersion.Platform != PlatformID.WinCE)
            {
                var font = new Font(value.Name, value.Size, value.Style);
                base.Font = innerControl.Font = font;
            }
            else 
                base.Font = innerControl.Font = value;
        }
    }
 
    public override string Text
    {
        get { return innerControl.Text; }
        set { innerControl.Text = value; }
    }
 
    public override bool Focused
    {
        get { return innerControl.Focused; }
    }
}

Now that we have this base control we can easily add borders to any control. Here’s an example of how to use the the bordered control base:

public class BorderedTextBox : BorderedControlBase<TextBox> 
{
}
 
public class BorderedComboBox : BorderedControlBase<ComboBox> 
{
}

Of course you will still have to wrap all the members of the wrapped control you wish to expose to access them. Hope you find this useful. If you need the Visual Studio solution then you can grab it here.