// MFC_CmnControlDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MFC_CmnControl.h"
#include "MFC_CmnControlDlg.h"

// For Progress Dialog demo:
#include "PNProgressDlg.h"
// For CInputDlg class
#include "InputDlg.h"

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


HTREEITEM PNTreeViewFindItemText( CTreeCtrl* pTree, const char* pItemText, HTREEITEM hItem )
{
	// Default to Root Node
   if (hItem == 0 )
   	hItem = pTree->GetRootItem();
    
	// Check all siblings
	while( hItem != NULL )
	{
		CString Buffer;
		HTREEITEM hChildItem;

		// Is this the item?
		Buffer = pTree->GetItemText( hItem );
		if( Buffer.Compare( pItemText ) == 0)
			return hItem;

		// Look for children items
		hChildItem = pTree->GetChildItem( hItem );
		if( hChildItem )
		{
			// Recursive call: Check children node(s)
			HTREEITEM hItemFound = PNTreeViewFindItemText( pTree, 
				pItemText, hChildItem);

			// Did child call find it?
			if (hItemFound != NULL)
				return hItemFound;
		}

		// Go to next sibling item.
		hItem = pTree->GetNextItem( hItem, TVGN_NEXT );
	}

	// Didn't find it
	return NULL;

}

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

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

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

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

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

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMFC_CmnControlDlg dialog

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

