This article describes several ways to keep your application at the top level.

Problem description

In general, if you want to place your application at the top level, set its TopMost property to true. For multiple applications with the TopMost attribute set, the latter is activated above.

But some applications, such as the global shortcut toolbar, need to be on top of all applications, even those with the TopMost set.

solution

Note: It is a false proposition that one application should never be overwritten by another. Because if two programs (A and B) do this, dragging two Windows so that they overlap, one of the two Windows must be on top of the other, which is logically contradictory.

So try to avoid this, and if you do, here are a few ways to do it (don’t overlap two such apps, or you’ll end up at the top).

First, the application needs to set its TopMost property to true so that the normal window itself is underneath it. This article focuses on how this window can be placed above a window with the TopMost property set.

Scenario 1: Capture the WM_WINDOWPOSCHANGING message

We know that using Win32’s SetWindowPos interface can change the window’s Z Order, so we can guess that our application will change its Z Order when another application is on top, so we can try to capture the WM_WINDOWPOSCHANGING message.

When the size, position, and Z-order of a window change, the window receives a WM_WINDOWPOSCHANGING message, which can be processed using WNDPROC. When this message is caught, we can try to put the application on top again. The key code is as follows, the test works, but not sure if there are side effects:

/// < Summary > // Capture the WM_WINDOWPOSCHANGING message, and without the SWP_NOZORDER flag, // </summary bb0 private IntPtr WndProc(IntPtr HWND, int MSG, IntPtr wParam, IntPtr lParam, IntPtr) ref bool handled) { switch (msg) { case Win32Api.WM_WINDOWPOSCHANGING: Win32Api.WINDOWPOS wp = (Win32Api.WINDOWPOS)Marshal.PtrToStructure( lParam, typeof(Win32Api.WINDOWPOS)); if ((wp.flags & Win32Api.SWP_NOZORDER) == 0) _ = SetTopMostLater(); // If you do not use the deprecate compiler, it will issue a warning break; } return IntPtr.Zero; } private async Task SetTopMostLater() { await Task.Delay(300); var interopHelper = new WindowInteropHelper(this); Win32Api.SetWindowPos(interopHelper.Handle, Win32Api.HWND_TOPMOST, 0, 0, 0, 0, Win32Api.TOPMOST_FLAGS); }

Scheme two: cyclic top placement

This is an easy solution to come up with, and it is also feasible to set TopMost for the application at regular intervals:

/// < Summary > // // </summary> // < Returns ></ Returns > private async Task setTopMostLoop () {while (true) {await Task.Delay(2000);  var interopHelper = new WindowInteropHelper(this); Win32Api.SetWindowPos(interopHelper.Handle, Win32Api.HWND_TOPMOST, 0, 0, 0, 0, Win32Api.TOPMOST_FLAGS); }}

Scenario 3: Use hooks

If you think about it, most of the time, using other input devices, such as a mouse or keyboard, will lead to the top of the window being stolen, so you can use global hooks to capture input events and then process them.

This scheme is flawed because there are cases where an application is opened without an input device, in which case the top effect will be preempted by the newly opened top application.

// Option 3: When the mouse to press the top (only consider the mouse) private void MouseHook_OnMouseActivity (object sender, System.Windows.Forms.MouseEventArgs e) { Console.WriteLine("mouse down......" ); _ = SetTopMostLater(); } private MouseHook _mouseHook;

Finally, this article is some of my solutions to this problem. The task manager of Windows system can run on the top layer of all applications. Maybe Microsoft just took the false proposition mentioned above into consideration, so it didn’t open this interface.

See GitHub for full demos of the three solutions in this article, and the links you can refer to (the discussion on this topic is older) are: Links 1 and 2.