Click here to Skip to main content
15,884,917 members
Articles / Desktop Programming / MFC

Subselection Dialog

Rate me:
Please Sign up or sign in to vote.
3.17/5 (3 votes)
17 Nov 19992 min read 52.1K   1.6K   22  
Subselection dialog.
//    Project     : any                                                       
//    Customer    : intern                                               
//    Plattform   : WINDOWS 32bit                                            
//    File        : SubSelectionDlg.cpp                                                       
//    Programmer  : dz, Softtoys                                    
//    Copyright   : Public Domain                                          
//    Contact     : softtoys@webshuttle.ch                                       
//    Description : Class for selection and ordering subsets
//    History     : 01.09.1998                                                    


#include "stdafx.h"
#include "SelectDlg.h"
#include "SubSelectionDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// Dialogfeld CSubSelectionDlg 


CSubSelectionDlg::CSubSelectionDlg(UINT idd,UINT ListBox1ID,UINT ListBox2ID, CWnd* pParent /*=NULL*/)
	: CDialog(idd, pParent)
{
	//{{AFX_DATA_INIT(CSubSelectionDlg)
		// HINWEIS: Der Klassen-Assistent f�gt hier Elementinitialisierung ein
	//}}AFX_DATA_INIT
	m_nListBox1ID = ListBox1ID;
	m_nListBox2ID = ListBox2ID;

	m_bShowAll = false;
	m_nInsertPos = SELDLG_INSERT_AFTER;
	m_nLastDeletedItem = LB_ERR;
}


void CSubSelectionDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSubSelectionDlg)
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CSubSelectionDlg, CDialog)
	//{{AFX_MSG_MAP(CSubSelectionDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Behandlungsroutinen f�r Nachrichten CSubSelectionDlg 

void CSubSelectionDlg::InitListBox1() // Virtual function
{
}

void CSubSelectionDlg::InitListBox2() // Virtual function
{

}


void CSubSelectionDlg::OnExclude() 
// Here the selected items are deleted and moved back into the origing box
{
	// first we check if the user did select anything
	int nSelItems = m_pSelectionList2->GetSelCount();
//	ASSERT(nSelItems != LB_ERR);
	if (nSelItems == LB_ERR) nSelItems = 1; // when single selection in ListCntl is chosen
	if (nSelItems == 0) {
		AfxMessageBox(IDS_SELECTIONDLG_NO_SELECTION);
	}

	CString sText; 
	int nLastDeletedItem = LB_ERR;
	for (int i = 0; i < m_pSelectionList2->GetCount(); i++) {
		int bSel = m_pSelectionList2->GetSel(i);
		ASSERT(bSel != LB_ERR);
		if ((bSel)
		&& (bSel != LB_ERR)) {
			// this item has been selected, we now remove it from this box
			// and reinsert it into the original box
			m_pSelectionList2->GetText(i,sText);
			DWORD dw = m_pSelectionList2->GetItemData(i);			
			// create it in th original listbox
			if (!m_bShowAll) {
				int nItem = m_pSelectionList1->AddString(sText);
				ASSERT(nItem != LB_ERR);
				ASSERT(nItem != LB_ERRSPACE);
				VERIFY(m_pSelectionList1->SetItemData(nItem,dw) != LB_ERR);
			}
			// delete it in the second listbox
			nLastDeletedItem = i;
			VERIFY(m_pSelectionList2->DeleteString(i--) != LB_ERR);
		}
	}
	if (nLastDeletedItem != LB_ERR) {
		// Select the previous String, and if its the first one then select the next one
		if (nLastDeletedItem >= m_pSelectionList2->GetCount()) {
			nLastDeletedItem = m_pSelectionList2->GetCount() - 1;
		}
		m_pSelectionList2->SetSel(nLastDeletedItem,TRUE); // no check for LB_ERR , becaus this time its valid
	}

}

void CSubSelectionDlg::OnInclude() 
// the selected items are moved from the origin box to the selected box
{
	// first we check if the user did select anything
	int nSelItems = m_pSelectionList1->GetSelCount();
//	ASSERT(nSelItems != LB_ERR);
	if (nSelItems == LB_ERR) nSelItems = 1; // because when using a single selection box
	if (nSelItems == 0) {
		AfxMessageBox(IDS_SELECTIONDLG_NO_SELECTION);
	}

	int nLastMoved = -1;

	CString sText;
	if (m_nInsertPos == SELDLG_INSERT_BEFORE) {
		for (int i = m_pSelectionList1->GetCount() - 1;i >= 0; i--) {
			int bSel = m_pSelectionList1->GetSel(i);
			ASSERT(bSel != LB_ERR);
			if ((bSel)
			&& (bSel != LB_ERR)) {
				Include(i);
				nLastMoved = i;
			}
		}
	}
	else { // Insert after
		for (int i = 0; i < m_pSelectionList1->GetCount(); i++) {
			int bSel = m_pSelectionList1->GetSel(i);
			ASSERT(bSel != LB_ERR);
			if ((bSel)
			&& (bSel != LB_ERR)) {
				Include(i);
				if (!m_bShowAll) {
					i--; // because we just removed a entry !
				}
				nLastMoved = i;
			}
		}
	}
	if (m_bShowAll) {
		m_pSelectionList1->SetSel(nLastMoved,FALSE); // this has bee copied, 'unselect' it
	}
	m_pSelectionList1->SetSel(nLastMoved + 1,TRUE); // set the next item to selected again
}


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

	m_pSelectionList1 = (CListBox*)GetDlgItem(m_nListBox1ID);
  	ASSERT(m_pSelectionList1);
	m_pSelectionList2 = (CListBox*)GetDlgItem(m_nListBox2ID);
  	ASSERT(m_pSelectionList2);

	InitListBox1();
	InitListBox2();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zur�ckgeben
}

int CSubSelectionDlg::getLastSelectedItem(CListBox * p)
{
	for (int i = (p->GetCount() - 1);i >= 0; i--) {
		int bSel = p->GetSel(i);
		ASSERT(bSel != LB_ERR);
		if ((bSel)
		&&  (bSel != LB_ERR)) {
			return(i);
		}
	}
	return(LB_ERR);
}

int CSubSelectionDlg::getFirstSelectedItem(CListBox * p)
{
	for (int i = 0; i < p->GetCount(); i++) {
		int bSel = p->GetSel(i);
		ASSERT(bSel != LB_ERR);
		if ((bSel)
		&&  (bSel != LB_ERR)) {
			return(i);
		}
	}
	return(LB_ERR);
}


void CSubSelectionDlg::OnMovedown() 
{
	// first we check if the user did select anything
	int nSelItems = m_pSelectionList2->GetSelCount();
	if (nSelItems == LB_ERR) nSelItems = 1; // when single selection in ListCntl is chosen
	if (nSelItems == 0) {
		AfxMessageBox(IDS_SELECTIONDLG_NO_SELECTION);
	}

	CString sText; 
	for (int i = m_pSelectionList2->GetCount() - 1; i >= 0; i--) {
		int bSel = m_pSelectionList2->GetSel(i);
		ASSERT(bSel != LB_ERR);
		if ((bSel)
		&& (bSel != LB_ERR)) {
			// this item has been selected, we now remove it from this box
			// and reinsert after the previous item in the same box
			m_pSelectionList2->GetText(i,sText);
			DWORD dw = m_pSelectionList2->GetItemData(i);			
			if (i < (m_pSelectionList2->GetCount() - 1)) { // we need at least 1 items after this position to be able to move it down
				VERIFY(m_pSelectionList2->DeleteString(i) != LB_ERR);
				// insert it again further up
				int nItem = m_pSelectionList2->InsertString(i + 1,sText);
				ASSERT(nItem != LB_ERR);
				ASSERT(nItem != LB_ERRSPACE);
				VERIFY(m_pSelectionList2->SetItemData(nItem,dw) != LB_ERR);
				m_pSelectionList2->SetSel(nItem,TRUE); // no check for LB_ERR , because this time its valid
			}
		}
	}
}

