Как предотвратить кражу фокуса моим приложением C # winforms, когда я правильно установил видимое в true? - PullRequest
6 голосов
/ 15 мая 2010

У меня есть приложение C # winforms, которое работает в фоновом режиме, прислушиваясь к нажатию горячих клавиш. Когда горячая клавиша нажата, моя форма выглядит кратко. Форма всегда запущена, но устанавливается на скрытое, пока не получит событие горячей клавиши, после чего для свойства visible установлено значение true. Код выглядит так:

void hook_volumeDown(object sender, KeyPressedEventArgs e)
{
    this.Visible = true;
}

Следует отметить, что самое верхнее свойство этой формы установлено в true.

Действительно странная часть: после того, как мое приложение на C # украло фокус из другого приложения, оно никогда не сделает это снова. Например: я запускаю свое приложение, а затем запускаю какое-то приложение, такое как Team Fortress 2. Затем нажимаю горячую клавишу. Team Fortress 2 сворачивается, и я вижу свою форму. Затем, однако, я могу восстановить TF2 и снова нажать мою горячую клавишу, сколько захочу (с желаемым эффектом), и TF2 останется сфокусированным.

В любом случае, я ищу способ это исправить. Я нашел много вопросов, касающихся подобных проблем, но все они связаны с созданием / запуском новой формы, а не с тем, чтобы сделать видимую существующую (если я что-то пропустил). Я мог бы переделывать приложение, чтобы создавать новую форму каждый раз, когда она мне понадобится, но это повлечет за собой создание еще одной формы, которая будет все время невидимой, просто чтобы ждать событий горячих клавиш, поэтому я бы предпочел оставить все как есть. *

Есть идеи?

Ответы [ 2 ]

6 голосов
/ 15 мая 2010

Я думаю, что ваша проблема связана с тем, что Visible = true ведет себя по-разному между первым и последующими вызовами. Вызывается первый раз, когда видимый и дескриптор окна не был создан, Окно создается путем вызова CreateWindowEx, который имеет некоторые параметры стиля, которые управляют поведением окна. Я думаю, вам нужно убедиться, что окно создано в стиле WS_EX_NOACTIVATE, что вы можете сделать, переопределив CreateParams.

Другие вещи, которые стоит попробовать:

1) Функция ShowWindow (используется Visible = true) игнорирует параметр фокуса при первом его вызове (http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx), если программа предоставляет структуру STARTUPINFO. Копайте в рефлектор и узнайте, есть ли класс Form предоставляет структуру STARTUPINFO и, если да, то как ее манипулировать.

2) Форма имеет свойство ShowWithoutActivation, которое можно переопределить и установить в значение true, переопределили ли вы это?

Извините за "нет точного ответа", но я надеюсь, что это, по крайней мере, даст вам некоторые отправные точки для дальнейшего изучения. Удачи.

1 голос
/ 15 мая 2010

Вид использования KeyPressedEventArgs в вашей функции выглядит действительно странным. Горячие клавиши могут быть реализованы с помощью P / Invoking API-функции RegisterHotKey (). Он отправляет сообщение в ваше окно при нажатии горячей клавиши. Вот пример формы, которая невидима при запуске, оживает при нажатии горячей клавиши. Ctrl + Alt + U в этом случае:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        private const int MYKEYID = 0;    // In case you want to register more than one...
        public Form1() {
            InitializeComponent();
            this.FormClosing += (s, args) => UnregisterHotKey(this.Handle, MYKEYID);
        }
        protected override void SetVisibleCore(bool value) {
            if (value && !this.IsHandleCreated) {
                this.CreateHandle();
                RegisterHotKey(this.Handle, MYKEYID, MOD_CONTROL + MOD_SHIFT, Keys.U);
                value = false;
            }
            base.SetVisibleCore(value);
        }
        protected override void WndProc(ref Message m) {
            if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == MYKEYID) {
                this.Visible = true;
                if (this.WindowState == FormWindowState.Minimized)
                    this.WindowState = FormWindowState.Normal;
                SetForegroundWindow(this.Handle);
            }
            base.WndProc(ref m);
        }
        // P/Invoke declarations
        private const int WM_HOTKEY = 0x312;
        private const int MOD_ALT = 1;
        private const int MOD_CONTROL = 2;
        private const int MOD_SHIFT = 4;
        [DllImport("user32.dll")]
        private static extern int RegisterHotKey(IntPtr hWnd, int id, int modifier, Keys vk);
        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
    }
}

Обратите внимание, что функция SetForegroundWindow () является проблемой, возможно, также источником проблемы, которую вы описываете в своем вопросе. Windows не позволяет приложению открывать окно в лицо пользователя, когда пользователь активно использует другое окно. По крайней мере несколько секунд бездействия должно истечь, прежде чем оно позволит окну украсть фокус. С данным кодом, который достаточно легко увидеть, кнопка панели задач вашей формы будет мигать. Не устанавливайте для свойства ShowInTaskbar значение false. С этим кодом делать это не обязательно, кнопка на панели задач не будет отображаться, пока не нажата горячая клавиша.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...