Как препятствовать тому, чтобы мое приложение C# winforms крало фокус, когда я установил видимое правильно на истинный?

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

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

Нужно отметить, что самое верхнее свойство этой формы имеет значение true.

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

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

Какие-либо идеи?

6
задан Fopedush 15 May 2010 в 03:43
поделиться

2 ответа

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

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

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

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

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

6
ответ дан 17 December 2019 в 00:05
поделиться

Наблюдение за использованием KeyPressedEventArgs в вашей функции выглядит действительно странным. Горячие клавиши могут быть реализованы с помощью P / Вызов функции 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. В этом коде нет необходимости, кнопка панели задач не будет отображаться, пока не будет нажата горячая клавиша.

1
ответ дан 17 December 2019 в 00:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: