Click here to Skip to main content
15,891,184 members
Articles / Programming Languages / C++

Tray Me!

Rate me:
Please Sign up or sign in to vote.
4.98/5 (21 votes)
1 Aug 2008CPOL9 min read 93.6K   3.7K   138  
A Beginner's Guide to Windows Hooks
#include "stdafx.h"
#include "resource.h"
#include "RegisterdMessages.h"

#define ARRAY_SIZE 1024

#pragma data_seg (".SHARED")
	HHOOK g_hPreviousMouseHook = 0;
	HHOOK g_hPreviousWinProcHook = 0;
	HINSTANCE g_hInstance = 0;
	HWND g_hMinimizedWindowList[ARRAY_SIZE] = {0};
	int g_iMinimizedWindowCount = 0;
#pragma data_seg()

#pragma comment(linker,"/SECTION:.SHARED,RWS")

bool TrayMe(HWND hWnd)
{
	bool bReturn = false;
	try
	{
		if(g_iMinimizedWindowCount >= ARRAY_SIZE)
		{
			MessageBox(NULL,_T("Can not Tray application. \n\t Reached the Tray limit."),_T("Tray Me !"),0);
			return bReturn;
		}

		TCHAR szModuleFileName[ARRAY_SIZE] = {0};
		HMODULE hModule = (HMODULE) OpenProcess(0,FALSE,GetWindowThreadProcessId(hWnd,0));
		GetModuleFileName(hModule,szModuleFileName,ARRAY_SIZE);
		OutputDebugString(szModuleFileName);

		TCHAR szCaption[128] = {0};

		//HICON hIcon = (HICON) SendMessage(pMouseHooksStruct->hwnd,WM_GETICON,ICON_SMALL,0);
		SHFILEINFO shFileInfo;
		shFileInfo.hIcon = NULL;
		SHGetFileInfo(szModuleFileName,FILE_ATTRIBUTE_NORMAL,&shFileInfo,sizeof(SHFILEINFO),SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON);

		if(!shFileInfo.hIcon)
			OutputDebugString(_T("NULL Icon handle."));

		NOTIFYICONDATA objNotifyIcon;
		objNotifyIcon.cbSize = sizeof(NOTIFYICONDATA);
		objNotifyIcon.hWnd = hWnd;
		objNotifyIcon.uID = 1;
		objNotifyIcon.uCallbackMessage = WM_NOTIFY_CALLBACK_MESSAGE;
		objNotifyIcon.hIcon = (shFileInfo.hIcon == NULL) ? LoadIcon(NULL,IDI_QUESTION) : shFileInfo.hIcon;
		objNotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;

		GetWindowText(hWnd,szCaption,127);
		wcscpy_s(objNotifyIcon.szTip,127,szCaption);

		Shell_NotifyIcon(NIM_ADD,&objNotifyIcon);
		ShowWindow(hWnd,SW_HIDE);
		g_hMinimizedWindowList[g_iMinimizedWindowCount++] = hWnd;
		bReturn = true;
	}
	catch(...)
	{
		OutputDebugString(_T("Caught Exception in TrayMe !"));
		bReturn = false;
	}

	return bReturn;
}

bool UnTrayApplication(HWND hWnd)
{
	bool bReturn = false;
	try
	{
		::ShowWindow(hWnd,SW_SHOW);
		::SetForegroundWindow(hWnd);

		NOTIFYICONDATA objNotifyIcon;
		objNotifyIcon.cbSize = sizeof(NOTIFYICONDATA);
		objNotifyIcon.hWnd = hWnd;
		objNotifyIcon.uID = 1;
		Shell_NotifyIcon(NIM_DELETE,&objNotifyIcon);
		
		for(int i = 0; i < g_iMinimizedWindowCount; i++)
			if(hWnd == g_hMinimizedWindowList[i])
			{
				g_hMinimizedWindowList[i] = g_hMinimizedWindowList[--g_iMinimizedWindowCount];
				g_hMinimizedWindowList[g_iMinimizedWindowCount] = 0;
				break;
			}

		bReturn = true;
	}
	catch(...)
	{
		OutputDebugString(_T("Caught Exception in UnTrayMe !"));
		bReturn = false;
	}

	return bReturn;
}

