www.gusucode.com > VC++个人考勤软件源代码-源码程序 > VC++个人考勤软件源代码-源码程序/code/dduallistmanager.cpp

    ///////////////////////////////////////////////////////////////////////////////
// Download by http://www.NewXing.com
//  Filename:       DualListManager.cpp
//
//  AUTHOR     :    Copyright (C) Steve Aube, February 2000
//                  SteveAube@yahoo.com
//
//                  You can reuse and redistribute this code, provided this 
//                  header is kept as is.
//
//  Description:    This class is intended to handle moving item between two
//                  listboxes. One list represents the list of available items
//                  and the other represents the list of choosen items. This
//                  class is intended to be a member of CDialog, CFormView or
//                  CPropertyPage. All the parent class has to do is properly 
//                  initialize this class and call a couple of member functions
//                  and this class will take care of the following things:
//                  - If the "Add" button is pressed the selected item(s) are
//                    moved from the available list to the choosen list.
//                  - If the "Add All" button is pressed all of the items in
//                    are moved from the available list to the choosen list.
//                  - If the "Remove" button is pressed the selected item(s) 
//                    are moved from the choosen list to the available list.
//                  - If the "Remove All" button is pressed all of the items in
//                    are moved from the choosen list to the available list.
//                  - If the "Move Up" button is pressed the selected item(s)
//                    in the choosen list are moved up in the list by one.
//                    This button can be pressed repeatedly until all of the 
//                    selected items have reached the top of the list. When
//                    that occurs the button is disabled.
//                  - If the "Move Down" button is pressed the selected item(s)
//                    in the choosen list are moved down in the list by one.
//                  - Allows double clicking on an item to move it to the
//                    opposite list.
//                  - When item(s) are moved from one list to another the 
//                    item that was moved is selected in the list it was moved
//                    to. The list that had the item removed selects the item
//                    that is at the location of the first item that was moved.
//                    If the item at the bottom of the list is moved the item
//                    immediately above it is selected. If the last item in 
//                    the list is removed there is no selection.
//                  - Enabling/disabling of buttons - when items are moved 
//                    between lists and up and down in the choosen list the 
//                    availability of buttons changes. For instance if an item
//                    is moved to the top of the choosen list the "Move Up" 
//                    button doesn't make sense. When this occurs the "Move Up"
//                    button is automatically disabled.
//                  - Keyboard support - disabling a button that has the focus
//                    causes problems for keyboard users. This code checks to 
//                    see if a button has the focus before it disables it. If
//                    it does the focus is forwarded to the next avaiabled 
//                    control.
//                  
//                  How to use this class:
//                  - Add a member variable of this class type to the dialog
//                    box, property page or form view where you want to use it.
//                  - From the initialization method (OnInitDialog() for a 
//                    dialog box and a property page and OnInitialUpdate() for
//                    a view) do the following things in this order:
//                    - Add the items to the available and choosen lists with
//                      the calls AddItemToAvailableList(...) and 
//                      AddItemToChoosenList(...). The first parameter is the
//                      name of the item and the second parameter is a unique
//                      identifier for the item.
//                    - Call InitializeControls(...) with a pointer the parent
//                      window and the IDs of all of the controls.
//                  - Override OnCmdMsg(...) 
//                  
//                  Notes:
//                  - If you don't need certain features (like the ability to
//                    move an item up or down in the choosen list) simply
//                    provide a NULL value for that id. The rest of the class
//                    will continue work correctly. The IDs for the two lists
//                    are required since a dual list manager doesn't make sense
//                    unless it has two lists to work with.
//                  - This code will work with single, multiple and extended
//                    listboxes.
//                  - The order of the controls doesn't matter. You can put 
//                    the choosen list on the left, right, top or bottom of the
//                    selected list. Just make sure you supply the control IDs
//                    in the right order.
//                  
//                  Implementation details:
//                  This class keeps track of the items in both listboxes in
//                  internal CArrays. The names associated with the items
//                  are tracked in a CMap and the item data value is used as
//                  the key. Keeping these separate lists simplfies moving
//                  items and keeping track of selection state.
//
////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DualListManager.h"

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


