Click here to Skip to main content
15,879,535 members
Articles / Desktop Programming / MFC

Easy Installer

Rate me:
Please Sign up or sign in to vote.
4.81/5 (57 votes)
14 Sep 2006CPOL11 min read 276.4K   3.7K   155  
The Easy Installer program
// CreateInstallerDlg.cpp : implementation file
//
// This is the program that creates the Installer (self-extracting exe) program:
//		Run this program to create your install program.
// 

#include "stdafx.h"
#include "CreateInstaller.h"
#include "CreateInstallerDlg.h"
#include "zip.h"
#include ".\createinstallerdlg.h"
#include "about.h"

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

/////////////////////////////////////////////////////////////////////////////
// CCreateInstallerDlg dialog

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

void CCreateInstallerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CCreateInstallerDlg)
	DDX_Control(pDX, IDC_INLIST, m_lstInFiles);
	DDX_Control(pDX, IDC_OUTFNAME, m_edtTarget);
	DDX_Text(pDX, IDC_OUTFNAME, m_target);
	DDX_Text(pDX, IDC_EDIT3, m_license);
	DDX_Text(pDX, IDC_EDIT4, m_info);
	//}}AFX_DATA_MAP
	DDX_Control(pDX, IDC_COMBO1, m_cmbProjectList);
	DDX_Control(pDX, IDC_CHECK1, m_btn95);
	DDX_Control(pDX, IDC_CHECK2, m_btn98);
	DDX_Control(pDX, IDC_CHECK3, m_btnME);
	DDX_Control(pDX, IDC_CHECK4, m_btnNT35);
	DDX_Control(pDX, IDC_CHECK5, m_btnNT4);
	DDX_Control(pDX, IDC_CHECK6, m_btn2K);
	DDX_Control(pDX, IDC_CHECK7, m_btnXP);
	DDX_Control(pDX, IDC_EDIT1, m_edtWebCaption);
	DDX_Control(pDX, IDC_EDIT2, m_edtWebURL);
	DDX_Control(pDX, IDC_EDIT3, m_edtLicense);
	DDX_Control(pDX, IDC_EDIT4, m_edtInfo);
	DDX_Control(pDX, IDC_CHECK8, m_btn2K3);
	DDX_Control(pDX, IDC_CHECK9, m_btnVista);
}

BEGIN_MESSAGE_MAP(CCreateInstallerDlg, CDialog)
	//{{AFX_MSG_MAP(CCreateInstallerDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(ID_MAKEEXE, OnMakeInstaller)
	ON_BN_CLICKED(IDC_INBROWSE, OnInBrowse)
	ON_BN_CLICKED(IDC_OUTBROWSE, OnOutBrowse)
	ON_BN_CLICKED(IDC_DELINFILES, OnDelinfiles)
	//}}AFX_MSG_MAP
	ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelchangeCombo1)
	ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON4, OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON5, OnBnClickedButton5)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCreateInstallerDlg message handlers

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

	// 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

	char path[MAX_PATH];
	char dir[MAX_PATH];
	char drive[MAX_PATH];
	char file[MAX_PATH];
	char ext[MAX_PATH];
	GetModuleFileName(NULL, path, MAX_PATH);
	_splitpath(path, drive, dir, file, ext);
	iniFileName.Format("%s%sCreateSetup.ini", drive, dir);

	TCHAR lastProject[100];
	int ret;
	ret = GetPrivateProfileString("CONFIG", "last", "", lastProject, 99, iniFileName);
	if(!ret)
		m_cmbProjectList.SetWindowText("Project");
	else
		GetProject(lastProject);

	TCHAR sections[10000];
	PTCHAR ss = sections;
	GetPrivateProfileSectionNames(sections, sizeof(TCHAR)*10000, iniFileName);
	// loop through all section names - skip CONFIG
	CString s;
	int idx = 0;
	int sel = -1;
	while(1)
	{
		s.Format("%s", ss);
		if(s.GetLength() == 0)
			break;
		ss += s.GetLength() + 1;
		if(!s.Compare("CONFIG"))
			continue;
		m_cmbProjectList.AddString(s);
		if(!s.Compare(lastProject))
			sel = idx;
		idx++;
	}
	m_cmbProjectList.SetCurSel(sel);

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

