www.pudn.com > 完整的FTP客户端ftpwanderersrc.zip > TransferManagerDlg.cpp


/****************************************************************/ 
/*																*/ 
/*  TransferManagerDlg.cpp										*/ 
/*																*/ 
/*  Implementation of the CTransferManagerDlg class.			*/ 
/*																*/ 
/*  Programmed by Pablo van der Meer							*/ 
/*  Copyright Pablo Software Solutions 2002						*/ 
/*	http://www.pablovandermeer.nl								*/ 
/*																*/ 
/*  Last updated: 15 may 2002									*/ 
/*																*/ 
/****************************************************************/ 
 
#include "stdafx.h" 
#include "ftpwanderer.h" 
#include "TransferManagerDlg.h" 
#include "MainFrm.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
CTransferManagerDlg::CTransferManagerDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CTransferManagerDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CTransferManagerDlg) 
		// NOTE: the ClassWizard will add member initialization here 
	//}}AFX_DATA_INIT 
	m_bShow = FALSE; 
	m_nActiveTransfers = 0; 
	m_bRemoveFailed = FALSE; 
	m_bBuildingQueue = FALSE; 
} 
 
 
void CTransferManagerDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CTransferManagerDlg) 
	DDX_Control(pDX, IDC_QUEUELIST, m_QueueList); 
	//}}AFX_DATA_MAP 
	m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_TRANSFERMANAGER));  
} 
 
 
CTransferManagerDlg::~CTransferManagerDlg() 
{ 
	// kill all running download threads 
    while(!m_DownloadThreads.IsEmpty()) 
    { 
        m_DownloadThreads.RemoveHead()->KillThread(); 
    }	 
 
	// kill all running upload threads 
    while(!m_UploadThreads.IsEmpty()) 
    { 
        m_UploadThreads.RemoveHead()->KillThread(); 
    }	 
} 
 
 
BEGIN_MESSAGE_MAP(CTransferManagerDlg, CDialog) 
	//{{AFX_MSG_MAP(CTransferManagerDlg) 
	ON_WM_SIZE() 
	ON_WM_CLOSE() 
	ON_WM_DESTROY() 
	ON_WM_TIMER() 
	ON_NOTIFY(NM_RCLICK, IDC_QUEUELIST, OnRclickQueuelist) 
	ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectall) 
	ON_COMMAND(ID_EDIT_INVERTSELECTION, OnEditInvertselection) 
	ON_COMMAND(ID_TRANSFER_CANCEL, OnTransferCancel) 
	ON_COMMAND(ID_TRANSFER_RESUBMIT, OnTransferResubmit) 
	ON_COMMAND(ID_TRANSFER_EXIT, OnTransferExit) 
	//}}AFX_MSG_MAP 
	ON_MESSAGE(WM_DOWNLOAD_FINISHED, OnDownloadFinished) 
	ON_MESSAGE(WM_UPLOAD_FINISHED, OnUploadFinished) 
	ON_MESSAGE(WM_FTP_STATUS, OnFtpStatus) 
