Pokazać formularz bez kradzieży ostrości?

Używam formularza do wyświetlania powiadomień (pojawia się w prawym dolnym rogu ekranu), ale kiedy pokazuję ten formularz, kradnie ostrość z głównego formularza. Czy jest sposób, aby pokazać ten formularz "powiadomienia" bez kradzieży ostrości?

Author: Peter Mortensen, 2008-10-01

17 answers

Hmmm, to nie tylko nadrzędna forma.Pokaz bez aktywacji wystarczy?

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

I jeśli nie chcesz, aby użytkownik klikał to okno powiadomień, możesz nadpisać 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;
  }
}
 153
Author: Martin Plante,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-29 12:29:25

Skradziony z PInvoke.net 'S ShowWindow metoda:

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

(Alex Lyman odpowiedział na to, po prostu rozszerzam go poprzez bezpośrednie wklejenie kodu. Ktoś z uprawnieniami do edycji może skopiować to tam i usunąć to dla mnie;))

 65
Author: TheSoftwareJedi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-07 12:45:48

Jeśli chcesz użyć Win32 P / Invoke , Następnie możesz użyć metody ShowWindow (pierwsza próbka kodu robi dokładnie to, co chcesz).

 14
Author: Alex Lyman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-07 12:37:03

To mi się udało. Zapewnia najwyższą, ale bez kradzieży ostrości.

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

Pamiętaj, aby pominąć ustawienie TopMost w Visual Studio designer, lub gdzie indziej.

To jest kradzione, błądzić, pożyczone, stąd (kliknij na obejścia):

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

 10
Author: RenniePet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-09 14:09:12

Robienie tego wydaje się hack, ale wydaje się działać:

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

Edit: uwaga, to tylko podnosi już utworzony formularz bez kradzieży ostrości.

 9
Author: Matthew Scharley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 03:20:25

Przykładowy kod z pinvoke.net w Alex Lyman / TheSoftwareJedi odpowiedzi sprawią, że okno będzie" najwyższym " oknem, co oznacza, że nie można umieścić go za normalnymi oknami po jego wyskoczeniu. Biorąc pod uwagę Opis Matiasa, do czego chce to wykorzystać, to może być to, czego chce. Ale jeśli chcesz, aby użytkownik mógł umieścić swoje okno za innymi oknami, po prostu użyj HWND_TOP (0) zamiast hwnd_topmost (-1) w próbce.

 8
Author: Micah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 04:44:40

W WPF możesz rozwiązać to tak:

W oknie umieść te atrybuty:

<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>

Ostatnim atrybutem jest ten, którego potrzebujesz ShowActivated= "False".

 6
Author: Ziketo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-20 23:36:21

Utwórz i uruchom formularz powiadomienia w osobnym wątku i zresetuj fokus z powrotem do głównego formularza po otwarciu formularza. W formularzu powiadomień należy podać Zdarzenie OnFormOpened, które zostanie wywołane ze zdarzenia Form.Shown. Coś takiego:

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
}

Możesz również zachować uchwyt do obiektu NotifcationForm, aby mógł być programowo zamknięty przez główny formularz (frm.Close()).

Brakuje pewnych szczegółów, ale mam nadzieję, że to sprawi, że będziesz w dobrym stanie kierunek.

 3
Author: Bob Nadler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 03:24:46

Możesz rozważyć, jakiego rodzaju powiadomienie chcesz wyświetlić.

Jeśli jest absolutnie krytyczne, aby poinformować użytkownika o jakimś zdarzeniu, za pomocą Messagebox.Show byłoby zalecanym sposobem, ze względu na swój charakter, aby zablokować wszelkie inne zdarzenia do głównego okna, dopóki użytkownik nie potwierdzi tego. Należy jednak pamiętać o pop-up ślepoty.

Jeśli jest to mniej niż krytyczne, możesz użyć alternatywnego sposobu wyświetlania powiadomień, takiego jak pasek narzędzi na dole ekranu okno. Napisałeś, że powiadomienia wyświetlasz w prawym dolnym rogu ekranu-standardowym sposobem na to byłoby użycie końcówki balonu z kombinacją ikony w tacce systemowej .

 3
Author: Silver Dragon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-07 12:39:09

Mam coś podobnego, po prostu pokazuję formularz zgłoszeniowy, a potem robię

this.Focus();

Aby skupić się z powrotem na głównej formie.

 2
Author: pkr298,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-15 22:25:29

To działa dobrze:

[System.Runtime.InteropServices.DllImport("user32")]

public static extern long OpenIcon(long hwnd);

[System.Runtime.InteropServices.DllImport("user32")]

public static extern long SetForegroundWindow(long hwnd);


