none
Form immer im Vordergrund halten RRS feed

  • Frage

  • Ich habe eine kleine Uhr programmiert. Diese soll nach möglich keit immer sichtbar sein, selbst wenn Sie nicht den Fokus hat und andere Programme im Vollbild laufen. Mit der Eigenschaft TopMost klappt es nicht wenn ein anderes Programm im Vollbild ist. Was kann man da noch machen?
    Koopakiller - http://koopakiller.ko.ohost.de/
    Donnerstag, 22. Dezember 2011 20:50

Antworten

  • Hallo,

    auch wenn es immer wieder gerne versucht wird, so richtig kann da nicht funktionieren,

    Raymond Chen hat das mehrfach erläutert:
    How do I create a topmost window that is never covered by other topmost windows?
    und What if two programs did this?

    Gruß Elmar

    Donnerstag, 22. Dezember 2011 21:14
    Beantworter
  • Hallo K.,

    Diese Frage wurde hier in Forum schon behandelt.

    Programm permanent aktiv im Vordergrund halten?
    http://social.msdn.microsoft.com/Forums/de/visualcsharpde/thread/b3e63c1c-803f-4ba5-ad6f-9a9b6c288616

    Sieh dir dort bitte auch meine Kommentare an.

    Gruß
    Marcel

    Freitag, 23. Dezember 2011 07:20
    Moderator
  • Hallo K.,

    > Ich sage mal, wenn Windows oder die UAC was verlangt, hohlen die sich doch eh in Vordergrund, oder?

    Deine Anwendung könnte ja auch Fokus-Ping-Pong spielen wollen... Das kann dann eine Weile dauern, und ein Weilchen länger.

    > Mit SetForegroundWindow bleibt das Fenster ja schonmal im Vordergrund, wenn ich es regelmäßig in einem Timer aufrufe. Mein Problem dabei ist aber das meine Anwendung dabei den Fokus bekommt, was aber eben nicht geschehen soll.

    Ich würde da einen anderen Weg gehen:

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1() { InitializeComponent(); }
    
            private void buttonShowClockForm_Click(object sender, EventArgs e) {
                ClockForm clockForm = new ClockForm();
                clockForm.Show();
                NativeMethods.MakeFormTopMostInactive(clockForm.Handle, clockForm.Location, clockForm.Size);
            }
        }
    
        public class NativeMethods {
            private static IntPtr HWND_TOPMOST = new IntPtr(-1);
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
    
            public static void MakeFormTopMostInactive(IntPtr handle, Point location, Size size) {
                ShowWindow(handle, ShowWindowCommands.ShowNoActivate);
                SetWindowPos(handle, HWND_TOPMOST, location.X, location.Y, size.Width, size.Height, SetWindowPosFlags.DoNotActivate);
            } 
        }
    
        enum ShowWindowCommands : int {
            Hide = 0,
            Normal = 1,
            ShowMinimized = 2,
            Maximize = 3, // is this the right value?
            ShowMaximized = 3,
            ShowNoActivate = 4,
            Show = 5,
            Minimize = 6,
            ShowMinNoActive = 7,
            ShowNA = 8,
            Restore = 9,
            ShowDefault = 10,
            ForceMinimize = 11
        }
    
        [Flags()]
        enum SetWindowPosFlags : uint {
            SynchronousWindowPosition = 0x4000,
            DeferErase = 0x2000,
            DrawFrame = 0x0020,
            FrameChanged = 0x0020,
            HideWindow = 0x0080,
            DoNotActivate = 0x0010,
            DoNotCopyBits = 0x0100,
            IgnoreMove = 0x0002,
            DoNotChangeOwnerZOrder = 0x0200,
            DoNotRedraw = 0x0008,
            DoNotReposition = 0x0200,
            DoNotSendChangingEvent = 0x0400,
            IgnoreResize = 0x0001,
            IgnoreZOrder = 0x0004,
            ShowWindow = 0x0040,
        }
    }
    


    ShowWindow function:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx

    SetWindowPos function:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms633545(v=vs.85).aspx

    Details zu den Funktionen und Enumerationen findest Du auch auf pinvoke.net.

    Ich würde mir also eher einen milden, umsichtigen Umgang mit Anwendungen wünschen, die den Fokus "stehlen". Windows ist ein kooperatives System. Ein Timer scheint mir da viel zu aggressiv. Unsachgemäße Verwendung kann bis hin zur Blockierung des gesamten Systems führen (Raymond Chen, den ich ebenfalls in meinen Postings vom 23. Mai 2011 zitierte, ist in diesem Punkt sehr überzeugend). Viel Glück.

    Gruß
    Marcel

    Freitag, 23. Dezember 2011 18:33
    Moderator

Alle Antworten

  • Hallo,

    auch wenn es immer wieder gerne versucht wird, so richtig kann da nicht funktionieren,

    Raymond Chen hat das mehrfach erläutert:
    How do I create a topmost window that is never covered by other topmost windows?
    und What if two programs did this?

    Gruß Elmar

    Donnerstag, 22. Dezember 2011 21:14
    Beantworter
  • Hallo K.,

    Diese Frage wurde hier in Forum schon behandelt.

    Programm permanent aktiv im Vordergrund halten?
    http://social.msdn.microsoft.com/Forums/de/visualcsharpde/thread/b3e63c1c-803f-4ba5-ad6f-9a9b6c288616

    Sieh dir dort bitte auch meine Kommentare an.

    Gruß
    Marcel

    Freitag, 23. Dezember 2011 07:20
    Moderator
  • Ich sage mal, wenn Windows oder die UAC was verlangt, hohlen die sich doch eh in Vordergrund, oder?

    Mit SetForegroundWindow bleibt das Fenster ja schonmal im Vordergrund, wenn ich es regelmäßig in einem Timer aufrufe. Mein Problem dabei ist aber das meine Anwendung dabei den Fokus bekommt, was aber eben nicht geschehen soll.


    Koopakiller - http://koopakiller.ko.ohost.de/
    Freitag, 23. Dezember 2011 10:09
  • Hi Koppakiller,

     

    ich hab ein Pragramm geschriben, was unten rechts Meldungen einblendet.

     

    Im new Konstruktor der Form setze ich  Me.TopMost = True

    und im Show  gehe ich hin und hole mir den Handel der aktuellen Form

     

     Public Shadows Sub Show()
            mintCurrentForegroundWindow = GetForegroundWindow
            MyBase.Show()
        End Sub
    
     ''' <summary>
        ''' Gets the handle of the window that currently has focus.
        ''' </summary>
        ''' <returns>
        ''' The handle of the window that currently has focus.
        ''' </returns>
        <DllImport("user32")> _
        Friend Shared Function GetForegroundWindow() As IntPtr
        End Function
    
    
    

     


    Beim Activate gebe ich in wider an die Form zurück

     

     

    Private Sub Form_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
    
                      SetForegroundWindow(Me.mintCurrentForegroundWindow)
    
        End Sub
    
    
     <DllImport("User32")> _
        Friend Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Long
        End Function

     

    MFG

    Björn

     

     

     

     

     


    • Bearbeitet Palin Freitag, 23. Dezember 2011 10:39
    Freitag, 23. Dezember 2011 10:34
  • Hallo,

    UAC ist ein anderer Leiterwagen... in allen anderen Fällen gilt:
    "Note to self: Do not get into a walls-and-ladders contest with Raymond."
    (denn der wird immer gewinnen, da er zum Windows Team gehört ;-)

    Für "normale" Anwendungen sollte gelten:
    Lasse den Anwender entscheiden was ihm wichtig ist.

    Für mich gilt: Sind Anwendungen zu aufdringlich, werden sie deinstalliert, den mein Desktop gehört mir!

    Gruß Elmar

    Freitag, 23. Dezember 2011 11:09
    Beantworter
  • Für "normale" Anwendungen sollte gelten:

    Lasse den Anwender entscheiden was ihm wichtig ist.

    Für mich gilt: Sind Anwendungen zu aufdringlich, werden sie deinstalliert, den mein Desktop gehört mir!

    So denke ich auch! Darum habe ich die TopMost eigenschaft auch mit einer CheckBox in den Einstellungen verknüpft, sodass der Benutzer auswählen kann ob das Programm stetig im Vordergrund sein soll.

    Koopakiller - http://koopakiller.ko.ohost.de/
    Freitag, 23. Dezember 2011 11:39
  • Hallo K.,

    > Ich sage mal, wenn Windows oder die UAC was verlangt, hohlen die sich doch eh in Vordergrund, oder?

    Deine Anwendung könnte ja auch Fokus-Ping-Pong spielen wollen... Das kann dann eine Weile dauern, und ein Weilchen länger.

    > Mit SetForegroundWindow bleibt das Fenster ja schonmal im Vordergrund, wenn ich es regelmäßig in einem Timer aufrufe. Mein Problem dabei ist aber das meine Anwendung dabei den Fokus bekommt, was aber eben nicht geschehen soll.

    Ich würde da einen anderen Weg gehen:

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1() { InitializeComponent(); }
    
            private void buttonShowClockForm_Click(object sender, EventArgs e) {
                ClockForm clockForm = new ClockForm();
                clockForm.Show();
                NativeMethods.MakeFormTopMostInactive(clockForm.Handle, clockForm.Location, clockForm.Size);
            }
        }
    
        public class NativeMethods {
            private static IntPtr HWND_TOPMOST = new IntPtr(-1);
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
    
            public static void MakeFormTopMostInactive(IntPtr handle, Point location, Size size) {
                ShowWindow(handle, ShowWindowCommands.ShowNoActivate);
                SetWindowPos(handle, HWND_TOPMOST, location.X, location.Y, size.Width, size.Height, SetWindowPosFlags.DoNotActivate);
            } 
        }
    
        enum ShowWindowCommands : int {
            Hide = 0,
            Normal = 1,
            ShowMinimized = 2,
            Maximize = 3, // is this the right value?
            ShowMaximized = 3,
            ShowNoActivate = 4,
            Show = 5,
            Minimize = 6,
            ShowMinNoActive = 7,
            ShowNA = 8,
            Restore = 9,
            ShowDefault = 10,
            ForceMinimize = 11
        }
    
        [Flags()]
        enum SetWindowPosFlags : uint {
            SynchronousWindowPosition = 0x4000,
            DeferErase = 0x2000,
            DrawFrame = 0x0020,
            FrameChanged = 0x0020,
            HideWindow = 0x0080,
            DoNotActivate = 0x0010,
            DoNotCopyBits = 0x0100,
            IgnoreMove = 0x0002,
            DoNotChangeOwnerZOrder = 0x0200,
            DoNotRedraw = 0x0008,
            DoNotReposition = 0x0200,
            DoNotSendChangingEvent = 0x0400,
            IgnoreResize = 0x0001,
            IgnoreZOrder = 0x0004,
            ShowWindow = 0x0040,
        }
    }
    


    ShowWindow function:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx

    SetWindowPos function:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms633545(v=vs.85).aspx

    Details zu den Funktionen und Enumerationen findest Du auch auf pinvoke.net.

    Ich würde mir also eher einen milden, umsichtigen Umgang mit Anwendungen wünschen, die den Fokus "stehlen". Windows ist ein kooperatives System. Ein Timer scheint mir da viel zu aggressiv. Unsachgemäße Verwendung kann bis hin zur Blockierung des gesamten Systems führen (Raymond Chen, den ich ebenfalls in meinen Postings vom 23. Mai 2011 zitierte, ist in diesem Punkt sehr überzeugend). Viel Glück.

    Gruß
    Marcel

    Freitag, 23. Dezember 2011 18:33
    Moderator
  • Hallo Koopakiller,

    Ich gehe davon aus, dass die Antworten Dir weitergeholfen haben.
    Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.

    Grüße,
    Robert


    Robert Breitenhofer, MICROSOFT  Twitter Facebook
    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Donnerstag, 29. Dezember 2011 16:06
    Moderator