Remove Tabs From the Windows Taskbar

I'm very picky about my desktop environment. I like windows, toolbars, icons, etc. to be arranged in a certain way. Typically, I turn off annoying prompts and nag screens in Windows, and unhide "scary" advanced options in OS X. One hard-to-fix pet peeve is when applications put an icon in the notification area (near the clock) AND leave a tab in the taskbar. This wastes valuable taskbar real estate.

I use Spark on my workstation to connect to the company's internal IM server. The application works alright, but the contacts window always appears in the taskbar. So I started to think about ways I could programmatically solve my problem.

I could set the WS_EX_TOOLWINDOW style on the window, but that would alter the window's appearance. What I really wanted was a way to tell Windows to remove the tab. A quick search on Google turned up the answer: use COM to create an instance of ITaskbarList. The interface has the function ITaskbarList::DeleteTab() which takes a window handle. Perfect!

Now I just needed to get the window's handle. FindWindow() would have worked, but that meant hard-coding my username into the program. I felt a more elegant solution was to enumerate all of the windows, and look for the one with the right class and title prefix.

Since the tab would reappear every time I brought the contact list window to the foreground, I ended up wrapping my fix with a loop and a timer. Here's the finished product:

/* NoSpark.cpp - Hides the Spark contacts window tab in the taskbar */
#include <windows.h>
#include <Shobjidl.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
	HANDLE htmr = CreateWaitableTimer(NULL, TRUE, L"CheckSpark");
	ITaskbarList* ptl;
	__int64 qwdt = -60 * 10000000; /* 1 minute */
	lidt.LowPart = (DWORD)(qwdt & 0xFFFFFFFF);
	lidt.HighPart = (LONG)(qwdt >> 32);
	while (TRUE) {
		SetWaitableTimer(htmr, &lidt, 0, NULL, NULL, FALSE);
		WaitForSingleObject(htmr, INFINITE);
		HWND hsparkwnd = 0;
		EnumWindows(&EnumWindowsProc, (LPARAM)&hsparkwnd);
		if (hsparkwnd == 0) continue;
		HRESULT ret = CoCreateInstance(
			(LPVOID*) &ptl
		if (ret == S_OK)
	return 0;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
	int tmpsz = 16;
	LPWSTR lptmp = (LPWSTR)malloc(sizeof(WCHAR) * tmpsz);
	RtlZeroMemory(lptmp, tmpsz);
	GetClassName(hwnd, lptmp, tmpsz);
	if (wcscmp(lptmp, L"SunAwtFrame") != 0) {
		return TRUE;
	RtlZeroMemory(lptmp, tmpsz);
	GetWindowText(hwnd, lptmp, tmpsz);
	if (wcscmp(lptmp, L"Spark -") > 0) {
		*((HWND*) lParam) = hwnd;
		return FALSE;
	return TRUE;

To compile this program, create a new, empty Visual C++ project. Create a new cpp file and drop the code above inside. If you get compile errors about converting wchar_t* to const char* then change your character set from Multibyte to Unicode in the project properties.