END_MESSAGE_MAP() 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnInitDialog										*/ 
/* Description   : Initialize dialog.								*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CTransferManagerDlg::OnInitDialog()  
{ 
	CDialog::OnInitDialog(); 
	 
	WINDOWPLACEMENT wp; 
 
	if (AfxGetApp()->GetProfileInt("Settings", "SavePosition", 1)) 
	{ 
		// only restore if there is a previously saved position 
		if ( -1 != (wp.rcNormalPosition.top = AfxGetApp()->GetProfileInt("TransferManager", "WndTop",      -1)) && 
			 -1 != (wp.rcNormalPosition.left = AfxGetApp()->GetProfileInt("TransferManager", "WndLeft",     -1)) && 
			 -1 != (wp.rcNormalPosition.bottom = AfxGetApp()->GetProfileInt("TransferManager", "WndBottom",   -1)) && 
			 -1 != (wp.rcNormalPosition.right = AfxGetApp()->GetProfileInt("TransferManager", "WndRight",    -1)) 
		   )  
		{ 
			// make sure the window is not completely out of sight 
			int max_x = GetSystemMetrics(SM_CXSCREEN) - GetSystemMetrics(SM_CXICON); 
			int max_y = GetSystemMetrics(SM_CYSCREEN) - GetSystemMetrics(SM_CYICON); 
			wp.rcNormalPosition.left = min(wp.rcNormalPosition.left, max_x); 
			wp.rcNormalPosition.top = min(wp.rcNormalPosition.top, max_y); 
			wp.showCmd = m_bShow ? SW_SHOWNA : SW_HIDE; 
			// Save main window position 
			SetWindowPlacement(&wp); 
		} 
	} 
 
	CRect rc; 
	GetClientRect(rc); 
	rc.right -= 7*GetSystemMetrics(SM_CXBORDER); 
 
	// insert columns 
	m_QueueList.InsertColumn(0, "Filename", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(1, "Host", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(2, "From", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(3, "To", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(4, "Status", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(5, "Progress", LVCFMT_LEFT, rc.Width()/6); 
 
	DWORD dwStyle = m_QueueList.GetExtendedStyle(); 
	dwStyle |= LVS_EX_FULLROWSELECT; 
    m_QueueList.SetExtendedStyle(dwStyle); 
 
	// do not take ownership of the imagelist! 
	m_QueueList.ModifyStyle(0, LVS_SHAREIMAGELISTS); 
	InitListViewImageList(); 
 
	// set a nicer icon 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
	SetIcon(m_hIcon, TRUE); 
 
	// always on top 
	SetWindowPos(&wndTopMost, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); 
 
	SetTimer(1, 1000, NULL); 
	return TRUE; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnSize											*/ 
