【发布时间】:2019-01-24 15:30:15
【问题描述】:
如何使用 C# 以编程方式显示/隐藏桌面图标?
我正在尝试创建一个使用小部件的替代桌面,并且我需要隐藏旧图标。
【问题讨论】:
-
我已经为类似的问题发布了C++ answer,也许有人可以将其翻译成 C#。
标签: c# .net icons desktop show-hide
如何使用 C# 以编程方式显示/隐藏桌面图标?
我正在尝试创建一个使用小部件的替代桌面,并且我需要隐藏旧图标。
【问题讨论】:
标签: c# .net icons desktop show-hide
您可以使用 Windows API 执行此操作。下面是切换桌面图标的 C# 示例代码。
[DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)] static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
enum GetWindow_Cmd : uint
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
[DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private const int WM_COMMAND = 0x111;
static void ToggleDesktopIcons()
{
var toggleDesktopCommand = new IntPtr(0x7402);
IntPtr hWnd = GetWindow(FindWindow("Progman", "Program Manager"), GetWindow_Cmd.GW_CHILD);
SendMessage(hWnd, WM_COMMAND, toggleDesktopCommand, IntPtr.Zero);
}
这会向 Progman 的 SHELLDLL_DefView 子窗口发送一条消息,告诉它切换其唯一子“FolderView”的可见性(通过添加或删除 WS_VISIBLE 样式)。 “FolderView”是包含图标的实际窗口。
要测试图标是否可见,可以使用GetWindowInfo函数查询WS_VISIBLE样式,如下所示:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool GetWindowInfo(IntPtr hwnd, ref WINDOWINFO pwi);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
private int _Left;
private int _Top;
private int _Right;
private int _Bottom;
}
[StructLayout(LayoutKind.Sequential)]
struct WINDOWINFO
{
public uint cbSize;
public RECT rcWindow;
public RECT rcClient;
public uint dwStyle;
public uint dwExStyle;
public uint dwWindowStatus;
public uint cxWindowBorders;
public uint cyWindowBorders;
public ushort atomWindowType;
public ushort wCreatorVersion;
public WINDOWINFO(Boolean? filler)
: this() // Allows automatic initialization of "cbSize" with "new WINDOWINFO(null/true/false)".
{
cbSize = (UInt32)(Marshal.SizeOf(typeof(WINDOWINFO)));
}
}
这是一个调用上面代码的函数,如果窗口可见则返回true,否则返回false。
static bool IsVisible()
{
IntPtr hWnd = GetWindow(GetWindow(FindWindow("Progman", "Program Manager"), GetWindow_Cmd.GW_CHILD), GetWindow_Cmd.GW_CHILD);
WINDOWINFO info = new WINDOWINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
GetWindowInfo(hWnd, ref info);
return (info.dwStyle & 0x10000000) == 0x10000000;
}
可以在此处找到 Windows API 代码以及有关窗口样式的更多信息:http://www.pinvoke.net/default.aspx/user32/GetWindowInfo.html
【讨论】:
尽管当我尝试 Ondrej Balas 的 answer 时这已经很老了,但我发现此解决方案的一个问题是,如果使用 ToggleDesktop 命令显示桌面(也启用了墙纸旋转),它也不起作用。
在这两种情况下,作为 ToggleDesktopIcons 函数中的 toggleDesktopCommand 的接收者的 SHELLDLL_DefView 窗口不是“程序管理器”窗口的子窗口,而是“WorkerW”窗口的子窗口。(参见 WinApi - How to obtain SHELLDLL_DefView 和 @ 987654323@.
基于这些并在 Ondrej Balas 早期的 answer 的基础上,将 ToggleDesktopIcons 函数更改为:
static void ToggleDesktopIcons()
{
var toggleDesktopCommand = new IntPtr(0x7402);
SendMessage(GetDesktopSHELLDLL_DefView(), WM_COMMAND, toggleDesktopCommand, IntPtr.Zero);
}
并添加一个 GetDesktopSHELLDLL_DefView 函数:
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
[DllImport("user32.dll", SetLastError = false)]
static extern IntPtr GetDesktopWindow();
static IntPtr GetDesktopSHELLDLL_DefView()
{
var hShellViewWin = IntPtr.Zero;
var hWorkerW = IntPtr.Zero;
var hProgman = FindWindow("Progman", "Program Manager");
var hDesktopWnd = GetDesktopWindow();
// If the main Program Manager window is found
if (hProgman != IntPtr.Zero)
{
// Get and load the main List view window containing the icons.
hShellViewWin = FindWindowEx(hProgman, IntPtr.Zero, "SHELLDLL_DefView", null);
if (hShellViewWin == IntPtr.Zero)
{
// When this fails (picture rotation is turned ON, toggledesktop shell cmd used ), then look for the WorkerW windows list to get the
// correct desktop list handle.
// As there can be multiple WorkerW windows, iterate through all to get the correct one
do
{
hWorkerW = FindWindowEx(hDesktopWnd, hWorkerW, "WorkerW", null);
hShellViewWin = FindWindowEx(hWorkerW, IntPtr.Zero, "SHELLDLL_DefView", null);
} while (hShellViewWin == IntPtr.Zero && hWorkerW != IntPtr.Zero);
}
}
return hShellViewWin;
}
现在,无论桌面切换或墙纸旋转如何,ToggleDesktopIcons 都应该始终有效。
作为参考,这是我的切换桌面功能,它导致原始 ToggleDesktopIcons 功能出现问题
static public void ToggleDesktop(object sender, EventArgs e)
{
var shellObject = new Shell32.Shell();
shellObject.ToggleDesktop();
}
响应 James M,此函数返回当前状态:
bool IconsVisible()
{
var hWnd = GetDesktopListView();
var info = new User32.WINDOWINFO(null);
User32.GetWindowInfo(hWnd, ref info);
return (info.dwStyle & User32.WindowStyle.WS_VISIBLE) == User32.WindowStyle.WS_VISIBLE;
}
【讨论】:
另一种方法是创建一个单独的桌面并显示它。它不会有图标。
【讨论】:
您可以创建一个全屏视图应用程序并将其设置为最顶部的窗口。
然后让你的应用程序用windows启动。
【讨论】:
您可以在 RegEdit 中执行此操作 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced 将 HideIcons 更改为 1
static void HideIcons()
{
RegistryKey myKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", true);
if (myKey != null)
{
myKey.SetValue("HideIcons", 1);
myKey.Close();
}
}
使用此处描述的 Registry 类。
http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.aspx
【讨论】:
您以错误的方式处理此问题。你真正想做的是更换外壳。 Windows 提供了这一点,因此您应该充分利用它。编写自己的 shell 来替换 explorer。
【讨论】: