Click here to Skip to main content
15,892,737 members
Articles / Desktop Programming / MFC

Build Manager AddIn [VC 6.0]

Rate me:
Please Sign up or sign in to vote.
4.00/5 (3 votes)
27 Jul 20032 min read 60.4K   1.1K   27  
Enhancement of the AutoBld sample AddIn
//***************************************************************************
//*
//*	File:			DialogBuild.cpp
//*	Description:	Dialog for executing builds
//*
//***************************************************************************

//
//--------------------------------------------------------------- PRECOMPILED
//

#include "stdafx.h"

//
//--------------------------------------------------- DECLARATION DEPENDENCIES
//

#include "BuildMgr2.h"

//
//--------------------------------------------------------------- DECLARATION
//

#include "DialogBuild.h"

//
//--------------------------------------------------- DEFINITION DEPENDENCIES
//

#include "DialogProgress.h"

//
//-------------------------------------------------------------- PREPROCESSOR
//

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

#pragma	warning ( disable : 4239 )	//	passing CString to CArray< CString, CString& >

//
//---------------------------------------------------------------- DEFINITION
//

static CDialogProgress* g_pdlgProgress = NULL;

//
//---------------------------------------------------------------------------------------------------
//*************************************     CON/DESTRUCTION     *************************************
//---------------------------------------------------------------------------------------------------
//

//***************************************************************************************************
//**																					  Constructor	  
//***************************************************************************************************
//**	@DOC		CONSTRUCTION
//**	@MFUNC		Default constructor
//**	@PARM		[in|opt] Pointer to parent window
//**	@END
//***************************************************************************************************
//inline
CDialogBuild::CDialogBuild(CWnd* pParent /*=NULL*/)
	: CDialog(CDialogBuild::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDialogBuild)
	m_iMode						= 1						;
	//}}AFX_DATA_INIT

	this->m_pIApplication		= NULL					;
	this->m_enuFinishAction		= EFinishAction_Continue;
}

//
//---------------------------------------------------------------------------------------------------
//*****************************************     GET/SET     *****************************************
//---------------------------------------------------------------------------------------------------
//

//***************************************************************************************************
//**																				   SetApplication
//***************************************************************************************************
//**	@DOC		SET
//**	@MFUNC		Sets the pointer to the application's interface
//**	@PARM		[in] Pointer to application's interface
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::SetApplication( IApplication *a_pIApplication )
{
	this->m_pIApplication = a_pIApplication;
}

//
//---------------------------------------------------------------------------------------------------
//***************************************     PERSISTENCE     ***************************************
//---------------------------------------------------------------------------------------------------
//

//***************************************************************************************************
//**																					  LoadProfile 
//***************************************************************************************************
//**	@DOC		PERSISTENCE
//**	@MFUNC		Loads the dialog's settings from the registry
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::LoadProfile( void )
{
	//
	//	CLEAR LIST CONTROL
	//
	this->m_ctrlListConfigurations.DeleteAllItems();

	//
	//	SETUP VARS
	//
	CString strWorkspacePath	;
	CString strWorkspaceName	;
	CString strProjectPath		;
	CString strProjectName		;
	CString	strConfigurations	;
	CString strSection			;
	UINT	iProjects			= 0;
	UINT	iStyle				= 0;
	DWORD	dwCount				= 0;

	///
	//	GET APP
	//
	CWinApp* pApplication =	::AfxGetApp();

	//
	//	GET SECTION KEY
	//
	CRegKey	keySection;	
			keySection.Attach( pApplication->GetSectionKey( _T( "Configure" ) ) );

	//
	//	READ PROJECT COUNT
	//
	iProjects = pApplication->GetProfileInt( _T( "Configure" ), _T( "NumProjects" ), 0 );

	//
	//	READ PROJECTS
	//
	for ( UINT iProject = 0; iProject < iProjects; iProject++ )
	{
		//
		//	SETUP SECTION
		//
		strSection.Format( "Project.%04d", iProject );

		//
		//	GET SUB KEY
		//
		CRegKey keyProject	;
				keyProject.Open( keySection, strSection );

		//
		//	READ PROJECT
		//
		dwCount = _MAX_PATH; keyProject.QueryValue( strProjectName		.GetBuffer( _MAX_PATH )	, _T( "0.Project.Name"		), &dwCount );	
		dwCount = _MAX_PATH; keyProject.QueryValue( strProjectPath		.GetBuffer( _MAX_PATH )	, _T( "1.Project.Path"		), &dwCount );	
		dwCount = _MAX_PATH; keyProject.QueryValue( strWorkspaceName	.GetBuffer( _MAX_PATH )	, _T( "2.Workspace.Name"	), &dwCount );	
		dwCount = _MAX_PATH; keyProject.QueryValue( strWorkspacePath	.GetBuffer( _MAX_PATH )	, _T( "3.Workspace.Path"	), &dwCount );	
		dwCount = _MAX_PATH; keyProject.QueryValue( strConfigurations	.GetBuffer( _MAX_PATH )	, _T( "4.Configurations"	), &dwCount );	
		dwCount = _MAX_PATH; keyProject.QueryValue( (DWORD&) iStyle								, _T( "5.Style"				) ); 

		strProjectName		.ReleaseBuffer();
		strProjectPath		.ReleaseBuffer();
		strWorkspaceName	.ReleaseBuffer();
		strWorkspacePath	.ReleaseBuffer();
		strConfigurations	.ReleaseBuffer();
		
		//
		//	CLOSE THE KEY
		//
		keyProject.Close();

		//
		//	ADD CONFIGURATIONS
		//
		this->AddProject( strProjectName, strProjectPath, strWorkspaceName, strWorkspacePath, strConfigurations, iStyle );
	}
}

//***************************************************************************************************
//**																					 WriteProfile 
//***************************************************************************************************
//**	@DOC		PERSISTENCE
//**	@MFUNC		Saves the dialog's settings to the registry
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::WriteProfile( void ) const
{
}

//
//---------------------------------------------------------------------------------------------------
//****************************************     EXECUTION     ****************************************
//---------------------------------------------------------------------------------------------------
//

//***************************************************************************************************
//**																						  Execute
//***************************************************************************************************
//**	@DOC		EXECUTION
//**	@MFUNC		Executes the selected configurations' build process.
//**	@RDESC		<t TRUE> if successful, <t FALSE> otherwise.
//**	@END
//***************************************************************************************************
//inline
BOOL CDialogBuild::Execute( void )
{
	//
	//	CREATE PROGRESS DIALOG
	//
	CDialogProgress dlgProgress( this );
	dlgProgress.Create( IDD_PROGRESS, this );
	dlgProgress.SetApplication( this->m_pIApplication );

	//
	//	This is a bit of a hack:
	//
	//		Store a pointer to the progress dialog for routing
	//		incoming BuildFinished events through to it
	//
	::g_pdlgProgress = &dlgProgress;

	//
	//	SHOW PROGRESS DIALOG
	//
	dlgProgress.ShowWindow( SW_SHOW );

	//
	//	SETUP RESULT
	//
	BOOL bResult = TRUE;

	//
	//	FOR EACH ACTIVE CONFIGURATION
	//
	int iBuilt = 0;

	for ( int iItem = 0; iItem < this->m_ctrlListConfigurations.GetItemCount(); iItem++ )
	{
		//
		//	CHECK WHETHER THIS CONFIGURATION IS ENABLED
		//
		if ( TRUE == this->m_ctrlListConfigurations.GetCheck( iItem ) )
		{
			//
			//	EXECUTE ALL ACTIVE PROJECTS CONTAINING THIS CONFIGURATION
			//
			bResult &= dlgProgress.Execute( this->m_ctrlListConfigurations.GetItemText( iItem, 0 ), static_cast< CDialogProgress::EBuildMode > (this->m_iMode) );

			//
			//	INCREMENT NUMBER OF BUILT CONFIGURATIONS
			//
			++iBuilt;
		}
	}

	//
	//	Stop routing events to the progress dialog
	//
	::g_pdlgProgress = NULL;

	//
	//	HIDE PROGRESS DIALOG
	//
	dlgProgress.ShowWindow( SW_HIDE );

	//
	//	CHECK NUMBER OF BUILT CONFIGURATIONS
	//
	if ( 0 == iBuilt )
	{
		this->MessageBox( "No projects have been built. Skipping shutdown mode evaluation.", "Information", MB_ICONINFORMATION );

		return bResult;
	}

	//
	//	SET FINISH MODE
	//
	this->m_enuFinishAction	= static_cast< EFinishAction > (dlgProgress.m_iFinishedAction);

	//
	//	RETURN RESULT
	//
	return bResult;
}