/* Description   : Resize queue list.								*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnSize(UINT nType, int cx, int cy)  
{ 
	CDialog::OnSize(nType, cx, cy); 
	 
	if (IsWindow(m_QueueList.m_hWnd)) 
	{ 
		m_QueueList.MoveWindow(2, 2, cx-4, cy-4); 
	}  
} 
 
/* 
BOOL CTransferManagerDlg::Create(CWnd* pParentWnd, BOOL bShow) 
{ 
	m_bShow = bShow; 
 
	// ToolBar 
	if(!CDialog::Create(pParentWnd, WS_CHILD | WS_VISIBLE| CBRS_TOP | CBRS_SIZE_DYNAMIC), IDD_TRANSFERMANAGER) 
	{ 
		return FALSE; 
	} 
 
	SetBorders(4,4,4,4); 
 
	// ListCtrl 
	if(!m_QueueList.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_AUTOARRANGE | LVS_REPORT, CRect(2, 1, 0, 0), this, IDC_QUEUELIST)) 
	{ 
		return FALSE; 
	} 
 
//	ShowWindow(m_bShow ? SW_SHOW : SW_HIDE); 
 
	SetWindowText("Transfer Manager"); 
	 
//	EnableDocking(CBRS_ALIGN_ANY); 
 
	m_bChangeDockedSize = TRUE; 
    m_sizeFloating = m_sizeDocked = CSize(500, 100); 
 
  CRect rc; 
	GetClientRect(rc); 
	rc.right -= 7*GetSystemMetrics(SM_CXBORDER); 
 
	// insert columns 
	m_QueueList.InsertColumn(0, "Filename", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(1, "Host", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(2, "From", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(3, "To", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(4, "Status", LVCFMT_LEFT, rc.Width()/6); 
	m_QueueList.InsertColumn(5, "Progress", LVCFMT_LEFT, rc.Width()/6); 
 
	DWORD dwStyle = m_QueueList.GetExtendedStyle(); 
	dwStyle |= LVS_EX_FULLROWSELECT; 
    m_QueueList.SetExtendedStyle(dwStyle); 
 
	InitListViewImageList(); 
 
	// set a nicer icon 
//	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
//	SetIcon(m_hIcon, TRUE); 
 
	// always on top 
//	SetWindowPos(&wndTopMost, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); 
 
	SetTimer(1, 1000, NULL); 
 
	return TRUE; 
} 
 
 
CSize CTransferManagerDlg::CalcDynamicLayout(int nLength, DWORD dwMode) 
{ 
	ASSERT(GetParent()); 
 
	CRect rcFrame; 
	GetParent()->GetClientRect(&rcFrame); 
 
	CSize size(dwMode & LM_HORZ ? 502 : m_sizeDocked.cx, dwMode & LM_HORZ ? m_sizeDocked.cy : 500); 
 
	if(dwMode & LM_HORZDOCK) 
		size.cx = max(size.cx, rcFrame.right);// + 4); 
	else 
		size.cy = max(size.cy, rcFrame.bottom);// + 4); 
	 
	if (IsFloating()) 
	{ 
		// Return default if it is being docked or floated 
       if ((dwMode & LM_VERTDOCK) || (dwMode & LM_HORZDOCK)) 
       { 
       } 
	   else 
       if (dwMode & LM_MRUWIDTH) 
           size = m_sizeFloating; 
	   else 
       // In all other cases, accept the dynamic length 
       if (dwMode & LM_LENGTHY) 
	   { 
           size = CSize(m_sizeFloating.cx, (m_bChangeDockedSize) ? 
                        m_sizeFloating.cy = m_sizeDocked.cy = nLength : 
                        m_sizeFloating.cy = nLength); 
	   } 
       else 
	   { 
           size = CSize((m_bChangeDockedSize) ? 
                        m_sizeFloating.cx = m_sizeDocked.cx = nLength : 
                        m_sizeFloating.cx = nLength, m_sizeFloating.cy); 
	   } 
	} 
 
	if(m_QueueList.m_hWnd != NULL) 
	{ 
		m_QueueList.SetWindowPos(NULL, 0, 0, size.cx-16, size.cy - 16, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOCOPYBITS); 
		int cx = size.cx- 16 - 7*GetSystemMetrics(SM_CXBORDER); 
		m_QueueList.SetColumnWidth(0, cx/6); 
		m_QueueList.SetColumnWidth(1, cx/6); 
		m_QueueList.SetColumnWidth(2, cx/6); 
		m_QueueList.SetColumnWidth(3, cx/6); 
		m_QueueList.SetColumnWidth(4, cx/6); 
		m_QueueList.SetColumnWidth(5, cx/6); 
	} 
	return size; 
} 
*/ 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : Create											*/ 
/* Description   : Create modeless dialog.							*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CTransferManagerDlg::Create(BOOL bShow) 
{ 
	m_bShow = bShow; 
	if (CDialog::Create(CTransferManagerDlg::IDD)) 
	{ 
		ShowWindow(m_bShow ? SW_SHOW : SW_HIDE); 
		return TRUE; 
	} 
	return FALSE; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : PostNcDestroy									*/ 
/* Description   : Destroy attached class.							*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::PostNcDestroy()  
{ 
	CDialog::PostNcDestroy(); 
	delete this; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnOK												*/ 
/* Description   : Prevent pressing ENTER closing dialog.			*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnOK()  
{ 
//	CDialog::OnOK(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnCancel											*/ 
/* Description   : Prevent pressing ESC closing dialog.				*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnCancel()  
{ 
//	CDialog::OnCancel(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnClose											*/ 
/* Description   : Do not close but hide dialog on WM_CLOSE.		*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnClose()  
{ 
	AfxGetApp()->WriteProfileInt("Settings", "ShowTransferManager", 0); 
	ShowWindow(SW_HIDE); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnDestroy										*/ 
/* Description   : Save window position.							*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnDestroy()  
{ 
	if (AfxGetApp()->GetProfileInt("Settings", "SavePosition", 1)) 
	{ 
		// Save main window position 
		WINDOWPLACEMENT wp; 
		GetWindowPlacement(&wp); 
		AfxGetApp()->WriteProfileInt("TransferManager", "WndStatus", wp.showCmd); 
		AfxGetApp()->WriteProfileInt("TransferManager", "WndTop",    wp.rcNormalPosition.top); 
		AfxGetApp()->WriteProfileInt("TransferManager", "WndLeft",   wp.rcNormalPosition.left); 
		AfxGetApp()->WriteProfileInt("TransferManager", "WndBottom", wp.rcNormalPosition.bottom); 
		AfxGetApp()->WriteProfileInt("TransferManager", "WndRight",  wp.rcNormalPosition.right); 
	}	 
	CDialog::OnDestroy(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : QueueDownload									*/ 
/* Description   : Create thread and add download to queue.			*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::QueueDownload(LPCTSTR lpszServerName, LPCTSTR lpszUserName, LPCTSTR lpszPassword, LPCTSTR lpszRemoteName, LPCTSTR lpszLocalName, LPCTSTR lpszCurrentDirectory, DWORD dwFileLength, DWORD dwTransferType, int nRetries, int nRetryDelay, int nPort, BOOL bUsePASVMode, BOOL bFailed) 
{ 
	CDownloadThread *pThread; 
    pThread = new CDownloadThread; 
    if (pThread != NULL) 
    { 
		ASSERT_VALID(pThread); 
        // Create Thread in a suspended state so we can set the Priority 
        // before it starts gettings away from us ... 
        if (!pThread->CreateThread(CREATE_SUSPENDED)) 
        { 
			delete pThread; 
			return; 
        } 
		 
		BOOL bIsDirectory = (lstrlen(lpszRemoteName) == 0); 
 
		int nIcon = GetIconIndex(lpszRemoteName, bIsDirectory); 
		int nIndex = m_QueueList.InsertItem(m_QueueList.GetItemCount(), bIsDirectory ? "" : lpszRemoteName, nIcon); 
		 
		m_QueueList.SetItemText(nIndex, 1, lpszServerName); 
		 
		CString str = lpszCurrentDirectory; 
		// make sure we only have 1 slash 
		str.TrimRight('/'); 
		str += "/"; 
		str += lpszRemoteName; 
 
		m_QueueList.SetItemText(nIndex, 2, str); 
		m_QueueList.SetItemText(nIndex, 3, lpszLocalName); 
		m_QueueList.SetItemText(nIndex, 4, bFailed ? "Failed" : "Queued"); 
		m_QueueList.SetItemData(nIndex, pThread->m_nThreadID); 
		 
		DoEvents(); 
 
        // since everything is successful, add the thread to our list 
        m_DownloadThreads.AddTail(pThread); 
	 
		// set priority to normal for now ... 
        VERIFY(pThread->SetThreadPriority(THREAD_PRIORITY_NORMAL)); 
 
		// initialize thread 
		pThread->m_strServerName = lpszServerName; 
		pThread->m_strUserName = lpszUserName; 
		pThread->m_strPassword = lpszPassword; 
		pThread->m_strRemoteName = lpszRemoteName; 
		pThread->m_strLocalName = lpszLocalName; 
		pThread->m_strCurrentDirectory = lpszCurrentDirectory; 
		pThread->m_dwFileLength = dwFileLength; 
		pThread->m_dwTransferType = dwTransferType; 
		pThread->m_nRetries = nRetries; 
		pThread->m_nRetryDelay = nRetryDelay; 
		pThread->m_nConnectionTimeout = m_nConnectionTimeout*1000; 
		pThread->m_nPort = nPort; 
		pThread->m_bUsePASVMode = bUsePASVMode; 
 
        pThread->m_pTransferManager = this; 
		 
		CheckTransferQueue();         
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : QueueUpload										*/ 
/* Description   : Create thread and add upload to queue.			*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::QueueUpload(LPCTSTR lpszServerName, LPCTSTR lpszUserName, LPCTSTR lpszPassword, LPCTSTR lpszLocalName, LPCTSTR lpszRemoteName, LPCTSTR lpszCurrentDirectory, DWORD dwTransferType, int nRetries, int nRetryDelay, int nPort, BOOL bUsePASVMode, BOOL bFailed) 
{ 
	CUploadThread *pThread; 
    pThread = new CUploadThread; 
    if (pThread != NULL) 
    { 
		ASSERT_VALID(pThread); 
        // Create Thread in a suspended state so we can set the Priority 
        // before it starts gettings away from us ... 
        if (!pThread->CreateThread(CREATE_SUSPENDED)) 
        { 
			delete pThread; 
        } 
 
		BOOL bIsDirectory = FALSE; 
 
		int nIcon = GetIconIndex(lpszLocalName, bIsDirectory); 
 
		int nIndex = m_QueueList.InsertItem(m_QueueList.GetItemCount(), lpszLocalName, nIcon); 
		m_QueueList.SetItemText(nIndex, 1, lpszServerName); 
		 
		CString str = lpszCurrentDirectory; 
		// make sure we only have 1 slash 
		str.TrimRight('/'); 
		str += "/"; 
		str += lpszRemoteName; 
 
		m_QueueList.SetItemText(nIndex, 2, lpszLocalName); 
		m_QueueList.SetItemText(nIndex, 3, str); 
		m_QueueList.SetItemText(nIndex, 4, bFailed ? "Failed" : "Queued"); 
		m_QueueList.SetItemData(nIndex, pThread->m_nThreadID); 
		 
		DoEvents(); 
 
        // since everything is successful, add the thread to our list 
        m_UploadThreads.AddTail(pThread); 
	 
		// set priority to normal for now ... 
        VERIFY(pThread->SetThreadPriority(THREAD_PRIORITY_NORMAL)); 
 
		// initialize thread 
		pThread->m_strServerName = lpszServerName; 
		pThread->m_strUserName = lpszUserName; 
		pThread->m_strPassword = lpszPassword; 
		pThread->m_strRemoteName = lpszRemoteName; 
		pThread->m_strLocalName = lpszLocalName; 
		pThread->m_strCurrentDirectory = lpszCurrentDirectory; 
		pThread->m_dwFileLength = 0; 
		pThread->m_dwTransferType = dwTransferType; 
		pThread->m_nRetries = nRetries; 
		pThread->m_nRetryDelay = nRetryDelay; 
		pThread->m_nConnectionTimeout = m_nConnectionTimeout*1000; 
		pThread->m_nPort = nPort; 
		pThread->m_bUsePASVMode = bUsePASVMode; 
 
		pThread->m_pTransferManager = this; 
 
		CheckTransferQueue();         
    } 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnFtpStatus										*/ 
