1

我有一个使用紧凑框架 (NETCF) 的 Windows Mobile 应用程序,我想响应某人按下发送键并让电话拨打我的应用程序中选择的号码。有没有办法使用紧凑的框架来捕获发送密钥?我看过几篇关于捕获密钥的文章,但我还没有找到包含“发送”密钥的文章。

更新

我发现一篇文章将 SetWindowsHookEx 描述为 Windows Mobile 上未记录的 API。如果是这种情况,那么我真的不想使用它。

Windows Mobile 上的 SetWindowsHookEx

经过更多搜索后,我发现“发送”键在 Windows Mobile 术语中称为“通话”键。然后,我找到了一篇关于使用 SHCMBM_OVERRIDEKEY 消息来指示操作系统在用户按下 Talk 键时向我的应用程序发送 WM_HOTKEY 消息的博客文章。

Jason Fuller 关于使用“谈话”按钮的博客文章

博客文章和它指向的文档似乎正是我正在寻找的。我找不到一个可行的例子,而且我发现很多人无法让它发挥作用。看起来智能手机不支持 VK_TTALK。我很想听听有人在智能手机和 PocketPC 手机上实际使用此功能。

4

3 回答 3

3

我可以确认使用 SHCMBM_OVERRIDEKEY 在 PPC 和 SP 设备上都有效。我已经在 WM5 PPC、WM5 SP、WM6 PPC、WM6 SP 上对其进行了测试。我还没有尝试过 WM6.1 或 WM6.5,但我有点假设它们可以工作,因为 WM6 工作。

另外,您可能还需要在通话期间支持 DTMF 吗?

由于我正在编写 LAP dll,因此我遵循了以下页面,您可能会发现它很有用: LAP 实施问题

这些示例是用 C 语言编写的,因此您必须将它们翻译成 C#。

要为特定窗口设置“谈话”键的陷印,您需要执行以下操作:

SendMessage(SHFindMenuBar(window_hwnd), 
            SHCMBM_OVERRIDEKEY, 
            VK_TTALK, 
            MAKELPARAM((SHMBOF_NODEFAULT|SHMBOF_NOTIFY), (SHMBOF_NODEFAULT|SHMBOF_NOTIFY));

您可以随时打开/关闭陷阱。要关闭陷阱也很容易:

SendMessage(SHFindMenuBar(window_hwnd), 
            SHCMBM_OVERRIDEKEY, 
            VK_TTALK, 
            MAKELPARAM(0, (SHMBOF_NODEFAULT|SHMBOF_NOTIFY));

要检测何时按下“谈话”键,您需要在窗口 proc 上捕获 WM_HOTKEY 窗口消息:

case WM_HOTKEY:
    switch(HIWORD(lParam))
    {
    case VK_TTALK:
        // make ph call
        break;
    }
    return TRUE;

要拨打电话,您需要使用“PhoneMakeCall”API:

#include <phone.h>

void MakePhoneCall(const wchar_t* number)
{
    PHONEMAKECALLINFO call;
    memset(&call, 0x0, sizeof(PHONEMAKECALLINFO));
    call.cbSize = sizeof(PHONEMAKECALLINFO);
    call.dwFlags = PMCF_DEFAULT;
    call.pszDestAddress = number;
    PhoneMakeCall(&call);
}

要在通话期间支持 DTMF,您需要使用SNAPI跟踪电话(我相信有一个 C# 库可以帮助您解决SystemProperty)。

开始通话后的设置:

  #include <snapi.h>
  RegistryNotifyWindow(SN_PHONEACTIVECALLCOUNT_ROOT, SN_PHONEACTIVECALLCOUNT_PATH, SN_PHONEACTIVECALLCOUNT_VALUE, window_hwnd, callback_window_msg_number /*e.g. WM_APP */, 0, NULL, &phone_call_notify_handle);

当呼叫计数发生变化时,您将通过您提供的窗口消息被回叫。您需要阅读注册表并检查调用计数是否降至零。如果确实如此,您需要关闭 SNAPI 句柄:

RegistryCloseNotification(phone_call_notify_handle);

在通话中使用用户按下的键向 cprog 应用程序发送消息:

#define WM_CPROG_SEND_VKEY_DTMF (WM_APP+3) // Sends the DTMF tone(s) through to the current call (converting from VKEY to DTMF chars)

  BOOL PhoneSendDTMF(UINT uvKey)
  {
    BOOL bRet = FALSE;
    static HWND s_hwndCProg = NULL;
    TCHAR chDTMF = MapVKeyToChar(uvKey);

    // Attempt to find the cprog window (MSCprog).
    // Try to keep this window handle cached.
    if(NULL == s_hwndCProg || !IsWindow(s_hwndCProg))
    {
      s_hwndCProg = FindWindow(TEXT("MSCprog"), NULL);
    }

    // Send WM_CPROG_SEND_VKEY_DTMF to the CProg window.
    if(NULL != s_hwndCProg)
    {
      bRet = BOOLIFY(PostMessage(s_hwndCProg,
                              WM_CPROG_SEND_VKEY_DTMF, (WPARAM)chDTMF, 0));
    }

    return bRet;
  }
于 2009-02-16T19:57:31.240 回答
2

您可以通过 keyhook 捕捉世界中的所有键(除了桌面上的 CTRL+ALT+DEL):

static extern IntPtr SetWindowsHookEx(HookType hook, HookProc callback, IntPtr hMod, uint dwThreadId);

您可以通过 coredll.dll(而不是 user32)在 CE 中使用它(或其他覆盖之一)。

但是,这不在 .NET Compact Framework 中,需要 P/Invoke。“免费”按键的最大乐趣是 Form.KeyPreview = true; 并且只为您提供在表单聚焦时被击中的键,有时在处理具有特殊键的设备时(可能例如您的“发送”键,因为我在 Intermec 上的“Application1”键有类似的情况)不久前的单位)。

然而,还有一个很棒的替代方案,我相信OpenNETCF 要么已经使用,要么很快就会使用 keyhook(通过上面的 WinAPI 调用)来展示令人愉快的托管包装器。喜悦!

如果这还没有准备好,那么有大量文章和代码在展示如何通过 Google 使用它,所以在最坏的情况下,如果你执行这样的搜索,你应该能够找到一些东西。也许是这样的?

于 2008-12-09T22:10:04.480 回答
0

不使用指定的PhoneMakeCall背后有什么特别的原因吗?它适用于 Smartphone 和 Windows Mobile 6 Professional。

编辑:我有点误读了这个问题。我现在看到您想要捕获Send 事件。不过,我让我的答案留下来供参考。

于 2009-02-13T08:30:32.270 回答