void CMFC_CmnControlDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMFC_CmnControlDlg)
	DDX_Control(pDX, IDC_DRVTREE, m_DirTree);
	DDX_Control(pDX, IDC_GENTREE, m_GenTree);
	DDX_Control(pDX, IDC_DRVLIST2, m_DrvList2);
	DDX_Control(pDX, IDC_DRVLIST, m_DrvList);
	DDX_Control(pDX, IDC_SLIDERV, m_SliderV);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMFC_CmnControlDlg, CDialog)
	//{{AFX_MSG_MAP(CMFC_CmnControlDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_NOTIFY(UDN_DELTAPOS, IDC_SPININCH, OnDeltaposSpininch)
	ON_BN_CLICKED(IDC_PROGRESSGO, OnProgressgo)
	ON_WM_HSCROLL()
	ON_BN_CLICKED(IDC_DLGPROGDEMO, OnDlgprogdemo)
	ON_NOTIFY(NM_DBLCLK, IDC_DRVLIST, OnDblclkDrvlist)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_DRVLIST, OnItemchangedDrvlist)
	ON_BN_CLICKED(IDC_ADDTREE, OnAddtree)
	ON_BN_CLICKED(IDC_EDITTREE, OnEdittree)
	ON_BN_CLICKED(IDC_DELTREE, OnDeltree)
	ON_NOTIFY(TVN_SELCHANGED, IDC_DRVTREE, OnSelchangedDrvtree)
	ON_NOTIFY(TVN_ENDLABELEDIT, IDC_GENTREE, OnEndlabeleditGentree)
	ON_NOTIFY(TCN_SELCHANGE, IDC_TABDEMO, OnSelchangeTabdemo)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMFC_CmnControlDlg message handlers

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

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 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
	
	// TODO: Add extra initialization here
	m_Static.CreateEx( WS_EX_CLIENTEDGE, "STATIC", "0", WS_VISIBLE|WS_CHILD, 
		CRect(164, 46, 189, 68), this, 4000, 0 );
	m_Static.SetWindowText( "0" );
	m_Static.SetFont( GetFont() );
	m_Spin.Create( WS_CHILD|WS_VISIBLE|UDS_AUTOBUDDY|UDS_SETBUDDYINT,
		CRect(189,46,193,68), this, 4001);
	m_Spin.SetRange32( 0, 100 );

	// Set Minimum and maximum positions for spin control
	CWnd* pChild = GetDlgItem( IDC_SPIN1 );
	pChild->SendMessage( UDM_SETRANGE32, 0, 100 );
	SendDlgItemMessage( IDC_SPININCH, UDM_SETRANGE32, 0, 1000 );

	// Set default for the Inch spin control demo
	SetDlgItemText( IDC_EDITINCH, "1.00\"" );

	// Set Progress Bar range (from zero to 100)
	SendDlgItemMessage( IDC_PROGRESS1, PBM_SETRANGE32, 0, 100 );


	// Set the slider control range from zero to 100 (which is default anyway)
	SendDlgItemMessage( IDC_SLIDERH, TBM_SETRANGE, TRUE, MAKELONG(0,100) );

	// Alternative method, using the CSLiderCtrl:
	CSliderCtrl* pSlider = (CSliderCtrl*)GetDlgItem( IDC_SLIDERH );
	pSlider->SetRange( 0, 100, TRUE );
	

	// Demo: Set Slider selection range to 0 to 50, using CSliderCtrl data member 
	m_SliderV.SetSelection( 0, 50 );

	// Image List loading
	m_SmileyImages.Create( IDB_FACEIMGLIST, 16, 1, RGB(255,255,255) );

	// ListView initialization
	CListCtrl* pList = (CListCtrl*)GetDlgItem( IDC_FACELIST );
	pList->SetImageList( &m_SmileyImages, LVSIL_SMALL );
	pList->InsertColumn( 0, "Faces" );
	pList->InsertItem( 0, "Smiley", 0 );
	pList->InsertItem( 1, "Average", 1 );
	pList->InsertItem( 2, "Frowny", 2 );
	pList->InsertItem( 3, "Surprise", 3 );
	CRect Rect;
	pList->GetClientRect( &Rect );
	pList->SetColumnWidth( 0, Rect.Width() );
	ListView_SetExtendedListViewStyle( pList->m_hWnd, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); 


	// Tree View Initialization
	CTreeCtrl* pTree = (CTreeCtrl*)GetDlgItem( IDC_GENTREE );
	pTree->SetImageList( &m_SmileyImages, TVSIL_NORMAL );
	pTree->InsertItem( "Root", 0, 3 );


	// Tab Control initialization
	CTabCtrl* pTab = (CTabCtrl*)GetDlgItem( IDC_TABDEMO );
	pTab->InsertItem( 0, "Animation" );
	pTab->InsertItem( 1, "RichEdit" );
	pTab->InsertItem( 2, "DateTime" );
	pTab->InsertItem( 3, "IP Address" );
	pTab->SetWindowPos( 0, 0, 0, 250, 220, SWP_NOZORDER|SWP_NOMOVE );


	// Determine display area of the tab control
	CRect TabRect;
	pTab->GetClientRect( &Rect );
	pTab->GetItemRect( 0, &TabRect);
	Rect.top = 8;
	Rect.left = 8;
	Rect.bottom -= (8+TabRect.bottom);
	Rect.right -=8;

	// Initialize animation control, and place it in the tab control
	CAnimateCtrl * pAnimate = (CAnimateCtrl *)GetDlgItem( IDC_ANIMATE );
	if( pAnimate->Open( IDR_AVI1 ) != FALSE )
		pAnimate->Play( 0, -1, -1 );
	pAnimate->SetParent( pTab );
	pAnimate->SetWindowPos( 0, 8, TabRect.bottom+8, Rect.right-8, Rect.bottom-8, SWP_NOZORDER );

	// Initialize Rich edit control, and place it in the tab control
	CRichEditCtrl* pRich = (CRichEditCtrl*) GetDlgItem( IDC_RICHEDIT );
	pRich->SetParent( pTab );
	pRich->SetWindowPos( 0, 8, TabRect.bottom+8, Rect.right-8, Rect.bottom-8, SWP_NOZORDER );
	pRich->ShowWindow( SW_HIDE );

	CHARFORMAT CharFormat;
	CharFormat.cbSize = sizeof( CharFormat );
	CharFormat.dwMask = CFM_FACE|CFM_ITALIC;
	CharFormat.dwEffects = CFE_ITALIC;
	strcpy( CharFormat.szFaceName, "Times New Roman" );
	pRich->SetDefaultCharFormat( CharFormat );

	
	// Date Time picker control: Make it a child to the tab control,
	// reposition and resize it, and then hide it.
	CDateTimeCtrl* pDateTime = (CDateTimeCtrl*)GetDlgItem( IDC_DATETIMEPICKER );
	pDateTime->SetParent( pTab );
	pDateTime->SetWindowPos( 0, 8, TabRect.bottom+8, Rect.right-8, Rect.bottom-8, SWP_NOZORDER|SWP_NOSIZE );
	pDateTime->ShowWindow( SW_HIDE );

	// Month control: Make it child of the tab control
	CMonthCalCtrl* pMonth = (CMonthCalCtrl*)GetDlgItem( IDC_MONTHCALENDAR );
	pMonth->SetParent( pTab );
	pMonth->SetWindowPos( 0, 8, TabRect.bottom+36, Rect.right-8, Rect.bottom-36, SWP_NOZORDER );
	pMonth->ShowWindow( SW_HIDE );

	// IP: Make it child of the tab control
	CIPAddressCtrl* pIP = (CIPAddressCtrl*)GetDlgItem( IDC_IPADDRESS );
	pIP->SetParent( pTab );
	pIP->SetWindowPos( 0, 8, TabRect.bottom+36, Rect.right-8, Rect.bottom-36, SWP_NOZORDER|SWP_NOSIZE );
	pIP->ShowWindow( SW_HIDE );

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

