c# - ¿Abrir un formulario de WinForms con TopMost=true pero no tenerlo para robar el foco?
(7)
Tengo un formulario que aparece en la pantalla de un usuario y tiene TopMost=true
, pero roba el foco. ¿Cómo puedo conseguir que no robe el foco cuando aparece por primera vez?
En lugar de escribir .setfocus()
en el evento _activated
; .shown
a .shown
evento del formulario.
Esto es lo que funcionó para mí. Proporciona TopMost pero sin robo de enfoque.
protected override bool ShowWithoutActivation
{
get { return true; }
}
private const int WS_EX_TOPMOST = 0x00000008;
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= WS_EX_TOPMOST;
return createParams;
}
}
Recuerde omitir la configuración TopMost en el diseñador de Visual Studio o en cualquier otro lugar.
Esto es robado, errado, prestado, desde aquí (haga clic en Soluciones provisionales):
Me encontré con el mismo problema. No estoy usando C # pero C ++. Me imagino que esto podría ser útil de todos modos:
Utilizando windows.h:
BOOL WINAPI SetWindowPos(
__in HWND hWnd,
__in_opt HWND hWndInsertAfter,
__in int X,
__in int Y,
__in int cx,
__in int cy,
__in UINT uFlags
);
Pasar la bandera SWP_NOACTIVATE al argumento uFlags funcionó para mí.
Pega este código en tu formulario:
protected override bool ShowWithoutActivation
{
get { return true; }
}
Probé el siguiente código usando un temporizador en form1 para crear una instancia y mostrar form2 con form1 como propietario.
En el evento Mostrado de form2, puse el foco en el propietario, que es la forma activa actual.
Tengo un cuadro de texto en form1 y pude escribir continuamente en el cuadro de texto sin perder el enfoque durante este proceso.
Mi código de temporizador en form1:
private void timer1_Tick(object sender, EventArgs e)
{
Form2 popup = new Form2();
popup.TopMost = true;
popup.Show(this);
timer1.Enabled = false;
}
Mi código en el evento Mostrado de form2:
private void Form2_Shown(object sender, EventArgs e)
{
this.Owner.Focus();
}
Puede hacer esto o simplemente establecer TopMost en falso y usar la anulación de ShowWithoutActivation como lo indicó Hans Passant.
Edición: (O use p / invoke como se ve en el comentario adicional de Hans Passant que extrañé mientras escribía esto)
Puede configurar:
this.TopMost = True;
en el evento de carga de esa forma.
Esta bien conmigo
Puedes hacerlo así:
private const int SW_SHOWNOACTIVATE = 4;
private const int HWND_TOPMOST = -1;
private const uint SWP_NOACTIVATE = 0x0010;
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern bool SetWindowPos(
int hWnd, // Window handle
int hWndInsertAfter, // Placement-order handle
int X, // Horizontal position
int Y, // Vertical position
int cx, // Width
int cy, // Height
uint uFlags); // Window positioning flags
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool ShowWindow(System.IntPtr hWnd, int nCmdShow);
public static void ShowInactiveTopmost(System.Windows.Forms.Form frm)
{
try
{
ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
frm.Left, frm.Top, frm.Width, frm.Height,
SWP_NOACTIVATE);
}
catch (System.Exception ex)
{
// error handling
}
}