Как программно минимизировать открытые папки с окнами
Как я могу получить список открытых папок, перечислить его и свернуть каждую папку программно?
Иногда некоторые открытые папки крадут фокус у инструмента при переходе от одной формы в приложении к другой. Предотвращение этого имеет первостепенное значение для нашего клиента. Клиенты - люди с нарушениями зрения, поэтому они получают доступ к аппарату только через программы чтения с экрана. Минимизация других окон (папок) не является проблемой, на самом деле это требование.
Я попробовал это:
foreach (Process p in Process.GetProcessesByName("explorer"))
{
p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
}
Как и ожидалось, это не принесло пользы.
Обновление:
Из ответов здесь я попробовал это:
delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processID)
{
List<IntPtr> handles = new List<IntPtr>();
EnumThreadDelegate addWindowHandle = delegate(IntPtr hWnd, IntPtr param)
{
handles.Add(hWnd);
return true;
};
foreach (ProcessThread thread in Process.GetProcessById(processID).Threads)
EnumThreadWindows(thread.Id, addWindowHandle, IntPtr.Zero);
return handles;
}
const int SW_MINIMIZED = 6;
[DllImport("user32.dll")]
static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
private void button1_Click(object sender, EventArgs e)
{
foreach (IntPtr handle in EnumerateProcessWindowHandles(Process.GetProcessesByName("explorer")[0].Id))
ShowWindow(handle, SW_MINIMIZED);
}
Это создает множество невидимых окон проводника, которые внезапно появляются на панели таксбар из ниоткуда. Я немного новичок в работе с Windows API, поэтому сам код на самом деле поможет.
5 ответов
Существует менее "хакерское" решение, чем принятый ответ, доступный здесь: сверните папку
Он основан на объектах оболочки для сценариев. Образец:
const int SW_SHOWMINNOACTIVE = 7;
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void MinimizeWindow(IntPtr handle)
{
ShowWindow(handle, SW_SHOWMINNOACTIVE);
}
//call it like:
foreach (IWebBrowser2 window in new Shell().Windows())
{
if (window.Name == "Windows Explorer")
MinimizeWindow((IntPtr)window.HWND);
}
То же самое можно сделать с помощью объектной модели Internet Explorer.
// add a reference to "Microsoft Internet Controls" COM component
// also add a 'using SHDocVw;'
foreach (IWebBrowser2 window in new ShellWindows())
{
if (window.Name == "Windows Explorer")
MinimizeWindow((IntPtr)window.HWND);
}
Пожалуйста, попробуйте это (код несколько запутан, но для этой цели вы должны быть в состоянии пройти через это;))
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Text;
using System.Globalization;
namespace WindowsFormsApplication20
{
static class Program
{
[STAThread]
static void Main()
{
foreach (IntPtr handle in EnumerateProcessWindowHandles(Process.GetProcessesByName("explorer")[0].Id))
{
SendMessage(handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
}
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
static string GetDaClassName(IntPtr hWnd)
{
int nRet;
StringBuilder ClassName = new StringBuilder(100);
//Get the window class name
nRet = GetClassName(hWnd, ClassName, ClassName.Capacity);
if (nRet != 0)
{
return ClassName.ToString();
}
else
{
return null;
}
}
delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processID)
{
List<IntPtr> handles = new List<IntPtr>();
EnumThreadDelegate addWindowHandle = delegate(IntPtr hWnd, IntPtr param)
{
string className = GetDaClassName(hWnd);
switch (className)
{
case null:
break;
case "ExploreWClass":
handles.Add(hWnd);
break;
case "CabinetWClass":
handles.Add(hWnd);
break;
default:
break;
}
return true;
};
foreach (ProcessThread thread in Process.GetProcessById(processID).Threads)
EnumThreadWindows(thread.Id, addWindowHandle, IntPtr.Zero);
return handles;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
const int WM_SYSCOMMAND = 274;
const int SC_MINIMIZE = 0xF020;
}
}
С наилучшими пожеланиями,
Żubrówka
// Создание экземпляра класса оболочки с помощью ссылки на библиотеку COM "Элементы управления и автоматизация Microsoft Shell" -shell32.dll
Shell32.ShellClass objShell = new Shell32.ShellClass();
//Show Desktop
((Shell32.IShellDispatch4)objShell).ToggleDesktop();
Изменить: показать ваше приложение (активировать или развернуть / восстановить) после переключения на самом деле оказалось довольно сложно:
Я старался:
Application.DoEvents();
System.Threading.Thread.Sleep(5000);
Даже переопределив WndProc не удалось запечатлеть событие:
private const Int32 WM_SYSCOMMAND = 0x112;
private const Int32 SC_MINIMIZE = 0xf020;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_SYSCOMMAND)
{
if (m.WParam.ToInt32() == SC_MINIMIZE)
return;
}
base.WndProc(ref m);
}
Поэтому я предлагаю вместо того, чтобы свернуть все остальные окна, просто вставьте свое во время операции, а затем, как только вы закончите, выключите Always On Top:
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
public static void MakeTopMost (IntPtr hWnd)
{
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
}
Если вы хотите использовать p-invoke, вы можете использовать EnumThreadWindows для перечисления всех окон процесса. Затем используйте ShowWindow, чтобы минимизировать их.
Я знаю, что это старый пост, но здесь гораздо более короткий и простой способ, если люди все еще ищут решение:
Использование Windows API:
Объявите дескриптор окна: (минимизирует вызывающий исполняемый файл)
HWND wHandle; //can be any scope - I use it in main
Вызовите следующее где угодно (в зависимости от объема wHandle):
wHandle = GetActiveWindow();
ShowWindow(wHandle, SW_SHOWMINNOACTIVE);