void CMFC_CmnControlDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

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

void CMFC_CmnControlDlg::OnDeltaposSpininch(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
	// TODO: Add your control notification handler code here

	CString Text;
	
	// Base new value on Value from Edit box
	GetDlgItemText( IDC_EDITINCH, Text );
	int NewPos = int(atof( Text ) * 100) + pNMUpDown->iDelta;
	
	// Insure minimum and maximum values are enforced
	int Upper, Lower;
	SendDlgItemMessage( IDC_SPININCH, UDM_GETRANGE32, (WPARAM)&Lower, (LPARAM)&Upper );
	if( NewPos<Lower )
		NewPos=Lower;
	else if (NewPos > Upper )
		NewPos = Upper;

	// Put value into the Edit box
	Text.Format( "%-2.2f\"", NewPos/100.0 );
	SetDlgItemText( IDC_EDITINCH, Text );
	
	*pResult = 0;
}


void CMFC_CmnControlDlg::OnProgressgo() 
{
	// TODO: Add your control notification handler code here
	CWaitCursor Tmp;

	// Enter our loop (simulated processing)
	for( int i=0; i < 100; i++ )
	{
		// Simulate a delay:
		Sleep( 10 );
		// Update progress bar with new position:
		SendDlgItemMessage( IDC_PROGRESS1, PBM_SETPOS, i, 0 );
	}
	
}

void CMFC_CmnControlDlg::OnDlgprogdemo() 
{
	CPNProgressDlg Prog( this );

	// Enter our loop (simulated processing)
	Prog.Reset( 0, 100 );
	CString Tmp;

	for( int i=0; i < 100; i++ )
	{
		// Simulate a delay:
		Sleep( 10 );
		// Update progress bar with new position:
		Tmp.Format( "%d of %d", i+1, 100 );
		if( Prog.SetPos( i, Tmp ) == false ) 
			break; // break out of loop if user canceled
		// Perform actual processing here
	}
	if( Prog.WasCancelled() )
		MessageBox( "Processing canceled" );
}

void CMFC_CmnControlDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// In MFC, Slider messages are sent as WM_HSCROLL to the parent window:
	if( pScrollBar->GetDlgCtrlID() == IDC_SLIDERH ) // Make sure it's the control we want
	{
		// Typecast the CScrollBar pointer to a CSliderCtrl pointer
		CSliderCtrl* pSlider = (CSliderCtrl*)pScrollBar;
		if( nSBCode==TB_THUMBPOSITION )
			TRACE( "TB_THUMBPOSITION %d\n", nPos );
		else
			if( nSBCode == TB_ENDTRACK )
				TRACE( "TB_ENDTRACK %d\n", nPos );

		nPos = pSlider->GetPos();
	
		// Place the position into a static control, for additional user feedback:
		CString Tmp;
		Tmp.Format( "%d", nPos );
		SetDlgItemText( IDC_SLIFERVAL, Tmp );

		// For demo purposes, update another slider with the same position
		// This would be useful when you update a slider from an edit box.
		SendDlgItemMessage( IDC_SLIDERV, TBM_SETPOS, TRUE, nPos );
	}
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}


