33
votes

I have written a little app that disables the titlebar and taskbar icons of all windows of the Windows OS in C#. Here is the code:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace IconKiller
{
    class Program
    {
        /// Import the needed Windows-API functions:
        // ... for enumerating all running desktop windows
        [DllImport("user32.dll")]
        static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDesktopWindowsDelegate lpfn, IntPtr lParam);
        private delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam);

        // ... for loading an icon
        [DllImport("user32.dll")]
        static extern IntPtr LoadImage(IntPtr hInst, string lpsz, uint uType, int cxDesired, int cyDesired, uint fuLoad);

        // ... for sending messages to other windows
        [DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);


        /// Setup global variables
        // Pointer to empty icon used to replace all other application icons
        static IntPtr m_pIcon = IntPtr.Zero;

        // Windows API standard values
        const int IMAGE_ICON = 1;
        const int LR_LOADFROMFILE = 0x10;
        const int WM_SETICON = 0x80;
        const int ICON_SMALL = 0;        

        static void Main(string[] args)
        {
            // Load the empty icon 
            string strIconFilePath = @"blank.ico";
            m_pIcon = LoadImage(IntPtr.Zero, strIconFilePath, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);

            // Setup the break condition for the loop
            int counter = 0;
            int max = 10 * 60 * 60;

            // Loop to catch new opened windows            
            while (counter < max)
            {
                // enumerate all desktop windows
                EnumDesktopWindows(IntPtr.Zero, new EnumDesktopWindowsDelegate(EnumDesktopWindowsCallback), IntPtr.Zero);
                counter++;
                System.Threading.Thread.Sleep(100);
            }

            // ... then restart application
            Application.Restart();
        }

        private static bool EnumDesktopWindowsCallback(IntPtr hWnd, int lParam)
        {
            // Replace window icon
            SendMessage(hWnd, WM_SETICON, ICON_SMALL, m_pIcon);

            return true;
        }
    }
}

This code seems to work fine with native windows applications. My only problem is now that Java apparently uses a different instance of its application icon to display in the taskbar. Meaning that my little app removes the icon in the titlebar of Java programs, but not the one in the taskbar (Netbeans is a good example).

How to resolve that issue? Is it maybe possible to pass a message to those programs through the JVM, similar to the trick I used with the windows API, to call JFrame.setIconImage() on running Java applications or something along those lines?

EDIT: I am not bound to just C#, I am very much willing to write something like a "helper" app in java that I would execute in my main app, should it be necessary.

3
I'm curious... why do you want to get rid of the icons that provide an easy way of visually distinguishing the applicationsGus
Have you tried this? stackoverflow.com/questions/50398/…Diego
@Diego How would that be of help?user743382
The window which appears on the taskbar and doesn't want to change icon has a window text theAwtToolkitWindowecle

3 Answers

1
votes

The problem is using EnumDesktopWindows instead of EnumWindows. The following code works fine on my pc:

using System;
using System.Runtime.InteropServices;

namespace IconKiller
{
    class Program
    {
        /// Import the needed Windows-API functions:
        // ... for enumerating all running desktop windows
        [DllImport("user32.dll")]
        static extern bool EnumWindows(EnumDesktopWindowsDelegate lpfn, IntPtr lParam);
        private delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam);

        // ... for loading an icon
        [DllImport("user32.dll")]
        static extern IntPtr LoadImage(IntPtr hInst, string lpsz, uint uType, int cxDesired, int cyDesired, uint fuLoad);

        // ... for sending messages to other windows
        [DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);


        /// Setup global variables
        // Pointer to empty icon used to replace all other application icons
        static IntPtr m_pIcon = IntPtr.Zero;

        // Windows API standard values
        const int IMAGE_ICON = 1;
        const int LR_LOADFROMFILE = 0x10;
        const int WM_SETICON = 0x80;
        const int ICON_SMALL = 0;

        static void Main(string[] args)
        {
            // Load the empty icon 
            string strIconFilePath = @"C:\clicknrun.ico";
            m_pIcon = LoadImage(IntPtr.Zero, strIconFilePath, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);

            // Setup the break condition for the loop
            int counter = 0;
            int max = 10 * 60 * 60;

            // Loop to catch new opened windows            
            while (counter < max)
            {
                // enumerate all desktop windows
                EnumWindows((EnumDesktopWindowsCallback), IntPtr.Zero);
                counter++;
                System.Threading.Thread.Sleep(100);
            }

            // ... then restart application
            Console.WriteLine("done");
            Console.ReadLine();
        }

        private static bool EnumDesktopWindowsCallback(IntPtr hWnd, int lParam)
        {
            // Replace window icon
            SendMessage(hWnd, WM_SETICON, ICON_SMALL, m_pIcon);

            return true;
        }
    }
}
0
votes

Is this what you're looking for?:

[DllImport("user32.dll")]
        static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDesktopWindowsDelegate lpfn, IntPtr lParam);
        private delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam);

[DllImport("user32.dll")]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder title, int size);
        [DllImport("user32.dll")]
        private static extern bool IsWindowVisible(IntPtr hWnd);

[DllImport("user32.dll")]
        static extern IntPtr LoadImage(IntPtr hInst, string lpsz, uint uType, int cxDesired, int cyDesired, uint fuLoad);

[DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

static IntPtr m_pIcon = IntPtr.Zero;

static string[] m_astrFilter = new string[] { "Start", "Program Manager" };

        static void Main(string[] args)
        {

        string strIconFilePath = @"H:\IconEmpty.ico";
        const int IMAGE_ICON = 1;
        const int LR_LOADFROMFILE = 0x10;
        m_pIcon = LoadImage(IntPtr.Zero, strIconFilePath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
        while (true) 
        { 
        EnumDesktopWindows(IntPtr.Zero, new EnumDesktopWindowsDelegate(EnumDesktopWindowsCallback), IntPtr.Zero);                       System.Threading.Thread.Sleep(100); 
        } 
                Console.ReadKey();
        }

private static bool EnumDesktopWindowsCallback(IntPtr hWnd, int lParam)
        {

        StringBuilder title = new StringBuilder(256);
            GetWindowText(hWnd, title, 256);
            string strTitle = title.ToString();
        bool bVisible = IsWindowVisible(hWnd);

if (bVisible && // ... visible
               !String.IsNullOrEmpty(strTitle) && // ... has title
               !m_astrFilter.Contains(strTitle)) // ... not in filter list
            {

        SendMessage(hWnd, 0x80, IntPtr.Zero, m_pIcon);
        }

            return true;
        }
0
votes

You could use the Windows API Code Pack to overlay the taskbar icons. Here are some examples.