65.9K
CodeProject 正在变化。 阅读更多。
Home

在 .NET Compact Framework 上的 Windows Mobile 编程技巧:第二部分

2011年2月23日

CPOL

4分钟阅读

viewsIcon

47937

downloadIcon

1660

本文为 Windows Mobile/CE 开发人员提供并描述了一些有用的代码片段。

引言

这是关于 Windows Mobile 编程技巧的文章的第二部分。 我创建这篇文章的原因是,以下技巧要么无法使用纯托管代码实现,要么不容易在 .NET CF 提供的庞大类集合中找到。我们公司发现这些是开发人员经常需要克服的一些障碍,因此决定分享这些技巧。如果您有任何扩展此项目的想法,或者想要分享其他的技巧,欢迎与我联系。

我将向您展示如何:

  • SIM 卡
    • 获取 IMSI
  • 电话
    • 获取 IMEI
    • 获取或设置手机铃声的音量
  • 内存
    • 获取总物理内存
    • 获取可用内存量
    • 获取已用内存量
  • Device
    • 获取或设置系统音量
    • 软复位设备

获取 IMSI 和/或 IMEI

找到 IMSI(国际移动用户识别码)对于多种目的很有用。前三位数字是国家代码。通过这种方式,您可以识别呼叫者的国家。后两位数字是运营商识别码。要获取手机的 IMSI,我们将使用以下平台调用:

internal class Tapi
{
    [DllImport("coredll")]
    public static extern int lineInitializeEx(out IntPtr lpm_hLineApp, 
      IntPtr hInstance, IntPtr lpfnCallback, string lpszFriendlyAppName, 
      out int lpdwNumDevs, ref int lpdwAPIVersion, 
      ref LINEINITIALIZEEXPARAMS lpLineInitializeExParams);

    [DllImport("coredll")]
    public static extern int lineOpen(IntPtr m_hLineApp, int dwDeviceID, 
      out IntPtr lphLine, int dwAPIVersion, int dwExtVersion, 
      IntPtr dwCallbackInstance, int dwPrivileges, 
      int dwMediaModes, IntPtr lpCallParams);

    [DllImport("coredll")]
    public static extern int lineNegotiateAPIVersion(IntPtr m_hLineApp, 
      int dwDeviceID, int dwAPILowVersion, int dwAPIHighVersion, 
      out int lpdwAPIVersion, out LINEEXTENSIONID lpExtensionId);

    [DllImport("cellcore")]
    public static extern int lineGetGeneralInfo(IntPtr hLine, byte[] bytes);

    [DllImport("cellcore")]
    public static extern int lineGetGeneralInfo(IntPtr hLine, 
           ref LINEGENERALINFO lineGenerlInfo);

    [DllImport("coredll")]
    public static extern int lineClose(IntPtr hLine);

    [DllImport("coredll")]
    public static extern int lineShutdown(IntPtr m_hLineApp);
}

public static string GetIMSIandIMEI()
{
    if (m_IMSI.Equals(String.Empty))
    {
        string manufacturer;
        string model;
        string revision;
        string imsi;
        string imei;

        PhoneInfo.Get(out manufacturer, out model, 
                      out revision, out imei, out imsi);
        m_IMSI = imsi;
        m_IMEI = imei;
    }

    return m_IMSI;
}

此代码中的关键方法是 PhoneInfo.Get(...) 方法。此方法的源代码很长。您可以在本文开头的存档中找到它,或者在本文底部的网站上找到它。此方法还负责检索手机的 IMEI(国际移动设备识别码)。IMEI(有时也称为序列号 - 这是不正确的,因为序列号只是 IMEI 的一部分)唯一地标识每个移动电话。

获取或设置手机铃声的音量

电话铃声的音量实际上存储在 Windows 注册表中。但是,为了使更改生效,我们需要调用 AudioUpdateFromRegistry API 函数。所以我们将这样声明它:

[DllImport("coredll.dll")]
private static extern void AudioUpdateFromRegistry();

static readonly string KeyVolRegKey = 
   @"HKEY_CURRENT_USER\ControlPanel\Volume";
static readonly string KeyRingRegKey = 
   @"HKEY_CURRENT_USER\ControlPanel\SoundCategories\Ring";

附加的项目包含一个示例应用程序,该应用程序还提供了一个 GUI 来查看或更改音量

这是我们将用来调整音量的属性:

public static int PhoneRingVolume
{
    set
    {
        long volumeValue;
        switch (value)
        {
            case 0:
                volumeValue = 0;
                break;
            case 1:
                volumeValue = (long)858993459;
                break;
            case 2:
                volumeValue = (long)1717986918;
                break;
            case 3:
            default:
                volumeValue = (long)-1717986919;
                break;
            case 4:
                volumeValue = (long)-858993460;
                break;
            case 5:
                volumeValue = (long)-1;
                break;

        }

        Registry.SetValue(KeyVolRegKey, "Ringer", volumeValue, 
                          RegistryValueKind.QWord);
        Registry.SetValue(KeyRingRegKey, "InitVol", 
                         (uint)value, RegistryValueKind.DWord);
        AudioUpdateFromRegistry();
    }
    get
    {
        switch (Convert.ToInt64((Registry.GetValue(KeyVolRegKey, 
                                 "Ringer", 2576980377))))
        {
            case 0:
                return 0;
            case 858993459:
                return 1;

            case 1717986918:
                return 2;

            case 3435973836:
            case -858993460:
                return 4;

            case 4294967295:
            case -1:
                return 5;

            case -1717986919:
            default:
                return 3;
        }
    }
}

获取有关设备内存的信息

