CoInternetSetFeatureEnabled with FEATURE_BLOCK_INPUT_PROMPTS does not work - c#

I am trying to use CoInternetSetFeatureEnabled API for blocking prompt dialog as it show below in application that hosts WebBrowser control, but it does not work. Updating registry does not work either, following MSDN - Internet Feature Controls (I..L). I am using IE9 on Win7 64 bit.
FEATURE_BLOCK_INPUT_PROMPTS Internet Explorer 7. Enable or disable the
pop-up blocker to show input prompt dialog boxes. Used pop-up blocker
to mitigate the risk of spoofing.
private const int FEATURE_BLOCK_INPUT_PROMPTS = 27;
[DllImport("urlmon.dll")]
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
public static extern int CoInternetSetFeatureEnabled(
int FeatureEntry,
[MarshalAs(UnmanagedType.U4)] int dwFlags,
bool fEnable);
public static int disableInputPrompts(bool state)
{
return CoInternetSetFeatureEnabled(
FEATURE_BLOCK_INPUT_PROMPTS, SET_FEATURE_ON_PROCESS, state);
}
Update Just have tried in WinXP with IE8 and this feature is working. Does it depends on something else?
Update According to msdn this feature is by default enabled in IE9 but it does not work. Clicking on "Try It" button in w3schools sample initiates the prompt dialog, is that a security bug?
By default, this feature is enabled for Internet Explorer and disabled for
applications hosting the WebBrowser Control.
Any working alternative on how to block prompt dialog in WebBrowser control?
Can this be done by implementing custom security manager IInternetSecurityManager?

