Click here to Skip to main content
15,885,944 members
Articles / Desktop Programming / MFC

The Ultimate Toolbox Home Page

Rate me:
Please Sign up or sign in to vote.
4.97/5 (141 votes)
25 Aug 2007CPOL13 min read 3.2M   91.4K   476  
The Ultimate Toolbox is now Open Source
// ApplicationsDialog.cpp : implementation file
//

#include "stdafx.h"
#include "systemstateinfo.h"
#include "ApplicationsDialog.h"

#include "UTBStrOp.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


#define APPLICATIONREF_FLAG			0xffee0000
#define WINDOWREF_FLAG				0xffdd0000
#define PROCESSREF_FLAG				0xffcc0000

/////////////////////////////////////////////////////////////////////////////
// CApplicationsDialog dialog


CApplicationsDialog::CApplicationsDialog() : CPageDialog()
{
	//{{AFX_DATA_INIT(CApplicationsDialog)
	m_nExpandLevel = 0;
	m_nExpandType = 1;
	//}}AFX_DATA_INIT
	m_nCurrentIndex=-1;
}


void CApplicationsDialog::DoDataExchange(CDataExchange* pDX)
{
	CPageDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CApplicationsDialog)
	DDX_Control(pDX, IDC_SPIN_EXPANDLEVEL, m_spinExpandLevel);
	DDX_Control(pDX, IDC_EDIT_EXPANDLEVEL, m_editExpandLevel);
	DDX_Control(pDX, IDC_TREE_APPLICATIONS, m_tree);
	DDX_Text(pDX, IDC_EDIT_EXPANDLEVEL, m_nExpandLevel);
	DDX_Radio(pDX, IDC_RADIO_EXPANDLEVEL, m_nExpandType);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CApplicationsDialog, CPageDialog)
	//{{AFX_MSG_MAP(CApplicationsDialog)
	ON_BN_CLICKED(IDC_RADIO_EXPANDALL, OnRadioExpandall)
	ON_BN_CLICKED(IDC_RADIO_EXPANDLEVEL, OnRadioExpandlevel)
	ON_NOTIFY(NM_DBLCLK, IDC_TREE_APPLICATIONS, OnDblclkTreeServices)
	ON_NOTIFY(NM_RCLICK, IDC_TREE_APPLICATIONS, OnRclickTreeApplications)
	//}}AFX_MSG_MAP
	ON_COMMAND(IDM_APP_SWITCHTO, OnAppWndSwitchTo)
	ON_COMMAND(IDM_APP_BRINGTOFRONT, OnAppWndBringToFront)
	ON_COMMAND(IDM_APP_MINIMIZE, OnAppWndMinimize)
	ON_COMMAND(IDM_APP_MAXIMIZE, OnAppWndMaximize)
	ON_COMMAND(IDM_APP_RESTORE, OnAppWndRestore)
	ON_COMMAND(IDM_APP_CLOSE, OnAppWndClose)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CApplicationsDialog message handlers
void CApplicationsDialog::OnInitDialog() 
{
	CPageDialog::OnInitDialog();

	// TODO: Add your specialized creation code here

	m_ilTree.Create(::GetSystemMetrics(SM_CXSMICON),
		::GetSystemMetrics(SM_CYSMICON),ILC_COLOR8|ILC_MASK,0,0);
	m_tree.SetImageList(&m_ilTree,TVSIL_NORMAL);

	LV_COLUMN lvc={ sizeof(lvc) };
	lvc.fmt=LVCFMT_LEFT;
	lvc.cx=237;
	lvc.pszText=_T("Item");
	lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
	m_tree.SetColumn(0,&lvc);
	m_tree.InsertColumn(1,_T("Value"),LVCFMT_LEFT,200,1);

	// set COXTreeCtrl styles
	m_tree.ModifyExStyle(0,TVOXS_PICKANYWHERE|TVOXS_ROWSEL);
	m_tree.ModifyStyle(0,TVS_SHOWSELALWAYS|TVS_HASBUTTONS|
		TVS_HASLINES|TVS_LINESATROOT);


	// spin control
	m_spinExpandLevel.SetRange(0,3);
	m_spinExpandLevel.SetPos(0);
	
	// layout manager 
	//
	m_LayoutManager.Attach(this);
	
	// tree control
	m_LayoutManager.TieChild(IDC_TREE_APPLICATIONS,OX_LMS_ANY,OX_LMT_SAME);
	//////////////////

	// radio buttons and expand level edit control
	m_LayoutManager.TieChild(IDC_RADIO_EXPANDALL,
		OX_LMS_LEFT|OX_LMS_BOTTOM,OX_LMT_SAME);

	m_LayoutManager.TieChild(IDC_RADIO_EXPANDLEVEL,
		OX_LMS_LEFT|OX_LMS_BOTTOM,OX_LMT_SAME);

	m_LayoutManager.TieChild(IDC_EDIT_EXPANDLEVEL,OX_LMS_LEFT,
		OX_LMT_OPPOSITE,IDC_RADIO_EXPANDLEVEL);
	m_LayoutManager.TieChild(IDC_EDIT_EXPANDLEVEL,OX_LMS_BOTTOM,OX_LMT_SAME);

	m_LayoutManager.TieChild(IDC_SPIN_EXPANDLEVEL,OX_LMS_LEFT,
		OX_LMT_OPPOSITE,IDC_EDIT_EXPANDLEVEL);
	m_LayoutManager.TieChild(IDC_SPIN_EXPANDLEVEL,OX_LMS_BOTTOM,OX_LMT_SAME);
	//////////////////

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

	PopulateTree();

	ShowControls();
}

void CApplicationsDialog::Refresh() 
{
	PopulateTree();
}

void CApplicationsDialog::PopulateTree()
{
	if(!UpdateData())
		return;

	CWaitCursor waitCursor;

	m_tree.SetRedraw(FALSE);
	// kill and close all threads
	CleanThreads();
	// remove all items
	m_tree.DeleteAllItems();
	COXTreeHeader* pHeader=(COXTreeHeader*)m_tree.GetDlgItem(0);
	ASSERT(pHeader);
	pHeader->SortColumn(-1,0);
	// clean up image list
	for(int nIndex=0; nIndex<m_ilTree.GetImageCount(); nIndex++)
		VERIFY(m_ilTree.Remove(0));

	// create fonts to customize tree items appearance
	LOGFONT lf;
	CFont fontRoot;
	CFont fontSubRoot;
	CFont* pFontRoot=GetFont();
	if(pFontRoot->GetLogFont(&lf))
	{
		lf.lfHeight=-14;
		UTBStr::tcsncpy(lf.lfFaceName, LF_FACESIZE,_T("Arial"),LF_FACESIZE);
		fontRoot.CreateFontIndirect(&lf);

		lf.lfHeight=-12;
		lf.lfWeight=FW_BOLD;
		UTBStr::tcsncpy(lf.lfFaceName,LF_FACESIZE,_T("Times New Roman"),LF_FACESIZE);
		fontSubRoot.CreateFontIndirect(&lf);
	}
	pFontRoot=((HFONT)fontRoot!=NULL) ? &fontRoot : NULL;
//	CFont* pFontSubRoot=((HFONT)fontSubRoot!=NULL) ? &fontSubRoot : NULL;

	CString sValue;
	HTREEITEM htiRoot=NULL;
	HTREEITEM htiSelectItem=NULL;
	HTREEITEM htiItem=NULL;

	COLORREF clrTopic=RGB(0,0,255);
	COLORREF clrValue=RGB(0,128,0);

	m_arrAppInfo.RemoveAll();
	if(::EnumWindows(&EnumMainWindows,(LPARAM)&m_arrAppInfo))
	{
		for(int nIndex=0; nIndex<m_arrAppInfo.GetSize(); nIndex++)
		{
			CWnd* pAppWnd=CWnd::FromHandle(m_arrAppInfo[nIndex].hMainWnd);
			if(pAppWnd!=NULL && ::IsWindow(pAppWnd->GetSafeHwnd()))
			{
				// main window text
				CString sWindowText;
				pAppWnd->GetWindowText(sWindowText);
				///////////////////

				// work out icon...
				int nIconIndex=-1;
				HICON hIcon=(HICON)(DWORD_PTR)::GetClassLongPtr(pAppWnd->m_hWnd,GCL_HICONSM);
				if(hIcon==NULL)
					hIcon=(HICON)(DWORD_PTR)::GetClassLongPtr(pAppWnd->m_hWnd,GCL_HICON);
				if(hIcon==NULL && m_arrAppInfo[nIndex].bGotRespond)
				{
					if(!::SendMessageTimeout(m_arrAppInfo[nIndex].hMainWnd,
						WM_GETICON,ICON_SMALL,0,SMTO_ABORTIFHUNG,
						1000,(LPDWORD)&hIcon) || hIcon==NULL)
					{
						::SendMessageTimeout(m_arrAppInfo[nIndex].hMainWnd,
							WM_GETICON,ICON_BIG,0,SMTO_ABORTIFHUNG,
							1000,(LPDWORD)&hIcon);
					}
				}
				if(hIcon!=NULL)
					// add icon
					nIconIndex=m_ilTree.Add(hIcon);
				///////////////////

				htiRoot=InsertItem(sWindowText,NULL,nIconIndex,
					pFontRoot,clrTopic);
				VERIFY(m_tree.SetSubItem(htiRoot,1,OX_SUBITEM_TEXT|
					OX_SUBITEM_COLOR,(m_arrAppInfo[nIndex].bGotRespond ? 
					_T("Running") : _T("Not reponding")),0,NULL,clrValue));
				VERIFY(m_tree.SetItemData(htiRoot,APPLICATIONREF_FLAG+nIndex));
				if(htiSelectItem==NULL)
					htiSelectItem=htiRoot;
				///////////////////

				// Executable
				if(m_process.GetProcessImageFileName(
					m_arrAppInfo[nIndex].dwProcessID,sValue))
				{
					htiItem=InsertItem(_T("Executable"),htiRoot);
					VERIFY(m_tree.SetSubItem(htiItem,1,
						OX_SUBITEM_TEXT|OX_SUBITEM_COLOR,
						sValue,0,NULL,clrValue));
					VERIFY(m_tree.
						SetItemDrawEllipsis(htiItem,DT_PATH_ELLIPSIS,1));
				}
				///////////////////

				// Process ID
				htiItem=InsertItem(_T("Process ID"),htiRoot);
				sValue.Format(_T("0x%x"),m_arrAppInfo[nIndex].dwProcessID);
				VERIFY(m_tree.SetSubItem(htiItem,1,
					OX_SUBITEM_TEXT|OX_SUBITEM_COLOR,
					sValue,0,NULL,clrValue));
				VERIFY(m_tree.SetItemData(htiItem,PROCESSREF_FLAG+nIndex));
				///////////////////

				// Main Window
				htiItem=InsertItem(_T("Main window handle"),htiRoot);
				sValue.Format(_T("0x%x"),m_arrAppInfo[nIndex].hMainWnd);
				VERIFY(m_tree.SetSubItem(htiItem,1,
					OX_SUBITEM_TEXT|OX_SUBITEM_COLOR,
					sValue,0,NULL,clrValue));
				VERIFY(m_tree.SetItemData(htiItem,WINDOWREF_FLAG+nIndex));
				///////////////////

			}
		}
	}

	ExpandTree((m_nExpandType==0 ? m_nExpandLevel : -1));

	m_tree.SetFocus();
	m_tree.SelectItem(htiSelectItem);

	m_tree.SetRedraw(TRUE);
}


