Click here to Skip to main content
15,891,905 members
Articles / Desktop Programming / MFC

Task Manager Extension 2.0

Rate me:
Please Sign up or sign in to vote.
4.92/5 (149 votes)
22 Jan 2007CDDL11 min read 598K   18.7K   263  
Task Manager Extension. This is a Windows Task Manager (NT/2000/XP/2003) plug-in. It adds lots of useful features to the standard Task Manager. It can show process modules, memory map, used handles, open files, file properties and a lot of other info!
//////////////////////////////////////////////////////////////
// File:		// SplashWnd.cpp
// File time:	// 21.04.2005	11:15
// Version: 	// 1.0
// Author:		// Sergey Kolomenkin <register@tut.by>
// Copyright:	// (c) Sergey Kolomenkin, Minsk, 2005
// Description: //////////////////////////////////////////////
//   Some useful routines...
//   

#include "stdafx.h"
//#include <windows.h>
#include "SplashWnd.h"
#include "MakeWindowTransparent.h"
#include "Resource.h"

#include "../TaskManagerExDll/Localization.h"
#include "../TaskManagerExDll/TaskManagerEx.h"
#include "../TaskManagerExDll/product.h"

//////////////////////////////////////////////////////////////

#pragma  comment (lib, "gdi32.lib")

//////////////////////////////////////////////////////////////

//#include <stdlib.h>

DWORD	g_dwSplashScreenTimeToLive	= 0;
BOOL	g_bStopSplashOnTimer		= TRUE;

const COLORREF crText			= RGB(59,126,236); // RGB(150,210,125);
const COLORREF crTextBorder		= RGB(0,0,0);
const COLORREF crDarkBorder		= RGB( 9, 63, 155 );
const COLORREF crTransparent	= RGB(255,255,255);
const COLORREF crBackground		= RGB(185,223,221); // crTransparent;

//#define EXIT_AFTER_SPLASH
//#define EXIT_ON_MOUSE_CLICK
//#define EXIT_ON_KBD_HIT
//#define TOGGLE_SPLASH	// dubug purposes

const int iSplashWidth			= 550;
const int iSplashHeight			= 150;

const int iSplashInternalWidth	= 500;
const int iSplashInternalHeight	= 110;

const int iTextHeightName		= 40;	// percent of window height
const int iTextHeightVersion	= 30;	// percent of window height
const int iTextHeightCopy1		= 15;	// percent of window height
const int iTextHeightCopy2		= 15;	// percent of window height

const int iCharWidthVersion		= 80;	// percent of Name char width
const int iCharWidthCopy1		= 32;	// percent of Name char width
const int iCharWidthCopy2		= 32;	// percent of Name char width

const BYTE transparentFactor	= 200;

HFONT MakeFont( int CharWidth, int CharHeight )
{
	HFONT hf = CreateFont( CharHeight, CharWidth, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 
		OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
		NULL);
	return hf;
}

void DrawText( HDC hdc, int y, LPCTSTR szText, int CharWidth, int CharHeight, int WindowWidth,
			  COLORREF ColorText, COLORREF ColorBorder )
{
	SIZE sz;

	HFONT	hf		= MakeFont( CharWidth, CharHeight );
	HBRUSH	hbr		= ::CreateSolidBrush( ColorText );
	HPEN	hpen	= ::CreatePen( PS_SOLID, 1, ColorBorder );

	HFONT	hf1		= (HFONT)	::SelectObject(hdc, hf);
	HBRUSH	hbr1	= (HBRUSH )	::SelectObject(hdc, hbr);
	HPEN	hpen1	= (HPEN)	::SelectObject(hdc, hpen);

	int len = _tcslen(szText);
	GetTextExtentPoint( hdc, szText, len, &sz );

	int TextWidth = sz.cx;

	::SetBkMode(hdc, TRANSPARENT);

	::BeginPath(hdc);
	::TextOut(hdc, (WindowWidth - TextWidth)/2, y, szText, len );
	::EndPath(hdc);

	::StrokeAndFillPath(hdc);

	::SelectObject(hdc, hf1);
	::SelectObject(hdc, hbr1);
	::SelectObject(hdc, hpen1);

	::DeleteObject(hf);
	::DeleteObject(hbr);
	::DeleteObject(hpen);
}