/* Description   : Status of upload or download has changed.		*/ 
/*																	*/ 
/********************************************************************/ 
LRESULT CTransferManagerDlg::OnFtpStatus(WPARAM wParam, LPARAM lParam) 
{ 
	CWinThread *pThread = (CWinThread *)wParam; 
	 
	LPSTR lpszData = (LPSTR)lParam; 
	 
	LVFINDINFO lvFindInfo; 
 
	lvFindInfo.flags = LVFI_PARAM; 
	lvFindInfo.lParam = pThread->m_nThreadID; 
 
	int nIndex = m_QueueList.FindItem(&lvFindInfo); 
	if (nIndex != -1) 
	{ 
		m_QueueList.SetItemText(nIndex, 4, lpszData); 
	 
		m_QueueList.GetItemText(nIndex, 0); 
		CString str; 
		str.Format("[%d] \"%s\" transfer status: %s", pThread->m_nThreadID, m_QueueList.GetItemText(nIndex, 0), lpszData); 
		AfxGetMainWnd()->SendMessage(WM_FTP_STATUS, 0,(LPARAM)(LPCTSTR)str); 
		delete[] lpszData; 
	} 
	return 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnDownloadFinished								*/ 
/* Description   : Download has finished							*/ 
/*																	*/ 
/********************************************************************/ 
LRESULT CTransferManagerDlg::OnDownloadFinished(WPARAM wParam, LPARAM lParam) 
{ 
	CDownloadThread *pThread = (CDownloadThread *)wParam; 
	CString strResult; 
	strResult.Format("[%d] %s", pThread->m_nThreadID, pThread->GetLastError()); 
	 
	AfxGetMainWnd()->SendMessage(WM_DOWNLOAD_FINISHED, (WPARAM)pThread->m_bTransferFailed ? 3 : 1, (LPARAM)(LPCTSTR)strResult); 
 
	LVFINDINFO lvFindInfo; 
 
	lvFindInfo.flags = LVFI_PARAM; 
	lvFindInfo.lParam = pThread->m_nThreadID; 
 
	int nIndex = m_QueueList.FindItem(&lvFindInfo); 
	if (nIndex != -1) 
	{ 
		m_QueueList.DeleteItem(nIndex); 
	} 
 
	// remove thread from list 
	POSITION pos = m_DownloadThreads.Find(pThread); 
	if (pos != NULL) 
	{ 
		m_DownloadThreads.RemoveAt(pos); 
	} 
	m_nActiveTransfers--; 
 
	if (pThread->m_bTransferFailed && !m_bRemoveFailed) 
	{ 
		// add the download at the end of the que with 'Failed" status 
		QueueDownload(pThread->m_strServerName,  
					  pThread->m_strUserName,  
					  pThread->m_strPassword,  
					  pThread->m_strRemoteName,  
					  pThread->m_strLocalName,  
					  pThread->m_strCurrentDirectory,  
					  pThread->m_dwFileLength, 
					  pThread->m_dwTransferType, 
					  pThread->m_nRetries, 
					  pThread->m_nRetryDelay, 
					  pThread->m_nPort, 
					  pThread->m_bUsePASVMode, 
					  TRUE); 
	} 
	pThread->KillThread(); 
	 
	CheckTransferQueue(); 
	return 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnUploadFinished									*/ 
/* Description   : Upload has finished								*/ 
/*																	*/ 
/********************************************************************/ 
LRESULT CTransferManagerDlg::OnUploadFinished(WPARAM wParam, LPARAM lParam) 
{ 
	CUploadThread *pThread = (CUploadThread *)wParam; 
	CString strResult; 
	strResult.Format("[%d] %s", pThread->m_nThreadID, pThread->GetLastError()); 
 
	AfxGetMainWnd()->SendMessage(WM_UPLOAD_FINISHED, (WPARAM)pThread->m_bTransferFailed ? 3 : 1, (LPARAM)(LPCTSTR)strResult); 
 
	LVFINDINFO lvFindInfo; 
 
	lvFindInfo.flags = LVFI_PARAM; 
	lvFindInfo.lParam = pThread->m_nThreadID; 
 
	int nIndex = m_QueueList.FindItem(&lvFindInfo); 
	if (nIndex != -1) 
	{ 
		m_QueueList.DeleteItem(nIndex); 
	} 
 
	// remove thread from list 
	POSITION pos = m_UploadThreads.Find(pThread); 
	if (pos != NULL) 
	{ 
		m_UploadThreads.RemoveAt(pos); 
	} 
	// successfull upload ? 
	if ((BOOL)lParam == TRUE) 
	{ 
		if (pThread->m_dwFileLength != -1) 
		{ 
			((CMainFrame *)AfxGetMainWnd())->AddNewFile(pThread->m_strRemoteName, pThread->m_dwFileLength, pThread->m_strCurrentDirectory); 
		} 
		else 
		{ 
			pThread->m_strRemoteName.TrimRight('/'); 
			// only add 'root' level directories 
			if (pThread->m_strRemoteName.Find('/') == -1) 
				((CMainFrame *)AfxGetMainWnd())->AddNewFolder(pThread->m_strRemoteName, pThread->m_strCurrentDirectory); 
		} 
	} 
 
	m_nActiveTransfers--; 
 
	if (pThread->m_bTransferFailed && !m_bRemoveFailed) 
	{ 
		// add the download at the end of the que with 'Failed" status 
		QueueUpload(pThread->m_strServerName,  
					  pThread->m_strUserName,  
					  pThread->m_strPassword,  
					  pThread->m_strLocalName,  
					  pThread->m_strRemoteName,  
					  pThread->m_strCurrentDirectory,  
					  pThread->m_dwTransferType, 
					  pThread->m_nRetries, 
					  pThread->m_nRetryDelay, 
					  pThread->m_nPort, 
					  pThread->m_bUsePASVMode, 
					  TRUE); 
	} 
 
	pThread->KillThread(); 
 
	CheckTransferQueue(); 
	return 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnTimer											*/ 
/* Description   : Check for queued transfers						*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnTimer(UINT nIDEvent)  
{ 
	if (nIDEvent == 1) 
	{ 
		CheckTransferQueue(); 
	} 
	CDialog::OnTimer(nIDEvent); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : CheckTransferQueue								*/ 
/* Description   : Check if any of the queued transfers can be		*/ 
/*				   activated.										*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::CheckTransferQueue() 
{ 
	if (m_bBuildingQueue) 
		return; 
 
	if ((m_nActiveTransfers <= m_nMaximumTransfers) || m_nMaximumTransfers == 0) 
	{ 
		for (int i = 0; i < m_QueueList.GetItemCount(); i++) 
		{ 
			CString strStatus = m_QueueList.GetItemText(i, 4); 
			DWORD nThreadID = m_QueueList.GetItemData(i); 
			if (strStatus == "Queued") 
			{ 
				// find thread in download list 
				POSITION pos = m_DownloadThreads.GetHeadPosition(); 
				while(pos != NULL) 
				{ 
					CDownloadThread *pThread = (CDownloadThread *)m_DownloadThreads.GetNext(pos); 
					if (pThread->m_nThreadID == nThreadID) 
					{ 
						m_nActiveTransfers++; 
						pThread->ResumeThread(); 
						break; 
					} 
				} 
				 
				// find thread in upload list 
				pos = m_UploadThreads.GetHeadPosition(); 
				while(pos != NULL) 
				{ 
					CUploadThread *pThread = (CUploadThread *)m_UploadThreads.GetNext(pos); 
					if (pThread->m_nThreadID == nThreadID) 
					{ 
						// start transfer 
						m_nActiveTransfers++; 
						pThread->ResumeThread(); 
						break; 
					} 
				} 
			} 
			if ((m_nActiveTransfers >= m_nMaximumTransfers) && (m_nMaximumTransfers != 0)) 
				break; 
		} 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnRclickQueuelist								*/ 
/* Description   : Show context menu								*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnRclickQueuelist(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	int nIndex = m_QueueList.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);  
	if (nIndex == -1) 
		return; 
 
	CMenu menu; 
	menu.LoadMenu(MAKEINTRESOURCE(IDR_TRANSFERMANAGER)); 
 
	POINT pt; 
	GetCursorPos(&pt); 
 
	menu.GetSubMenu(0)->TrackPopupMenu(0, pt.x, pt.y, this, NULL);	 
 
	*pResult = 0; 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnEditSelectall									*/ 
/* Description   : Select all items in the list						*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnEditSelectall()  
{ 
	for (int i = 0; i < m_QueueList.GetItemCount(); i++) 
	{ 
		m_QueueList.SetItemState(i, LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnEditInvertselection							*/ 
/* Description   : Invert selection									*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnEditInvertselection()  
{ 
	for (int i = 0; i < m_QueueList.GetItemCount(); i++) 
	{ 
		if (m_QueueList.GetItemState(i, LVNI_SELECTED)) 
			m_QueueList.SetItemState(i, ~LVIS_SELECTED, LVIS_SELECTED); 
		else 
			m_QueueList.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); 
	} 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : PreTranslateMessage								*/ 
/* Description   :													*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CTransferManagerDlg::PreTranslateMessage(MSG* pMsg)  
{ 
	if (m_hAccelTable)  
	{ 
		if (::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg))  
		{ 
			return(TRUE); 
		} 
	} 
	return CDialog::PreTranslateMessage(pMsg); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnTransferCancel									*/ 
/* Description   : Cancel transfer									*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnTransferCancel()  
{ 
	// get selected item 
	int nIndex = m_QueueList.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);  
	while (nIndex != -1) 
	{ 
		DWORD nThreadID = m_QueueList.GetItemData(nIndex); 
		// remove thread from download list 
		POSITION pos = m_DownloadThreads.GetHeadPosition(); 
		while(pos != NULL) 
		{ 
			CDownloadThread *pThread = (CDownloadThread *)m_DownloadThreads.GetNext(pos); 
			if (pThread->m_nThreadID == nThreadID) 
			{ 
				// cancel transfer 
				SetEvent(pThread->m_hEventKill); 
 
				// make sure it is running 
				while (pThread->ResumeThread() > 1); 
 
				break; 
			} 
		} 
		// remove thread from upload list 
		pos = m_UploadThreads.GetHeadPosition(); 
		while(pos != NULL) 
		{ 
			CUploadThread *pThread = (CUploadThread *)m_UploadThreads.GetNext(pos); 
			if (pThread->m_nThreadID == nThreadID) 
			{ 
				// cancel transfer 
				SetEvent(pThread->m_hEventKill); 
 
				// make sure it is running 
				while (pThread->ResumeThread() > 1); 
 
				break; 
			} 
		} 
		nIndex = m_QueueList.GetNextItem(nIndex, LVNI_ALL | LVNI_SELECTED); 
	}	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnTransferResubmit								*/ 
/* Description   : Activate queued transfer							*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnTransferResubmit()  
{ 
	// get selected item 
	int nIndex = m_QueueList.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);  
	while (nIndex != -1) 
	{ 
		DWORD nThreadID = m_QueueList.GetItemData(nIndex); 
		CString strStatus = m_QueueList.GetItemText(nIndex, 4); 
 
		if (strStatus == "Queued" || strStatus == "Failed") 
		{ 
			// remove thread from list 
			POSITION pos = m_DownloadThreads.GetHeadPosition(); 
			while(pos != NULL) 
			{ 
				CDownloadThread *pThread = (CDownloadThread *)m_DownloadThreads.GetNext(pos); 
				if (pThread->m_nThreadID == nThreadID) 
				{ 
					// cancel transfer 
					m_nActiveTransfers++; 
					pThread->ResumeThread(); 
					break; 
				} 
			} 
		} 
		nIndex = m_QueueList.GetNextItem(nIndex, LVNI_ALL | LVNI_SELECTED); 
	}	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : InitListViewImageList							*/ 
/* Description   : Use system imagelist for the file icons			*/ 
/*																	*/ 
/********************************************************************/ 
BOOL CTransferManagerDlg::InitListViewImageList() 
{ 
	HIMAGELIST himlSmall; 
	SHFILEINFO sfi; 
 
	himlSmall = (HIMAGELIST) SHGetFileInfo ((LPCSTR) "C:\\",  
		0, &sfi, sizeof (SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON); 
 
	if (himlSmall) 
	{ 
		::SendMessage(m_QueueList.m_hWnd, LVM_SETIMAGELIST, (WPARAM)LVSIL_SMALL, (LPARAM)himlSmall); 
		return TRUE; 
	} 
	return FALSE; 
}  
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnTransferExit									*/ 
/* Description   : Use system imagelist for the file icons			*/ 
/*																	*/ 
/********************************************************************/ 
void CTransferManagerDlg::OnTransferExit()  
{ 
	OnClose(); 
}