【问题标题】:Is there a way to capture the send key on Windows Mobile and have it dial a specific number?有没有办法在 Windows Mobile 上捕获发送键并让它拨打特定号码?
【发布时间】:2010-09-26 03:29:36
【问题描述】:

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

更新

我发现一篇文章将 SetWindowsHookEx 描述为 Windows Mobile 上未记录的 API。如果是这样,那我真的不想用了。

SetWindowsHookEx on Windows Mobile

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

Jason Fuller Blog post about using the Talk button

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

【问题讨论】:

    标签: c# windows-mobile compact-framework key


    【解决方案1】:

    您可以通过 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 either already does or will very soon roll with a keyhook(通过上面的 WinAPI 调用)公开了一个令人愉快的托管包装器。快乐!

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

    【讨论】:

    • Intermecs,哦。 CN3 上有一个小灯泡按钮,它兼作零数字键,我永远无法找到访问其事件的方法。你知道 SetWindowsHook 是否会捕捉到它吗?
    • 可能,这就是我关闭应用程序键以将其置于“信息亭模式”的方式。 Intermec 似乎有选择奇怪键码的习惯,在 730 上,右上角的“Action”键是 Enter,稍后是 F 键,Enter 是右下角,所以使用这些键做不同的事情是.... 呃...有趣。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      这些示例是用 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));
      

      要检测何时按下“谈话”键,您需要在窗口进程中捕获 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;
        }
      

      【讨论】:

      • 谢谢,如果你能发布一个例子就好了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-02
      • 1970-01-01
      相关资源
      最近更新 更多