// 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 CCreateInstallerDlg::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 CCreateInstallerDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CCreateInstallerDlg::SetFileListScroll()
{
	// Find the longest string in the list box.
	CString		str;
	CSize		sz;
	int			dx = 0;
	TEXTMETRIC	tm;
	CDC*		pDC = m_lstInFiles.GetDC();
	CFont*		pFont = m_lstInFiles.GetFont();

	// Select the listbox font, save the old font
	CFont* pOldFont = pDC->SelectObject(pFont);
	// Get the text metrics for avg char width
	pDC->GetTextMetrics(&tm); 

	for (int i = 0; i < m_lstInFiles.GetCount(); i++)
	{
		m_lstInFiles.GetText(i, str);
		sz = pDC->GetTextExtent(str);

		// Add the avg width to prevent clipping
   		sz.cx += tm.tmAveCharWidth;
		if (sz.cx > dx)
			dx = sz.cx;
	}

	// Select the old font back into the DC
	pDC->SelectObject(pOldFont);
	m_lstInFiles.ReleaseDC(pDC);

	// Set the horizontal extent so every character of all strings 
	// can be scrolled to.
	m_lstInFiles.SetHorizontalExtent(dx);
}

// Shows browse dialog box for addition of new files in list
void CCreateInstallerDlg::OnInBrowse() 
{
	UpdateData();
	static CString strFName;
	CFileDialog dlg(TRUE, NULL, strFName, OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT, "All Files(*.*)|*.*||", this);
	if(dlg.DoModal() == IDOK)
	{
		// Deselect any selected items in list
		for(int i = 0; i < m_lstInFiles.GetCount(); ++i)
			m_lstInFiles.SetSel(i,FALSE);
		// Add each file name selected to list
		for(POSITION pos = dlg.GetStartPosition(); pos != NULL; )
		{
			strFName = dlg.GetNextPathName(pos);
			// If this is the first file name in list create an exe name and set it as output file
			if(m_lstInFiles.GetCount() == 0)
			{
				if(strFName.ReverseFind('.') == -1)
					m_target += ".exe";
				else
					m_target = strFName.Left(strFName.ReverseFind('.')) + ".exe";
			}
			// Add and Select new file name
			m_lstInFiles.SetSel(m_lstInFiles.AddString(strFName));
		}
		UpdateData(FALSE);
		m_lstInFiles.SetFocus();
	}

	SetFileListScroll();
}

// delete the selected files in list
void CCreateInstallerDlg::OnDelinfiles()
{
	// Create an array to store selected items
	int nCount = m_lstInFiles.GetSelCount();
	CArray<int,int> aryListBoxSel;

	aryListBoxSel.SetSize(nCount);
	m_lstInFiles.GetSelItems(nCount, aryListBoxSel.GetData());

	// Delete the selected items while considering that indexes will be reduced by deletion of an item
	for(int i = 0; i < nCount; ++i)
		m_lstInFiles.DeleteString(aryListBoxSel[i] - i);
}

// Show browse dialog box for output file name
void CCreateInstallerDlg::OnOutBrowse()
{
	UpdateData();
	CFileDialog dlg(FALSE, NULL, m_target, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "All Files(*.)|*.*||", this);
	if(dlg.DoModal() == IDOK)
	{
		m_target = dlg.GetPathName();
		UpdateData(FALSE);
		m_edtTarget.SetSel(0, -1);
		m_edtTarget.SetFocus();
	}
}

void CCreateInstallerDlg::OnMakeInstaller()
{
	UpdateData();

	if(m_target.IsEmpty())
	{
		AfxMessageBox("You need to enter in an Output path (full path name and file name).");
		return;
	}
	
	CString str;

	wrap.Init();

	// project name to class
	CString prjName;
	m_cmbProjectList.GetWindowText(prjName);
	wrap.SetProjectName(prjName);

	// clear the proj parms so that we can save the new ones
	WritePrivateProfileSection(prjName, NULL, iniFileName);

	// add files to class
	int numFiles = m_lstInFiles.GetCount(); 
	if(numFiles == 0)
	{
		AfxMessageBox("Please enter at least one input file name");
		return;
	}
	for(int i = 0; i < numFiles; ++i)
	{
		// add to wrap class
		CString str1;
		m_lstInFiles.GetText(i, str);
		wrap.AddFile(str);

		// write to config file
		TCHAR addStr[10];
		sprintf(addStr, "add%02d", i+1);
		WritePrivateProfileString(prjName, addStr, str, iniFileName);
	}

	// agreement

	// web site caption
	m_edtWebCaption.GetWindowText(str);
	wrap.SetWebSiteCaption(str);
	WritePrivateProfileString(prjName, "webcaption", str, iniFileName);

	// web site URL
	m_edtWebURL.GetWindowText(str);
	wrap.SetWebSiteURL(str);
	WritePrivateProfileString(prjName, "webURL", str, iniFileName);

	// license agreement
	m_edtLicense.GetWindowText(str);
	wrap.AddAgreement(str);
	WritePrivateProfileString(prjName, "agreement", str, iniFileName);

	// info file
	m_edtInfo.GetWindowText(str);
	wrap.AddInfo(str);
	WritePrivateProfileString(prjName, "info", str, iniFileName);

	// which version of Windows
	DWORD winVer = 0;
	if(m_btn95.GetCheck())
		winVer |= 0x01;
	if(m_btn98.GetCheck())
		winVer |= 0x02;
	if(m_btnME.GetCheck())
		winVer |= 0x04;
	if(m_btnNT35.GetCheck())
		winVer |= 0x10;
	if(m_btnNT4.GetCheck())
		winVer |= 0x20;
	if(m_btn2K.GetCheck())
		winVer |= 0x40;
	if(m_btnXP.GetCheck())
		winVer |= 0x80;
	if(m_btn2K3.GetCheck())
		winVer |= 0x0100;
	if(m_btnVista.GetCheck())
		winVer |= 0x0200;

	wrap.SetWinVer(winVer);
	str.Format(_T("%d"), winVer);
	WritePrivateProfileString(prjName, "winver", str, iniFileName);

	wrap.SetTargetName(m_target);
	WritePrivateProfileString(prjName, "out", m_target, iniFileName);

	// Now do the install
	wrap.CreateInstaller();
	CString strMsg;
	strMsg.Format("%s successfully created from %d files.", m_target, m_lstInFiles.GetCount());
	WritePrivateProfileString("CONFIG", "last", prjName, iniFileName);
	AfxMessageBox(strMsg, MB_ICONINFORMATION | MB_OK);
	UpdateData(FALSE);
}

void CCreateInstallerDlg::OnCbnSelchangeCombo1()
{
	int sel = m_cmbProjectList.GetCurSel();
	CString selStr;
	m_cmbProjectList.GetLBText(sel, selStr);
	GetProject(selStr);
}

void CCreateInstallerDlg::GetProject(CString prj)
{
	TCHAR	str[255];
	int		rc;
	int		idx = 1;
	TCHAR	addStr[10];
	m_lstInFiles.ResetContent();
	while(1)
	{
		sprintf(addStr, "add%02d", idx);
		rc = GetPrivateProfileString(prj, addStr, "", str, 254, iniFileName);
		if(!rc)
			break;
		m_lstInFiles.AddString(str);
		idx++;
	}
	SetFileListScroll();

	rc = GetPrivateProfileString(prj, _T("out"), _T(""), str, 254, iniFileName);
	m_edtTarget.SetWindowText(str);

	DWORD winVer = GetPrivateProfileInt(prj, "winver", 0, iniFileName);
	int set;
	set = (winVer & 0x01) ? 1 : 0;
	m_btn95.SetCheck(set);
	set = (winVer & 0x02) ? 1 : 0;
	m_btn98.SetCheck(set);
	set = (winVer & 0x04) ? 1 : 0;
	m_btnME.SetCheck(set);
	set = (winVer & 0x10) ? 1 : 0;
	m_btnNT35.SetCheck(set);
	set = (winVer & 0x20) ? 1 : 0;
	m_btnNT4.SetCheck(set);
	set = (winVer & 0x40) ? 1 : 0;
	m_btn2K.SetCheck(set);
	set = (winVer & 0x80) ? 1 : 0;
	m_btnXP.SetCheck(set);
	set = (winVer & 0x0100) ? 1 : 0;
	m_btn2K3.SetCheck(set);
	set = (winVer & 0x0200) ? 1 : 0;
	m_btnVista.SetCheck(set);

	CString s;
	s.Format(_T("%s web site"), prj);
	rc = GetPrivateProfileString(prj, _T("webcaption"), s, str, 99, iniFileName);
	m_edtWebCaption.SetWindowText(str);
	rc = GetPrivateProfileString(prj, _T("webURL"), _T("< web site URL >"), str, 99, iniFileName);
	m_edtWebURL.SetWindowText(str);

	rc = GetPrivateProfileString(prj, _T("agreement"), _T(""), str, 99, iniFileName);
	m_edtLicense.SetWindowText(str);
	rc = GetPrivateProfileString(prj, _T("info"), _T(""), str, 99, iniFileName);
	m_edtInfo.SetWindowText(str);
}