The only option I have for now is to use SetWindowsHookEx, and is based on Suppressing Hosted WebBrowser Control Dialogs sample.
internal static class WindowsInterop
{
private const Int32 WM_COMMAND = 0x0111;
private const Int32 WM_INITDIALOG = 0x0110;
private const Int32 WM_SYSCOMMAND = 0x0112;
private const Int32 SC_CLOSE = 0xF060;
private static IntPtr _pWH_CALLWNDPROCRET = IntPtr.Zero;
private static HookProcedureDelegate _WH_CALLWNDPROCRET_PROC =
new HookProcedureDelegate(WindowsInterop.WH_CALLWNDPROCRET_PROC);
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(Int32 hooktype,
HookProcedureDelegate callback, IntPtr hMod, UInt32 dwThreadId);
[DllImport("user32.dll")]
private static extern IntPtr UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern Int32 CallNextHookEx(IntPtr hhk, Int32 nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern Int32 GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern Int32 GetWindowText(IntPtr hWnd,
StringBuilder text, Int32 maxLength);
[DllImport("user32.dll", SetLastError = false)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg,
IntPtr wParam, IntPtr lParam);
// Hook Types
private const Int32 WH_CALLWNDPROCRET = 12;
[StructLayout(LayoutKind.Sequential)]
private struct CWPRETSTRUCT
{
public IntPtr lResult;
public IntPtr lParam;
public IntPtr wParam;
public UInt32 message;
public IntPtr hwnd;
};
// Delegate for a WH_ hook procedure
private delegate Int32 HookProcedureDelegate(Int32 iCode,
IntPtr pWParam, IntPtr pLParam);
// Delegate for the EnumChildWindows method
private delegate Boolean EnumerateWindowDelegate(IntPtr pHwnd, IntPtr pParam);
// Add a Hook into the CALLWNDPROCRET notification chain
internal static void Hook()
{
if (WindowsInterop._pWH_CALLWNDPROCRET == IntPtr.Zero)
{
WindowsInterop._pWH_CALLWNDPROCRET = SetWindowsHookEx(
WH_CALLWNDPROCRET,
WindowsInterop._WH_CALLWNDPROCRET_PROC,
IntPtr.Zero,
(uint)AppDomain.GetCurrentThreadId());
}
}
// Remove the Hook into the CALLWNDPROCRET notification chain
internal static void Unhook()
{
if (WindowsInterop._pWH_CALLWNDPROCRET != IntPtr.Zero)
{
UnhookWindowsHookEx(WindowsInterop._pWH_CALLWNDPROCRET);
}
}
// Hook proceedure called by the OS when a message has been processed by the target Window
private static Int32 WH_CALLWNDPROCRET_PROC(Int32 iCode,
IntPtr pWParam, IntPtr pLParam)
{
if (iCode < 0)
return CallNextHookEx(WindowsInterop._pWH_CALLWNDPROCRET,
iCode, pWParam, pLParam);
CWPRETSTRUCT cwp = (CWPRETSTRUCT)
Marshal.PtrToStructure(pLParam, typeof(CWPRETSTRUCT));
Console.WriteLine(cwp.message);
if (cwp.message == WM_INITDIALOG)
{
// A dialog was initialised, find out what sort it was via it's Caption text
Int32 iLength = GetWindowTextLength(cwp.hwnd);
StringBuilder sb = new StringBuilder(iLength + 1);
GetWindowText(cwp.hwnd, sb, sb.Capacity);
var title = sb.ToString();
if (String.IsNullOrEmpty(title) == false &&
title.IndexOf("prompt", StringComparison.OrdinalIgnoreCase) >= 0)
{
// just close it
SendMessage(cwp.hwnd, WM_SYSCOMMAND, new IntPtr(SC_CLOSE), IntPtr.Zero);
return 1;
}
}
// Call the next hook in the chain
return CallNextHookEx(WindowsInterop._pWH_CALLWNDPROCRET, iCode, pWParam, pLParam);
}
}

Related

Hook up click event after AppendMenu of 3rd party Application

i'm trying to add a new MenuItem using DLL Fucntions imported of the user32.dll using DLLImort to a third party application out of my WPF app.
No I'd like to get the click event of the newly generated MenuItem. Any ideas?
Here's the code so far. I know there are functions of SetWindowHookEx or something else, but I'm stuck.
It's some test code and not bulletproofed..
public partial class MainWindow : Window
{
[DllImport("user32.dll")]
private static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
[DllImport("user32.dll")]
private static extern int GetMenuItemCount(IntPtr hMenu);
[DllImport("user32.dll")]
private static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool
fByPosition, [In] ref MENUITEMINFO lpmii);
[DllImport("user32.dll")]
private static extern bool DrawMenuBar(IntPtr hWnd);
internal const UInt32 MIIM_FTYPE = 0x00000100;
internal const UInt32 MF_STRING = 0x00000000;
internal const UInt32 MF_OWNERDRAW = 0x00000100;
const uint MF_POPUP = 0x00000010;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern bool AppendMenu(IntPtr hMenu, MenuFlags uFlags, uint uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
static extern IntPtr CreatePopupMenu();
[Flags]
public enum MenuFlags : uint
{
MF_STRING = 0,
MF_BYPOSITION = 0x400,
MF_SEPARATOR = 0x800,
MF_REMOVE = 0x1000,
MF_POPUP = 0x00000010,
}
[StructLayout(LayoutKind.Sequential)]
struct MENUITEMINFO
{
public uint cbSize;
public uint fMask;
public uint fType;
public uint fState;
public uint wID;
public IntPtr hSubMenu;
public IntPtr hbmpChecked;
public IntPtr hbmpUnchecked;
public IntPtr dwItemData;
public string dwTypeData;
public uint cch;
public IntPtr hbmpItem;
// return the size of the structure
public static uint sizeOf
{
get { return (uint)Marshal.SizeOf(typeof(MENUITEMINFO)); }
}
}
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
createMenuEntry();
}
private void createMenuEntry()
{
Process[] proceses = Process.GetProcessesByName("spotify");
Process process = proceses.Where(e => e.MainWindowTitle == "Spotify").First();
IntPtr handle = process.MainWindowHandle;
IntPtr mainMenu = GetMenu(handle);
int mainMenuItemCount = GetMenuItemCount(mainMenu);
AppendMenu(mainMenu, MenuFlags.MF_STRING, 555, "TestEntry");
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
//HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
//source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages...
Debug.WriteLine((int)wParam);
if (((int)wParam == 555))
{
MessageBox.Show("Click");
}
return IntPtr.Zero;
}
}
Thanks for any ideas or suggestions in advance.
Your first step is to put down the C# and understand how the native menu API works. Start here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms647553.aspx
I strongly recommend that you create a new C++ project and write a simple program to add a menu and respond to clicks.
The key information is found in the documentation I linked to, with my emphasis:
When the user chooses a command item, the system sends a command message to the window that owns the menu. If the command item is on the window menu, the system sends the WM_SYSCOMMAND message. Otherwise, it sends the WM_COMMAND message.
You need to intercept that message. I suspect that means to need to use a global WH_CALLWNDPROC hook. That's going to need an unmanaged DLL to implement the hook.