///////////////////////////////////////////////////////////////////////////////
//
//  Method:			CDualListManager
//
//  Purpose:		Constructor - initializes member data
//
//  Inputs:
//
//		void
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		None
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
CDualListManager::CDualListManager(void)
: m_pWndParent(NULL)
, m_iIDAvailableList(0)
, m_iIDChoosenList(0)
, m_iIDAddButton(0)
, m_iIDAddAllButton(0)
, m_iIDRemoveButton(0)
, m_iIDRemoveAllButton(0)
, m_iIDMoveUpButton(0)
, m_iIDMoveDownButton(0)
, m_bAvailableListSingleSelType(0)
, m_bChoosenListSingleSelType(0)
{
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			~CDualListManager
//
//  Purpose:		Destructor - detach the listbox handles
//
//  Inputs:
//
//      void
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		None
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
CDualListManager::~CDualListManager(void)
{
    m_ctrlAvailableList.Detach();
    m_ctrlChoosenList.Detach();
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			InitializeControls
//
//                  Should be called from the initialization method 
//                  (OnInitDialog() for a dialog box and a property page and 
//                  OnInitialUpdate() for a view). Before calling this method 
//                  the client code should add the listbox items to the two 
//                  lists with calls to AddItemToAvailableList(...) and 
//                  AddItemToChoosenList(...). 
//                  
//                  This method sets up this class to handle all of the 
//                  messages for the given controls.
//  Inputs:
//
//		CWnd*  pWndParent   - pointer to the parent window (should be a CDialog
//                            CPropertyPage, CFormView etc.)
//
//		int    iIDAvailableList - resource id of the available listbox
//
//		int    iIDChoosenList - resource id of the choosen listbox
//
//		int    iIDAddButton - resource id of the add button
//
//		int    iIDAddAllButton - resource id of the add all button
//
//		int    iIDRemoveButton - resource id of the remove button
//
//		int    iIDRemoveAllButton - resource id of the remove all button
//
//		int    iIDMoveUpButton - resource id of the up button
//
//		int    iIDMoveDownButton - resource id of the down button
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::InitializeControls(CWnd*  pWndParent,
                                         int    iIDAvailableList,
                                         int    iIDChoosenList,
                                         int    iIDAddButton,
                                         int    iIDAddAllButton,
                                         int    iIDRemoveButton,
                                         int    iIDRemoveAllButton,
                                         int    iIDMoveUpButton,
                                         int    iIDMoveDownButton)
{
    // Hold on to all of the passed in parameters.
    m_pWndParent = pWndParent;
    m_iIDAvailableList = iIDAvailableList;
    m_iIDChoosenList = iIDChoosenList;
    m_iIDAddButton = iIDAddButton;
    m_iIDAddAllButton = iIDAddAllButton;
    m_iIDRemoveButton = iIDRemoveButton;
    m_iIDRemoveAllButton = iIDRemoveAllButton;
    m_iIDMoveUpButton = iIDMoveUpButton;
    m_iIDMoveDownButton = iIDMoveDownButton;
    m_bAvailableListSingleSelType = FALSE;
    m_bChoosenListSingleSelType = FALSE;

    // This class doesn't make sense unless a parent window and two listboxes 
    // are supplied. It also doesn't make sense without at least some of the 
    // other controls. However, there is no specific set of controls that are 
    // required so no checks are done here.
    ASSERT(m_pWndParent);
    ASSERT(m_iIDAvailableList);
    ASSERT(m_iIDChoosenList);

    // Attach the control items to the windows. The lists have to exist and we
    // access them continually so having a listbox control just simplifies this
    // code.
    m_ctrlAvailableList.Attach(m_pWndParent->GetDlgItem(m_iIDAvailableList)->GetSafeHwnd());
    m_ctrlChoosenList.Attach(m_pWndParent->GetDlgItem(m_iIDChoosenList)->GetSafeHwnd());

    // Check to see whether each list is a single or multi select listbox
    m_bAvailableListSingleSelType = (m_ctrlAvailableList.GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) ? FALSE: TRUE ;
    m_bChoosenListSingleSelType   = (m_ctrlChoosenList.GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) ? FALSE: TRUE ;

    // Re-fill the listboxes with the contents of the array
    FillListboxes();

    // Select the first item in each of the listboxes
    SelectLBItem(m_ctrlAvailableList, 0);
    SelectLBItem(m_ctrlChoosenList, 0);

    // Now enable/disable the move buttons based on the contents and selction 
    // state of the listbox controls.
    EnableButtons();
}


///////////////////////////////////////////////////////////////////////////////
//
//  Method:			AddItemToAvailableList
//
//  Purpose:		Adds the passed in item to the array of items identified
//                  as being currently available for selection.  Also adds the 
//                  item to the map so the name can be looked up later.
//
//  Inputs:
//
//		LPCTSTR lpszItem
//
//		long lItemData
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::AddItemToAvailableList(LPCTSTR lpszItem, long lItemData)
{
    m_ArrayAvailable.Add(lItemData);
    m_KeyMap.SetAt(lItemData, lpszItem);
}


///////////////////////////////////////////////////////////////////////////////
//
//  Method:			AddItemToChoosenList
//
//  Purpose:		Adds the passed in item to the array of items identified
//                  as being currently choosen. Also adds the item to the
//                  map so the name can be looked up later.
//
//  Inputs:
//
//		LPCTSTR lpszItem
//
//		long lItemData
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::AddItemToChoosenList(LPCTSTR lpszItem, long lItemData)
{
    m_ArrayChoosen.Add(lItemData);
    m_KeyMap.SetAt(lItemData, lpszItem);
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			MoveAll
//
//  Purpose:		Moves all of the selected items from one listbox to the
//                  other.
//
//  Inputs:
//
//		CListBox & rLBFrom - listbox moving from
//
//		CArray<long, long> & rArrayFrom - array moving from
//
//		CArray<long, long> & rArrayTo - array moving to
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::MoveAll(CListBox & rLBFrom, CListBox & rLBTo, CArray<long, long> & rArrayFrom, CArray<long, long> & rArrayTo) 
{
    CString csName;

    // Move all of the remaining items in the listbox to the opposite array
    int iCount = rLBFrom.GetCount();
    for(int iIndex = 0; iIndex < iCount; ++iIndex)
    {
        long lVal = rLBFrom.GetItemData(iIndex);
        rArrayTo.Add(lVal);
    }

    // Clear the array of items we are clearing out
    rArrayFrom.RemoveAll();

    // Re-fill the listboxes with the contents of the array
    FillListboxes();

    // Select the first item in the to listbox
    SelectLBItem(rLBTo, 0);
}


///////////////////////////////////////////////////////////////////////////////
//
//  Method:			MoveSelected
//
//  Purpose:		Moves the selected items from one listbox and places them
//                  in the other listbox.
//
//  Inputs:
//
//		CListBox & rLBFrom - listbox moving from
//
//		CArray<long, long> & rArrayFrom - array moving from
//
//		CArray<long, long> & rArrayTo - array moving to
//
//		BOOL bRemoving - TRUE if we are removing items 
//                       FALSE if we are adding items
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::MoveSelected(CListBox & rLBFrom, CArray<long, long> & rArrayFrom, CArray<long, long> & rArrayTo, BOOL bRemoving)
{
    CArray<long, long>  SelectedArray;

    // Loops through all of the items in the from listbox 
    int iSelFirst = -1;
    int iCount    = rLBFrom.GetCount();
    for(int iIndex = 0; iIndex < iCount; ++iIndex)
    {
        // Check to see if this item is currently selected
        if( 0 < rLBFrom.GetSel( iIndex ) )
        {
            // Hang onto the first selected item in the list so we can keep
            // the item at that position selected.
            if(-1 == iSelFirst)
                iSelFirst = iIndex;

            // Get the item data for this item
            long lItemData = rLBFrom.GetItemData(iIndex);

            // Add the item data value to the list of selected items
            SelectedArray.Add(lItemData);

            // Add this item to the other array of items 
            rArrayTo.Add(lItemData);

            // Find this item in the array we are moving it out of and remove it
            int iCount2 = rArrayFrom.GetSize();
            for(int iIndex2 = 0; iIndex2 < iCount2; ++iIndex2)
            {
                if( lItemData == rArrayFrom[iIndex2] )
                {
                    rArrayFrom.RemoveAt(iIndex2);
                    break;
                }
            }
        }
    }

    // Re-fill the listboxes with the contents of the array
    FillListboxes(&SelectedArray, bRemoving);

    // Select one item in the from listbox at the location of the first 
    // selected item before the items were moved.
    if(-1 != iSelFirst)
    {
        SelectLBItem(rLBFrom, rLBFrom.GetCount() <= iSelFirst 
                              ? rLBFrom.GetCount() - 1 : iSelFirst);
    }
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			MoveUpOrDown
//
//  Purpose:		Moves the hilighted items in the list of choosen items 
//                  either up or down depending on the value of the passed in
//                  flag.
//                  
//                  If more than one item is selected all of the items are
//                  moved as a block. If one or more items have reached the 
//                  top or bottom while other haven't those items stay at their
//                  current location and the other continue to move.
//
//  Inputs:
//
//		BOOL bMovingUp - TRUE if the items should be moved up
//                       FALSE if the items should be moved down
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::MoveUpOrDown(BOOL bMovingUp) 
{
    int                 iIndex, iIndex2, iCount, iCount2, iOffset, iInsertAt;
    int                 iIndexSelectedMarker = -1;
    long                lItemData;
    CString             csName;
    CArray<long, long>  SelectedArray;

    // Get the count of items in the list control
    iCount = m_ctrlChoosenList.GetCount();

    // Set the base loop index and the increment/decrement value based on the
    // direction the item are being moved (up or down).
    iIndex  = (TRUE  == bMovingUp) ? 0  : iCount - 1;
    iOffset = (TRUE  == bMovingUp) ? -1 : 1;
    
    // Loop through all of the items in the list.
    while( (TRUE  == bMovingUp && iIndex < iCount) || 
           (FALSE == bMovingUp && iIndex >= 0) )
    {
        // Check if this item is selected.
        if( 0 < m_ctrlChoosenList.GetSel( iIndex ) )
        {
            // Get the item data for this item
            lItemData = m_ctrlChoosenList.GetItemData(iIndex);

            // Build a list of the selected items so we can reselect them
            // later.
            SelectedArray.Add(lItemData);

            // Don't move selected items past other selected items
            if(-1 != iIndexSelectedMarker)
            {
                // Loop through the enabled list looking for the current item
                // which is identified by the item data value.
                iCount2 = m_ArrayChoosen.GetSize();

                for(iIndex2 = 0; iIndex2 < iCount2; ++iIndex2)
                {
                    // Find the index of this item in enabled list
                    if( lItemData == m_ArrayChoosen[iIndex2] )
                    {
                        // Remove the item from its current position
                        m_ArrayChoosen.RemoveAt(iIndex2);

                        // Reinsert the item in the array one space higher 
                        // than its previous position
                        iInsertAt = (iIndex2 + iOffset) < 0 ? 0 : iIndex2 + iOffset;
                        m_ArrayChoosen.InsertAt(iInsertAt, lItemData);
                        break;
                    }
                }
            }
        }
        // If this item wasn't selected save the index so we can check it later
        // so we don't move past the any selected items.
        else if(-1 == iIndexSelectedMarker)
        {
            iIndexSelectedMarker = iIndex;
        }

        iIndex = (TRUE  == bMovingUp) ? iIndex + 1 : iIndex - 1;
    }

    // Re-fill the listboxes with the contents of the array
    FillListboxes(&SelectedArray);
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			FillListboxes
//
//  Purpose:		Fills both listboxes with the current contents of their
//                  associated arrays. This method also reselects the items
//                  in the passed in array of selected items in appropriate
//                  list.
//
//  Inputs:
//
//		CArray<long
//
//		long> * pSelectedArray
//
//		BOOL bRemoving
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::FillListboxes(CArray<long, long> * pSelectedArray, BOOL bRemoving)
{
    int     iIndex, iIndex2, iCount;
    CString csName;

    // Clear and refill the listbox of disabled commands from the disabled
    // command array.
    m_ctrlAvailableList.ResetContent();
    iCount = m_ArrayAvailable.GetSize();
    for(iIndex = 0; iIndex < iCount; ++iIndex)
    {
        m_KeyMap.Lookup(m_ArrayAvailable[iIndex], csName);
        iIndex2 = m_ctrlAvailableList.AddString(csName);
        m_ctrlAvailableList.SetItemData(iIndex2, m_ArrayAvailable[iIndex]);
    }

    // Clear and refill the listbox of enabled commands from the enabled
    // command array.
    m_ctrlChoosenList.ResetContent();
    iCount = m_ArrayChoosen.GetSize();
    for(iIndex = 0; iIndex < iCount; ++iIndex)
    {
        m_KeyMap.Lookup(m_ArrayChoosen[iIndex], csName);
        iIndex2 = m_ctrlChoosenList.AddString(csName);
        m_ctrlChoosenList.SetItemData(iIndex2, m_ArrayChoosen[iIndex]);
    }

    // Now reselect the items that were selected before we moved them.
    if(NULL != pSelectedArray)
    {
        iCount = pSelectedArray->GetSize();
        for(iIndex = 0; iIndex < iCount; ++iIndex)
        {
            m_KeyMap.Lookup(pSelectedArray->GetAt(iIndex), csName);
            if(TRUE == bRemoving)
            {
                iIndex2 = m_ctrlAvailableList.FindStringExact(-1, csName);
                SelectLBItem(m_ctrlAvailableList, iIndex2);
            }
            else
            {
                iIndex2 = m_ctrlChoosenList.FindStringExact(-1, csName);
                SelectLBItem(m_ctrlChoosenList, iIndex2);
            }
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			EnableButtons
//
//  Purpose:		Enables/disables all of the buttons Add; Add All; Remove: 
//                  Remove All; Move Up; Move Down; based on the contents and 
//                  selction state of the listbox controls.
//
//  Inputs:
//
//		void
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::EnableButtons(void)
{
    int     iSelCountAvailable;
    int     iCountAvailable    = m_ctrlAvailableList.GetCount();
    int     iSelCountChoosen   = m_ctrlChoosenList.GetSelCount();
    int     iCountChoosen      = m_ctrlChoosenList.GetCount();

    // If either of the listboxes are single selection listboxes the call to 
    // GetSelCount() will return -1 even if an item is selected. This code 
    // checks the style flag for each control and calls GetCurSel or 
    // GetSelCount depending on which style the given listbox has.
    // Get the count for the available list
    if(TRUE == m_bAvailableListSingleSelType)
    {
        iSelCountAvailable = (-1 == m_ctrlAvailableList.GetCurSel()) ? 0 : 1;
    }
    else
    {
        iSelCountAvailable = m_ctrlAvailableList.GetSelCount();
    }
    // Get the count for the choosen list
    if(TRUE == m_bChoosenListSingleSelType)
    {
        iSelCountChoosen = (-1 == m_ctrlChoosenList.GetCurSel()) ? 0 : 1;
    }
    else
    {
        iSelCountChoosen = m_ctrlChoosenList.GetSelCount();
    }

    BOOL    bEnableMoveUp   = FALSE;
    BOOL    bEnableMoveDown = FALSE;

    // Now enable/disable the move buttons based on the contents and selction 
    // state of the listbox controls.
    EnableWindow( m_iIDAddButton, iSelCountAvailable > 0 ? TRUE : FALSE);
    EnableWindow( m_iIDAddAllButton, iCountAvailable > 0 ? TRUE : FALSE);
    EnableWindow( m_iIDRemoveButton, iSelCountChoosen > 0 ? TRUE : FALSE);
    EnableWindow( m_iIDRemoveAllButton, iCountChoosen > 0 ? TRUE : FALSE);

    // Determine whether or not the up and down buttons should be enabled or
    // disabled based on what is selected and where it is in the list.
    if(0 < iSelCountChoosen)
    {
        int     iSelFirst = -1, iSelLast = -1;

        // Loop through all of the items in the list.
        for(int iIndex = 0; iIndex < iCountChoosen; ++iIndex)
        {
            // Check if this item is selected.
            if( 0 < m_ctrlChoosenList.GetSel( iIndex ) )
            {
                if(-1 == iSelFirst)
                {
                    iSelFirst = iIndex;
                }
                iSelLast = iIndex;
            }
        }

        // Up is disabled if all of the selected items are at the top of the listbox
        bEnableMoveUp   = (iSelFirst == 0 &&  (iSelLast - iSelFirst + 1) == iSelCountChoosen)
                          ? FALSE: TRUE;

        // Down is disabled if all of the selected items are at the bottom of the listbox
        bEnableMoveDown = (iSelLast == iCountChoosen - 1  &&  (iSelLast - iSelFirst + 1) == iSelCountChoosen)
                          ? FALSE: TRUE;
    }

    // Enable/disable the up and down buttons
    EnableWindow(m_iIDMoveUpButton, bEnableMoveUp);
    EnableWindow(m_iIDMoveDownButton, bEnableMoveDown);
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			EnableWindow
//
//  Purpose:		Enables/disables a control based on the contents and 
//                  selection state of the listboxes. Advances the focus to the
//                  next control if the control being disabled has the focus.
//
//  Inputs:
//
//		int iIDControl
//
//		BOOL bEnable
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::EnableWindow(int iIDControl, BOOL bEnable)
{
    // If we are about to disable a control and it is the control that currently
    // has the focus advance the focus to the next control before disabling it.
    CWnd * pWnd = m_pWndParent->GetFocus();
    if(NULL != pWnd)
    {
        if( FALSE == bEnable && m_pWndParent->GetFocus()->GetDlgCtrlID() == iIDControl)
        {
            // Use SendMessage instead of call NextDlgCtrl() which would force
            // us to cast the rWndParent. Since we don't know if it is a CDialog,
            // CView, CProperyPage etc. calling SendMessage is the way to go.
            m_pWndParent->SendMessage(WM_NEXTDLGCTL, 0, 0L);
        }
    }

    // Now disable the control whose id was passed in if it is a valid window.
    // It may not be if this class was constructed with a NULL ID for a given
    // control
    pWnd = m_pWndParent->GetDlgItem(iIDControl);
    if(NULL != pWnd)
    {
        pWnd->EnableWindow( bEnable );
    }
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			SelectLBItem
//
//  Purpose:		Checks to see if the listbox is a single or multi select
//                  listbox and calls the appropriate selection method on the
//                  CListBox class.
//
//  Inputs:
//
//		CListBox & rListBox
//
//		int iItem
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		void 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
void CDualListManager::SelectLBItem(CListBox & rListBox, int iItem)
{
    if(rListBox.GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
    {
        rListBox.SetSel(iItem);
    }
    else
    {
        rListBox.SetCurSel(iItem);
    }
}

///////////////////////////////////////////////////////////////////////////////
//
//  Method:			ProcessCmdMsg
//
//  Purpose:		Should be called from the parents OnCmdMsg(...) method.
//                  Processes the windows commands associated with the buttons
//                  and listbox controls. Normally this would happen in the 
//                  message map but since the ids of the controls are passed
//                  into this class the message map cannot be used.
//                  
//                  The parent can also process the message if it wants or it
//                  can check the return code and bypass the message if it was
//                  handled by this method.
//
//  Inputs:
//
//		int nID - id of the control the message is associated with
//
//		int nCode - message value
//
//  Outputs:
//
//		None
//
//  Return value:
//
//		BOOL 
//
//  Exceptions:		None
//
///////////////////////////////////////////////////////////////////////////////
BOOL CDualListManager::ProcessCmdMsg(int nID, int nCode) 
{
    BOOL bProcessed = TRUE;

    // Add - button handler
    if(nID == m_iIDAddButton)
        MoveSelected(m_ctrlAvailableList, m_ArrayAvailable, m_ArrayChoosen, FALSE);
    // Add All - button handler
    else if(nID == m_iIDAddAllButton)
        MoveAll(m_ctrlAvailableList, m_ctrlChoosenList, m_ArrayAvailable, m_ArrayChoosen);
    // Remove - button handler
    else if(nID == m_iIDRemoveButton)
        MoveSelected(m_ctrlChoosenList, m_ArrayChoosen, m_ArrayAvailable, TRUE);
    // Remove All - button handler
    else if(nID == m_iIDRemoveAllButton)
        MoveAll(m_ctrlChoosenList, m_ctrlAvailableList, m_ArrayChoosen, m_ArrayAvailable);
    // Move Down - button handler
    else if(nID == m_iIDMoveDownButton)
        MoveUpOrDown(FALSE);
    // Move Up - button handler
    else if(nID == m_iIDMoveUpButton)
        MoveUpOrDown(TRUE);
    // Double Click on an item in the from list - handler
	else if(nID == m_iIDAvailableList && nCode == LBN_DBLCLK)
        MoveSelected(m_ctrlAvailableList, m_ArrayAvailable, m_ArrayChoosen, FALSE);
    // Double Click on an item in the to list - handler
	else if(nID == m_iIDChoosenList && nCode == LBN_DBLCLK)
        MoveSelected(m_ctrlChoosenList, m_ArrayChoosen, m_ArrayAvailable, TRUE);
    // Selection changed in the from list - handler
	else if(nID == m_iIDAvailableList && nCode == LBN_SELCHANGE)
        EnableButtons();
    // Selection changed in the to list - handler
	else if(nID == m_iIDChoosenList && nCode == LBN_SELCHANGE)
        EnableButtons();
    // All other messages are sent to the base class.
    else
        bProcessed = FALSE;

    // If we processed the message then update the buttons to reflect any 
    // changes we made.
    if(TRUE == bProcessed)
    {
        EnableButtons();
    }
	
    return bProcessed;
}

/////////////////////////////////////////////////////////////////////////////
// CDualListManager dialog


CDualListDialog::CDualListDialog(CWnd* pParent /*=NULL*/)
	: CDialog(CDualListDialog::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDualListManager)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CDualListDialog::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDualListManager)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDualListDialog, CDialog)
	//{{AFX_MSG_MAP(CDualListManager)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDualListManager message handlers

BOOL CDualListDialog::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}