如果我们想要创建稳定且性能良好的应用程序,那么能够找出我们有多少可用内存是非常有价值的。假设我们知道应用程序的最低内存要求。如果总物理内存小于我们的要求,我们可以关闭应用程序并告知用户内存量不足。这当然比尝试运行应用程序然后以内存不足异常结束它更好。我们将使用以下代码:

public class MemoryStatus
{
    private struct MEMORYSTATUS
    {
        public uint Length;
        public uint MemoryLoad;
        public uint TotalPhys;
        public uint AvailPhys;
        public uint TotalPageFile;
        public uint AvailPageFile;
        public uint TotalVirtual;
        public uint AvailVirtual;
    }

    [DllImport("coredll.dll", EntryPoint = "GlobalMemoryStatus", SetLastError = true)]
    private static extern void GlobalMemoryStatus(ref MEMORYSTATUS lpBuffer);

    /// <summary>
    /// Retrieves information about the system's current available physical memory.
    /// </summary>
    /// <returns>Available memory in mega bytes.</returns>
    public static float GetAvailableMemory()
    {
        MEMORYSTATUS mem = new MEMORYSTATUS();
        GlobalMemoryStatus(ref mem);

        return (float)mem.AvailPhys / 1048576.0f;
    }

    /// <summary>
    /// Retrieves information about the system's current usage of physical memory.
    /// </summary>
    /// <param name="aTotalMem">Total memory in mega bytes.</param>
    /// <param name="anUsedMem">Used memory in mega bytes.</param>
    /// <param name="aFreeMem">Available memory in mega bytes.</param>
    public static void GetAvailableMemory(out float aTotalMem, 
           out float anUsedMem, out float aFreeMem)
    {
        MEMORYSTATUS mem = new MEMORYSTATUS();
        GlobalMemoryStatus(ref mem);

        aTotalMem = (float)mem.TotalPhys / 1048576.0f;
        aFreeMem = (float)mem.AvailPhys / 1048576.0f;
        anUsedMem = aTotalMem - aFreeMem;
    }
}

附加的示例项目显示了如何使用此代码来显示内存信息

获取或设置系统音量

系统音量是操作系统播放系统声音的音量级别(例如,如果用户点击屏幕或在键盘上键入)。如果您想在您的应用程序中提供一个用户界面,供用户更改系统音量,您可能会使用以下代码:

///<summary> 
/// Specifies the volume levels.
/// </summary>
public enum Volumes : int
{
    OFF = 0,
    LOW = 858993459,
    NORMAL = 1717986918,
    MEDIUM = -1717986919,
    HIGH = -858993460,
    VERY_HIGH = -1
}


/// <summary>
/// Allows you to change the volume on Windows Mobile.
/// </summary>
public class VolumeControl
{
    [DllImport("coredll.dll", SetLastError = true)]
    internal static extern int waveOutSetVolume(IntPtr device, int volume);

    [DllImport("coredll.dll", SetLastError = true)]
    internal static extern int waveOutGetVolume(IntPtr device, ref int volume);

    public static Volumes Volume
    {
        get
        {
            int v = (int)0;

            waveOutGetVolume(IntPtr.Zero, ref v);

            switch (v)
            {
                case (int)Volumes.OFF:
                    return Volumes.OFF;

                case (int)Volumes.LOW:
                    return Volumes.LOW;

                case (int)Volumes.NORMAL:
                    return Volumes.NORMAL;

                case (int)Volumes.MEDIUM:
                    return Volumes.MEDIUM;

                case (int)Volumes.HIGH:
                    return Volumes.HIGH;

                case (int)Volumes.VERY_HIGH:
                    return Volumes.VERY_HIGH;

                default:
                    return Volumes.OFF;
            }
        }
        set
        {
            waveOutSetVolume(IntPtr.Zero, (int)value);
        }
    }
}

执行软复位

有时执行软复位可能很有用,尤其是在对系统进行更改后,这些更改只有在复位后才会显示出来。我们可以调用此例程来执行用户设备的软复位,以便更改立即生效。我们永远不应该忘记先询问用户是否同意软复位。未经询问就重置设备被认为是非常粗鲁的,并且可能导致用户数据丢失。

///<summary> 
/// Represents a functionality to reset the whole device.
/// </summary>
public class ResetDevice
{
    private const uint FILE_DEVICE_HAL = 0x00000101;
    private const uint METHOD_BUFFERED = 0;
    private const uint FILE_ANY_ACCESS = 0;

    private static uint CTL_CODE(uint DeviceType, 
            uint Function, uint Method, uint Access)
    {
        return ((DeviceType << 16) | (Access << 14) | 
                (Function << 2) | Method);
    }

    [DllImport("Coredll.dll")]
    private extern static uint KernelIoControl
    (
        uint dwIoControlCode,
        IntPtr lpInBuf,
        uint nInBufSize,
        IntPtr lpOutBuf,
        uint nOutBufSize,
        ref uint lpBytesReturned
    );

    /// <summary>
    /// Reset device.
    /// </summary>
    /// <returns></returns>
    public static uint ResetPocketPC()
    {
        uint bytesReturned = 0;
        uint IOCTL_HAL_REBOOT = CTL_CODE(FILE_DEVICE_HAL, 15,
          METHOD_BUFFERED, FILE_ANY_ACCESS);
        return KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0,
          IntPtr.Zero, 0, ref bytesReturned);
    }
}

结论

本文的第二部分到此结束。所有源代码以及示例应用程序都可以在本文开头下载,也可以从 Bee Mobile 网站 http://beemobile4.net/?mod=products&action=det&id=3 下载。 整个源代码是 Bee Mobile 的 Free Utils 项目的一部分。 Free Utils 项目的目标是将源代码放在一起,这些代码展示了如何在 .NET Compact Framework 环境中克服 Windows Mobile / Windows CE 开发的一些典型障碍。

本文的第一部分可在此处找到:这里

© . All rights reserved.