void OnSplashWndPaint( HWND hWnd )
{
	PAINTSTRUCT ps;
	HDC		hdc = NULL;
	RECT	rt;

	USES_CONVERSION;

	LPCTSTR szProduct = TMEX_NAME;
	LPCTSTR szVersion = A2T( VERSIONPRODUCTVERSIONSTR );
	LPCTSTR szCopy1 = A2T( COPYRIGHT1 );
	LPCTSTR szCopy2 = A2T( COPYRIGHT2 );

	hdc = BeginPaint(hWnd, &ps);

	::GetClientRect(hWnd, &rt);
	int width = rt.right - rt.left;
//	int height = rt.bottom - rt.top;

	int charWidth = width/_tcslen(szProduct);
	int MainTextHeight = iSplashInternalHeight*iTextHeightName/100;
	int y = (iSplashHeight - iSplashInternalHeight)/2;
	int TextWidth = 0;

	do
	{
		charWidth--;
		HFONT hf = MakeFont( charWidth, MainTextHeight );
		HFONT hf1 = (HFONT)::SelectObject(hdc, hf);

		SIZE sz;
		GetTextExtentPoint( hdc, szProduct, _tcslen(szProduct), &sz );
		TextWidth = sz.cx;

		::SelectObject(hdc, hf1);
		::DeleteObject( hf );

	} while( TextWidth > iSplashInternalWidth && charWidth > 1 );


	HPEN hPen = CreatePen( PS_SOLID, 1, crDarkBorder ); //GetSysColor(COLOR_WINDOWFRAME) );
	HPEN hPen1 = (HPEN) ::SelectObject(hdc, hPen);
	HBRUSH hBrush = CreateSolidBrush( crBackground );

	::Rectangle( hdc, rt.left, rt.top, rt.right, rt.bottom );

	rt.left++, rt.top++, rt.right--, rt.bottom--; // Inflate rectangle by 1 pixel

	::FillRect( hdc, &rt, hBrush );

	::DeleteObject( hBrush );
	::SelectObject(hdc, hPen1);
	::DeleteObject(hPen);

	int h;

	h = MainTextHeight;
	DrawText( hdc, y, szProduct, charWidth, h, width, crText, crTextBorder );
	y += h;

	h = iSplashInternalHeight*iTextHeightVersion/100;
	DrawText( hdc, y, szVersion, charWidth*iCharWidthVersion/100, h, width, crText, crTextBorder );
	y += h;

	h = iSplashInternalHeight*iTextHeightCopy1/100;
	DrawText( hdc, y, szCopy1, charWidth*iCharWidthCopy1/100, h, width, crText, crDarkBorder );
	y += h;

	h = iSplashInternalHeight*iTextHeightCopy2/100;
	DrawText( hdc, y, szCopy2, charWidth*iCharWidthCopy2/100, h, width, crText, crDarkBorder );
	y += h;

	EndPaint(hWnd, &ps);
}

// Following function was cut from MFC sources and adapted.

void CenterWindow( HWND m_hWnd )
{
	ASSERT(::IsWindow(m_hWnd));

	// determine owner window to center against
	DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
	HWND hWndCenter = NULL;

	{
		if (dwStyle & WS_CHILD)
			hWndCenter = ::GetParent(m_hWnd);
		else
			hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
	}

	// get coordinates of the window relative to its parent
	RECT rcDlg;
	::GetWindowRect( m_hWnd, &rcDlg );
	RECT rcArea;
	RECT rcCenter;
	HWND hWndParent;
	if (!(dwStyle & WS_CHILD))
	{
		// don't center against invisible or minimized windows
		if (hWndCenter != NULL)
		{
			DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
			if (!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
				hWndCenter = NULL;
		}

		MONITORINFO mi;
		mi.cbSize = sizeof(mi);

		// center within appropriate monitor coordinates
		if (hWndCenter == NULL)
		{
			HWND hwDefault = m_hWnd;

			GetMonitorInfo(
				MonitorFromWindow(hwDefault, MONITOR_DEFAULTTOPRIMARY), &mi);
			rcCenter = mi.rcWork;
			rcArea = mi.rcWork;
		}
		else
		{
			::GetWindowRect(hWndCenter, &rcCenter);
			GetMonitorInfo(
				MonitorFromWindow(hWndCenter, MONITOR_DEFAULTTONEAREST), &mi);
			rcArea = mi.rcWork;
		}
	}
	else
	{
		// center within parent client coordinates
		hWndParent = ::GetParent(m_hWnd);
		ASSERT(::IsWindow(hWndParent));

		::GetClientRect(hWndParent, &rcArea);
		ASSERT(::IsWindow(hWndCenter));
		::GetClientRect(hWndCenter, &rcCenter);
		::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
	}

	int rcDlg_Width = rcDlg.right - rcDlg.left;
	int rcDlg_Height = rcDlg.bottom - rcDlg.top;

	// find dialog's upper left based on rcCenter
	int xLeft = (rcCenter.left + rcCenter.right) / 2 - rcDlg_Width / 2;
	int yTop = (rcCenter.top + rcCenter.bottom) / 2 - rcDlg_Height / 2;

	// if the dialog is outside the screen, move it inside
	if (xLeft < rcArea.left)
		xLeft = rcArea.left;
	else if (xLeft + rcDlg_Width > rcArea.right)
		xLeft = rcArea.right - rcDlg_Width;

	if (yTop < rcArea.top)
		yTop = rcArea.top;
	else if (yTop + rcDlg_Height > rcArea.bottom)
		yTop = rcArea.bottom - rcDlg_Height;

	// map screen coordinates to child coordinates
	::SetWindowPos( m_hWnd, NULL, xLeft, yTop, -1, -1,
		SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}

BOOL	g_bDragSplash = FALSE;
POINT	g_ptMouseDragBegin;
RECT	g_rWindowDragBegin;

LRESULT CALLBACK SplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int iRes;
	switch (message) 
	{
		case WM_CREATE:
			TRACE( _T("SplashWndProc> WM_CREATE\n") );
			iRes = SetTimer( hWnd, 1, g_dwSplashScreenTimeToLive, NULL );
//			InvalidateRect( hWnd, NULL, FALSE );
//			OnSplashWndPaint(hWnd);
			CenterWindow( hWnd );
			MakeWindowTransparent( hWnd, transparentFactor, crTransparent );
			SetCursor( LoadCursor( NULL, MAKEINTRESOURCE(IDC_ARROW) ) );
			break;

		case WM_PAINT:
//			TRACE( _T("SplashWndProc> WM_PAINT\n") );
			OnSplashWndPaint(hWnd);
			break;

		case WM_LBUTTONUP:
			if( g_bDragSplash )
			{
				g_bDragSplash = FALSE;
				ReleaseCapture();
			}
			break;

		case WM_MOUSEMOVE:
			if( g_bDragSplash )
			{
				POINT	p1 = g_ptMouseDragBegin;
				RECT	r = g_rWindowDragBegin;
				POINT	p2;
				GetCursorPos( &p2 );
				int dx = p2.x - p1.x;
				int dy = p2.y - p1.y;

				MoveWindow( hWnd, r.left + dx, r.top + dy, r.right - r.left, r.bottom - r.top, TRUE );
			}
			break;

		case WM_LBUTTONDOWN:
			#ifdef EXIT_ON_MOUSE_CLICK
				::DestroyWindow(hWnd);
			#else
			SetCapture(hWnd);
			GetCursorPos( &g_ptMouseDragBegin );
			GetWindowRect( hWnd, &g_rWindowDragBegin );
			g_bDragSplash = TRUE;	// Set flag to check for key down in mouse move
									// message.
			#endif
			break;
			
		case WM_MBUTTONDOWN:
		case WM_RBUTTONDOWN:
//			TRACE( _T("SplashWndProc> Mouse click\n") );
			#ifdef EXIT_ON_MOUSE_CLICK
				::DestroyWindow(hWnd);
			#else
				#ifdef TOGGLE_SPLASH
					g_bStopSplashOnTimer = !g_bStopSplashOnTimer;
				#endif
			#endif
			break;


		case WM_KEYDOWN:
//			TRACE( _T("SplashWndProc> WM_KEYDOWN: VK = %X\n"), wParam );
			if( wParam == VK_ESCAPE )
			{
				::DestroyWindow(hWnd);
			}
			else
			{
				#ifdef EXIT_ON_KBD_HIT
					::DestroyWindow(hWnd);
				#else
					#ifdef TOGGLE_SPLASH
						g_bStopSplashOnTimer = !g_bStopSplashOnTimer;
					#endif
				#endif
			}

			//return DefWindowProc(hWnd, message, wParam, lParam);
			break;

		case WM_TIMER:
			TRACE( _T("SplashWndProc> WM_TIMER\n") );
			if( g_bStopSplashOnTimer )
			{
				::DestroyWindow(hWnd);
			}
			break;

		case WM_DESTROY:
			TRACE( _T("SplashWndProc> WM_DESTROY\n") );
			#ifdef EXIT_AFTER_SPLASH
				PostQuitMessage( 0 );
			#endif
			break;

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

void RegisterWndClass( LPCTSTR szWindowClass )
{
	WNDCLASSEX wcex;
	wcex.cbSize			= sizeof(wcex); 
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)SplashWndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= NULL;
	wcex.hIcon			= NULL;
	wcex.hCursor		= NULL;
	wcex.hbrBackground	= NULL;
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= NULL;

	RegisterClassEx(&wcex);
}

BOOL CreateSplashScreen( DWORD milliseconds )
{
	TCHAR szWindowClass[] = _T("SpashWindowCLASS");

	// -------------------------------------------------------

	HWND hDesktopWnd = ::GetDesktopWindow();
	int tx = iSplashWidth;
	int ty = iSplashHeight;

	// -------------------------------------------------------------

	g_dwSplashScreenTimeToLive = milliseconds;
	g_bStopSplashOnTimer = TRUE;
	g_bDragSplash = FALSE;

	RegisterWndClass( szWindowClass );

//	HWND hForeWnd = GetForegroundWindow();

	HWND hWndUser = CreateWindowEx(
		WS_EX_TOPMOST, szWindowClass,
		TMEX_NAME, WS_VISIBLE | WS_POPUP,
		0, 0, tx, ty, hDesktopWnd, NULL, NULL, NULL);

	ShowWindow(hWndUser, SW_SHOW);
//	SetForegroundWindow( hForeWnd ); // It works strange ????

	return TRUE;
}

//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////

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 Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
Belarus Belarus
He is a young and forward-looking software developer. He also has lots of interesting hobbies like snowboarding, bicycle riding, carting racing and of course talking about himself in a third person. Smile | :)

github.com/kolomenkin

Curriculum Vitae

Comments and Discussions