Pergunta

Eu tenho um aplicativo MDI .net escrito em vb.net. Estou tentando programar uma forma que permitirá que o usuário selecione um caractere especial, como °, µ, ², ³, ? e assim por diante e ter esse caráter inserido em qualquer controle foi focada antes da sua lançando a forma através de um hot-chave ou o menu principal do pai MDI.

A maneira fácil de fazer isso seria a de descobrir qual o controle foi focada no que formulário filho MDI quando o formulário de seleção de personagens é invocado, mas não consigo encontrar qualquer informação sobre como fazer isso.

Todas as idéias?

Foi útil?

Solução 3

Encontrada uma maneira mais fácil -

[Parent Form].ActiveMdiChild.ActiveControl

Outras dicas

Parece que a mensagem WM_SETFOCUS não estão vindo através .... My bad. Tenho certeza de que eles viriam através do método Control.WndProc . Como em torno do trabalho, tive de p / invoke GetFocus evertime chegou uma mensagem e armazenar o identificador do controle que tem foco.

A seção 1 ° código é a classe de filtro e a seção 2 código é o código de teste.



    public class LastFocusedControlFilter : IMessageFilter
    {
        [DllImport("user32")]
        private static extern IntPtr GetFocus();

        private IntPtr? _lastCtrl;
        private readonly Control _ctrlToIgnore;

        public LastFocusedControlFilter(Control controlToIgnore)
        {
            _ctrlToIgnore = controlToIgnore;
        }

        public bool PreFilterMessage(ref Message m)
        {
            if (!_ctrlToIgnore.IsHandleCreated || _ctrlToIgnore.Disposing || _ctrlToIgnore.IsDisposed)
            {
                return false;
            }
            IntPtr handle = GetFocus();
            if (handle != _ctrlToIgnore.Handle)
            {
                _lastCtrl = handle;
            }
            return false;
        }

        public Control GetLastFocusedControl()
        {
            return _lastCtrl.HasValue ? Control.FromHandle(_lastCtrl.Value) : null;
        }
    }
static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        using (Form form = new Form())
        {
            Action resetBackColor = null;
            for (int i = 0; i < 10; i++)
            {
                TextBox textBox = new TextBox();
                resetBackColor += delegate { textBox.BackColor = Color.White; };
                textBox.Text = ((char)('a' + i)).ToString();
                textBox.Location = new Point(0, textBox.Height * i);
                form.Controls.Add(textBox);
            }
            Button showTextButton = new Button();
            LastFocusedControlFilter msgFilter = new LastFocusedControlFilter(showTextButton);
            showTextButton.Dock = DockStyle.Bottom;
            showTextButton.Text = "Show text of last selected control";
            showTextButton.Click += delegate(object sender, EventArgs e)
             {
                 resetBackColor();
                 Control lastControl = msgFilter.GetLastFocusedControl();
                 if (lastControl == null)
                 {
                     MessageBox.Show("No control previous had focus.");
                 }
                 else
                 {
                     lastControl.BackColor = Color.Red;
                     MessageBox.Show(string.Format("Control of type {0} had focus with text '{1}'.", lastControl.GetType(), lastControl.Text));
                 }
             };
            form.Controls.Add(showTextButton);

            Application.AddMessageFilter(msgFilter);
            Application.Run(form);
        }
    }
}

Adicionar um IMessageFilter eo monitor para mensagens do Windows, como WM_SETFOCUS ou < a href = "http://msdn.microsoft.com/en-us/library/ms646274%28VS.85%29.aspx" rel = "nofollow noreferrer"> WM_ACTIVATE . Você pode usar Control.FromHandle para IntPtrs converter para Controles NET.

Você pode adicionar uma classe como este para seu projeto:

public class FocusWatcher
{
    private static System.Windows.Forms.Control _focusedControl;
    public static System.Windows.Forms.Control FocusedControl
    {
        get
        {
            return _focusedControl;
        }
    }

    public static void GotFocus(object sender, EventArgs e)
    {
        _focusedControl = (System.Windows.Forms.Control)sender;
    }
}

Então, para qualquer controle sobre qualquer forma que você quer ser um candidato para "mais controle recentemente focado", você faria isso:

textBox1.GotFocus += FocusWatcher.GotFocus;

e, em seguida, FocusWatcher.FocusedControl acesso para obter o controle mais recentemente focado. as mensagens de Monitoramento irá funcionar, mas você tem que ignorar as mensagens que você não quer (como WM_ACTIVATE do formulário MDI).

Você pode iterar por todos os controles em cada formulário e adicionar esse manipulador para o evento GotFocus, mas certamente há controles que você não quero isso para (como botões, por exemplo). Você poderia, em vez iterate e só adicionar o manipulador para TextBoxes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top