Показать форму без кражи фокуса? - PullRequest
133 голосов
/ 01 октября 2008

Я использую форму для показа уведомлений (она появляется в правом нижнем углу экрана), но когда я показываю эту форму, она крадет фокус у основной формы. Есть ли способ показать эту форму "уведомления" без кражи фокуса?

Ответы [ 17 ]

157 голосов
/ 01 октября 2008

Хммм, разве не просто переопределить форму? Показывать без активации достаточно?

protected override bool ShowWithoutActivation
{
  get { return true; }
}

И если вы не хотите, чтобы пользователь нажимал на это окно уведомлений, вы можете переопределить CreateParams:

protected override CreateParams CreateParams
{
  get
  {
    CreateParams baseParams = base.CreateParams;

    const int WS_EX_NOACTIVATE = 0x08000000;
    const int WS_EX_TOOLWINDOW = 0x00000080;
    baseParams.ExStyle |= ( int )( WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW );

    return baseParams;
  }
}
66 голосов
/ 01 октября 2008

украдено из PInvoke.net ShowWindow метод:

private const int SW_SHOWNOACTIVATE = 4;
private const int HWND_TOPMOST = -1;
private const uint SWP_NOACTIVATE = 0x0010;

[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
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

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

static void ShowInactiveTopmost(Form frm)
{
     ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
     SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
     frm.Left, frm.Top, frm.Width, frm.Height,
     SWP_NOACTIVATE);
}

(Алекс Лайман ответил на это, я просто расширяю его, напрямую вставляя код. Кто-то с правами на редактирование может скопировать его туда и удалить, если мне все равно;))

14 голосов
/ 01 октября 2008

Если вы хотите использовать Win32 P / Invoke , тогда вы можете использовать метод ShowWindow (первый пример кода делает именно то, что вы хотите ).

11 голосов
/ 09 августа 2014

Вот что у меня сработало. Он обеспечивает 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 или в другом месте.

Это украдено, ошибочно, заимствовано отсюда (нажмите на обходные пути):

https://connect.microsoft.com/VisualStudio/feedback/details/401311/showwithoutactivation-is-not-supported-with-topmost

9 голосов
/ 01 октября 2008

Это похоже на хак, но, похоже, работает:

this.TopMost = true;  // as a result the form gets thrown to the front
this.TopMost = false; // but we don't actually want our form to always be on top

Редактировать: Обратите внимание, что это просто вызывает уже созданную форму без кражи фокуса.

8 голосов
/ 01 октября 2008

Пример кода с pinvoke.net в ответах Алекса Лаймана / TheSoftwareJedi сделает окно «самым верхним» окном, что означает, что вы не можете поместить его за обычные окна после его появления. Учитывая описание Матиасом того, для чего он хочет это использовать, это может быть тем, чего он хочет. Но если вы хотите, чтобы пользователь мог ставить ваше окно за другими окнами после того, как вы его открыли, просто используйте HWND_TOP (0) вместо HWND_TOPMOST (-1) в примере.

6 голосов
/ 21 февраля 2012

В WPF вы можете решить это так:

В окне поставьте эти атрибуты:

<Window
    x:Class="myApplication.winNotification"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Notification Popup" Width="300" SizeToContent="Height"
  WindowStyle="None" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True" Focusable="False" ShowActivated="False" >
</Window>

Последний атрибут - это тот, который вам нужен. ShowActivation = "False".

3 голосов
/ 01 октября 2008

Создайте и запустите форму уведомления в отдельном потоке и верните фокус обратно на вашу основную форму после открытия формы. Пусть форма уведомления предоставит событие OnFormOpened, которое запускается из события Form.Shown. Как то так:

private void StartNotfication()
{
  Thread th = new Thread(new ThreadStart(delegate
  {
    NotificationForm frm = new NotificationForm();
    frm.OnFormOpen += NotificationOpened;
    frm.ShowDialog();
  }));
  th.Name = "NotificationForm";
  th.Start();
} 

private void NotificationOpened()
{
   this.Focus(); // Put focus back on the original calling Form
}

Вы также можете хранить дескриптор вашего объекта NotifcationForm, чтобы он мог быть программно закрыт основной формой (frm.Close()).

Некоторые детали отсутствуют, но, надеюсь, это поможет вам двигаться в правильном направлении.

3 голосов
/ 01 октября 2008

Возможно, вы захотите подумать, какое уведомление вы хотите отобразить.

Если абсолютно необходимо сообщить пользователю о каком-либо событии, рекомендуется использовать Messagebox.Show из-за его природы блокировать любые другие события в главном окне, пока пользователь не подтвердит это. Однако помните о всплывающей слепоте.

Если это не так важно, вы можете использовать альтернативный способ отображения уведомлений, например, панель инструментов в нижней части окна. Вы писали, что отображаете уведомления в правом нижнем углу экрана - стандартный способ сделать это - использовать всплывающую подсказку с комбинацией значок в системном трее .

3 голосов
/ 16 ноября 2011

У меня что-то похожее, я просто показываю форму уведомления и затем делаю

this.Focus();

чтобы вернуть фокус на основную форму.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...