Click here to Skip to main content
Click here to Skip to main content

Window Hiding with C#

By , 26 Mar 2012
 

Introduction 

This source project will demonstrate the implementation of hot keys, enumerable collections, enums, binary serialization, DllImports of Win32 API, Window Enumeration, CallBacks/Delegates, Custom Events and Event Handlers, and more. It's quite a bit of code to look through but some of you may find it interesting.

Most of the heavy lifting in this project is in the Window and Windows classes that enumerate and manipulate the windows you choose:

using System;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;

namespace WindowHider
{
    /// <summary>
    /// Object used to control a Windows Form.
    /// </summary>
    public class Window
    {
        /// <summary>
        /// Win32 API Imports
        /// </summary>
        [DllImport("user32.dll")] private static extern 
            bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        [DllImport("user32.dll")] private static extern 
            bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("user32.dll")] private static extern 
            bool IsIconic(IntPtr hWnd);
        [DllImport("user32.dll")] private static extern 
            bool IsZoomed(IntPtr hWnd);
        [DllImport("user32.dll")] private static extern 
            IntPtr GetForegroundWindow();
        [DllImport("user32.dll")] private static extern 
            IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
        [DllImport("user32.dll")] private static extern 
            IntPtr AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, int fAttach);

        /// <summary>
        /// Win32 API Constants for ShowWindowAsync()
        /// </summary>
        private const int SW_HIDE = 0;
        private const int SW_SHOWNORMAL = 1;
        private const int SW_SHOWMINIMIZED = 2;
        private const int SW_SHOWMAXIMIZED = 3;
        private const int SW_SHOWNOACTIVATE = 4;
        private const int SW_RESTORE = 9;
        private const int SW_SHOWDEFAULT = 10;

        /// <summary>
        /// Private Fields
        /// </summary>
        private IntPtr m_hWnd;
        private string m_Title;
        private bool m_Visible = true;
        private string m_Process;
        private bool m_WasMax = false;

        /// <summary>
        /// Window Object's Public Properties
        /// </summary>
        public IntPtr hWnd
        {
            get{return m_hWnd;}
        }
        public string Title
        {
            get{return m_Title;}
        }
        public string Process
        {
            get{return m_Process;}
        }

        /// <summary>
        /// Sets this Window Object's visibility
        /// </summary>
        public bool Visible
        {
            get{return m_Visible;}
            set
            {
                //show the window
                if(value == true)
                {
                    if(m_WasMax)
                    {
                        if(ShowWindowAsync(m_hWnd,SW_SHOWMAXIMIZED))
                            m_Visible = true;
                    }
                    else
                    {
                        if(ShowWindowAsync(m_hWnd,SW_SHOWNORMAL))
                            m_Visible = true;
                    }
                }
                //hide the window
                if(value == false)
                {
                    m_WasMax = IsZoomed(m_hWnd);
                    if(ShowWindowAsync(m_hWnd,SW_HIDE))
                        m_Visible = false;
                }
            }
        }

        /// <summary>
        /// Constructs a Window Object
        /// </summary>
        /// <param name="Title">Title Caption</param>
        /// <param name="hWnd">Handle</param>
        /// <param name="Process">Owning Process</param>
        public Window(string Title, IntPtr hWnd, string Process)
        {
            m_Title = Title;
            m_hWnd = hWnd;
            m_Process = Process;
        }

        //Override ToString() 
        public override string ToString()
        {
            //return the title if it has one, if not return the process name
            if (m_Title.Length > 0)
            {
                return m_Title;
            }
            else
            {
                return m_Process;
            }
        }

        /// <summary>
        /// Sets focus to this Window Object
        /// </summary>
        public void Activate()
        {
            if(m_hWnd == GetForegroundWindow())
                return;

            IntPtr ThreadID1 = GetWindowThreadProcessId(GetForegroundWindow(),
                                                        IntPtr.Zero);
            IntPtr ThreadID2 = GetWindowThreadProcessId(m_hWnd,IntPtr.Zero);
            
            if (ThreadID1 != ThreadID2)
            {
                AttachThreadInput(ThreadID1,ThreadID2,1);
                SetForegroundWindow(m_hWnd);
                AttachThreadInput(ThreadID1,ThreadID2,0);
            }
            else
            {
                SetForegroundWindow(m_hWnd);
            }

            if (IsIconic(m_hWnd))
            {
                ShowWindowAsync(m_hWnd,SW_RESTORE);
            }
            else
            {
                ShowWindowAsync(m_hWnd,SW_SHOWNORMAL);
            }
        }
    }

    /// <summary>
    /// Collection used to enumerate Window Objects
    /// </summary>
    public class Windows : IEnumerable, IEnumerator
    {
        /// <summary>
        /// Win32 API Imports
        /// </summary>
        [DllImport("user32.dll")] private static extern 
              int GetWindowText(int hWnd, StringBuilder title, int size);
        [DllImport("user32.dll")] private static extern 
              int GetWindowModuleFileName(int hWnd, StringBuilder title, int size);
        [DllImport("user32.dll")] private static extern 
              int EnumWindows(EnumWindowsProc ewp, int lParam); 
        [DllImport("user32.dll")] private static extern 
              bool IsWindowVisible(int hWnd);

        //delegate used for EnumWindows() callback function
        public delegate bool EnumWindowsProc(int hWnd, int lParam);

        private int m_Position = -1; // holds current index of wndArray, 
                                     // necessary for IEnumerable
        
        ArrayList wndArray = new ArrayList(); //array of windows
        
        //Object's private fields
        private bool m_invisible = false;
        private bool m_notitle = false;

        /// <summary>
        /// Collection Constructor with additional options
        /// </summary>
        /// <param name="Invisible">Include invisible Windows</param>
        /// <param name="Untitled">Include untitled Windows</param>
        public Windows(bool Invisible, bool Untitled)
        {
            m_invisible = Invisible;
            m_notitle = Untitled;

            //Declare a callback delegate for EnumWindows() API call
            EnumWindowsProc ewp = new EnumWindowsProc(EvalWindow);
            //Enumerate all Windows
            EnumWindows(ewp, 0);
        }
        /// <summary>
        /// Collection Constructor
        /// </summary>
        public Windows()
        {
            //Declare a callback delegate for EnumWindows() API call
            EnumWindowsProc ewp = new EnumWindowsProc(EvalWindow);
            //Enumerate all Windows
            EnumWindows(ewp, 0);
        }
        //EnumWindows CALLBACK function
        private bool EvalWindow(int hWnd, int lParam)
        {
            if (m_invisible == false && !IsWindowVisible(hWnd))
                return(true);

            StringBuilder title = new StringBuilder(256);
            StringBuilder module = new StringBuilder(256);

            GetWindowModuleFileName(hWnd, module, 256);
            GetWindowText(hWnd, title, 256);

            if (m_notitle == false && title.Length == 0)
                return(true);

            wndArray.Add(new Window(title.ToString(), (IntPtr)hWnd, 
                                    module.ToString()));

            return(true);
        }
        
        //implement IEnumerable
        public IEnumerator GetEnumerator()
        {
            return (IEnumerator)this;
        }
        //implement IEnumerator
        public bool MoveNext()
        {
            m_Position++;
            if (m_Position < wndArray.Count)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public void Reset()
        {
            m_Position = -1;
        }
        public object Current
        {
            get
            {
                return wndArray[m_Position];
            }
        }
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Taylor Wood
Web Developer
United States United States
Member
I write c#

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5 [modified]memberAlbert Jann11 May '12 - 7:07 
In my multi part application I had problem of restoring hidden processes. After reading this article - not anymore Thumbs Up | :thumbsup: . Now time to make good Java | [Coffee] . My vote is 5. Thanks!

modified 11 May '12 - 13:29.

Questionnot badmemberCIDev27 Mar '12 - 6:14 
The code is fairly well commented and has many useful examples. I would, however, like to see more description in the article itself.
Just because the code works, it doesn't mean that it is good code.

QuestionGreat article.memberJimShat3 Sep '11 - 16:45 
Very elegant
thanks,
jim
GeneralMy vote of 5memberJaikrishan17 Feb '11 - 0:45 
This is a great article and project source code help me to achieve my project requiremt.
Thank you very much.
GeneralMy vote of 4memberRajdeep Pathak20 Nov '10 - 0:09 
Any specific window gets hidden only problem is the current application window is shown else great work
GeneralExcellent!memberflippydeflippydebop4 Oct '10 - 4:42 
This code is just what I needed and works just as advertised.. You saved me lots of time here. Smile | :)
Questionhide window after startup ???memberpukino1802 Oct '10 - 22:48 
I know someone advise how this could be done?
I want my applications will run in the background and at a certain key combination, I view the form Hmmm | :| Confused | :confused:
GeneralMy vote of 5memberalpesh_11_3_198914 Sep '10 - 2:30 
The application sample is above excellent... superb.
Generalreading control details on windowmemberS Irfan H Zaidi3 Oct '09 - 4:20 
Is this possible to read values in a list box on any window and save them in clipboard or file, by amending this code or some other?
QuestionProblem with user32.dll APImemberbennykatz20 Mar '09 - 9:20 
These classes are really nicely designed. I do have a problem that I wonder if anyone else has experienced. When obtaining the module name of a given window, the function GetWindowModuleFileName() sometimes (rarely) insists on returning the wrong module name, in fact, for the given window that I'm interested in, it returns the file name of the application running in debug mode, where this new class is! I have tried running both with Visual Studio closed, with the same effect. Strange, right? or am I a dunce?
GeneralHelp reqd for adding a button to a different app.memberaditya.jk@gmail.com19 Feb '09 - 5:36 
Hi,
I have tried but failed to do the following requirement. Any input from you folks will be helpful.
 
Requirement: there is a windows app1 in C++, i need to use .net create a console app (app2) that disables a button (b1) in app1 and adds another button (b2)to app1. The b2 button then does some verification from the form details in app1 and then enables b1.
Also I am not allowed to make any code changes in app1
 
my problems:
- how to disable a button of a different app.
- how to add a button to a different app.
- how to pass various textbox values from app1 to app2.
 

 
Regards,
Adi
GeneralRe: Help reqd for adding a button to a different app.memberS Irfan H Zaidi3 Oct '09 - 4:23 
Hi Adi,
 
Did you get the answer or solution to your issue?
 
I need somewhat same solutions, as I need to retrieve listbox values in another app to may app.
 
Is this possible, through some win32 api using handles, etc. in C#?
 
Awaiting....
GeneralCreate an application like Microsoft On Screen Keyboard.membernovarajat13 Dec '08 - 6:10 
Hey man, great work
 
I am running this piece of application flawlessly on vista.
i am trying to develop a virtual keyboard which has the same functionality as microsoft on screen keyboard. I am using
 
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
 
IntPtr test;
 

 
private void Button_MouseEnter(object sender, MouseEventArgs e)
{
test = GetForegroundWindow();
}
 
private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
SetForegroundWindow(test);
}
 
