none
Как отловить смену фокуса в приложении RRS feed

  • Вопрос

  • Добрый день.

    Мне необходимо отловить изменения фокуса в приложении. Неважно в каком пользовательском элементе. Что-то типа глобального FocusManager в границах приложения.

    Как этого можно добиться?

    26 апреля 2013 г. 8:22

Ответы

  • Можно отлавливать все сообщения посылаемые приложению и выбирать только те, на которые нужно реагировать "глобально".

    Вот пример кода:

    using System.Security.Permissions;
    
    namespace FocusManager
    {
    	[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    	public class TestMessageFilter : IMessageFilter
    	{
    		public bool PreFilterMessage(ref Message m)
    		{
    			if (m.Msg == 257 && (Int32)m.WParam == 0x09)
    			{
    				MessageBox.Show("Фокус вода перемещен.");
    				return false;
    			}
    			return false;
    		}
    	}
    
    	static class Program
    	{
    		/// <summary>
    		/// Главная точка входа для приложения.
    		/// </summary>
    		[STAThread]
    		static void Main()
    		{
    			Application.EnableVisualStyles();
    			Application.SetCompatibleTextRenderingDefault(false);
    			Application.AddMessageFilter(new TestMessageFilter());
    			Application.Run(new Form1());
    		}
    	}
    }

    В методе Main вызывается метод AddMessageFilter класса Application. Этот метод принимает в качестве параметра - объект класса TestMessageFilter, который реализует IMessageFilter. Через метод PreFilterMessage проходят все сообщения посылаемые приложению, в том числе сообщения получения/потери фокуса ввода. В данном случае, в примере проверяется ввод с клавиатуры (m.Msg == 257) и если была нажата клавиша TAB ((Int32)m.WParam == 0x09), то происходит обработка сообщения. Если метод PreFilterMessage возвращает true то сообщение считается обработанным и дальше в цепочку обработчиков не передается, если false то передается следующему обработчику.

    Как перехватить все остальные варианты потери фокуса (от мыши или программно) я не знаю, т. к. разные типы сообщений нужно ловить по разному.

    Думаю, что где то в этих разделах справки можно найти все что нужно.

    29 апреля 2013 г. 5:57

Все ответы

  • Во первых, нужно знать вашу платформу, WinForms или WPF? Во-вторых, что конкретно нужно? Отловить когда пользователь был в приложении, а потом переключился на другое или отловить перескоки с элемента на элемент внутри приложения?

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    26 апреля 2013 г. 9:17
    Отвечающий
  • Прошу прощение за неточность.

    Платформа Windows Forms.

    Необходимо отловить "перескоки" между элементами внутри приложения.

    26 апреля 2013 г. 9:25
  • Плохо, что Windows Forms. Пусть меня поправят, но кажется в Windows Forms нужно для каждого элемента реагировать на события LostFocus и GotFocus

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    26 апреля 2013 г. 9:29
    Отвечающий
  • Совершенно верно. Но мне как раз и необходимо отловить перескоки глобально, внутри приложения. В этом-то и вся соль.
    26 апреля 2013 г. 9:31
  • Совершенно верно. Но мне как раз и необходимо отловить перескоки глобально, внутри приложения. В этом-то и вся соль.
    К сожалению у меня идей нет. Может кто другой подскажет. В WPF нам бы помогло пузырьковое распространение события, но WinForms такого по умолчанию нет.

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    26 апреля 2013 г. 10:40
    Отвечающий
  • Создайте свой базовый класс и унаследуйте от него ваши формы. Можете добавить рекурсию если есть вложенные контролы.

        public partial class MyBaseForm : Form
        {
            public event EventHandler ControlFocusChanged;
    
            protected virtual void OnControlFocusChanged(object sender, EventArgs e)
            {
                EventHandler handler = this.ControlFocusChanged;
                if (handler != null)
                {
                    handler(sender, e);
                }
            }
    
            protected override void OnLoad(EventArgs e)
            {
                base.OnLoad(e);
    
                foreach (Control c in this.Controls)
                {
                    c.GotFocus += new EventHandler(OnControlFocusChanged);
                }
            }
        }

    26 апреля 2013 г. 11:47
  • Спасибо, не подходит....
    26 апреля 2013 г. 12:04
  • Можно отлавливать все сообщения посылаемые приложению и выбирать только те, на которые нужно реагировать "глобально".

    Вот пример кода:

    using System.Security.Permissions;
    
    namespace FocusManager
    {
    	[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    	public class TestMessageFilter : IMessageFilter
    	{
    		public bool PreFilterMessage(ref Message m)
    		{
    			if (m.Msg == 257 && (Int32)m.WParam == 0x09)
    			{
    				MessageBox.Show("Фокус вода перемещен.");
    				return false;
    			}
    			return false;
    		}
    	}
    
    	static class Program
    	{
    		/// <summary>
    		/// Главная точка входа для приложения.
    		/// </summary>
    		[STAThread]
    		static void Main()
    		{
    			Application.EnableVisualStyles();
    			Application.SetCompatibleTextRenderingDefault(false);
    			Application.AddMessageFilter(new TestMessageFilter());
    			Application.Run(new Form1());
    		}
    	}
    }

    В методе Main вызывается метод AddMessageFilter класса Application. Этот метод принимает в качестве параметра - объект класса TestMessageFilter, который реализует IMessageFilter. Через метод PreFilterMessage проходят все сообщения посылаемые приложению, в том числе сообщения получения/потери фокуса ввода. В данном случае, в примере проверяется ввод с клавиатуры (m.Msg == 257) и если была нажата клавиша TAB ((Int32)m.WParam == 0x09), то происходит обработка сообщения. Если метод PreFilterMessage возвращает true то сообщение считается обработанным и дальше в цепочку обработчиков не передается, если false то передается следующему обработчику.

    Как перехватить все остальные варианты потери фокуса (от мыши или программно) я не знаю, т. к. разные типы сообщений нужно ловить по разному.

    Думаю, что где то в этих разделах справки можно найти все что нужно.

    29 апреля 2013 г. 5:57