void CMFC_CmnControlDlg::OnDblclkDrvlist(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	CString Text;
	int i= m_DrvList.GetNextItem( -1, LVNI_SELECTED );
	if( i >=0 )
	{
		Text = m_DrvList.GetItemText( i, 0 );
		MessageBox( Text, "You selected" );
	}

	*pResult = 0;
}

void CMFC_CmnControlDlg::OnItemchangedDrvlist(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

	CString Text;
	int i= m_DrvList.GetNextItem( -1, LVNI_SELECTED );
	if( i >=0 )
	{
		Text = m_DrvList.GetItemText( i, 0 );
		SetDlgItemText( IDC_DRVSELECTED, Text );
	}
	*pResult = 0;
}

void CMFC_CmnControlDlg::OnAddtree() 
{

	CInputDlg Tmp;
	Tmp.m_Prompt = "Enter text for new item:";
	if( Tmp.DoModal() == IDOK )
	{
		HTREEITEM hItem = m_GenTree.GetSelectedItem();
		m_GenTree.InsertItem( Tmp.m_Text, 0, 3, hItem );
		m_GenTree.InvalidateRect(NULL);
	}
}

void CMFC_CmnControlDlg::OnEdittree() 
{
	CInputDlg Tmp;
	HTREEITEM hItem = m_GenTree.GetSelectedItem();
	if( hItem == 0 )
	{
		MessageBox("Please select an item to edit" );
		return;
	}

	Tmp.m_Prompt = "Edit text as desired:";
	Tmp.m_Text = m_GenTree.GetItemText( hItem );
	if( Tmp.DoModal() == IDOK )
		m_GenTree.SetItemText( hItem, Tmp.m_Text );
	
}

void CMFC_CmnControlDlg::OnDeltree() 
{
	CInputDlg Tmp;
	HTREEITEM hItem = m_GenTree.GetSelectedItem();
	if( hItem == 0 )
	{
		MessageBox("Please select an item to delete" );
		return;
	}

	if( MessageBox( "Are you sure you want to delete the selected item?", "Confirmation", MB_ICONINFORMATION|MB_YESNO ) == IDYES )
		m_GenTree.DeleteItem( hItem );

}


void CMFC_CmnControlDlg::OnSelchangedDrvtree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here

	HTREEITEM hItem = m_DirTree.GetSelectedItem();

	if( hItem )
		SetDlgItemText( IDC_DRVSELECTEDTREE, m_DirTree.GetFullPath( hItem ) );

	*pResult = 0;
}

void CMFC_CmnControlDlg::OnEndlabeleditGentree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;

	CTreeCtrl* pTree = (CTreeCtrl*)GetDlgItem( IDC_GENTREE );
	pTree->SetItem( &pTVDispInfo->item );

	*pResult = 0;
}

void CMFC_CmnControlDlg::OnSelchangeTabdemo(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CTabCtrl* pTab = (CTabCtrl*)GetDlgItem( IDC_TABDEMO );
	int Index = pTab->GetCurSel();

	CWnd* pWin;
	
	// Page 1
	pWin = pTab->GetDlgItem( IDC_ANIMATE );
	pWin->ShowWindow( Index==0? SW_SHOW : SW_HIDE );

	// Page 2
	pWin = pTab->GetDlgItem( IDC_RICHEDIT );
	pWin->ShowWindow( Index==1? SW_SHOW : SW_HIDE );

	// Page 3
	pWin = pTab->GetDlgItem( IDC_DATETIMEPICKER );
	pWin->ShowWindow( Index==2? SW_SHOW : SW_HIDE );
	pWin = pTab->GetDlgItem( IDC_MONTHCALENDAR );
	pWin->ShowWindow( Index==2? SW_SHOW : SW_HIDE );

	// Page 4
	pWin = pTab->GetDlgItem( IDC_IPADDRESS );
	pWin->ShowWindow( Index==3 ? SW_SHOW : SW_HIDE );
	 
	*pResult = 0;
}