//
//---------------------------------------------------------------------------------------------------
//*****************************************     HELPERS     *****************************************
//---------------------------------------------------------------------------------------------------
//

//***************************************************************************************************
//**																					   AddProject
//***************************************************************************************************
//**	@DOC		HELPERS
//**	@MFUNC		Adds the specified project to the dialog
//**	@PARM		[in] The project's name
//**	@PARM		[in] The project's path
//**	@PARM		[in] The workspace's name
//**	@PARM		[in] The workspace's path
//**	@PARM		[in] The project's style flags
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::AddProject( const CString& a_strProjectName, const CString& a_strProjectPath, const CString& a_strWorkspaceName, const CString& a_strWorkspacePath, const CString& a_strConfigurations, int a_iStyle )
{
	//
	//	SPLIT CONFIGURATIONS
	//
	CArray< CString, CString& >	arrConfigurations;
	CString						strConfigurations( a_strConfigurations );
	CString						strConfiguration ;

	int iPos = strConfigurations.Find( ';' );

	while ( iPos >= 0 )
	{
		//
		//	ADD CONFIGURATION
		//
		arrConfigurations.Add( strConfigurations.Left( iPos ) );

		//
		//	REMOVE CONFIGURATION
		//
		strConfigurations = strConfigurations.Right( strConfigurations.GetLength() - iPos - 1 );

		//
		//	FIND NEXT CONFIGURATION
		//
		iPos = strConfigurations.Find( ';' );
	}

	if ( ! strConfigurations.IsEmpty() )
	{
		arrConfigurations.Add( strConfigurations );
	}

	//
	//	ADD MISSING CONFIGURATIONS TO THE LIST CONTROL [i know, this can be optimized]
	//
	for ( int iConfiguration = 0; iConfiguration < arrConfigurations.GetSize(); iConfiguration++ )
	{
		//
		//	SETUP SKIP INDICATOR
		//
		bool bSkip = false;

		//
		//	CHECK EACH ITEM
		//
		for ( int iItem = 0; iItem < this->m_ctrlListConfigurations.GetItemCount(); iItem++ )
		{
			strConfiguration = this->m_ctrlListConfigurations.GetItemText( iItem, 0 );

			if ( strConfiguration == arrConfigurations[ iConfiguration ] )
			{
				bSkip = true;	// skip this configuration
				break;			// stop searching
			}
		}

		//
		//	CHECK FOR SKIP
		//
		if ( true == bSkip )
		{
			continue;
		}

		//
		//	OK, ADD THE CONFIGURATION
		//
		this->m_ctrlListConfigurations.InsertItem( 0, arrConfigurations[ iConfiguration ], 0 );
	}	
}

