Pregunta

¿Alguien sabe de una manera de determinar qué ventana recibirá atención cuando se desactiva un formulario?

¿Fue útil?

Solución

He encontrado la respuesta. En lugar de suscribirse a los eventos activados y desactivados, maneje el WM_ACTIVATE mensaje (usado tanto para la activación como para la desactivación) en WndProc. Ya que informa que el identificador de la ventana se está activando, puedo comparar ese identificador con los manejadores de mis formularios y determinar si el enfoque cambia a alguno de ellos.

const int WM_ACTIVATE = 0x0006;
const int WA_INACTIVE = 0;
const int WA_ACTIVE = 1;  
const int WA_CLICKACTIVE = 2;  

protected override void WndProc(ref Message m)  
{  
    if (m.Msg == WM_ACTIVATE)  
    {  
         // When m.WParam is WA_INACTIVE, the window is being deactivated and
         // m.LParam is the handle of the window that will be activated.

         // When m.WParam is WA_ACTIVE or WA_CLICKACTIVE, the window is being 
         // activated and m.LParam is the handle of the window that has been 
         // deactivated.
    }  

    base.WndProc(ref m);  
} 

Editar: Este método se puede usar fuera de la ventana a la que se aplica (por ejemplo, afuera en una ventana emergente).

Puede usar NativeWindow para adjuntarse a cualquier ventana en función de su identificador y ver su bucle de mensajes. Vea el ejemplo de código a continuación:

public class Popup : Form
{
    const int WM_ACTIVATE = 0x0006;
    const int WA_INACTIVE = 0;
    private ParentWindowIntercept parentWindowIntercept;

    public Popup(IntPtr hWndParent)
    {
        this.parentWindowIntercept = new ParentWindowIntercept(hWndParent);
    }

    private class ParentWindowIntercept : NativeWindow
    {
        public ParentWindowIntercept(IntPtr hWnd)
        {
            this.AssignHandle(hWnd);
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_ACTIVATE)
            {
                if ((int)m.WParam == WA_INACTIVE)
                {
                    IntPtr windowFocusGoingTo = m.LParam;
                    // Compare handles here
                }
            }

            base.WndProc(ref m);
        } 
    }
}

Otros consejos

Debería poder determinar el formulario activo utilizando la propiedad estática Form.ActiveForm .

Tengo el mismo problema al implementar una ventana emergente de autocompletar (similar a la ventana Intellisense en VS).

El

problema con el enfoque WndProc es que el código debe agregarse a cualquier formulario que suceda para hospedar la ventana emergente.

El enfoque alternativo consiste en utilizar un temporizador y verificar Form.ActiveControl después de un breve intervalo. De esta manera, el código se encapsula mejor, dentro del control del editor o el formulario emergente .

Form _txPopup;

// Subscribe whenever convenient
public void IntializeControlWithPopup(Form _hostForm)
{
    _hostForm.Deactivate + OnHostFormDeactivate;
}

Timer _deactivateTimer;
Form _hostForm;
void OnHostFormDeactivate(object sender, EventArgs e)
{
    if (_deactivateTimer == null) 
    {
        _mainForm = sender as Form;
        _deactivateTimer = new Timer();
        _deactivateTimer.Interval = 10;
        _deactivateTimer.Tick += DeactivateTimerTick;
    }
    _deactivateTimer.Start();
}

void  DeactivateTimerTick(object sender, EventArgs e)
{
    _deactivateTimer.Stop();
    Form activeForm = Form.ActiveForm;
    if (_txPopup != null && 
        activeForm != _txPopup && 
        activeForm != _mainForm) 
    { 
        _txPopup.Hide(); 
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top