C# Win32 Interop Crashes when Enumerating Window Handles

I have a C# wrapper for some Win32 operations involving window handles, but I am experiencing an unexpected crash, with no details, when I call a Win32 function.
Interestingly, this whole code sample works fine when the class is constructed (at application init time), but later fails when the same buildCache() method is called.
Here is the relevant code:
public delegate bool CallBack(int hWnd, int lParam);
public class Win32Interop {
private Dictionary<int, string> windowCache = new Dictionary<int, string>();
public Win32Interop() {
buildCache();
}
public void buildCache() {
windowCache.Clear();
CallBack hWndCacher = new CallBack(saveHWndHandler);
EnumWindows(hWndCacher, 0);
}
public void doThings(string title, uint message, bool rebuildCache = false) {
//Use the window title to get its handle
int hWnd = titleToHWnd(title, rebuildCache);
SendMessage(hWnd, message, 0, 0);
}
private bool saveHWndHandler(int hWnd, int lParam) {
if(IsWindow(hWnd) != 0) { / ***** CRASHES HERE ***** /
int length = GetWindowTextLength(hWnd);
StringBuilder title = new StringBuilder(length + 1);
GetWindowText(hWnd, title, title.Capacity);
string formatted = title.ToString().Trim();
windowCache.Add(hWnd, formatted);
}
return true;
}
private int titleToHWnd(string title, bool rebuildCache = false) {
if(rebuildCache)
buildCache();
if(windowCache.ContainsValue(title)) {
return windowCache.FirstOrDefault(x => x.Value.Contains(title)).Key;
} else {
throw new KeyNotFoundException(string.Format("\"{0}\" is not a window title which is available in the cache.", title));
}
}
#region Win32 API Functions
[DllImport("user32.dll")]
private static extern int EnumWindows(CallBack lpEnumFunc, int lParam);
[DllImport("user32.dll")]
private static extern int GetWindowText(int hWnd, StringBuilder lpString, int maxCount);
[DllImport("user32.dll")]
private static extern int GetWindowTextLength(int hWnd);
[DllImport("user32.dll")]
private static extern int IsWindow(int hWnd);
[DllImport("user32.lib")]
private static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
#endregion
}
Inside of the saveHWndHandler() method, I've marked the line were the debugger shows execution stops. Interestingly, there are usually ~300 window handles returned by EnumWindows(), and it always crashes on iteration number 45 or 46. The window handle it crashes on is a reasonable value, such as 12345.
According to MSDN, IsWindow() should return 0, if a window was not associated with the handle, not crash the thread.
Does anyone know why this is happening? There isn't a thrown exception, or any details in the Windows event log.
Thank you.
For those who don't want to figure out the buildCache() process works:
(1.) When buildCache() is called, the dictionary of <HWnd, Title> values is cleared.
(2.) The Win32 function EnumWindows() is called, which calls the saveHWndHandler() method for each window handle.
(3.) saveHWndHandler() will check if the current window handle still exists, the call another Win32 to function to get the window title from the handle.
(4.) The title and window handle are added to the dictionary.
I can't reproduce your issue, but a likely problem is that all of your P/Invoke signatures are wrong. HWND, LPARAM, and WPARAM data types need to at least be mapped to IntPtr in P/Invoke code.
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString,
int nMaxCount);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam,
IntPtr lParam);
You'll need to change your corresponding instance method signatures and usages to match these correct signatures.

