Pregunta

Tengo una aplicación .net MDI escrita en vb.net. Estoy tratando de programar un formulario que permita al usuario seleccionar un carácter especial como °, µ, ², ³, ? y así sucesivamente y que ese carácter se inserte en cualquier control que se haya enfocado antes de lanzar el formulario a través de un tecla de acceso rápido o el menú principal en el MDI padre.

La manera fácil de hacer esto sería averiguar qué control se centró en qué formulario MDI Child cuando se invoca el formulario de selección de caracteres, pero no puedo encontrar ninguna información sobre cómo hacerlo.

¿Alguna idea?

¿Fue útil?

Solución 3

Encontrado una manera más fácil -

[Parent Form].ActiveMdiChild.ActiveControl

Otros consejos

Parece que los mensajes WM_SETFOCUS no llegan ... Mi problema. Estoy bastante seguro de que aparecerán en el Método Control.WndProc . Como solución, tuve que p / invocar GetFocus evertime llegó un mensaje y almacenó el identificador del control que tiene el foco.

La primera sección del código es la clase de filtro y la segunda sección del código es el código de prueba.



    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);
        }
    }
}

Agregue un IMessageFilter y monitoree para mensajes de Windows como WM_SETFOCUS o < a href = "http://msdn.microsoft.com/en-us/library/ms646274%28VS.85%29.aspx" rel = "nofollow noreferrer"> WM_ACTIVATE . Puede usar Control.FromHandle convertir IntPtrs a controles .NET.

Puede agregar una clase como esta a su proyecto:

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;
    }
}

Luego, para cualquier control en cualquier formulario que desee ser candidato para el "control centrado más recientemente", debe hacer esto:

textBox1.GotFocus += FocusWatcher.GotFocus;

y luego acceda a FocusWatcher.FocusedControl para obtener el control enfocado más recientemente. Los mensajes de monitoreo funcionarán, pero debe ignorar los mensajes que no desea (como WM_ACTIVATE del formulario Mdi).

Puede iterar a través de todos los controles en cada formulario y agregar este controlador para el evento GotFocus, pero seguramente hay controles para los que no desea esto (como Botones, por ejemplo). En su lugar, podría iterar y solo agregar el controlador para TextBoxes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top