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

Window Unhidder

Rate me:
Please Sign up or sign in to vote.
4.69/5 (15 votes)
14 Feb 20061 min read 39.7K   1.5K   40  
A utility to list and hide/unhide all application windows.
// WindowUnhidderDlg.cpp : implementation file
//

#include "stdafx.h"
#include "WindowUnhidder.h"
#include "WindowUnhidderDlg.h"

#include "hyperlink.h"
#include <sstream>

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

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	CHyperLink	m_www2;
	CHyperLink	m_www;
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	DDX_Control(pDX, IDC_STATIC_WWW2, m_www2);
	DDX_Control(pDX, IDC_STATIC_WWW, m_www);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWindowUnhidderDlg dialog
int HandleComp(CString s1, CString s2)
{
	char* stop;
	s1 = "0X" + s1.Mid(1);
	long i1 = strtol(s1,&stop,16);
	s2 = "0X" + s2.Mid(1);
	long i2 = strtol(s2,&stop,16);
	if(i1==i2)return 0;
	if(i1<i2) return -1;
	return 1;

}


CWindowUnhidderDlg::CWindowUnhidderDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CWindowUnhidderDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CWindowUnhidderDlg)
	m_WindowsFound = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	if(!LoadLibrary( _T("PSAPI.DLL") ))
		MessageBox("PSAPI.DLL not found. Processes names will not be shown",
				"WindowsUnhidder Warning",MB_ICONWARNING);
}

void CWindowUnhidderDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CWindowUnhidderDlg)
	DDX_Control(pDX, IDC_CHECK_PARENT_HANDLER, m_ParentHandler);
	DDX_Control(pDX, IDC_CHECK_FULLPATH, m_FullPath);
	DDX_Control(pDX, IDC_PROCESS, m_Process);
	DDX_Control(pDX, IDC_PID, m_PID);
	DDX_Control(pDX, IDOK, m_ExitButton);
	DDX_Control(pDX, IDC_REFRESH, m_RefreshButton);
	DDX_Control(pDX, IDC_PARENT, m_Padre);
	DDX_Control(pDX, IDC_VISIBLE, m_Visible);
	DDX_Control(pDX, IDC_ENABLED, m_Enabled);
	DDX_Control(pDX, IDC_TITLE, m_Title);
	DDX_Control(pDX, IDC_CLASS, m_Class);
	DDX_Control(pDX, IDC_HANDLE, m_Handle);
	DDX_Control(pDX, IDC_LIST, m_List);
	DDX_Text(pDX, IDC_STATIC_FOUND, m_WindowsFound);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CWindowUnhidderDlg, CDialog)
	//{{AFX_MSG_MAP(CWindowUnhidderDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
	ON_BN_CLICKED(IDC_VISIBLE, OnVisible)
	ON_BN_CLICKED(IDC_ENABLED, OnEnabled)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, OnItemchangedList)
	ON_WM_SIZE()
	ON_NOTIFY(NM_DBLCLK, IDC_LIST, OnDblclkList)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWindowUnhidderDlg message handlers

BOOL CWindowUnhidderDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	m_mWnd = NULL;

	int col=0;
	m_List.AddColumn("Handle",	col++,70); m_List.SetColumnSortCallback(col-1,HandleComp);
	m_List.AddColumn("PID",		col++,40,LVCFMT_RIGHT); m_List.SetColumnSortCallback(col-1,IntComp);
	m_List.AddColumn("Process",	col++,100);
	m_List.AddColumn("Visible",	col++,25);
	m_List.AddColumn("Enabled",	col++,25);
	m_List.AddColumn("Title",	col++,200);
	m_List.AddColumn("Class",	col++,100);
	m_List.AddColumn("Parent",	col++,150);

	CRect rlist,r;
	m_List.GetWindowRect(rlist);
	GetWindowRect(r);
	ScreenToClient(r);
	ScreenToClient(rlist);
	m_margin = r.Width() - rlist.left - rlist.Width();

	OnRefresh();
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CWindowUnhidderDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CWindowUnhidderDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CWindowUnhidderDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}




