Глобальные ключи C # и SetForegroundWindow

#c#

#c#

Вопрос:

Я использую приложение C # для прослушивания глобальной комбинации клавиш (ctrl F9), которая выведет на экран определенное окно.

Это код, который я использую для вывода окна на передний план, он работает, только если вызван событием Button:

     private void button3_Click(object sender, EventArgs e)
    {
        SetForegroundWindow(ptrActiveWindow.ToInt32());
        ShowWindowAsync(ptrActiveWindow, SW_RESTORE);
    }
  

Для подключения я использовал класс, взятый из http://www.codeproject.com/KB/cs/CSLLKeyboardHook.aspx , которые полностью перечислены здесь:

http://code.google.com/p/code-commenter/source/browse/trunk/key preview/globalKeyboardHook.cs?spec=svn3amp;r=3

Всякий раз, когда у меня происходит событие нажатия клавиши F9 после нажатия клавиши CTRL и перед нажатием клавиши CTRL (CTRL все еще нажат), я вызываю свой метод:

     private void restore(IntPtr hWnd)
    {

      IntPtr ptrCurrentActiveWindow = GetForegroundWindow(); //comment line
      ShowWindowAsync(ptrCurrentActiveWindow, SW_MINIMIZE); //comment line

        ShowWindowAsync(hWnd, SW_RESTORE);
        SetFocus(hWnd);
        SetForegroundWindow(hWnd.ToInt32());

    }
  

Это ничего не дает. Мое окно активируется в фоновом режиме (я вижу, как оно мигает на панели задач), но не восстанавливается.

Единственный способ, которым я могу обойти это, — использовать прокомментированный код: свернуть текущее активное окно и впоследствии восстановить окно, которое я хочу видеть.

Любая помощь приветствуется, спасибо.

Глобальная горячая клавиша, рабочая версия:

     private void Form1_Load(object sender, EventArgs e)
    {
        string atomName = Thread.CurrentThread.ManagedThreadId.ToString("X8")   this.GetType().FullName;
        short HotkeyID = GlobalAddAtom(atomName);
        if (!RegisterHotKey(this.Handle, HotkeyID, (uint)GlobalHotkeys.MOD_CONTROL, (uint)Keys.D5))
            listBox.Items.Add("failed: "   "unable to register hotkey. Error: "   Marshal.GetLastWin32Error().ToString());
        else
            listBox.Items.Add("succeeded adding hotkey id" (uint)Keys.D5);
    }

    protected override void WndProc(ref Message m)
    {
        const int WM_HOTKEY = 0x0312;

        if (m.Msg == WM_HOTKEY)
        {
            if ((short)m.WParam==HotkeyID)
                listBox.Items.Add("Hotkey."  (short)m.WParam);
        }
        base.WndProc(ref m);
    }
  

Ответ №1:

Ваша проблема в том, что вы не зарегистрировали глобальную горячую клавишу, а вместо этого использовали клавиатурный хук. Клавиатурные хуки не предназначены для использования в качестве глобальных горячих клавиш.

Вместо этого используйте RegisterHotKey функцию.
Проверьте этот пример: http://www.pinvoke.net/default.aspx/user32.registerhotkey

Ваша непосредственная проблема заключается в том, что приложение не может вывести себя на передний план, когда ему заблагорассудится. Потому что это раздражает пользователя. Это может быть сделано только во время определенного события. Как при запуске приложения или при работе с реальной глобальной горячей клавишей.

Система ограничивает, какие процессы могут устанавливать окно переднего плана. Процесс может установить окно переднего плана, только если выполняется одно из следующих условий:

  • Процесс является процессом переднего плана.
  • Процесс был запущен процессом переднего плана.
  • Процесс получил последнее событие ввода.
  • Процесс переднего плана отсутствует.
  • Процесс на переднем плане отлаживается.
  • Передний план не заблокирован (см. Lockset Foregroundwindow).
  • Истек тайм-аут блокировки переднего плана (см. SPI_GETFOREGROUNDLOCKTIMEOUT в SystemParametersInfo).
  • Никакие меню не активны.

Комментарии:

1. класс-оболочка немного испорчен, но, тем не менее, полезен. Спасибо!

2. хм, просматривая код, он сломан. Не используйте GetHashCode в качестве своего уникального идентификатора.

Ответ №2:

Попробуйте использовать другую константу SW_, например SW_SHOW. SW_RESTORE работает только с окнами, свернутыми с помощью SW_MINIMIZE

Комментарии:

1. Я использовал практически все константы. Кроме того, если это работает при вызове из события button, оно должно работать где угодно. Я предполагаю, что проблема заключается в использовании горячих клавиш.