bool UnTrayMe(TCHAR *szWindowTitle)
{
	bool bReturn = false;
	HWND hWnd = NULL;
	try
	{
		for(int i = 0;i < g_iMinimizedWindowCount;i++)
		{
			TCHAR szWinTitle[ARRAY_SIZE] = {0};
			GetWindowText(g_hMinimizedWindowList[i],szWinTitle,ARRAY_SIZE - 1); 
			if(_wcsicmp(szWindowTitle,szWinTitle) == 0)
			{
				hWnd = g_hMinimizedWindowList[i];
				break;
			}
		}

		if(NULL == hWnd)
			return FALSE;

		::ShowWindow(hWnd,SW_SHOW);
		::SetForegroundWindow(hWnd);

		NOTIFYICONDATA objNotifyIcon;
		objNotifyIcon.cbSize = sizeof(NOTIFYICONDATA);
		objNotifyIcon.hWnd = hWnd;
		objNotifyIcon.uID = 1;
		Shell_NotifyIcon(NIM_DELETE,&objNotifyIcon);
		
		for(int i = 0; i < g_iMinimizedWindowCount; i++)
			if(hWnd == g_hMinimizedWindowList[i])
			{
				g_hMinimizedWindowList[i] = g_hMinimizedWindowList[--g_iMinimizedWindowCount];
				g_hMinimizedWindowList[g_iMinimizedWindowCount] = 0;
				break;
			}

		bReturn = true;
	}
	catch(...)
	{
		OutputDebugString(_T("Caught Exception in UnTrayMe !"));
		bReturn = false;
	}

	return bReturn;
}

void UnTrayAll()
{
	//bool bReturn = false;
	try
	{
		while(g_iMinimizedWindowCount)
			UnTrayApplication(g_hMinimizedWindowList[0]);

		//bReturn = true;
	}
	catch(...)
	{
		MessageBox(NULL,_T("Failed to untray few applications."),_T("Tray Me !"),MB_ICONERROR);
		OutputDebugString(_T("Exception Caught In UnTrayAll."));
		//bReturn = false;
	}
	
	//return bReturn;
}

LRESULT CALLBACK MouseHookProcedure(int nCode, WPARAM wParam,LPARAM lParam)
{
	if(0 > nCode)
		return CallNextHookEx(g_hPreviousMouseHook,nCode,wParam,lParam);

	//OutputDebugString(_T("Mouse Hooked Event...\n"));

	MOUSEHOOKSTRUCT *pMouseHooksStruct = (MOUSEHOOKSTRUCT *) lParam;
	switch(wParam)
	{
		case WM_NCRBUTTONUP:
			if(HTMINBUTTON == pMouseHooksStruct->wHitTestCode)
			{
				OutputDebugString(_T("Mouse Clicked on Min Button...\n"));
				HMENU  hPopupMenu = ::CreatePopupMenu();
				::AppendMenu(hPopupMenu,MF_STRING,501,_T("&Try Me !")); 
				
				SetForegroundWindow(pMouseHooksStruct->hwnd);
				int iSelectedMenuId = ::TrackPopupMenu(hPopupMenu,TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD ,pMouseHooksStruct->pt.x,pMouseHooksStruct->pt.y,0,pMouseHooksStruct->hwnd,NULL);
				//PostMessage(WM_NULL,NULL,NULL);
				
				switch(iSelectedMenuId)
				{
					case 501:
						TrayMe(pMouseHooksStruct->hwnd);
						break;
				}
				
				DestroyMenu(hPopupMenu);
				return -1;
			}
			break;
	}

	return CallNextHookEx(g_hPreviousMouseHook,nCode,wParam,lParam);
}

LRESULT CALLBACK WinProcHookProcedure(int nCode, WPARAM wParam, LPARAM lParam)
{
	if(0 > nCode)
		return CallNextHookEx(g_hPreviousWinProcHook ,nCode,wParam,lParam);

	CWPSTRUCT *pwsStruct = (CWPSTRUCT *) lParam;
	
	if(WM_NOTIFY_CALLBACK_MESSAGE == pwsStruct->message)
	{
		if(WM_LBUTTONDBLCLK == pwsStruct->lParam)
		{
			OutputDebugString(_T("WM_NOTIFY_CALLBACK_MESSAGE WM_LBUTTONDBLCLK Fired.\n"));
			UnTrayApplication(pwsStruct->hwnd);
		}
		return -1;
	}

	return CallNextHookEx(g_hPreviousWinProcHook ,nCode,wParam,lParam);
}

