Implementation method
There are many ways to implement Windows Back to Desktop function, which can simulate shortcut keys or execute the following methods. The first method needs a reference. The method is to add a reference. Select COM to find "Microsoft Shell Controls and Automation", select and confirm, and also set its embedded interoperability type to false.
// Method 1, [Reference link](/questions/41598951/programmatically-show-the-desktop) objShel = new (); (); // Method 2, [Reference link](/Forums/vstudio/en-US/a27ca1e4-bd02-434b-8d02-06553c35f3d5/show-desktop-program-no-working)Type shellType = (""); object shell = (shellType); ("ToggleDesktop", , null, shell, new object[] { });
question
Under normal circumstances, both methods can be successfully executed.
However, today I encountered an unsuccessful operation of a device. The scenario is that when the WPF application receives the udp message, the operation back to the desktop fails.
I saw some netizens saying that when executing the above code, it must be executed in the STA thread, otherwise an error will be reported. Method 1 is that it needs to be executed in the STA thread, but it cannot solve the problem.
When analyzing the problem again, I found that when WPF is applied as the current active window, the operation is executed successfully, otherwise the execution fails. Therefore, activate the window first and then execute the above code can successfully solve the problem.
On the device where there is a problem, it is not possible to use the simple Show() and Active() methods to activate the window. It will only flash the icon in the taskbar. You can activate it using the following method.
(); ();
On most devices, the combination of Show and Activate allows the window to be active as the current user, and can be displayed through the Show method even if the window was previously minimized or hidden.
However, some device windows are covered under other windows. At this time, the window is still true. However, calling Activate will not allow the window to be placed on the upper level.
I saw many friends on the Internet calling the SetForegroundWindow method. In fact, WPF is now open source. You can see that the Activate method of Window is written like this
public bool Activate() { // this call ends up throwing an exception if Activate // is not allowed VerifyApiSupported(); VerifyContextAndObjectState(); VerifyHwndCreateShowState(); // Adding check for IsCompositionTargetInvalid if (IsSourceWindowNull || IsCompositionTargetInvalid) { return false; } return (new HandleRef(null, CriticalHandle)); }
Please read the source codegithub
That is, calling SetForegroundWindow is similar to calling Activate methods. If calling Activate is not useful, then calling SetForegroundWindow should be similar.
The following steps are required
1. Get the window handle FindWindow
2. Switch keyboard input focus AttachThreadInput
3. Show window ShowWindow (some windows are minimized/hidden)
4. Change the Zorder of the window and setWindowPos to make it top. In order not to affect the Zorder of the subsequent window, restore it after the modification.
5. Finally SetForegroundWindow
The corresponding change window order in WPF uses the Topmost property, and the setting order requires a little change.
Passed in WPFc# - Bring a window to the front in WPF - Stack OverflowYou can learn how to use the AttachThreadInput method
Please see the entire code below. I haven't written the specific win32 method. Please add it yourself.
private static void SetWindowToForegroundWithAttachThreadInput(Window window) { var interopHelper = new WindowInteropHelper(window); // The following Win32 method can be found in /kkwpsv/lsjutil/tree/master/Src/.Win32 var thisWindowThreadId = Win32.(, ); var currentForegroundWindow = Win32.(); var currentForegroundWindowThreadId = Win32.(currentForegroundWindow, ); // [c# - Bring a window to the front in WPF - ](/questions/257587/bring-a-window-to-the-front-in-wpf ) // [Correct usage of SetForegroundWindow - Ziwu - Blog Garden](/ziwuge/archive/2012/01/06/) /* 1. Get the window handle FindWindow 2. Switch keyboard input focus AttachThreadInput 3. Show window ShowWindow (some windows are minimized/hidden) 4. Change the Zorder of the window and setWindowPos to make it top. In order not to affect the Zorder of the subsequent window, restore it after the modification. 5. Finally SetForegroundWindow */ Win32.(currentForegroundWindowThreadId, thisWindowThreadId, true); (); (); // Remove the input links with other threads Win32.(currentForegroundWindowThreadId, thisWindowThreadId, false); // Used to kick off other windows on the upper level = true; = false;
This problem has been resolved.
In WPF, if you want to use code control, let a window be the logical focus of the input of the current user, that is, the uppermost window of the window where the current user is active, the Activate method is used by default. This method can be used on most devices to activate the window.
However, on some special devices, using the following code to adjust the window just flashes the icon in the taskbar without putting the window at the top level
The difficulty of this problem is that not all devices have this problem. I have two devices in my hand, and the operating system is the same, but one is good and the other is not. The device code in the problem is executed. I don’t know why it has no effect. The application must be set as an active window. Friends who know about this problem are welcome to discuss it.
Some of the codes for the test demo in this article are as follows, which can be seen in detailGithub。
// Wpf main windowpublic partial class MainWindow : Window { public MainWindow() { InitializeComponent(); InitLogger(); InitUdpThread(); showDesktop = Method1; (, $"start process, Main Thread id: {}"); } private void InitLogger() { var file = new FileLogger(""); (, "Init logger success"); } private void InitUdpThread() { Thread udpThread = new Thread(new ThreadStart(GetUdpMessage)); = true; (); } private void GetUdpMessage() { UdpClient udpClient = null; try { udpClient = new UdpClient(10001); } catch (Exception) { (, "create udp client failed"); return; } (, "create udp client success"); IPEndPoint remotePoint = null; while (true) { try { byte[] receiveData = (ref remotePoint); string receiveString = (receiveData); (, $"receive udp message: {receiveString}"); if (().Contains("showdesktop")) showDesktop?.Invoke(); } catch (Exception e) { (, ); } } } private void Button_Click(object sender, RoutedEventArgs e) { if (sender is Button btn) { switch () { case "method1": showDesktop = Method1; (, "turn to method1"); break; case "method2": showDesktop = Method2; (, "turn to method2"); break; case "activeFirst": showDesktop = ActiveFirst; (, "turn to activeFirst method"); break; default: break; } } } private void Method1() { Thread newSta = new Thread(()=> { objShel = new (); (); (, $"Current Thread id: {}"); }); (); (); } private void Method2() { Type shellType = (""); object shellObject = (shellType); ("ToggleDesktop", , null, shellObject, null); (, $"Current Thread id: {}"); } private void ActiveFirst() { (new Action(() => { (this); Method2(); })); } private Action showDesktop; }
The above is the detailed content of c#'s function to return to Windows desktop based on Win32Api. For more information about c#'s return to Windows desktop, please follow my other related articles!