频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

.NET Framework 精简版访问电话API

来源:Microsoft 作者: 出处:巧巧读书 2005-11-30 进入讨论组

讨论组http://group.qqread.com

使用 VB.NET 创建电话呼叫

  用 VB.NET 编写的 MakeCall 代码与使用 C# 编写的代码相似(详细代码如上文所示),几乎不需要太大的改动。我们使用 IntPtr 变量保存多数函数的值。两者的不同之处在于,在 MakeCall 的前向声明中,我们指定 PhoneMakeCallInfo 结构实例将作为引用传递。

<System.Runtime.InteropServices.DllImport("phone.dll")> _
Private Shared Function PhoneMakeCall(ByRef ppmci As
PhoneMakeCallInfo) As IntPtr
End Function

  我们基本上按照前面的方法处理 PhoneMakeCallInfo 结构。将 PhoneNumber 字符串分割为一个字符数组,然后将 iPhoneNumber 用作内存调整指针写入内存。

PhoneNumber.Insert(PhoneNumber.Length, " ")
Dim cPhoneNumber() As Char = PhoneNumber.ToCharArray()
Dim pAddr() As Char = cPhoneNumber

Dim info As PhoneMakeCallInfo = New PhoneMakeCallInfo
info.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(info)
Dim iPhoneNumber As IntPtr = Marshal.AllocHLocal(cPhoneNumber.Length)
System.Runtime.InteropServices.Marshal.Copy(cPhoneNumber, 0,
iPhoneNumber, cPhoneNumber.Length)
info.pszDestAddress = iPhoneNumber

  将 pszDestAddress 成员指向此内存空间并设置拨号前确认选项后,将此结构实例传入 PhoneMakeCall。

If PromptBeforeCall Then
info.dwFlags = PMCF_PROMPTBEFORECALLING
Else
info.dwFlags = PMCF_DEFAULT
End If
res = PhoneMakeCall(info)

  使用 C# 访问 SIM 信息

  虽然称不上是对 Pocket PC Phone Edition 平台上的可用 SIM 访问函数的详细介绍,但我们将通过介绍如何检索 SIM 所有者的主要电话号码和服务提供程序的名称,进一步说明 P/Invoke 的用途。我们首先定义一个结构,用以存放 ping SIM 卡时获得的值,如下所示。

[StructLayout(LayoutKind.Sequential)]
private struct SimRecord
{
public IntPtr cbSize;
public IntPtr dwParams;
public IntPtr dwRecordType;
public IntPtr dwItemCount;
public IntPtr dwSize;
}

  因为在本机代码和托管代码之间只能自动封送顺序布局结构,所以我们用顺序布局标记修饰我们的结构。cbSize 是所传递结构的大小。dwParams 是参数值,这里我们并不用担心。dwRecordType 表示记录的格式。选项包括:

说明
SIM_RECORDTYPE_UNKNOWN 未知的文件类型。
SIM_RECORDTYPE_TRANSPARENT 单个变长记录。
SIM_RECORDTYPE_CYCLIC 循环记录集,每个记录具有相同长度。
SIM_RECORDTYPE_LINEAR 线性记录集,每个记录具有相同长度。
SIM_RECORDTYPE_MASTER 每个 SIM 都有一个主记录,实际上是主节点。
SIM_RECORDTYPE_DEDICATED 实际上是作为其他记录的上级记录的“目录”文件。

  dwItemCount 是记录中的项数。dwSize 是记录中每项的大小。接下来,我们将有许多利用了 DLLImport 的函数声明。

  [DllImport("sms.dll")]
  private static extern IntPtr SmsGetPhoneNumber(IntPtr psmsaAddress);

  检索 SIM 所有者的电话号码。

[DllImport("cellcore.dll")]
private static extern IntPtr SimInitialize(IntPtr dwFlags, IntPtr
lpfnCallBack, IntPtr dwParam, out IntPtr lphSim);

  此函数是调用任何 SIM 访问函数所必需的。如果执行成功,则返回一个指向 HSIM 句柄的指针,以便在随后的调用中使用。

[DllImport("cellcore.dll")]
private static extern IntPtr SimGetRecordInfo(IntPtr hSim, IntPtr
dwAddress, ref SimRecord lpSimRecordInfo);

  此函数接受从 SimInitialize 返回的 HSIM 句柄以及一个 SIM 地址 (dwAddress) 和一个 SIM 记录结构,并用请求的信息填充此结构。

[DllImport("cellcore.dll")]
private static extern IntPtr SimReadRecord(IntPtr hSim, IntPtr
dwAddress, IntPtr dwRecordType, IntPtr dwIndex, byte[] lpData,
IntPtr dwBufferSize, ref IntPtr lpdwBytesRead);

  此函数接受从 SimInitialize 返回的 HSIM 句柄,以及一个 SIM 地址 (dwAddress)、一个 dwRecordType(请参见上表)、dwIndex(如果使用 SIM_RECORDTYPE_CYCLIC 或 SIM_RECORDTYPE_LINEAR)、lpData(指向数据缓冲区)、dwBufferSize(表示缓冲区大小)以及 lpdwBytesRead(表示要读取的字节数)。

  [DllImport("cellcore.dll")]
  private static extern IntPtr SimDeinitialize(IntPtr hSim );

  此函数发布在 SimInitialize 中创建的 HSIM 句柄的资源。

  我们将实现两种重要的电话 API 调用:获取当前 SIM 所有者的电话号码,并获取 SIM 当前访问的服务提供程序的名称。

  在 GetPhoneNumber 中,我们所做的只是定义一个大型字节缓冲区并将其传入 SmsGetPhoneNumber。

Byte[] buffer = new Byte[516];
fixed (byte* pAddr = buffer)
{
IntPtr res = SmsGetPhoneNumber((IntPtr)pAddr);
if (res != IntPtr.Zero)
throw new Exception("无法从 SIM 中获取电话号码");

  然后获取返回的 PhoneAddress 类型和 PhoneAddress 电话号码。

byte *pCurrent = pAddr;
phoneaddr.AddressType =
(AddressType)Marshal.ReadInt32((IntPtr)pCurrent);
pCurrent += Marshal.SizeOf(phoneaddr.AddressType);
phoneaddr.Address = Marshal.PtrToStringUni((IntPtr)pCurrent);
}

  此函数声明为 unsafe,因为我们是直接从内存中的托管代码读取。

  在下一个函数 GetServiceProvider 中,我们首先初始化 SIM

res = SimInitialize(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, out
hSim);
if (res != IntPtr.Zero)
throw new Exception("无法初始化 SIM");

  然后声明一个 SIM 记录结构实例,并请求在调用 SimGetRecordInfo 时检索包含 SERVICE_PROVIDER 的值的 SimRecord 的句柄。

SimRecord rec = new SimRecord();
rec.cbSize = (IntPtr)Marshal.SizeOf(rec);

res = SimGetRecordInfo(hSim, (IntPtr)SERVICE_PROVIDER, ref rec);
if (res != IntPtr.Zero)
throw new Exception("无法从 SIM 中读取服务提供程序的信息");

  然后,我们分配一个字节数组,用于存储 SIM 记录(包含 SERVICE_PROVIDER 详细信息)的内容。

byte[] bData = new byte[(int)rec.dwSize + 1];
IntPtr dwBytesRead = IntPtr.Zero;

  然后请求读取 SERVICE_PROVIDER 记录的内容。

res = SimReadRecord(hSim, (IntPtr)SERVICE_PROVIDER,
rec.dwRecordType, IntPtr.Zero, bData, (IntPtr)bData.Length, ref
dwBytesRead);
if (res != IntPtr.Zero)
throw new Exception("无法从 SIM 中读取服务提供程序");

  然后查看返回的结构,并删除在显示最终结果时可能会破坏代码的任何非标准 ASCII 字符。

byte[] bScrubbed = new byte[(int)dwBytesRead];
int nPos = 0;

// 删除非 ASCII 字符
for (int i = 0; i < (int)dwBytesRead; i ++)
{
if (((int)bData[i] > 19) && ((int)bData[i] < 125))
{
bScrubbed[nPos] = bData[i];
nPos++;
}
}

  然后取消初始化 SIM 并释放其资源。

  SimDeinitialize(hSim);

  最后,返回“已删除”字节缓冲区的字符串表示形式。

更多文章 更多内容请看.NET Framework新手入门.NET移动与嵌入式技术.NET开发手册专题,或进入讨论组讨论。
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
讨论组问题推荐
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章