bool InstallWinProcHook(void)
{
	bool bReturn = false;
	try
	{
		OutputDebugString(_T("WinProc Event Hooked.\n"));
		if(NULL == g_hInstance)
			OutputDebugString(_T("NULL g_hInstance\n"));

		g_hPreviousWinProcHook = SetWindowsHookEx(WH_CALLWNDPROC,&WinProcHookProcedure,g_hInstance,0);

		if(NULL == g_hPreviousWinProcHook)
		{
			TCHAR szErrorMsg[ARRAY_SIZE] = {0};
			wsprintf(szErrorMsg,_T("Failed to Hook WinProc Event.\nLast Error :%d\n"),GetLastError());
			OutputDebugString(szErrorMsg);
			bReturn = false;
		}
		else
		{
			OutputDebugString(_T("WinProc Event Hooked.\n"));
			bReturn = true;
		}
	}
	catch(...)
	{
		bReturn = false;
	}

	return bReturn;
}

bool UnInstallWinProcHook()
{
	bool bReturn = false;

	try
	{
		OutputDebugString(_T("WinProc Event UnHooked.\n"));
		if(UnhookWindowsHookEx(g_hPreviousWinProcHook) == FALSE)
		{
			TCHAR szError[ARRAY_SIZE] = {0};
			wsprintf(szError,_T("Last Error : %d"),GetLastError());
			OutputDebugString(_T("Failed to UnHook WinProc Event.\n"));
			OutputDebugString(szError);
			bReturn = false;
		}
		else
		{
			OutputDebugString(_T("WinProc Event UnHooked.\n"));
			bReturn = true;
		}
	}
	catch(...)
	{
		bReturn = false;
	}

	return bReturn;
}

bool InstallMouseHook()
{
	bool bReturn = false;

	try
	{
		OutputDebugString(_T("Mouse Event Hooked.\n"));
		g_hPreviousMouseHook = SetWindowsHookEx(WH_MOUSE,&MouseHookProcedure,g_hInstance,0);

		if(NULL == g_hPreviousMouseHook)
		{
			TCHAR szError[ARRAY_SIZE] = {0};
			wsprintf(szError,_T("Last Error : %d"),GetLastError());
			OutputDebugString(_T("Failed to Hook Mouse Event.\n"));
			OutputDebugString(szError);
			bReturn = false;
		}
		else
		{
			OutputDebugString(_T("Mouse Event Hooked.\n"));
			bReturn = true;
		}
	}
	catch(...)
	{
		bReturn = false;
	}

	return bReturn;
}

bool UnInstallMouseHook()
{
	bool bReturn = false;

	try
	{
		OutputDebugString(_T("Mouse Event UnHooked.\n"));
		if(UnhookWindowsHookEx(g_hPreviousMouseHook) == FALSE)
		{
			TCHAR szError[ARRAY_SIZE] = {0};
			wsprintf(szError,_T("Last Error : %d"),GetLastError());
			OutputDebugString(_T("Failed to UnHook Mouse Event.\n"));
			OutputDebugString(szError);
			bReturn = false;
		}
		else
		{
			OutputDebugString(_T("Mouse Event UnHooked.\n"));
			bReturn = true;
		}
	}
	catch(...)
	{
		bReturn = false;
	}

	return bReturn;
}


void GetMinimizedWinodwList(TCHAR szWindowCaptions[ARRAY_SIZE][100])
{
	for(int i=0;i<g_iMinimizedWindowCount;i++)
	{
		TCHAR szWndCaption[ARRAY_SIZE] = {0};
		::GetWindowText(g_hMinimizedWindowList[i], szWndCaption,ARRAY_SIZE - 1);
		
		if(NULL != szWindowCaptions[i])
		{
			wcscpy(szWindowCaptions[i],szWndCaption);
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer
India India
Hello All !
This is Mallinath S. Karkanti, from India. I'm working as a Software Developer in one of the Middle Scale Company... !

Comments and Discussions