This works but my screen flashes for moments.
Is there some better method or other way so that I can click my virtual keyboard buttons without removing focus from other window which already has focus.
GeneralRe: Create an application like Microsoft On Screen Keyboard.memberstyloverte11618 Jan '09 - 11:14 
you need to use SetWindowPos and call it with HWND_TOPMOST which is -1. You will need to cast that number to an IntPtr. to set a window to the front of everything to where nothing can go above it you use SetWindowPos(handle, (IntPtr)(-1), 0, 0, 0, 0, 1 | 2 | 16);
Generalhiding window during a startup - shorter varinatmemberCuchuk Sergey15 Jul '08 - 3:28 
using System;
using System.Runtime.InteropServices;
 
namespace xxx.Common
{
    public static class NativeMethods
    {
        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 
        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
 
        public static void SetWindowVisibility(bool visible, string title)
        {
            if (string.IsNullOrEmpty(title))
                throw new ArgumentNullException("title");
 
            IntPtr hWnd = NativeMethods.FindWindow(null, title);
 
            if (hWnd != IntPtr.Zero)
            {
                if (!visible)
                    //Hide the window                   
                    NativeMethods.ShowWindow(hWnd, 0); // 0 = SW_HIDE               
                else
                    //Show window again                   
                    NativeMethods.ShowWindow(hWnd, 1); //1 = SW_SHOWNORMAL
            }
        }
    }
}

GeneralBug with .Net Form containing a TabControl (and correction).memberikharus21 May '08 - 2:32 
First, sorry for my english, I lack practice!!
 
If you create a new Application in .NET with a simple Form (System.Windows.Forms.Form) containing a TabControl (System.Windows.Forms.TabControl) with 2 TabPage (System.Windows.Forms.TabPage) and some controls in both TabPage, and then you start this Application (which will display the first TabPage when the main form will be displayed) and then you Hide the Application with the Window Hider, the second TabPage will never show up its content once the Application is shown again. But if you show the second TabPage once before hiding it, this bug does not occur.
 
Therefore, every TabPage of a TabControl (.NET only) not shown before the parent Form is hidden by the Window Hider will be empty when the parent Form is shown again.
 
The solution is quite simple.
 
In the Window class, add the following const:
 
private const int SW_SHOW = 5;
 
Then, change the Visible property by the following one:
 
public bool Visible
{
    get { return m_Visible; }
    set
    {
        //show the window
        if (value == true)
        {
            if (ShowWindowAsync(m_hWnd, SW_SHOW))
                m_Visible = true;
        }
 
        //hide the window
        else if (value == false)
        {
            if (ShowWindowAsync(m_hWnd, SW_HIDE))
                m_Visible = false;
        }
    }
}
 
I don't know why the original property preserved the window state (wasMax) because when you use the SW_SHOW value with ShowWindowAsync, the Form is shown with the same state it had before being hidden. So no need to use the SW_SHOWNORMAL, SW_SHOWMINIMIZED, SW_SHOWMAXIMIZED, SW_SHOWNOACTIVATE and SW_RESTORE values.
 
In the Activate method, change the following code:
 
if (IsIconic(m_hWnd))
{
    ShowWindowAsync(m_hWnd,SW_RESTORE);
}
else
{
    ShowWindowAsync(m_hWnd,SW_SHOWNORMAL);
}
By this simple line:
 
ShowWindowAsync(m_hWnd,SW_SHOW);
 
With this correction (for my needs), the Window Hider seems to work as it worked before without the bug I have mentioned earlier.
 
Thanks and have a nice day.
QuestionProcess Handle?memberMartio17 Nov '07 - 10:32 
Please, I have some problem with this: (I will express by C# code, because my english is bad)
 
Process p = Process.GetProcessesByName("cmd")[0];
ShowWindowAsync(p.Handle, 0); // none action
 
When I write to while cycle:
 
while(true) // Console
{
Process p = Process.GetProcessesByName("cmd")[0];
ShowWindowAsync(p.Handle, 0); // sometimes action
}
 
If you don't have any ideas please try to write by alternative code or please some tutorial "How to get process/program handle".
 
Thanks Smile | :)

AnswerRe: Process Handle?memberMartio17 Nov '07 - 10:36 
You are use Enumerator and I have with Enumerators big problems...
 
Peace and love Big Grin | :-D

GeneralRe: Process Handle?membertajally123 Apr '08 - 23:15 
i have the same problem so i searched for the solution but with out Success so i posted my problem in MSDN Forums and found the solution.
 
p.Handel is the problem so it have to be changed to p.MainWindowHandle that points to the window that i want to process on
 
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3232949&SiteID=1[^]
General.net Lösungmemberumbauer30 Sep '07 - 20:55 
Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents=false;
proc.StartInfo.FileName=extern_app;
proc.StartInfo.Arguments = "" ;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.Start();
proc.WaitForExit();
Questioncapture application start?memberevrastil28 Aug '07 - 4:18 
Hi, great article. I just wonder if anybody knows if its posible to detect events when application starts or gains focus?
GeneralvistamemberMr Jen Withers17 Jun '07 - 3:41 
Maybe a silly question - but does this work in vista?
GeneralRe: vistamembernoctifer25 Jun '07 - 4:22 
Yes it does I'm using this code in Vista.
GeneralRe: vistamemberMember 430422917 Sep '08 - 5:39 
It only works for non-elevated processes on Vista...
QuestionUsing your code in another projectmembernoctifer10 Jun '07 - 0:25 
Hi there,
am I allowed to use your window class in another project which will be published under the GPL?
 
Thx in Advance
 
Steve

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 26 Mar 2012
Article Copyright 2002 by Taylor Wood
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid