Открытие формы WinForms с TopMost = true, но без фокуса?
У меня есть форма, которая появляется на экране пользователя и имеет TopMost=true
, но это крадет фокус. Как я могу заставить его не красть фокус, когда он появляется впервые?
7 ответов
Вставьте этот код в вашу форму:
protected override bool ShowWithoutActivation
{
get { return true; }
}
Это то, что сработало для меня. Он обеспечивает TopMost, но без кражи фокуса.
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;
}
}
Не забудьте пропустить настройку TopMost в конструкторе Visual Studio или в другом месте.
Это украдено, ошибочно, заимствовано отсюда (нажмите на обходные пути):
Вы можете сделать это так:
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
}
}
Вы можете установить:
this.TopMost = True;
на событие загрузки этой формы.
Со мной все в порядке!
Я протестировал приведенный ниже код, используя таймер в form1, чтобы создать экземпляр и показать form2 с form1 в качестве владельца.
В событии Shown формы2 я затем установил фокус на владельца, который является текущей активной формой.
У меня есть текстовое поле в форме form1, и я смог непрерывно писать в текстовом поле, не теряя фокус во время этого процесса.
Мой код таймера в форме 1:
private void timer1_Tick(object sender, EventArgs e)
{
Form2 popup = new Form2();
popup.TopMost = true;
popup.Show(this);
timer1.Enabled = false;
}
Мой код в показанном событии формы 2:
private void Form2_Shown(object sender, EventArgs e)
{
this.Owner.Focus();
}
Вы можете сделать это или просто установить TopMost в false и использовать переопределение ShowWithoutActivation, как заявил Ханс Пассант.
Редактировать: (Или используйте p/invoke, как видно из дополнительного комментария Ганса Пассанта, который я пропустил, когда писал это)
Я столкнулся с той же проблемой. Я не использую C#, но C++. Я полагаю, что это может быть полезно в любом случае:
Использование 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
);
Передача флага SWP_NOACTIVATE в аргумент uFlags работала для меня.
Вместо того чтобы писать .setfocus()
в _activated
событие; напиши это .shown
событие формы.