使用键盘挂钩和显示模式窗体时,Windows Mobile应用程序崩溃

时间:2013-06-20 13:06:38

标签: compact-framework

我已经设置了一个键盘钩子来捕捉用户按下的按钮。但它运行良好,当显示模式窗体(它实际上作为自定义消息框)时,应用程序崩溃。

我读过你永远不应该在钩子里调用阻塞函数;我读到的其中一个建议是在一个线程中调用hook事件。我试过这个但它仍然导致应用程序崩溃。

有没有人对如何解决这个问题有任何想法?或者如何在不使用键盘钩的情况下建议另一种方法来捕获按钮

由于

设置并启动挂钩

    public void Start()
    {
        if (m_HookHandle == IntPtr.Zero)
        {
            m_HookDelegate = new HookProc(this.HookProcedure);
            m_HookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, m_HookDelegate, GetModuleHandle(null), 0);

            if (m_HookHandle == IntPtr.Zero)
            {
                throw new SystemException("Failed to acquire a valid hook handle");
            }
        }
    } 

这是一个叫回来的Hook程序

    private int HookProcedure(int code, IntPtr wParam, IntPtr lParam)
    {
        bool handled = false;

        if ((code >= 0) && (wParam == (IntPtr)0x0100))
        {
            KBDLLHOOKSTRUCT hookStruct = new KBDLLHOOKSTRUCT();
            hookStruct.dwExtraInfo = IntPtr.Zero;
            hookStruct.flags = 0;
            hookStruct.scanCode = 0;
            hookStruct.time = 0;
            hookStruct.vkCode = 0;
            hookStruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));

            // Let clients determine what to do
            KeyboardHookEventArgs e = new KeyboardHookEventArgs();
            e.HCode = code;
            e.WParam = wParam;
            e.LParam = lParam;
            e.Handled = false;

            KeyBoardInfo keyInfo = new KeyBoardInfo();
            keyInfo.VKCode = hookStruct.vkCode;
            keyInfo.ScanCode = hookStruct.scanCode;

            PublishHookEvent(e, keyInfo);

            handled = e.Handled;
        }

        // Yield to the next hook in the chain
        if (handled)
            return -1;
        else
            return CallNextHookEx(m_HookHandle, code, wParam, lParam);
    }

每当收到一个钩子事件时,PublishHookEvent将调用每个注册的侦听器来处理钩子事件

    protected void PublishHookEvent(KeyboardHookEventArgs args, KeyBoardInfo keyBoardInfo)
    {
        if (this.m_KeyboardHookListeners.Count > 0)
        {
            if (args.WParam.ToInt32() == 256)
            {
                IMQKeyboardHookListener hookListener = null;
                for (int idx = 0; idx < this.m_KeyboardHookListeners.Count; idx++)
                {
                    hookListener = this.m_KeyboardHookListeners[idx];
                    if (hookListener != null)
                        hookListener.ProcessKeyboardHookEvent(args, keyBoardInfo);
                }
            }
        }
    }

以下是键盘钩子事件的一个侦听器

    public void ProcessKeyboardHookEvent(KeyboardHookEventArgs e, KeyBoardInfo keyBoardInfo)
    {
        if (this.InvokeRequired == true)
        {
            this.BeginInvoke(new Action<KeyboardHookEventArgs, KeyBoardInfo>(ProcessKeyboardHookEvent), new object[] { e, keyBoardInfo });
        }
        else
        {
            Keys keyCode = (Keys)keyBoardInfo.VKCode;

            if (keyCode == Keys.Return)
            {
                e.Handled = true;
                this.ProcessKeyboardEvent(keyCode, (char)keyCode);
            }
        }
    }

在调用MessageBoxForm之前,一切正常。这是一个自定义表单,添加了两个按钮OK / CANCEL。

    public DialogResult ShowMessageBox(string message)
    {
        this.MessageBoxForm.Message = message;
        DialogResult result = this.MessageBoxForm.ShowDialog();

        return result;
    }

应用程序在调用ShowDialog()期间崩溃或挂起。在调用ShowDialog()之前我也尝试过取消,有时这样可行,有时它不会。这个想法首先解开,以防止ShowDialog的阻塞调用出现任何问题,然后在窗体关闭时再次挂钩。

    public DialogResult ShowMessageBox(string message)
    {
        KeyboardHook.GetInstance().Unhook();

        this.MessageBoxForm.Message = message;
        DialogResult result = this.MessageBoxForm.ShowDialog();

        KeyboardHook.GetInstance().Hook();

        return result;
    }

0 个答案:

没有答案