Domanda

Qualcuno conosce un modo per determinare quale finestra riceverà lo stato attivo quando un modulo è disattivato?

È stato utile?

Soluzione

Ho trovato la risposta. Invece di iscriverti agli eventi attivati ??e disattivati, gestisci WM_ACTIVATE messaggio (utilizzato sia per l'attivazione che per la disattivazione) in WndProc. Dal momento che segnala l'attivazione della finestra, posso confrontare quella maniglia con le maniglie dei miei moduli e determinare se lo stato attivo sta cambiando in uno di essi.

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

Modifica: Questo metodo può essere utilizzato al di fuori della finestra a cui si applica (ad es. all'esterno in una finestra popup).

Puoi usare NativeWindow per collegarti a qualsiasi finestra in base al suo handle e visualizzare il suo loop di messaggi. Vedi l'esempio di codice di seguito:

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

Altri suggerimenti

Dovresti essere in grado di determinare il modulo attivo usando la proprietà statica Form.ActiveForm .

Sto riscontrando lo stesso problema durante l'implementazione di una finestra popup di completamento automatico (simile alla finestra Intellisense in VS).

Il problema con l'approccio WndProc è che il codice deve essere aggiunto a qualsiasi modulo che capiti di ospitare il popup.

L'approccio alternativo consiste nell'utilizzare un timer e controllare Form.ActiveControl dopo un breve intervallo. In questo modo, il codice viene incapsulato meglio, nel controllo dell'editor o nel modulo popup .

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(); 
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top