void CApplicationsDialog::ExpandTree(int nExpandLevel/*=-1*/,
									 HTREEITEM htiParent/*=NULL*/)
{
	if(nExpandLevel==0)
		return;

	if(htiParent==NULL)
	{
		htiParent=m_tree.GetRootItem();
		ASSERT(htiParent!=NULL);
	}

	HTREEITEM hti=m_tree.GetNextItem(htiParent,TVGN_CHILD);
	while(hti!=NULL)
	{
		m_tree.Expand(hti,TVE_EXPAND);

		COXTreeItem* xti=m_tree.GetXItem(hti);
		ASSERT(xti!=NULL);
		if(xti->ItemHasChildren())
			ExpandTree((nExpandLevel==-1 ? -1 : nExpandLevel-1),hti);

		hti=m_tree.GetNextItem(hti,TVGN_NEXT);
	}
}

HTREEITEM CApplicationsDialog::InsertItem(CString sItem, 
										  HTREEITEM htiParent/*=NULL*/, 
										  int nImage/*=-1*/, 
										  CFont* pFont/*=NULL*/, 
										  COLORREF clr/*=CLR_NONE*/)
{
	HTREEITEM hti=m_tree.InsertItem(sItem,htiParent);
	ASSERT(hti!=NULL);

	// associate new font
	if(pFont!=NULL)
		VERIFY(m_tree.SetItemFont(hti,pFont));
	// and new color
	if(clr!=CLR_NONE)
		VERIFY(m_tree.SetItemColor(hti,clr));

	m_tree.SetItemImage(hti,nImage,nImage);

	return hti;
}

void CApplicationsDialog::ShowControls()
{
	if(UpdateData())
	{
		CWnd* pDlgItem=GetDlgItem(IDC_EDIT_EXPANDLEVEL);
		ASSERT(pDlgItem!=NULL);
		pDlgItem->EnableWindow((m_nExpandType==0));
		pDlgItem=GetDlgItem(IDC_SPIN_EXPANDLEVEL);
		ASSERT(pDlgItem!=NULL);
		pDlgItem->EnableWindow((m_nExpandType==0));
	}
}

void CApplicationsDialog::OnRadioExpandall() 
{
	// TODO: Add your control notification handler code here
	
	ShowControls();
}

void CApplicationsDialog::OnRadioExpandlevel() 
{
	// TODO: Add your control notification handler code here
	
	ShowControls();
}

void CApplicationsDialog::OnDblclkTreeServices(NMHDR* pNMHDR, 
											   LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	UNREFERENCED_PARAMETER(pNMHDR);

	CPoint point;
	if(::GetCursorPos(&point))
	{
		m_tree.ScreenToClient(&point);
		UINT nFlags;
		int nItem=m_tree.HitTest(point,&nFlags);
		if(nItem!=-1)
		{
			HTREEITEM hti=m_tree.GetItemFromIndex(nItem);
			ASSERT(hti!=NULL);
			if(m_tree.GetItemIndent(hti)<point.x && 
				(nFlags&TVHT_ONITEM)==TVHT_ONITEM)
			{
				DWORD dwData=m_tree.GetItemData(hti);
				if((dwData&WINDOWREF_FLAG)==WINDOWREF_FLAG)
				{
					int nIndex=dwData&0x0000ffff;
					ASSERT(nIndex>=0 && nIndex<m_arrAppInfo.GetSize());
					if(m_arrAppInfo[nIndex].bGotRespond)
					{
						m_nCurrentIndex=nIndex;
						PostMessage(WM_COMMAND,IDM_APP_SWITCHTO);
					}
				}
			}
		}
	}

	*pResult = 0;
}