void CSubSelectionDlg::OnMoveup() 
{
	// first we check if the user did select anything
	int nSelItems = m_pSelectionList2->GetSelCount();
	if (nSelItems == LB_ERR) nSelItems = 1; // when single selection in ListCntl is chosen
	if (nSelItems == 0) {
		AfxMessageBox(IDS_SELECTIONDLG_NO_SELECTION);
	}

	CString sText; 
	for (int i = 0; i < m_pSelectionList2->GetCount(); i++) {
		int bSel = m_pSelectionList2->GetSel(i);
		ASSERT(bSel != LB_ERR);
		if ((bSel)
		&& (bSel != LB_ERR)) {
			// this item has been selected, we now remove it from this box
			// and reinsert after the previous item in the same box
			m_pSelectionList2->GetText(i,sText);
			DWORD dw = m_pSelectionList2->GetItemData(i);			
			// delete it in the second listbox
			if (i > 0) { // we need at least 2 items to be able to move it up
				VERIFY(m_pSelectionList2->DeleteString(i) != LB_ERR);
				// insert it again further up
				int nItem = m_pSelectionList2->InsertString(i - 1,sText);
				ASSERT(nItem != LB_ERR);
				ASSERT(nItem != LB_ERRSPACE);
				VERIFY(m_pSelectionList2->SetItemData(nItem,dw) != LB_ERR);
				m_pSelectionList2->SetSel(nItem,TRUE); // no check for LB_ERR , because this time its valid
			}
		}
	}
}

void CSubSelectionDlg::OnSelectAll() 
{
	m_pSelectionList1->SelItemRange(TRUE,0,m_pSelectionList1->GetCount() - 1);
	UpdateData(FALSE);
	OnInclude();
}

void CSubSelectionDlg::OnDblclkSelectionList1() 
{
	Include(m_pSelectionList1->GetCaretIndex());
}

void CSubSelectionDlg::OnDblclkSelectionList2() 
{
	int nSel = m_pSelectionList2->GetCaretIndex();
	OnExclude();
}

int CSubSelectionDlg::Include(int nSel)
{
	ASSERT(nSel != LB_ERR);
	if (nSel == LB_ERR) return(nSel);

	m_nLastDeletedItem = LB_ERR;

	CString sText;
	// this item has been selected, we now remove it from this box
	// and reinsert it into the selection box
	m_pSelectionList1->GetText(nSel,sText);
	DWORD dw = m_pSelectionList1->GetItemData(nSel);			
	// create it in the selection listbox
	int nItem;

	if (m_nInsertPos == SELDLG_INSERT_AT_END) {   // Always add it as last item
		nItem = m_pSelectionList2->AddString(sText);
	}
	else { // insert it after the last selection in the target box
		if (m_nInsertPos == SELDLG_INSERT_BEFORE) { // insert it after the last selection in the target box
			nItem = getFirstSelectedItem(m_pSelectionList2);
			if (nItem == LB_ERR) {  // nothing selected or an error
				nItem = 0;			//  we insert at the begining of the box
			}
			if (m_pSelectionList2->GetSelCount() == 1) { 
				// unselect the last item, but if only one item is selected,
				// do not touch any multiple selection
				m_pSelectionList2->SetSel(nItem + 1,FALSE);
			}
		}
		else {  // insert it after the last selection
			nItem = getLastSelectedItem(m_pSelectionList2);
			if (nItem == LB_ERR) {
				nItem = 0;   // to avoid an insertion attempt after the end oft the list
			}
			else {
				nItem++;
			}
			if (m_pSelectionList2->GetSelCount() == 1) { 
				// unselect the last item, if only one item is selected, do not touch any multiple selection
				m_pSelectionList2->SetSel(nItem - 1,FALSE); // unselect last item
			}
		}
		// now actually insert this thing :-)
		nItem = m_pSelectionList2->InsertString(nItem,sText);
	}
	ASSERT(nItem != LB_ERR);           // should actually NEVER occur, since we just added it
	ASSERT(nItem != LB_ERRSPACE);      // This could be handled, to be on the save side
	// Insertd and now selected
	m_pSelectionList2->SetSel(nItem,TRUE);
	// and transfer the data to it
	VERIFY(m_pSelectionList2->SetItemData(nItem,dw) != LB_ERR);
	
	// Do some checking
	if (!m_bShowAll) {
		// delete it in the original listbox
		m_nLastDeletedItem = nSel;
 	    VERIFY(m_pSelectionList1->DeleteString(nSel) != LB_ERR);
	}
	return(nItem);
}

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
Chief Technology Officer
Switzerland Switzerland
Professional IT developer since 1983. First projects with Cobol, then Pascal, Modula2, C and since Visual C++ 1.0 also with C++ and today C#. Works since 1986 as Consultant, between 1990 and 2008 for Infobrain in Switzerland, from 2008 until 2013 for enValue (also Switzerland) and currently working for Comfone (Bern, Switzerland).

Married, two grown-up daughters, Hobbies : Paragliding, Orienteering, Mountainbiking, Photography

Comments and Discussions