void CWindowUnhidderDlg::OnRefresh() 
{
	m_List.DelAll();

	// search windows:
	char title[512], titlepadre[512], clase[100];
	HWND mWnd = NULL;
	HWND mWndPad = NULL;
	HWND mWndSys = NULL;
	mWnd = ::FindWindowEx(NULL,mWnd,NULL,NULL);

	int ii=0;
	while ( mWnd )
	{
		::GetWindowText(mWnd, title, 256);
		::GetClassName(mWnd, clase, 100);
		CString vis = ::IsWindowVisible(mWnd)?'1':'0';
		CString ena = ::IsWindowEnabled(mWnd)?'1':'0';

		CString Cadena = "";
		mWndPad = mWnd;
		CString TitPad = "";
		memset(titlepadre,0,512);
		do
		{
			mWndPad = ::GetParent(mWndPad);
			if (mWndPad)
				if(m_ParentHandler.GetCheck()!=0)
					sprintf(titlepadre,"#%X",mWndPad);
				else
					::GetWindowText(mWndPad, titlepadre, 256);
			TitPad = titlepadre;
			TitPad.TrimRight();
			Cadena = CString(mWndPad?CString((TitPad=="")?"[no title]":TitPad):"[Desktop]") + CString(" :: ") + Cadena;
		}
		while (mWndPad);

		
		CString Tit = title;
		if(Tit=="")Tit="[no title]";
		
		DWORD wd=0;
		GetWindowThreadProcessId(mWnd,&wd);
		stringstream ss,ssw;
		ss<<wd;
		CString proc;
		bool full = m_FullPath.GetCheck() != 0;
		proc = GetProcessName(wd,full);

		int col=0;
		ssw<<"#"<<uppercase<<hex<<(int)mWnd;
		m_List.AddItem(ii,col++,ssw.str());
		m_List.AddItem(ii,col++,ss.str());
		m_List.AddItem(ii,col++,proc);
		m_List.AddItem(ii,col++,vis);
		m_List.AddItem(ii,col++,ena);
		m_List.AddItem(ii,col++,Tit);
		m_List.AddItem(ii,col++,clase);
		m_List.AddItem(ii,col++,Cadena);
		m_List.SetItemData(ii,DWORD(mWnd));

		ii++;

		mWnd = ::GetNextWindow(mWnd,GW_HWNDNEXT);
	}

	// selecto all the row
	m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT);

	ostringstream ss;
	ss<<"Windows found ("<<ii<<"):";
	m_WindowsFound = ss.str().c_str();
	ss.str("");
	ClearData();
	UpdateData(FALSE);


}

void CWindowUnhidderDlg::OnVisible() 
{
	::ShowWindow(m_mWnd,m_Visible.GetCheck()?SW_SHOW:SW_HIDE);
	m_List.SetFocus();
}

void CWindowUnhidderDlg::OnEnabled() 
{
	::EnableWindow(m_mWnd,m_Enabled.GetCheck()==1);
	m_List.SetFocus();
}

CString CWindowUnhidderDlg::GetProcessName(int processID, bool fullpath /*=false*/)
{
 typedef DWORD (WINAPI *PEnumProcesses)( DWORD*, \
                                         UINT, \
                                         DWORD* );

 typedef DWORD (WINAPI *PEnumProcessModules)( HANDLE, \
                                              HMODULE*, \
                                              UINT, \
                                              DWORD* );

 typedef DWORD (WINAPI *PGetModuleBaseName)( HANDLE, \
                                             HMODULE, \
                                             LPTSTR, \
                                             UINT );

  typedef DWORD (WINAPI *PGetModuleFileNameEx)( HANDLE, \
                                             HMODULE, \
                                             LPTSTR, \
                                             UINT );

 _TCHAR   szProcessName[MAX_PATH] = _T("unknown");
 int result = -1;


 HINSTANCE hPsApi = LoadLibrary( _T("PSAPI.DLL") );

 if ( hPsApi == NULL )
  return result;

 PEnumProcessModules EnumProcessModules =
 (PEnumProcessModules)GetProcAddress( hPsApi,
                                      "EnumProcessModules" );

#ifdef UNICODE
 PGetModuleBaseName GetModuleBaseName =
 (PGetModuleBaseName)GetProcAddress( hPsApi,
                                     "GetModuleBaseNameW" );
 PGetModuleFileNameEx GetModuleFileNameEx =
 (PGetModuleFileNameEx)GetProcAddress( hPsApi,
                                     "GetModuleFileNameExW" );
#else
 PGetModuleBaseName GetModuleBaseName =
 (PGetModuleBaseName)GetProcAddress( hPsApi,
                                     "GetModuleBaseNameA" );
 PGetModuleFileNameEx GetModuleFileNameEx =
 (PGetModuleFileNameEx)GetProcAddress( hPsApi,
                                     "GetModuleFileNameExA" );
#endif

    // Get a handle to the process.

    HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
                                   PROCESS_VM_READ,
                                   FALSE, processID );
    // Get the process name.
    if ( hProcess )
    {
        HMODULE hMod;
        DWORD cbNeeded;

        if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), 
             &cbNeeded) )
        {
			if(!fullpath)
            GetModuleBaseName( hProcess, hMod, szProcessName, 
                               sizeof(szProcessName) );
			else
			GetModuleFileNameEx(hProcess, hMod, szProcessName, 
                               sizeof(szProcessName) );
        }
		
		CloseHandle( hProcess );
    }
	
	FreeLibrary(hPsApi);
	CString str(szProcessName);
	return str;
}

