在我的 vb.net windows 窗体应用程序中,我想制作一个按钮,当用户单击该按钮时,应该显示桌面(显示桌面按钮)。
考虑一个表单名称为form1,它有一个像“显示桌面”这样的按钮,当用户点击时,所有的应用程序都应该被最小化并且它应该显示桌面,是否有VB.NET Windows Form应用程序的代码。
编辑
虽然我提出的解决方案有效,但我建议使用下面的 Code Gray 的 答案,因为这是正确的方法。
在 C# 中是这样的:
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1 {
class Program {
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true)]
static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);
const int WM_COMMAND = 0x111;
const int MIN_ALL = 419;
const int MIN_ALL_UNDO = 416;
static void Main(string[] args) {
IntPtr lHwnd = FindWindow("Shell_TrayWnd", null);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL, IntPtr.Zero);
System.Threading.Thread.Sleep(2000);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL_UNDO, IntPtr.Zero);
}
}
}
我使用在线转换器工具来转换上述代码,请验证它是否有效
Imports System
Imports System.Runtime.InteropServices
Namespace ConsoleApplication1
Class Program
<DllImport("user32.dll", EntryPoint := "FindWindow", SetLastError := True)> _
Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint := "SendMessage", SetLastError := True)> _
Private Shared Function SendMessage(hWnd As IntPtr, Msg As Int32, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
Const WM_COMMAND As Integer = &H111
Const MIN_ALL As Integer = 419
Const MIN_ALL_UNDO As Integer = 416
Private Shared Sub Main(args As String())
Dim lHwnd As IntPtr = FindWindow("Shell_TrayWnd", Nothing)
SendMessage(lHwnd, WM_COMMAND, DirectCast(MIN_ALL, IntPtr), IntPtr.Zero)
System.Threading.Thread.Sleep(2000)
SendMessage(lHwnd, WM_COMMAND, DirectCast(MIN_ALL_UNDO, IntPtr), IntPtr.Zero)
End Sub
End Class
End Namespace
现有答案中提出的解决方案是依赖于 Windows 未记录方面的黑客攻击。它们现在可以工作,但它们随时可能因 Windows 更新而停止工作。
Marshal 的解决方案试图在任务栏中找到实际的“显示桌面”按钮。一个明显的问题是窗口的名称和 ID 是硬编码的,这意味着如果操作系统本身发生更改,代码就会中断。这些操作系统内部没有记录,也没有用于应用程序的编程操作,并且随时可能更改。我也不知道如果用户修改他们的操作系统设置以不在任务栏中显示此按钮会发生什么。代码是否继续有效?这些消息是否仍受支持?我不知道。你?
Harsh 的解决方案依赖于合成按下Win+D组合键,这是显示桌面的键盘快捷键。这有合成键盘输入的所有标准问题,另外一个缺点是它使用了旧的、不推荐使用的keybd_event
函数 (SendInput
是它的替代品,它解决了 的一些问题keybd_input
,即没有办法处理错误,但没有解决合成键盘事件的更大问题。)此解决方案不太可能因 Windows 更新而中断,因为此键盘快捷键已记录在案,但可能会产生不良副作用以及与其他系统功能和/或应用程序交互的细微问题。
更好的解决方案是委托给 COM 组件 Shell32.dll,调用其记录的ToggleDesktop
方法,这正是您想要做的。从 MSDN 文档:
此方法与任务栏上的显示桌面按钮具有相同的效果。它要么隐藏所有打开的窗口以显示桌面,要么通过显示所有打开的窗口来隐藏桌面。该
ToggleDesktop
方法不显示用户界面,它只是调用切换操作。
由于这已记录在案,因此随着 Windows 的更新,它更有可能继续工作。由于它不依赖黑客或合成事件,因此不太可能导致细微的不兼容。它也更容易使用。
C# 和 VB.NET 都可以轻松访问 COM 库。在 C# 中,调用函数很简单:
Shell32.Shell shell = new Shell32.Shell();
shell.ToggleDesktop();
在 VB.NET 中,这变成(看 ma,没有分号):
Dim shell As Shell32.Shell = New Shell32.Shell()
shell.ToggleDesktop()
如果您的项目中尚不存在“Microsoft Shell 控件和自动化”(Shell32.dll 库),您可能需要添加一个引用。这是一个系统 DLL,因此它存在于所有系统上。
唯一的要求是您从使用单线程单元 (STA) 模型的线程调用此函数。换句话说,它不是线程安全的,也不处理自己的同步。然而,这并不是一个重大缺点,因为所有 Windows 窗体应用程序都使用 STA 线程:它是主线程,即处理 UI 和泵送消息的线程。UI 线程几乎总是 STA,并且保证在 WinForms 中也是如此。只是不要尝试从后台/工作线程调用它。不是你会,因为你应该只尝试显示桌面以响应直接的用户交互,无论如何这将在 UI 线程上处理。
检查此链接。这包含最小化所有显示桌面的窗口的代码。 http://www.dreamincode.net/code/snippet2109.htm
Public Sub ShowDesktop()
keybd_event(VK_LWIN, 0, 0, 0)
keybd_event(77, 0, 0, 0)
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0)
End Sub
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, _
ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Const KEYEVENTF_KEYUP = &H2
Private Const VK_LWIN = &H5B
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call ShowDesktop()
End Sub
shell:::{3080F90D-D7AD-11D9-BD98-0000947B0257}
确实是最好的解决方案,因为它是 MSDN 中已知的记录 CLSID
Shell("cmd.exe /c %windir%\explorer.exe shell:::{3080F90D-D7AD-11D9-BD98-0000947B0257}", AppWinStyle.MinimizedNoFocus)
最佳解决方案