//***************************************************************************************************
//**																						 MoveItem
//***************************************************************************************************
//**	@DOC		HELPERS
//**	@PARM		Swaps the contents of the items at the specified positions
//**	@PARM		[in] Source item's index
//**	@PARM		[in] Destination item's index
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::MoveItem( int a_iSrc, int a_iDst )
{
	//
	//	CHECK VALIDITY
	//
	if ( a_iSrc <  0											 )	return;
	if ( a_iDst <  0											 )	return;
	if ( a_iSrc >= this->m_ctrlListConfigurations.GetItemCount() )	return;
	if ( a_iDst >= this->m_ctrlListConfigurations.GetItemCount() )	return;

	//
	//	SETUP VARS
	//
	CString	strSwap	 ;
	CString	strTemp	 ;
	int		iSubItem = 0;

	//
	//	SWAP TEXTs
	//
	for ( iSubItem = 0; iSubItem < 1; iSubItem++ )
	{
		//
		//	STORE DESTINATION IN SWAP MEM
		//
		strSwap = this->m_ctrlListConfigurations.GetItemText( a_iDst, iSubItem );

		//
		//	COPY SOURCE TO DESTINATION
		//
		strTemp = this->m_ctrlListConfigurations.GetItemText( a_iSrc, iSubItem );
				  this->m_ctrlListConfigurations.SetItemText( a_iDst, iSubItem, strTemp.GetBuffer( _MAX_PATH ) );

		strTemp.ReleaseBuffer();

		//
		//	COPY SWAP TO SOURCE
		//
		this->m_ctrlListConfigurations.SetItemText( a_iSrc, iSubItem, strSwap.GetBuffer( _MAX_PATH ) );

		strSwap.ReleaseBuffer();
	}

	//
	//	SWAP ITEM STATES
	//
	UINT uiSrc = this->m_ctrlListConfigurations.GetItemState( a_iSrc, (UINT) -1 );
	UINT uiDst = this->m_ctrlListConfigurations.GetItemState( a_iDst, (UINT) -1 );

	this->m_ctrlListConfigurations.SetItemState( a_iSrc, uiDst, (UINT) -1 );
	this->m_ctrlListConfigurations.SetItemState( a_iDst, uiSrc, (UINT) -1 );
}

//
//---------------------------------------------------------------------------------------------------
//****************************************     VIRTUALS     *****************************************
//---------------------------------------------------------------------------------------------------
//

//***************************************************************************************************
//**																				   DoDataExchange
//***************************************************************************************************
//**	@DOC		VIRTUALS
//**	@MFUNC		Exchanges data between the dialog's members and its controls
//**	@PARM		[in/out] Pointer to data exchange context
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange( pDX );

	//{{AFX_DATA_MAP(CDialogBuild)
	DDX_Control( pDX, IDC_CONFIGURATIONS, m_ctrlListConfigurations	);
	DDX_CBIndex( pDX, IDC_BUILD			, m_iMode					);
	//}}AFX_DATA_MAP
}

//
//---------------------------------------------------------------------------------------------------
//****************************************     MESSAGES     *****************************************
//---------------------------------------------------------------------------------------------------
//

BEGIN_MESSAGE_MAP( CDialogBuild, CDialog )
	//{{AFX_MSG_MAP(CDialogBuild)
	ON_BN_CLICKED	(				IDC_MOVE_UP			, OnMoveUp				)
	ON_BN_CLICKED	(				IDC_MOVE_DOWN		, OnMoveDown			)
	ON_NOTIFY		( NM_CLICK	,	IDC_CONFIGURATIONS	, OnClickConfigurations	)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//***************************************************************************************************
//**																					 OnInitDialog
//***************************************************************************************************
//**	@DOC		MESSAGES
//**	@MFUNC		Called to initialize the dialog
//**	@END
//***************************************************************************************************
//inline
BOOL CDialogBuild::OnInitDialog() 
{
	//
	//	CALL BASE CLASS' IMPLEMENTATION
	//
	CDialog::OnInitDialog();

	//
	//	MODIFY LIST CONTROL
	//
	this->m_ctrlListConfigurations.InsertColumn( 0, _T( "Configuration" ), LVCFMT_LEFT, 250, 0 );
	this->m_ctrlListConfigurations.SetExtendedStyle( LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES );

	//
	//	READ PROFILE
	//
	this->LoadProfile();

	//
	//	ENABLE AUTO-FOCUS
	//
	return TRUE;  
}