void CCreateInstallerDlg::OnBnClickedButton1()
{
	CString sel;
	m_cmbProjectList.GetLBText(m_cmbProjectList.GetCurSel(), sel);
	CString s;
	s.Format(_T("Are you sure you want to delete the %s project?"), sel);
	int rc = AfxMessageBox(s, MB_ICONEXCLAMATION | MB_YESNO);
	if(rc == IDYES)
	{
		// delete project
		WritePrivateProfileSection(sel, NULL, iniFileName);
		m_cmbProjectList.DeleteString(m_cmbProjectList.GetCurSel());
	}
}

void CCreateInstallerDlg::OnBnClickedButton2()
{
	CAbout ca;
	ca.DoModal();
}

void CCreateInstallerDlg::OnBnClickedButton3()
{
	CString str;

	CString prjName;
	m_cmbProjectList.GetWindowText(prjName);

	// clear the proj parms so that we can save the new ones
	WritePrivateProfileSection(prjName, NULL, iniFileName);

	// save project files
	int numFiles = m_lstInFiles.GetCount(); 
	if(numFiles == 0)
	{
		AfxMessageBox("Please enter at least one input file name");
		return;
	}
	for(int i = 0; i < numFiles; ++i)
	{
		// write to config file
		TCHAR addStr[10];
		sprintf(addStr, "add%02d", i+1);
		WritePrivateProfileString(prjName, addStr, str, iniFileName);
	}

	// web site caption
	m_edtWebCaption.GetWindowText(str);
	WritePrivateProfileString(prjName, "webcaption", str, iniFileName);

	// web site URL
	m_edtWebURL.GetWindowText(str);
	WritePrivateProfileString(prjName, "webURL", str, iniFileName);

	// which version of Windows
	DWORD winVer = 0;
	if(m_btn95.GetCheck())
		winVer |= 0x01;
	if(m_btn98.GetCheck())
		winVer |= 0x02;
	if(m_btnME.GetCheck())
		winVer |= 0x04;
	if(m_btnNT35.GetCheck())
		winVer |= 0x10;
	if(m_btnNT4.GetCheck())
		winVer |= 0x20;
	if(m_btn2K.GetCheck())
		winVer |= 0x40;
	if(m_btnXP.GetCheck())
		winVer |= 0x80;
	if(m_btn2K3.GetCheck())
		winVer |= 0x0100;
	if(m_btnVista.GetCheck())
		winVer |= 0x0200;

	str.Format(_T("%d"), winVer);
	WritePrivateProfileString(prjName, "winver", str, iniFileName);

	// installer target name
	WritePrivateProfileString(prjName, "out", m_target, iniFileName);
}

void CCreateInstallerDlg::OnBnClickedButton4()
{
	// license agreement
	UpdateData();
	CFileDialog dlg(TRUE, NULL, m_license, OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT, "All Files(*.)|*.*||", this);
	if(dlg.DoModal() == IDOK)
	{
		m_license = dlg.GetPathName();
		UpdateData(FALSE);
		m_edtLicense.SetSel(0, -1);
		m_edtLicense.SetFocus();
	}
}

void CCreateInstallerDlg::OnBnClickedButton5()
{
	// info file
	UpdateData();
	CFileDialog dlg(TRUE, NULL, m_info, OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT, "All Files(*.)|*.*||", this);
	if(dlg.DoModal() == IDOK)
	{
		m_info = dlg.GetPathName();
		UpdateData(FALSE);
		m_edtInfo.SetSel(0, -1);
		m_edtInfo.SetFocus();
	}
}

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
Israel Israel
lichen farmer, semi-lingual, never saw a Sylvester Stallone movie

Comments and Discussions