void CWindowUnhidderDlg::OnItemchangedList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	
	*pResult = 0;

	//only check new selections
	if(pNMListView->uNewState == 0) return;
	
	ClearData();

	int pos = pNMListView->iItem;
	if (pos<0) return;

	m_mWnd = HWND(pNMListView->lParam);

 	char buff[512];
	if(!::IsWindow(m_mWnd))
	{
 		sprintf(buff,"#%X",m_mWnd);
 		m_Handle.SetWindowText(buff);

		MessageBox("Selected window does not exist. Refresh the list",
			"WindowUnhidder Warning",MB_ICONWARNING);
		return;
	}

 	// selected window properties
 	/////////////////////////////////////////////
 
 	sprintf(buff,"#%X",m_mWnd);
 	m_Handle.SetWindowText(buff);
 
 	::GetWindowText(m_mWnd, buff, 256);
 	m_Title.SetWindowText(buff);
 
 	::GetClassName(m_mWnd, buff, 100);
 	m_Class.SetWindowText(buff);
 
 	HWND mWndPad = ::GetParent(m_mWnd);
 	if (mWndPad)
 	{
		if(m_ParentHandler.GetCheck()!=0)
			sprintf(buff,"#%X",mWndPad);
		else
	 		::GetWindowText(mWndPad, buff, 256);
 		m_Padre.SetWindowText(buff);
 	}
 	else m_Padre.SetWindowText("[Desktop]");

	DWORD wd;
	GetWindowThreadProcessId(m_mWnd,&wd);
	char ch[8];
	sprintf(ch,"%d",wd);
	CString proc;
	bool full = m_FullPath.GetCheck() != 0;
	proc = GetProcessName(wd,full);

	m_PID.SetWindowText(ch);
	m_Process.SetWindowText(proc);

 
 	m_Visible.SetCheck(::IsWindowVisible(m_mWnd)?1:0);
 	m_Enabled.SetCheck(::IsWindowEnabled(m_mWnd)?1:0);	

	if(m_hWnd == m_mWnd)
	{
		m_Visible.EnableWindow(FALSE);
		m_Enabled.EnableWindow(FALSE);
	}
	else
	{
		m_Visible.EnableWindow(TRUE);
		m_Enabled.EnableWindow(TRUE);
	}

	*pResult = 0;
}


void CWindowUnhidderDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);

	if(!m_List) return;
	// TODO: Add your message handler code here
	CRect rlist,r;
	m_List.GetWindowRect(rlist);
	GetWindowRect(r);
	ScreenToClient(r);
	ScreenToClient(rlist);
	int lx = r.right - rlist.left - m_margin;
	int ly = r.bottom - rlist.top - m_margin;
	m_List.SetWindowPos(&wndTop,0,0,lx,ly,SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
	
	CRect rbutton;
	m_ExitButton.GetWindowRect(rbutton);
	ScreenToClient(rbutton);
	int px = rbutton.left;
	int py = r.bottom - rbutton.Height() - m_margin;
	m_ExitButton.SetWindowPos(&wndTop,px,py,0,0,SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);

	m_RefreshButton.GetWindowRect(rbutton);
	ScreenToClient(rbutton);
	px = rbutton.left;
	py = r.bottom - rbutton.Height() - m_margin;
	m_RefreshButton.SetWindowPos(&wndTop,px,py,0,0,SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
}

void CWindowUnhidderDlg::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	POSITION posit = m_List.GetFirstSelectedItemPosition( ) ;
	if(!posit) return;
	int pos = m_List.GetNextSelectedItem(posit) ;

	HWND mWnd = HWND(m_List.GetItemData(pos));
 	HWND mWndPad = ::GetParent(mWnd);
	if(!mWndPad) return;
	SelectParam(mWndPad);
	
	*pResult = 0;
}

void CWindowUnhidderDlg::SelectParam(HWND param)
{
	if(!param) return;
	LVFINDINFO FindInfo;
	FindInfo.flags = LVFI_PARAM;
	FindInfo.lParam = (LPARAM) param;
	
	int item = m_List.FindItem(&FindInfo);

    m_List.SetItem( item,0,LVIF_STATE,NULL,0,LVNI_SELECTED | LVNI_FOCUSED,LVNI_SELECTED | LVNI_FOCUSED,NULL); 

}

void CWindowUnhidderDlg::ClearData()
{
	m_Handle.SetWindowText("");
	m_Title.SetWindowText("");
	m_Class.SetWindowText("");
	m_Padre.SetWindowText("");
	m_PID.SetWindowText("");
	m_Process.SetWindowText("");
	m_Visible.SetCheck(0);
	m_Enabled.SetCheck(0);
	m_Visible.EnableWindow(FALSE);
	m_Enabled.EnableWindow(FALSE);

}

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Spain Spain
Javier Jimenez Shaw. Born in Madrid in 1975. Civil engineer, is working developing financial algorithms for exotic products.

Comments and Discussions