//***************************************************************************************************
//**																							 OnOK
//***************************************************************************************************
//**	@DOC		MESSAGES
//**	@MFUNC		Called when OK button is clicked
//**	@COMM		Executes the current settings, writes the profile and closes the dialog
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::OnOK() 
{
	//
	//	EXECUTE
	//
	this->Execute();												

	//
	//	WRITE PROFILE
	//
	this->WriteProfile();

	//
	//	CALL BASE CLASS' IMPLEMENTATION
	//
	CDialog::OnOK();
}

//***************************************************************************************************
//**																						 OnMoveUp
//***************************************************************************************************
//**	@DOC		MESSAGES
//**	@MFUNC		Called when the MoveUp button is pressed
//**	@COMM		Moves all selected items one place up while taking care of boundaries.
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::OnMoveUp() 
{
	//
	//	SETUP VARS
	//
	int	iPredecessor = 0;
	int	iItem		 = 0;

	//
	//	ENUMERATE SELECTED ITEMS
	//
	POSITION pos = this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();

	while ( NULL != pos )
	{
		//
		//	GET NEXT SELECTED ITEM'S INDEX
		//
		iItem = this->m_ctrlListConfigurations.GetNextSelectedItem( pos );

		//
		//	CHECK WHETHER WE CAN MOVE THAT ITEM
		//
		if ( iItem > iPredecessor )
		{
			//
			//	MOVE THAT ITEM
			//
			this->MoveItem( iItem, iItem - 1 );

			//
			//	KEEP ANY FOLLOWING ITEM FROM REPLACING THIS ITEM
			//
			iPredecessor = iItem;
		}
		else
		{
			//
			//	THIS ITEM COULD NOT BE MOVED
			//
			++iPredecessor;
		}
	}

	//
	//	ENSURE THAT OUR SELECTION IS VISIBLE
	//
	pos = this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();

	if ( NULL != pos )
	{
		//
		//	GET FIRST SELECTED ITEM'S POSITION
		//
		iItem = this->m_ctrlListConfigurations.GetNextSelectedItem( pos );

		//
		//	ENSURE THAT ITEMS's VISIBILITY
		//
		this->m_ctrlListConfigurations.EnsureVisible( iItem, FALSE );
	}

	//
	//	SET THE FOCUS BACK TO THE LIST CONTROL (neccessary in order to have the control re-display its selection)
	//
	this->m_ctrlListConfigurations.SetFocus();
}

//***************************************************************************************************
//**																					   OnMoveDown
//***************************************************************************************************
//**	@DOC		MESSAGES
//**	@MFUNC		Called when the MoveDown button is pressed
//**	@COMM		Moves all selected items one place down while taking care of boundaries.
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::OnMoveDown() 
{
	//
	//	GATHER SELECTED INDICES (for we must process them in reverse order)
	//
	CArray< int, int >	arrSelected	;
	POSITION			pos			= this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();

	if ( NULL == pos )
	{
		return;	// avoid messing around with GetUpperBound()
	}

	while ( NULL != pos )
	{
		//
		//	GET NEXT SELECTED ITEM'S INDEX
		//
		arrSelected.Add( this->m_ctrlListConfigurations.GetNextSelectedItem( pos ) );
	}

	//
	//	NOW, PROCESS THE ITEMS
	//
	int iSuccessor  = this->m_ctrlListConfigurations.GetItemCount() - 1;
	int iItem		= iSuccessor;
	int iSelected	= 0;

	for ( iSelected = arrSelected.GetUpperBound(); iSelected >= 0; iSelected-- )
	{
		//
		//	GET ITEM INDEX
		//
		iItem = arrSelected[ iSelected ];

		//
		//	CHECK WHETHER WE CAN MOVE THE ITEM
		//
		if ( iItem < iSuccessor )
		{
			//
			//	MOVE THAT ITEM
			//
			this->MoveItem( iItem, iItem + 1 );

			//
			//	PREVENT THAT ITEM FROM BEING OVERRIDEEN
			//
			iSuccessor = iItem;
		}
		else
		{
			//
			//	COULD NOT MOVE THAT ITEM
			//
			--iSuccessor;
		}
	}

	//
	//	ENSURE THAT OUR SELECTION IS VISIBLE
	//
	pos	= this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();

	while ( NULL != pos )
	{
		//
		//	GET LAST SELECTED ITEM'S POSITION
		//
		iItem = this->m_ctrlListConfigurations.GetNextSelectedItem( pos );
	}

	//
	//	ENSURE THAT ITEMS's VISIBILITY
	//
	this->m_ctrlListConfigurations.EnsureVisible( iItem, FALSE );

	//
	//	SET THE FOCUS BACK TO THE LIST CONTROL (neccessary in order to have the control re-display its selection)
	//
	this->m_ctrlListConfigurations.SetFocus();
}