Message loop is blocking application

I need to close a download popup in web browser control (disallow user to downloading file).
How i can achieve this?
I found this:
How to block downloads in .NET WebBrowser control?
And i used second answer. It's working but i have problem with it. It's seems that calling GetText of the created object is blocking a whole thread. I don't have any solution for it.
private static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (idObject == 0 && idChild == 0)
{
if(eventType == EVENT_OBJECT_CREATE)
{
string text = GetText(hwnd);
if (text.Contains("File Download"))
SendMessage(hwnd, 0x0010, IntPtr.Zero, IntPtr.Zero); //close window
}
}
}
public static string GetText(IntPtr hWnd)
{
int length = GetWindowTextLength(hWnd); //my app is freezing here - i think it's because i'm calling it from message loop.
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
}
//edit
Ok, thanks #sgorozco for suggestion. Now i'm using SetWindowsHookEx and WH_CBT. Then in message loop i'm catching HCBT_CREATEWND events. But i have problem with getting CBT_CREATEWND from lparm. I'm getting "Managed Debugging Assistant 'FatalExecutionEngineError'" exception.
Here is my current code:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct CREATESTRUCT
{
public IntPtr lpCreateParams;
public IntPtr hInstance;
public IntPtr hMenu;
public IntPtr hwndParent;
public int cy;
public int cx;
public int y;
public int x;
public int style;
public string lpszName;
public string lpszClass;
public int dwExStyle;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct CBT_CREATEWND
{
public IntPtr lpcs;
public IntPtr hwndInsertAfter;
}
private static IntPtr MessageLoopFuctnion(int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0)
{
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
if(code == 3)
{
CBT_CREATEWND info;
info = (CBT_CREATEWND)Marshal.PtrToStructure(lParam, typeof(CBT_CREATEWND));
CREATESTRUCT info1;
info1 = (CREATESTRUCT)Marshal.PtrToStructure(info.lpcs, typeof(CREATESTRUCT)); //here exception is throwing
if (info1.lpszName != null && info1.lpszName.Contains("File Download")))
SendMessage(wParam, 0x0010, IntPtr.Zero, IntPtr.Zero); //close popup
//Marshal.FreeHGlobal(info.lpcs); //error, why?
//Marshal.FreeHGlobal((IntPtr)lParam.ToUInt64());
}
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
//set hook
IntPtr hWinEventHook = SetWindowsHookEx(5, myCallbackDelegate, user32DLL, 0);
//edit 2
Here are my definitions:
private delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
private static HookProc myCallbackDelegate = new HookProc(MessageLoopFuctnion);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetWindowsHookEx(int hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
My myCallbackDelegate is a static field so it's not GC collected for sure.
Temporary i'm enumerating all windows every 500ms and look for dialog which contains text "File Download". But it is an ugly solution.
The reason for the FatalExecutionEngineError are the strings in CREATESTRUCT. Replace these with a IntPtr and you will get no exception.
[StructLayout(LayoutKind.Sequential)]
public struct CREATESTRUCT {
public IntPtr lpCreateParams;
public IntPtr hInstance;
public IntPtr hMenu;
public IntPtr hwndParent;
public int cy;
public int cx;
public int y;
public int x;
public int style;
public IntPtr lpszName;
public IntPtr lpszClass;
public int dwExStyle;
}
(Maybe you can use GetClassName and GetWindowText instead as workaround. not tested)

Controlling external Qt application - Open File

I need to be able to control an external Qt application so that I can open a file in the application.
I have tried using Process to get the Window Handle and then via PInvoke using GetMenu, GetSubMenu and GetMenuItemID to get all the parameters for using SendMessage and "Click" on the open menu in the external application
This works perfectly if I try it with Notepad as the external app, but not with the actual application which is written using Qt.
I do get the Window handle but GetMenu returns 0.
I have this code
[DllImport("user32.dll")]
private static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
[DllImport("user32.dll")]
private static extern uint GetMenuItemID(IntPtr hMenu, int nPos);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private void OpenButton_Click(object sender, EventArgs e)
{
OpenDocument("notepad", "test.doc");
}
public void OpenDocument(string windowTitle, string document)
{
IntPtr hWnd = GetWindow(windowTitle);
IntPtr hMenu = GetMenu(hWnd);
IntPtr hSubMenu = GetSubMenu(hMenu, 0); // File menu
uint menuItemId = GetMenuItemID(hSubMenu, 2); // Open
IntPtr ptr = SendMessage(hWnd, (uint)WM.COMMAND, (IntPtr)menuItemId, IntPtr.Zero);
}
private static IntPtr GetWindow(string windowTitle)
{
IntPtr hWnd = IntPtr.Zero;
Process[] processes = Process.GetProcesses();
foreach (Process p in processes)
{
if (p.MainWindowTitle.IndexOf(windowTitle, StringComparison.InvariantCultureIgnoreCase) > -1)
{
hWnd = p.MainWindowHandle;
break;
}
}
return hWnd;
}
How can I get the handles of the menu and submenu and the menuitemid from a Qt application?
// Anders

How to programmatically minimize opened window folders

How can I get the list of opened of folders, enumerate through it and minimize each folder programmatically?
At times some opened folders do steal focus from the tool when jumping from one form in the application to another. Preventing this is of high priority for our client. The customers are visually impaired people, so they access the machine only via screen readers. Minimizing other windows (folders) is not at all a problem, in fact a requirement.
I tried this:
foreach (Process p in Process.GetProcessesByName("explorer"))
{
p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
}
As expected it did no good.
Update:
From the answers here, I tried this:
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);
}
This creates a whole lot of invisible explorer windows to be suddenly listed in the taksbar out of no where. I am bit noob in dealing with Windows API, so the code itself will actually help.
Please try this (the code is somewhat messy but for the purpose you should be able to go through it ;))
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;
}
}
Best regards,
Żubrówka
//Create Instance Of Shell Class by referencing COM Library "Microsoft Shell Controls And Automation" -shell32.dll
Shell32.ShellClass objShell = new Shell32.ShellClass();
//Show Desktop
((Shell32.IShellDispatch4)objShell).ToggleDesktop();
Edit: to show your application (Activate or Maximize/Restore) after toggling actually turned out to be quite difficult:
I tried:
Application.DoEvents();
System.Threading.Thread.Sleep(5000);
Even overriding the WndProc didn't manage to capture the event:
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);
}
So I suggest instead of Minimising all other windows, just stick yours on top during the operation, then once your finished turn off 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);
}
There is a less 'hacky' solution than the accepted answer available here: Minimize a folder
It's based on the Shell Objects for Scripting. Sample:
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);
}
The same thing can be achieved using the Internet Explorer Object Model
// 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);
}
If you are willing to use p-invoke you can use EnumThreadWindows to enumerate all windows of a process. Then use ShowWindow to minimize them.
I know this is an old post, but here is a much shorter, simpler way in case people are still looking for a solution:
Using Windows API:
Declare a windows handle: (minimizes the calling executable)
HWND wHandle; //can be any scope - I use it in main
Call the following anywhere (depending on scope of wHandle):
wHandle = GetActiveWindow();
ShowWindow(wHandle, SW_SHOWMINNOACTIVE);

Categories