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






4.76/5 (9投票s)
本文为 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 开发的一些典型障碍。
本文的第一部分可在此处找到:这里。