public static void ActivateInstance()
{

    long MyHndl = 0;

    long result = 0;

    Process objProcess = Process.GetCurrentProcess();

    MyHndl = objProcess.MainWindowHandle.ToInt32();

    result = OpenIcon(MyHndl); // Restore the program.

    result = SetForegroundWindow(MyHndl); // Activate the application.

    //System.Environment.Exit(0); // End the current instance of the application.

}
 2
Author: Factor Mystic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-25 04:25:49

Ty możesz poradzić sobie z tym również logicznie, chociaż muszę przyznać, że powyższe sugestie, w których kończysz z metodą BringToFront bez kradzieży ostrości, są najbardziej eleganckie.

Tak czy inaczej, wpadłem na to i rozwiązałem to, używając właściwości DateTime, aby nie zezwalać na dalsze wywołania BringToFront, jeśli połączenia zostały wykonane już niedawno.

Przyjmij klasę core, 'Core', która obsługuje na przykład trzy formy, 'Form1, 2 i 3'. Każdy formularz wymaga właściwości DateTime i Zdarzenie aktywacji wywołujące Core, aby doprowadzić windows do przodu:

internal static DateTime LastBringToFrontTime { get; set; }

private void Form1_Activated(object sender, EventArgs e)
{
    var eventTime = DateTime.Now;
    if ((eventTime - LastBringToFrontTime).TotalMilliseconds > 500)
        Core.BringAllToFront(this);
    LastBringToFrontTime = eventTime;
}

A następnie utworzyć pracę w klasie Core:

internal static void BringAllToFront(Form inForm)
{
    Form1.BringToFront();
    Form2.BringToFront();
    Form3.BringToFront();
    inForm.Focus();
}

Na marginesie, jeśli chcesz przywrócić zminimalizowane okno do pierwotnego stanu (nie zmaksymalizowanego), użyj:

inForm.WindowState = FormWindowState.Normal;

Ponownie, wiem, że to tylko rozwiązanie patcha w braku BringToFrontWithoutFocus. Jest to sugestia, jeśli chcesz uniknąć pliku DLL.

 2
Author: Meta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-07 13:28:30

Nie wiem, czy jest to uważane za Necro-posting, ale to jest to, co zrobiłem, ponieważ nie mogłem go pracować z metodami "ShowWindow" i "SetWindowPos" user32. I nie, nadpisanie "ShowWithoutActivation" nie działa w tym przypadku, ponieważ nowe okno powinno być zawsze na górze. W każdym razie, stworzyłem metodę pomocniczą, która przyjmuje formę jako parametr; po wywołaniu pokazuje formę, przynosi ją do przodu i czyni ją najwyższą bez kradzieży fokusu bieżącego okna (najwyraźniej robi to, ale użytkownik nie zauważy).

    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern IntPtr SetForegroundWindow(IntPtr hWnd);

    public static void ShowTopmostNoFocus(Form f)
    {
        IntPtr activeWin = GetForegroundWindow();

        f.Show();
        f.BringToFront();
        f.TopMost = true;

        if (activeWin.ToInt32() > 0)
        {
            SetForegroundWindow(activeWin);
        }
    }
 1
Author: domi1819,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-03 06:54:36

Wiem, że może to zabrzmieć głupio, ale to zadziałało:

this.TopMost = true;
this.TopMost = false;
this.TopMost = true;
this.SendToBack();
 0
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-07 11:14:27

Musiałem to zrobić z moim oknem na górze. Zaimplementowałem metodę PInvoke powyżej, ale stwierdziłem, że moje Zdarzenie ładowania nie było wywoływane jak Talha powyżej. W końcu mi się udało. Może to komuś pomoże. Oto moje rozwiązanie:

        form.Visible = false;
        form.TopMost = false;
        ShowWindow(form.Handle, ShowNoActivate);
        SetWindowPos(form.Handle, HWND_TOPMOST,
            form.Left, form.Top, form.Width, form.Height,
            NoActivate);
        form.Visible = true;    //So that Load event happens
 0
Author: Steven Cvetko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-10 23:38:08

Podczas tworzenia nowego formularza za pomocą

Form f = new Form();
f.ShowDialog();

Kradnie focus, ponieważ twój kod nie może kontynuować wykonywania na głównym formularzu, dopóki ten formularz nie zostanie zamknięty.

Wyjątkiem jest użycie wątku do utworzenia nowego formularza, a następnie formularza.Show(). Upewnij się jednak, że wątek jest globalnie widoczny, ponieważ jeśli zadeklarujesz go w ramach funkcji, gdy tylko funkcja zakończy działanie, wątek zakończy się, a Formularz zniknie.

 -3
Author: Fry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 03:26:43

Rozgryzłem to: window.WindowState = WindowState.Minimized;.

 -4
Author: Pawel Pawlowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-09 18:06:58