有没有办法在Windows Mobile上捕获发送密钥并让它拨打特定号码?

时间:2008-12-09 21:57:34

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

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

更新

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

SetWindowsHookEx on Windows Mobile

在进行了更多搜索后,我发现“发送”键在Windows Mobile术语中称为“Talk”键。然后,我发现了一篇关于使用SHCMBM_OVERRIDEKEY消息的博客帖子,用于通知操作系统在用户按下Talk键时向我的应用发送WM_HOTKEY消息。

Jason Fuller Blog post about using the Talk button

博客文章及其指出的文档似乎正是我正在寻找的内容。我找不到一个有效的例子,我发现很多人都无法使用它。 SmartPhones也不支持VK_TTALK。我很想听听那些在智能手机和PocketPC手机上工作的人。

3 个答案:

答案 0 :(得分: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#。

要为特定窗口设置陷阱“talk”键,您需要执行以下操作:

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));

要检测何时按下'Talk'键,您需要在窗口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;
  }

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

如果尚未准备就绪,那么有大量文章和代码可以证明如何通过Google使用此功能,因此在最糟糕的情况下,如果您执行this之类的搜索,您应该可以找到一些内容。也许像this

答案 2 :(得分:0)

在使用指定的PhoneMakeCall背后是否​​有一些特殊的理由?它适用于智能手机和Windows Mobile 6 Professional。

编辑:我误解了这个问题。我现在看到你想陷阱发送事件。不过,我让我的回答留下来作为参考。