//***************************************************************************************************
//**																			OnClickConfigurations				  
//***************************************************************************************************
//**	@DOC		MESSAGES
//**	@MFUNC		Called when the user clicks within the configurations' list control
//**	@COMM		Assures that when the user (un-)checks a selected item, all other selected items
//**				will have the same check state.
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::OnClickConfigurations( NMHDR* pNMHDR, LRESULT* pResult ) 
{
	//
	//	GET LIST VIEW NOTIFICATION HEADER
	//
	NMLISTVIEW* pNMListView = reinterpret_cast< NMLISTVIEW* > (pNMHDR);

	//
	//	WE'RE ONLY INTERESTED IN CLICKS ON A SELECTED ITEM'S CHECK BOX
	//
	if ( pNMListView->ptAction.x >= 16 )	
	{
		return;								// not the check box [@HACK: assumes checkboxes are always 16 pixels wide]
	}

	if ( LVIS_SELECTED != this->m_ctrlListConfigurations.GetItemState( pNMListView->iItem, LVIS_SELECTED ) )
	{
		return;								// not selected
	}
	
	//
	//	GET THE ITEM's CHECK STATE
	//
	BOOL bChecked = this->m_ctrlListConfigurations.GetCheck( pNMListView->iItem );

	//
	//	SET INVERSE CHECK STATE FOR ALL SELECTED ITEMS EXCEPT THIS ONE
	//
	POSITION pos = this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();

	while( NULL != pos )
	{
		//
		//	GET NEXT SELECTED ITEM'S INDEX
		//
		int iItem = this->m_ctrlListConfigurations.GetNextSelectedItem( pos );

		//
		//	CHECK FOR CURRENT ITEM
		//
		if ( iItem == pNMListView->iItem )
		{
			continue;
		}

		//
		//	SET INVERSE CHECK
		//
		this->m_ctrlListConfigurations.SetCheck( iItem, bChecked ? FALSE : TRUE );
	}

	//
	//	RETURN RESULT
	//
	*pResult = 0;
}

//***************************************************************************************************
//**																				  OnBuildFinished
//***************************************************************************************************
//**	@DOC		MESSAGES
//**	@MFUNC		Called when DevStuido signals that a build has finished
//**	@PARM		[in] The number of errors
//**	@PARM		[in] The number of warnings
//**	@COMM		This is a plain proxy method that delegates the event further to the current 
//**				progress dialog (if any).
//**	@END
//***************************************************************************************************
//inline
void CDialogBuild::OnBuildFinished( long a_lErrors, long a_lWarnings )
{
	//
	//	CHECK WHETHER WE ARE URRENTLY IN THE MIDDLE OF A BUILD
	//
	if ( NULL == ::g_pdlgProgress )	
	{
		return;
	}

	//
	//	ROUTE THE EVENT TO THE PROGRESS DIALOG
	//
	::g_pdlgProgress->OnBuildFinished( a_lErrors, a_lWarnings );
}

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
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions