Click here to Skip to main content
15,886,026 members
Articles / Programming Languages / C++

Debug With Apps Displayed on Secondary Monitor

Rate me:
Please Sign up or sign in to vote.
4.54/5 (20 votes)
29 Nov 20062 min read 58.1K   731   29  
Here's some code that will automatically start your app on a secondary monitor if it's compiled with debug info.
// SecondaryDebug.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "SecondaryDebug.h"
#include "MainFrm.h"

#include "SecondaryDebugDoc.h"
#include "SecondaryDebugView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CSecondaryDebugApp

BEGIN_MESSAGE_MAP(CSecondaryDebugApp, CWinApp)
	ON_COMMAND(ID_APP_ABOUT, &CSecondaryDebugApp::OnAppAbout)
	// Standard file based document commands
	ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
	ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
END_MESSAGE_MAP()


// CSecondaryDebugApp construction

CSecondaryDebugApp::CSecondaryDebugApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}


// The one and only CSecondaryDebugApp object

CSecondaryDebugApp theApp;


// CSecondaryDebugApp initialization

BOOL CSecondaryDebugApp::InitInstance()
{
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);
	CWinApp::InitInstance();
	CSingleDocTemplate* pDocTemplate;
	pDocTemplate = new CSingleDocTemplate(
		IDR_MAINFRAME,
		RUNTIME_CLASS(CSecondaryDebugDoc),
		RUNTIME_CLASS(CMainFrame),       // main SDI frame window
		RUNTIME_CLASS(CSecondaryDebugView));
	if (!pDocTemplate)
		return FALSE;
	AddDocTemplate(pDocTemplate);
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);
	if (!ProcessShellCommand(cmdInfo))
	{
		return FALSE;
	}

	// The one and only window has been initialized, so show and update it


	////////////////////////////////////////////////////////////////////////////////
	// Our code starts
	////////////////////////////////////////////////////////////////////////////////

	// The object of this code is to cause the application to display on the 
	// first secondary monitor we find, but only if we're in _DEBUG mode. If 
	// we're nbot in debug mode, the app will display maximized on the 
	// primary monitor.
#ifdef _DEBUG
	UseSecondaryMonitor();

	// if we don't have a secondary monitor, go ahead and maximize the window
	if (m_secondaryRect.Width() + m_secondaryRect.Height() == 0)
	{
		m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
	}
	else
	// otherwise, use the rectange we got from UseSecondaryMonitor()
	{
		m_pMainWnd->MoveWindow(m_secondaryRect, TRUE);
	}
#else
	// The one and only window has been initialized, so show and update it.
	m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
#endif

	////////////////////////////////////////////////////////////////////////////////
	// Our code ends - our special functions are found at the end of this file.
	////////////////////////////////////////////////////////////////////////////////

	m_pMainWnd->UpdateWindow();
	return TRUE;
}



// CAboutDlg dialog used for App About

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

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

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

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()

// App command to run the dialog
void CSecondaryDebugApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}


// CSecondaryDebugApp message handlers

////////////////////////////////////////////////////////////////////////////////
// make the app display on the secondary monitor if we're in debug mode
///////////////////////////////////////////////////////////////////////////////

// a global CRect variable to hold the rectangle found by the callback function
CRect secondaryRect(0,0,0,0);

//------------------------------------------------------------------------------
// This callback function is called by EnumDisplayMonitors, and this is where 
// we snatch our secondary monitor rectangle.
//------------------------------------------------------------------------------
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor,  // handle to display monitor
                              HDC hdc1,           // handle to monitor DC
                              LPRECT lprcMonitor, // monitor intersection rectangle
                              LPARAM data)        // data
{
    RECT rc = *lprcMonitor;

	MONITORINFOEX mInfo;
	mInfo.cbSize = sizeof(mInfo);
	::GetMonitorInfo(hMonitor, &mInfo);

	if (mInfo.dwFlags != MONITORINFOF_PRIMARY)
	{
		// for purposes of example we always take the first secondary monitor 
		// we find.  I leave it as an exercise for the programmer to change 
		// the code to support multiple secondary displays (and therefore 
		// pick the desired monitor
		secondaryRect = mInfo.rcWork;
		// return 0 to stop the enumeration
		return 0;
	}
	// if we get here, the current monitor isn't a secondary monitor
    return 1;
}

//------------------------------------------------------------------------------
// This is the function we call to enumerate through all monitors attached to 
// the system.
//------------------------------------------------------------------------------
void CSecondaryDebugApp::UseSecondaryMonitor() 
{
	// init the memebr rectangle
	m_secondaryRect.SetRect(0,0,0,0);
	// enumerate
	::EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, 0);
	// store the secondary monitor's rectangle in our member rectangle
	m_secondaryRect = secondaryRect;
	// at this point, we are ready to display the application's window
}

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) Paddedwall Software
United States United States
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.

My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.

Comments and Discussions