void CApplicationsDialog::OnRclickTreeApplications(NMHDR* pNMHDR, 
												   LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	UNREFERENCED_PARAMETER(pNMHDR);
	
	CPoint point;
	if(::GetCursorPos(&point))
	{
		m_tree.ScreenToClient(&point);
		UINT nFlags;
		int nItem=m_tree.HitTest(point,&nFlags);
		if(nItem!=-1)
		{
			HTREEITEM hti=m_tree.GetItemFromIndex(nItem);
			ASSERT(hti!=NULL);
			if(m_tree.GetItemIndent(hti)<point.x && 
				(nFlags&TVHT_ONITEM)==TVHT_ONITEM)
			{
				DWORD dwData=m_tree.GetItemData(hti);
//				if((dwData&WINDOWREF_FLAG)==WINDOWREF_FLAG || 
//					(dwData&APPLICATIONREF_FLAG)==APPLICATIONREF_FLAG)
				{
					int nIndex=dwData&0x0000ffff;
					ASSERT(nIndex>=0 && nIndex<m_arrAppInfo.GetSize());
					m_nCurrentIndex=nIndex;

					CMenu popMenu;
					VERIFY(popMenu.LoadMenu(IDR_APPLICATION_POPUPMENU));

					MENUITEMINFO itemInfo={ sizeof(MENUITEMINFO) };
					itemInfo.fMask=MIIM_STATE;
					if(m_arrAppInfo[nIndex].bGotRespond)
					{
						if(m_arrAppInfo[nIndex].dwProcessID!=m_process.GetProcessID())
						{
							// set default item
							itemInfo.fState=MFS_DEFAULT;
							::SetMenuItemInfo(popMenu.m_hMenu,
								IDM_APP_SWITCHTO,FALSE,&itemInfo);
						}
						else
						{
							// disable items
							itemInfo.fState=MFS_DISABLED;
							::SetMenuItemInfo(popMenu.m_hMenu,
								IDM_APP_SWITCHTO,FALSE,&itemInfo);
							::SetMenuItemInfo(popMenu.m_hMenu,
								IDM_APP_BRINGTOFRONT,FALSE,&itemInfo);
						}

						DWORD dwStyle=::GetWindowLong(
							m_arrAppInfo[m_nCurrentIndex].hMainWnd,GWL_STYLE);
						BOOL bSysMenu=(dwStyle&WS_SYSMENU)!=0;
						BOOL bMaximizeBtn=bSysMenu & 
							((dwStyle&WS_MAXIMIZEBOX)!=0);
						BOOL bCanMaximize=bMaximizeBtn & 
							((dwStyle&WS_MAXIMIZE)==0);
						BOOL bMinimizeBtn=bSysMenu & 
							((dwStyle&WS_MINIMIZEBOX)!=0);
						BOOL bCanMinimize=bMinimizeBtn & 
							((dwStyle&WS_MINIMIZE)==0);

						itemInfo.fState=MFS_DISABLED;
						if(!bCanMaximize)
							::SetMenuItemInfo(popMenu.m_hMenu,
								IDM_APP_MAXIMIZE,FALSE,&itemInfo);
						if(!bCanMinimize)
							::SetMenuItemInfo(popMenu.m_hMenu,
								IDM_APP_MINIMIZE,FALSE,&itemInfo);
						if((bCanMaximize && bCanMinimize) ||
							(!bMaximizeBtn && bCanMinimize) || !bSysMenu)
							::SetMenuItemInfo(popMenu.m_hMenu,
								IDM_APP_RESTORE,FALSE,&itemInfo);
					}
					else
					{
						// disable items
						itemInfo.fState=MFS_DISABLED;
						::SetMenuItemInfo(popMenu.m_hMenu,
							IDM_APP_SWITCHTO,FALSE,&itemInfo);
						::SetMenuItemInfo(popMenu.m_hMenu,
							IDM_APP_BRINGTOFRONT,FALSE,&itemInfo);
						::SetMenuItemInfo(popMenu.m_hMenu,
							IDM_APP_MINIMIZE,FALSE,&itemInfo);
						::SetMenuItemInfo(popMenu.m_hMenu,
							IDM_APP_MAXIMIZE,FALSE,&itemInfo);
						::SetMenuItemInfo(popMenu.m_hMenu,
							IDM_APP_RESTORE,FALSE,&itemInfo);
					}
	
					if(m_arrAppInfo[nIndex].dwProcessID==m_process.GetProcessID())
					{
						// disable items
						itemInfo.fState=MFS_DISABLED;
						::SetMenuItemInfo(popMenu.m_hMenu,
							IDM_APP_CLOSE,FALSE,&itemInfo);
					}
					// show menu
					m_tree.ClientToScreen(&point);
					popMenu.GetSubMenu(0)->
						TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,
						point.x, point.y,this);
				}
			}
		}
	}

	*pResult = 0;
}

void CApplicationsDialog::OnAppWndSwitchTo()
{
	ASSERT(m_nCurrentIndex>=0 && m_nCurrentIndex<m_arrAppInfo.GetSize());
	ASSERT(m_arrAppInfo[m_nCurrentIndex].dwProcessID!=m_process.GetProcessID());
	ASSERT(m_arrAppInfo[m_nCurrentIndex].bGotRespond);
	if(m_nCurrentIndex<0 || m_nCurrentIndex>=m_arrAppInfo.GetSize() ||
		!m_arrAppInfo[m_nCurrentIndex].bGotRespond ||
		m_arrAppInfo[m_nCurrentIndex].dwProcessID==m_process.GetProcessID())
		return;

	::SetForegroundWindow(m_arrAppInfo[m_nCurrentIndex].hMainWnd);
	if((::GetWindowLong(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
		GWL_STYLE)&WS_MINIMIZE)==WS_MINIMIZE)
	{
		::SendMessage(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
			WM_SYSCOMMAND,SC_RESTORE,
			(LPARAM)m_arrAppInfo[m_nCurrentIndex].hMainWnd);
	}
}

void CApplicationsDialog::OnAppWndBringToFront()
{
	ASSERT(m_nCurrentIndex>=0 && m_nCurrentIndex<m_arrAppInfo.GetSize());
	ASSERT(m_arrAppInfo[m_nCurrentIndex].dwProcessID!=m_process.GetProcessID());
	ASSERT(m_arrAppInfo[m_nCurrentIndex].bGotRespond);
	if(m_nCurrentIndex<0 || m_nCurrentIndex>=m_arrAppInfo.GetSize() ||
		!m_arrAppInfo[m_nCurrentIndex].bGotRespond ||
		m_arrAppInfo[m_nCurrentIndex].dwProcessID==m_process.GetProcessID())
		return;

	if(::GetWindowLong(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
		GWL_STYLE)&WS_MINIMIZE)
	{
		OnAppWndRestore();
		AfxGetMainWnd()->SetForegroundWindow();
	}
	else
	{
		::SetWindowPos(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
			AfxGetMainWnd()->GetSafeHwnd(),0,0,0,0,
			SWP_SHOWWINDOW|SWP_ASYNCWINDOWPOS|SWP_NOACTIVATE|
			SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
	}
}

void CApplicationsDialog::OnAppWndMinimize()
{
	ASSERT(m_nCurrentIndex>=0 && m_nCurrentIndex<m_arrAppInfo.GetSize());
	ASSERT(m_arrAppInfo[m_nCurrentIndex].bGotRespond);
	if(m_nCurrentIndex<0 || m_nCurrentIndex>=m_arrAppInfo.GetSize() ||
		!m_arrAppInfo[m_nCurrentIndex].bGotRespond)
		return;

	::SendMessage(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
		WM_SYSCOMMAND,SC_MINIMIZE,
		(LPARAM)m_arrAppInfo[m_nCurrentIndex].hMainWnd);
}

void CApplicationsDialog::OnAppWndMaximize()
{
	ASSERT(m_nCurrentIndex>=0 && m_nCurrentIndex<m_arrAppInfo.GetSize());
	ASSERT(m_arrAppInfo[m_nCurrentIndex].bGotRespond);
	if(m_nCurrentIndex<0 || m_nCurrentIndex>=m_arrAppInfo.GetSize() ||
		!m_arrAppInfo[m_nCurrentIndex].bGotRespond)
		return;

	if(::GetWindowLong(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
		GWL_STYLE)&WS_MINIMIZE)
	{
		::SendMessage(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
			WM_SYSCOMMAND,SC_MAXIMIZE,
			(LPARAM)m_arrAppInfo[m_nCurrentIndex].hMainWnd);
		AfxGetMainWnd()->SetForegroundWindow();
	}
	else
	{
		::SendMessage(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
			WM_SYSCOMMAND,SC_MAXIMIZE,
			(LPARAM)m_arrAppInfo[m_nCurrentIndex].hMainWnd);
	}
}

void CApplicationsDialog::OnAppWndRestore()
{
	ASSERT(m_nCurrentIndex>=0 && m_nCurrentIndex<m_arrAppInfo.GetSize());
	ASSERT(m_arrAppInfo[m_nCurrentIndex].bGotRespond);
	if(m_nCurrentIndex<0 || m_nCurrentIndex>=m_arrAppInfo.GetSize() ||
		!m_arrAppInfo[m_nCurrentIndex].bGotRespond)
		return;

	if(::GetWindowLong(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
		GWL_STYLE)&WS_MINIMIZE)
	{
		::SendMessage(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
			WM_SYSCOMMAND,SC_RESTORE,
			(LPARAM)m_arrAppInfo[m_nCurrentIndex].hMainWnd);
		AfxGetMainWnd()->SetForegroundWindow();
	}
	else
	{
		::SendMessage(m_arrAppInfo[m_nCurrentIndex].hMainWnd,
			WM_SYSCOMMAND,SC_RESTORE,
			(LPARAM)m_arrAppInfo[m_nCurrentIndex].hMainWnd);
	}
}

void CApplicationsDialog::OnAppWndClose()
{
	ASSERT(m_nCurrentIndex>=0 && m_nCurrentIndex<m_arrAppInfo.GetSize());
	ASSERT(m_arrAppInfo[m_nCurrentIndex].dwProcessID!=m_process.GetProcessID());
	if(m_nCurrentIndex<0 || m_nCurrentIndex>=m_arrAppInfo.GetSize() ||
		m_arrAppInfo[m_nCurrentIndex].dwProcessID==m_process.GetProcessID())
		return;

	if(m_arrAppInfo[m_nCurrentIndex].bGotRespond)
	{
		::PostMessage(m_arrAppInfo[m_nCurrentIndex].hMainWnd,WM_QUIT,0,0);
		Refresh();
		return;
	}

	HANDLE hProcess=::OpenProcess(PROCESS_TERMINATE,FALSE,
		m_arrAppInfo[m_nCurrentIndex].dwProcessID);
	if(hProcess!=NULL)
	{
		::TerminateProcess(hProcess,FALSE);
		Refresh();
	}

}

void CApplicationsDialog::CleanThreads()
{
	// kill and close all threads
	for(int nIndex=0; nIndex<m_arrThreads.GetSize(); nIndex++)
	{
		HANDLE hThread=m_arrThreads[nIndex];
		DWORD dwExitCode;
		if(::GetExitCodeThread(hThread,&dwExitCode) && dwExitCode==STILL_ACTIVE)
			::TerminateThread(hThread,TRUE);
		::CloseHandle(hThread);
	}
	m_arrThreads.RemoveAll();
}



BOOL CALLBACK CApplicationsDialog::EnumMainWindows(HWND hWnd, LPARAM lParam)
{
	ASSERT(lParam!=NULL);
	CAppInfoArray* parrAppInfo=(CAppInfoArray*)lParam;

	// Window should be not-owned (to exclude dialogs) 
	if(::GetWindow(hWnd,GW_OWNER)==NULL &&
		(::GetWindowLong(hWnd,GWL_EXSTYLE)&WS_EX_TOOLWINDOW)==0 &&
		(::GetWindowLong(hWnd,GWL_STYLE)&WS_VISIBLE)==WS_VISIBLE)
	{
		APPLICATIONINFO appInfo;
		::GetWindowThreadProcessId(hWnd,&appInfo.dwProcessID);
		appInfo.hMainWnd=hWnd;

		// application status
		DWORD dwResult;
		appInfo.bGotRespond=PtrToInt(::SendMessageTimeout(hWnd,WM_NULL,0,0,
			SMTO_ABORTIFHUNG,5000,&dwResult));
		///////////////////

		parrAppInfo->Add(appInfo);
	}
	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 Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions