Sto riscontrando alcuni problemi nel far funzionare correttamente una casella di notifica in C#. Fondamentalmente sto mostrando una scheda senza bordo nella parte in basso a destra dello schermo, che mostra un messaggio per alcuni secondi e poi scompare. Il problema è che ho bisogno che appaia in cima alle altre finestre senza che sia mai in grado di rubare lo stato attivo. Idealmente, voglio che sia un codice puramente gestito, anche se osservando esempi simili dubito che ciò sia possibile.Finestra di notifica - Impedire alla finestra di ottenere sempre lo stato attivo
Al momento sto impedendogli di rubare messa a fuoco quando si chiama Form.Show() con un override:
protected override bool ShowWithoutActivation // stops the window from stealing focus
{
get { return true; }
}
e quindi ignorando clic del mouse con:
private const int WM_MOUSEACTIVATE = 0x0021;
private const int MA_NOACTIVATEANDEAT = 0x0004;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEACTIVATE)
{
m.Result = (IntPtr)MA_NOACTIVATEANDEAT;
return;
}
base.WndProc(ref m);
}
Tuttavia trovo che se li uso insieme a TopMost = true (di cui ho bisogno), ottiene comunque la messa a fuoco, e se tutte le altre finestre sono ridotte a icona, ottiene anche l'attenzione.
Quindi, esiste un modo per evitare che un modulo ottenga mai la messa a fuoco (sia tramite clic del mouse, alt-tab, ecc.), Pur rimanendo il più alto/secondo in alto nella maggior parte dei moduli? Anche solo dare fuoco immediatamente alla finestra che ha rubato avrebbe funzionato (anche se introdurre sfarfallio).
Qualsiasi suggerimento sarebbe molto apprezzato, sono davvero bloccato con questo.
EDIT:
Ok, così ho finalmente riuscito a ottenere questo lavoro utilizzando:
protected override bool ShowWithoutActivation // stops the window from stealing focus
{
get { return true; }
}
// and
const int WS_EX_NOACTIVATE = 0x08000000;
const int WS_EX_TOPMOST = 0x00000008;
protected override CreateParams CreateParams
{
get
{
CreateParams param = base.CreateParams;
param.ExStyle |= WS_EX_TOPMOST; // make the form topmost
param.ExStyle |= WS_EX_NOACTIVATE; // prevent the form from being activated
return param;
}
}
// and
[DllImport("user32.dll")]
private extern static IntPtr SetActiveWindow(IntPtr handle);
private const int WM_ACTIVATE = 6;
private const int WA_INACTIVE = 0;
private const int WM_MOUSEACTIVATE = 0x0021;
private const int MA_NOACTIVATEANDEAT = 0x0004;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEACTIVATE)
{
m.Result = (IntPtr)MA_NOACTIVATEANDEAT; // prevent the form from being clicked and gaining focus
return;
}
if (m.Msg == WM_ACTIVATE) // if a message gets through to activate the form somehow
{
if (((int)m.WParam & 0xFFFF) != WA_INACTIVE)
{
if (m.LParam != IntPtr.Zero)
{
SetActiveWindow(m.LParam);
}
else
{
// Could not find sender, just in-activate it.
SetActiveWindow(IntPtr.Zero);
}
}
}
Ho anche aggiunto Form.Hide() per l'evento attivato in modo che, anche se lo fa in qualche modo ottenere attenzione , semplicemente si chiude e esce dagli utenti appena possibile.
Inoltre, se qualcuno si chiede, le costanti per tutti gli stili di finestra ecc. Possono essere trovate in WINUSER.H, è in linea a http://www.woodmann.com/fravia/sources/WINUSER.H se non riesci a trovarlo.
Tuttavia, se qualcuno può vedere un modo più elegante di farlo, sarebbe apprezzato.
Grazie, questo è perfetto per evitare che si accenda, non appare nemmeno in alt-tab ora che è fantastico. L'unico problema minore che sto ancora avendo è che TopMost = true sembra sovrascrivere ShowWithoutActivation, quindi ottiene ancora lo stato attivo quando viene chiamato form.Show(). C'è un modo per aggirare questo? – yebetrollin
Vedi la risposta di Ziketo per quello. Ricorda anche di votare le domande delle persone che hanno aiutato. –