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   
QuestionExcellent But?memberbklynjava118 Dec '05 - 13:35 
wow this is a great little app it works flawlessly.
My dilema is I have an app that on Button1 starts another app that I need hidden I have tried every method and then tried this and it hides the app I need hidden.
 
So my question is how can I make it so the app that Button1 starts stays hidden?
 
I appreciate any help,
Thank you
 
Here is what I have and I have tried everey thing to no avail.
 
Process myProcess = new Process();
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
myProcess.StartInfo.FileName = "foo.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
myProcess.StartInfo.FileName = "c:/program files/MyHiddenapp/foo.exe";
myProcess.Start();
myProcess.WaitForExit();
 

GeneralBug in IEnumerator implementationmemberPaul Tallett9 Jun '05 - 22:07 
Nice code.
 
I took your Window and Windows classes and used them in my app, but found a bug.
 
I tried to use your Windows class in an inner loop, I was doing
 
foreach(Process p in processes)
{
foreach(Window w in windows)
{
...
}
}
 
but that doesn't work. The inner loop only executes for the first process then dries up and stops iterating the windows collection.
 
I tracked it down to:
 
//implement IEnumerator
public bool MoveNext()
{
m_Position++;
if (m_Position < wndArray.Count)
{
return true;
}
else
{
return false;
}
}
 
which should read:
 
//implement IEnumerator
public bool MoveNext()
{
m_Position++;
if (m_Position < wndArray.Count)
{
return true;
}
else
{
m_Position = -1;
return false;
}
}
 
or maybe you need to reset the position each time you give out an enumerator.
 
Cheers,
Paul

GeneralShowWindowAsync()membereggie59 May '05 - 16:25 
I'm assuming you chose ShowWindowAsynce() over just ShowWindow() because it's on a new thread and would be faster. If this is so, does the preformance difference really justify the choice.
 
I have never seen ShowWindowAsync() until your article and it sounds intersting.
 
I developed a similar application to hide Windows Media Player in the taskbar, but I used ShowWindow().
 
/\ |_ E X E GG
GeneralRe: ShowWindowAsync()memberFrank Silva1 May '06 - 9:16 
Hi there, I'm understanding your code and is quite clean and easy but I don't know ehre you found, or how you decided to use those API 32 constant values?. please help me understand that.
 
Frank Silva

Generalcool..membereligetiv13 Mar '05 - 12:39 
The code is wonderfull. Basically i want the window not to be seen on the task bar but i want it to be on the bar where volume control and other application icons are there.
 
Can i achieve this?
 

GeneralHide from task bar.sussRajendran Thiagarajan4 Jan '05 - 22:46 
Whether it is possible to hide the application only from task bar?..Because in our project we are planning to hide the applications from task bar. If possible let me know.
 

 
Thanks
Rajendran Thiagarajan
GeneralRe: Hide from task bar.memberazam's14 Feb '07 - 0:22 
Just make every forms showintaskbar property false...
Smile | :)
 
azam's
GeneralPure .NET implementationmemberShailesh Sathe20 Jul '04 - 17:46 
Is there anyway to implement the same without using WIN32 API?
GeneralRe: Pure .NET implementationmemberTaylor Wood21 Jul '04 - 6:06 
.NET uses the Win32 API under the hood for some of it's System.Windows.Form calls, so the short answer is no.
Maybe when Longhorn is released the C-style Win32 API will be a thing of the past and those API calls that Window Hider uses will be purely managed code.
Anyways, this is as close to a "Pure .NET implementation" as you can get right now. AFAIK, there is no way to manipulate the windows natively in CLR, as Windows Forms is mostly a wrapper around the API to begin with.
Generalcsharp windows and other &quot;windows&quot;memberkent gibson18 Jul '03 - 13:17 
This looks cool and I want to try it but I have no .net yet, so before I have to part with my cash can anyone answer this question (please) or questions:
 
1. if I start a c# windows form/program and then spawn another process (ie an .exe program) which brings up another window can I control the coordinates of the new formed window. For example, I create an application that brings up a mostly transparent window and then I start another a windows exe program, can I then position the new window that I have started in any way? Ideally I want to place my semitransparent window exactly above the newly started application. Is this possible in c# or maybe even in java?
 
2. is there any way to try .net Visual Studio before you buy it?
 
Any kind advice would be cool.
 
sincerely
 
k gibson
 
k gibson

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

Permalink | Advertise | Privacy | Mobile
Web01 | 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