Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

A Complete FTP Server

, 30 May 2005
This article presents a fully functional implementation of a FTP server.
/****************************************************************/
/*																*/
/*  ApplicationDlg.cpp											*/
/*																*/
/*  Implementation of the CApplicationDlg class.				*/
/*	This class is a part of Quick 'n Easy FTP Server.			*/
/*																*/
/*  Programmed by Pablo van der Meer							*/
/*  Copyright Pablo Software Solutions 2005						*/
/*	http://www.pablosoftwaresolutions.com						*/
/*																*/
/*  Last updated: May 28, 2005									*/
/*																*/
/****************************************************************/


#include "stdafx.h"
#include "FTPServerApp.h"
#include "FTPServer.h"
#include "ApplicationDlg.h"
#include "AboutDlg.h"
#include <afxpriv.h>

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

extern CFTPServerApp theApp;
extern CFTPServer theServer;

static UINT auIDStatusBar[] = 
{
	ID_SEPARATOR,
	ID_INDICATOR_DATA_RECEIVED,
	ID_INDICATOR_DATA_SEND,
	ID_INDICATOR_ONLINELED,
	ID_INDICATOR_OFFLINELED
};


/********************************************************************/
/*																	*/
/* Function name : CApplicationDlg									*/
/* Description   : Constructor										*/
/*																	*/
/********************************************************************/
CApplicationDlg::CApplicationDlg(CWnd* pParent /*=NULL*/)
	: CDialogResize(CApplicationDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CApplicationDlg)
	//}}AFX_DATA_INIT
	m_hIcon = AfxGetApp()->LoadIcon(IDI_FTPSERVER);
	m_bInitialized = FALSE;
}


/********************************************************************/
/*																	*/
/* Function name : ~CApplicationDlg									*/
/* Description   : Destructor										*/
/*																	*/
/********************************************************************/
CApplicationDlg::~CApplicationDlg()
{
}


/********************************************************************/
/*																	*/
/* Function name : DoDataExchange									*/		
/* Description   : Called by the framework to exchange and validate */
/*				   dialog data.										*/
/*																	*/
/********************************************************************/
void CApplicationDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogResize::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CApplicationDlg)
	DDX_Control(pDX, IDC_INFOBAR, m_InfobarCtrl);
	DDX_Control(pDX, IDC_OUTLOOKBAR, m_OutlookBar);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CApplicationDlg, CDialogResize)
	//{{AFX_MSG_MAP(CApplicationDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_SIZE()
	ON_WM_DESTROY()
	ON_COMMAND(ID_SERVER_START, OnServerStart)
	ON_UPDATE_COMMAND_UI(ID_SERVER_START, OnUpdateServerStart)
	ON_COMMAND(ID_SERVER_STOP, OnServerStop)
	ON_UPDATE_COMMAND_UI(ID_SERVER_STOP, OnUpdateServerStop)
	ON_COMMAND(ID_SERVER_EXIT, OnServerExit)
	ON_NOTIFY(NM_CLICK, IDC_OUTLOOKBAR, OnClickOutlookBar)
	ON_NOTIFY(LVN_KEYDOWN, IDC_OUTLOOKBAR, OnKeydownOutlookBar)
	ON_COMMAND(IDC_VIEW_TRACE, OnViewTrace)
	ON_COMMAND(IDC_VIEW_ONLINE_USERS, OnViewOnlineUsers)
	ON_COMMAND(IDC_VIEW_CONFIGURATION, OnViewConfiguration)
	ON_UPDATE_COMMAND_UI(IDC_VIEW_TRACE, OnUpdateViewTrace)
	ON_UPDATE_COMMAND_UI(IDC_VIEW_ONLINE_USERS, OnUpdateViewOnlineUsers)
	ON_UPDATE_COMMAND_UI(IDC_VIEW_CONFIGURATION, OnUpdateViewConfiguration)
	ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout)
	ON_COMMAND(IDC_VIEW_STATISTICS, OnViewStatistics)
	ON_UPDATE_COMMAND_UI(IDC_VIEW_STATISTICS, OnUpdateViewStatistics)
	ON_COMMAND(IDC_VIEW_USERACCOUNTS, OnViewUseraccounts)
	ON_UPDATE_COMMAND_UI(IDC_VIEW_USERACCOUNTS, OnUpdateViewUseraccounts)
	ON_WM_INITMENUPOPUP()
	ON_COMMAND(ID_HELP_GETLATESTVERSION, OnHelpGetLatestVersion)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_KICKIDLE, OnKickIdle)
    ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
	ON_COMMAND(IDC_APPLY, OnApply)
END_MESSAGE_MAP()


BEGIN_DLGRESIZE_MAP(CApplicationDlg)
	DLGRESIZE_CONTROL(IDC_OUTLOOKBAR, DLSZ_SIZE_Y)
	DLGRESIZE_CONTROL(IDC_DIALOG_AREA, DLSZ_SIZE_X | DLSZ_SIZE_Y)
	DLGRESIZE_CONTROL(AFX_IDW_STATUS_BAR, DLSZ_MOVE_Y | DLSZ_SIZE_X)
	DLGRESIZE_CONTROL(AFX_IDW_TOOLBAR, DLSZ_SIZE_X)
	DLGRESIZE_CONTROL(IDC_STATIC1, DLSZ_SIZE_X)
	DLGRESIZE_CONTROL(IDC_INFOBAR, DLSZ_SIZE_X)
END_DLGRESIZE_MAP()



/********************************************************************/
/*																	*/
/* Function name : OnInitDialog										*/		
/* Description   : Called by the framework in response to the		*/
/*				   WM_INITDIALOG message.							*/
/*																	*/
/********************************************************************/
BOOL CApplicationDlg::OnInitDialog()
{
	CDialogResize::OnInitDialog();
	
	// setup listview ctrl, so that it looks like the outbar control
	SetupOutlookBar();

	// Add statusbar to the dialog
    CreateStatusbar();

	CRect rect;
	GetDlgItem(IDC_STATIC1)->GetWindowRect(rect);
	ScreenToClient(rect);
	rect.right+=4;
	GetDlgItem(IDC_STATIC1)->MoveWindow(rect);
	
	InitResizing(FALSE);

	// create property pages
	m_TracePage.Create(IDD_PROPPAGE_TRACE, this);
	m_OnlineUsersPage.Create(IDD_PROPPAGE_ONLINE, this);
	m_UserAccountPage.Create(IDD_PROPPAGE_ACCOUNTS, this);
	m_ConfigurationPage.Create(IDD_PROPPAGE_CONFIGURATION, this);
	m_StatisticsPage.Create(IDD_PROPPAGE_STATISTICS, this);

	// activate main page 
	ActivatePage(0);

	// Set big icon
	SetIcon(m_hIcon, TRUE);			
	// Set small icon
	SetIcon(m_hIcon, FALSE);		
	
	// get registry values
	m_ConfigurationPage.m_nPort = AfxGetApp()->GetProfileInt("Settings", "Port", 21);
	m_ConfigurationPage.m_nMaxUsers = AfxGetApp()->GetProfileInt("Settings", "MaxUsers", 10);
	m_ConfigurationPage.m_nTimeout = AfxGetApp()->GetProfileInt("Settings", "Timeout", 5);
	m_ConfigurationPage.m_strWelcomeMessage = AfxGetApp()->GetProfileString("Settings", "WelcomeMsg", "Welcome to Pablo's FTP Server"); 
	m_ConfigurationPage.m_strGoodbyeMessage = AfxGetApp()->GetProfileString("Settings", "GoodbyeMsg", "Bye"); 
	m_ConfigurationPage.m_bLaunchOnStartup = AfxGetApp()->GetProfileInt("Settings", "LaunchOnStartup", 0);
	m_ConfigurationPage.m_bStartInTray = AfxGetApp()->GetProfileInt("Settings", "StartInTray", 0);
	m_ConfigurationPage.m_bAutoActivate = AfxGetApp()->GetProfileInt("Settings", "AutoActivate", 0);
	
	m_ConfigurationPage.UpdateData(FALSE);

	// and finally, let's add some tooltips
	m_ToolTipCtrl.Create(this);
	m_ToolTipCtrl.Activate(TRUE);

	// minimize at startup ?
	if (m_ConfigurationPage.m_bStartInTray)
	{
		PostMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
		// this seems to be a workaround to let the statement above to get working
		CRect rect;
		GetWindowRect(rect);
		SetWindowPos(&CWnd::wndTop, rect.left, rect.top, rect.Width(),  rect.Height(), SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE);
	}
	
	theServer.Initialize(this);

	if (m_ConfigurationPage.m_bAutoActivate)
	{
		OnServerStart();
	}

	m_bInitialized = TRUE;
	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : OnSysCommand										*/		
/* Description   : Here we catch the minimizing						*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{
	switch(nID)
	{
		case SC_MINIMIZE:
			// do not minimize to the taskbar
			ShowWindow(SW_HIDE);
			break;
		default:
			CDialog::OnSysCommand(nID, lParam);
			break;
	}
}


/********************************************************************/
/*																	*/
/* Function name : OnSize											*/		
/* Description   : Handle WM_SIZE message							*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialogResize::OnSize(nType, cx, cy);
	
	if (m_bInitialized)
		MoveChilds();
}


/********************************************************************/
/*																	*/
/* Function name : OnDestroy										*/		
/* Description   : Handle WM_DESTROY message						*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnDestroy() 
{
	OnServerStop();
	CDialogResize::OnDestroy();
}


/********************************************************************/
/*																	*/
/* Function name : OnServerStart									*/		
/* Description   : Start FTP server -> start listening on port 21	*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnServerStart() 
{
	m_ConfigurationPage.UpdateData();
	theServer.SetPort(m_ConfigurationPage.m_nPort);
	theServer.SetMaxUsers(m_ConfigurationPage.m_nMaxUsers);
	theServer.SetTimeout(m_ConfigurationPage.m_nTimeout);
	theServer.SetWelcomeMessage(m_ConfigurationPage.m_strWelcomeMessage);
	theServer.SetGoodbyeMessage(m_ConfigurationPage.m_strGoodbyeMessage);
	theServer.SetStatisticsInterval(5000);

	if (theServer.Start())
	{
		m_wndStatusBar.SetPaneText(0, "FTP Server is online", TRUE);
		SetOnlineLed(TRUE);
		SetOfflineLed(FALSE);
	}
}


/********************************************************************/
/*																	*/
/* Function name : OnUpdateServerStart								*/		
/* Description   : Update 'Start' status							*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnUpdateServerStart(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(!theServer.IsActive());	
}


/********************************************************************/
/*																	*/
/* Function name : OnServerStop										*/		
/* Description   : Stop FTP server									*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnServerStop() 
{
	theServer.Stop();
	m_wndStatusBar.SetPaneText(0, "FTP Server is offline", TRUE);
	SetOnlineLed(FALSE);
	SetOfflineLed(TRUE);
}


/********************************************************************/
/*																	*/
/* Function name : OnUpdateServerStop								*/		
/* Description   : Update 'Stop' status								*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnUpdateServerStop(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(theServer.IsActive());
}


/********************************************************************/
/*																	*/
/* Function name : OnKickIdle										*/		
/* Description   : Make ON_UPDATE_COMMAND_UI work for this dialog.	*/
/*																	*/
/********************************************************************/
LRESULT CApplicationDlg::OnKickIdle(WPARAM wParam, LPARAM lParam)
{
	UpdateDialogControls(this, FALSE);

	CMenu* pMainMenu = GetMenu();
    CCmdUI cmdUI;
    // update menu enable/disable state
    for (UINT n = 0; n < pMainMenu->GetMenuItemCount(); ++n)
    {
        CMenu* pSubMenu = pMainMenu->GetSubMenu(n);
        cmdUI.m_nIndexMax = pSubMenu->GetMenuItemCount();
        for (UINT i = 0; i < cmdUI.m_nIndexMax;++i)
        {
            cmdUI.m_nIndex = i;
            cmdUI.m_nID = pSubMenu->GetMenuItemID(i);
            cmdUI.m_pMenu = pSubMenu;
            cmdUI.DoUpdate(this, FALSE);
        }
    }
	// enable/disable toolbar buttons    
	if (m_wndToolBar.IsWindowVisible()) 
	{
		// OnUpdateCmdUI expects a CFrameWnd pointer, so let's fake it ..
		CFrameWnd *pParent = (CFrameWnd *)this;
		if (pParent)
			m_wndToolBar.OnUpdateCmdUI(pParent, TRUE);
	} 

	return Default();
}


/********************************************************************/
/*																	*/
/* Function name : OnHelpAbout										*/		
/* Description   : Show Aboutbox.									*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnHelpAbout() 
{
	CAboutDlg dlg;
	dlg.DoModal();
}


/********************************************************************/
/*																	*/
/* Function name : OnServerExit										*/		
/* Description   : Let's get out of here...							*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnServerExit() 
{
	OnCancel();	
}


/********************************************************************/
/*																	*/
/* Function name : CApplicationDlg::SetupOutlookBar					*/		
/* Description   : Initialize listview, change color/iconspacing to	*/
/*				   make it look a little bit like the outlook bar.	*/
/*																	*/
/********************************************************************/
void CApplicationDlg::SetupOutlookBar()
{
    // create Imagelist
	m_ImageList.Create(32, 32, ILC_COLOR16|ILC_MASK,1, 4);

    HICON hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_LOG));
    m_ImageList.Add(hIcon);
    hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_USERACCOUNTS));
    m_ImageList.Add(hIcon);
    hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_CONFIGURATION));
    m_ImageList.Add(hIcon);
    hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ONLINE_USERS));
    m_ImageList.Add(hIcon);
    hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_STATISTICS));
    m_ImageList.Add(hIcon);
    hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_INTERNET));
    m_ImageList.Add(hIcon);
	
	m_OutlookBar.SetImageList(&m_ImageList, LVSIL_NORMAL);

	CRect rc;
	m_OutlookBar.GetClientRect(rc);
	
	// set new icon spacing
	m_OutlookBar.SetIconSpacing(rc.Width(), 64);

	// change colors
	m_OutlookBar.SetTextColor(RGB(255,255,255));
	m_OutlookBar.SetTextBkColor(RGB(128,128,128));
	m_OutlookBar.SetBkColor(RGB(128,128,128));	

	// insert items
	m_OutlookBar.InsertColumn(0, "OutlookBar");

	m_OutlookBar.InsertItem(0, "Server Log", 0);
	m_OutlookBar.InsertItem(1, "User Accounts", 1);
	m_OutlookBar.InsertItem(2, "Configuration", 2);
	m_OutlookBar.InsertItem(3, "Online Users", 3);
	m_OutlookBar.InsertItem(4, "Statistics", 4);
	m_OutlookBar.InsertItem(5, "Update", 5);
}


/********************************************************************/
/*																	*/
/* Function name : CApplicationDlg::MoveChilds						*/		
/* Description   : Move child windows into place holder area.		*/
/*																	*/
/********************************************************************/
void CApplicationDlg::MoveChilds()
{
	// position property pages 
	CRect rcDlgs;
	
	// get dialog area rect
	GetDlgItem(IDC_DIALOG_AREA)->GetWindowRect(rcDlgs);
	
	ScreenToClient(rcDlgs);
	
	m_ConfigurationPage.MoveWindow(rcDlgs); 
	m_TracePage.MoveWindow(rcDlgs); 
	m_OnlineUsersPage.MoveWindow(rcDlgs); 
	m_StatisticsPage.MoveWindow(rcDlgs); 
	m_UserAccountPage.MoveWindow(rcDlgs); 
}


/********************************************************************/
/*																	*/
/* Function name : CApplicationDlg::ActivatePage					*/
/* Description   : Called when an icon on the outlookbar is pressed.*/
/*																	*/
/********************************************************************/
void CApplicationDlg::ActivatePage(int nIndex)
{
	// make sure outlookbar has correct selection
	m_OutlookBar.SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED); 

	switch(nIndex)
	{
		case 0:
			m_OnlineUsersPage.ShowWindow(SW_HIDE);	
			m_ConfigurationPage.ShowWindow(SW_HIDE);
			m_StatisticsPage.ShowWindow(SW_HIDE);	
			m_UserAccountPage.ShowWindow(SW_HIDE);
			m_TracePage.ShowWindow(SW_SHOW);
			m_InfobarCtrl.SetText("Server Log");
			break;
		case 1:
			m_TracePage.ShowWindow(SW_HIDE);	
			m_ConfigurationPage.ShowWindow(SW_HIDE);	
			m_StatisticsPage.ShowWindow(SW_HIDE);	
			m_OnlineUsersPage.ShowWindow(SW_HIDE);
			m_UserAccountPage.ShowWindow(SW_SHOW);
			m_InfobarCtrl.SetText("User Accounts");
			break;
		case 2:
			m_OnlineUsersPage.ShowWindow(SW_HIDE);	
			m_TracePage.ShowWindow(SW_HIDE);	
			m_StatisticsPage.ShowWindow(SW_HIDE);	
			m_UserAccountPage.ShowWindow(SW_HIDE);
			m_ConfigurationPage.ShowWindow(SW_SHOW);	
			m_InfobarCtrl.SetText("Configuration");
			break;
		case 3:
			m_TracePage.ShowWindow(SW_HIDE);	
			m_ConfigurationPage.ShowWindow(SW_HIDE);	
			m_StatisticsPage.ShowWindow(SW_HIDE);	
			m_OnlineUsersPage.ShowWindow(SW_SHOW);
			m_UserAccountPage.ShowWindow(SW_HIDE);
			m_InfobarCtrl.SetText("Online Users");
			break;
		case 4:
			m_OnlineUsersPage.ShowWindow(SW_HIDE);	
			m_TracePage.ShowWindow(SW_HIDE);	
			m_ConfigurationPage.ShowWindow(SW_HIDE);	
			m_UserAccountPage.ShowWindow(SW_HIDE);
			m_StatisticsPage.ShowWindow(SW_SHOW);	
			m_InfobarCtrl.SetText("Statistics");
			break;
		case 5:
			OnHelpGetLatestVersion();
			break;
		default:
			break;
	}
	MoveChilds();
}


/********************************************************************/
/*																	*/
/* Function name : CApplicationDlg::OnClickOutlookBar				*/
/* Description   : User clicked on our listview -> activate page.	*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnClickOutlookBar(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// get index of selected item
	int nIndex = m_OutlookBar.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); 
    
    if(nIndex == -1)
        return;
		
	ActivatePage(nIndex);

	*pResult = 0;
}


/********************************************************************/
/*																	*/
/* Function name : CApplicationDlg::OnKeydownOutlookBar				*/
/* Description   : User pressed a key -> activate page.				*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnKeydownOutlookBar(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;

    // get index of selected item
	int nIndex = m_OutlookBar.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); 
    
    if(nIndex == -1)
        return;

	if (pLVKeyDow->wVKey == VK_DOWN)
	{
		if (m_OutlookBar.GetItemCount()-1 > nIndex)
		{
			ActivatePage(nIndex+1);
		}
	}
	else
	if (pLVKeyDow->wVKey == VK_UP)
	{
		if (nIndex > 0)
		{
			ActivatePage(nIndex-1);
		}
	}
	else
	if ((pLVKeyDow->wVKey == VK_NEXT) || (pLVKeyDow->wVKey == VK_END))
	{
		ActivatePage(m_OutlookBar.GetItemCount()-1);
	}
	else
	if ((pLVKeyDow->wVKey == VK_PRIOR) || (pLVKeyDow->wVKey == VK_HOME))
	{
		ActivatePage(0);
	}

	*pResult = 1;
}



/********************************************************************/
/*																	*/
/* Function name : CreateStatusbar									*/	
/* Description   : This function creates a statusbar on a dialogbox.*/
/*																	*/
/********************************************************************/
BOOL CApplicationDlg::CreateStatusbar()
{
	// Create the Toolbar and attach the resource
	if(!m_wndToolBar.Create(this) || !m_wndToolBar.LoadToolBar(IDR_TOOLBAR1))
	{
		TRACE0("Failed to Create Dialog Toolbar\n");
		return FALSE;	
	}

	m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);
	
	// Make it flat.
	m_wndToolBar.ModifyStyle(0, m_wndToolBar.GetStyle()|TBSTYLE_FLAT);

	// Create status bar at the bottom of the dialog window
	if (m_wndStatusBar.Create(this))
	{
		m_wndStatusBar.SetIndicators(auIDStatusBar, sizeof(auIDStatusBar)/sizeof(UINT));
		
		m_wndStatusBar.SetPaneText(0, "FTP Server is offline", TRUE);
		// Make a sunken or recessed border around the first pane
		m_wndStatusBar.SetPaneInfo(0, m_wndStatusBar.GetItemID(0), SBPS_STRETCH, NULL );

		SetOnlineLed(FALSE);
		SetOfflineLed(TRUE);

		m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_INDICATOR_ONLINELED),ID_INDICATOR_ONLINELED, SBPS_NOBORDERS, 14);
		m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_INDICATOR_OFFLINELED),ID_INDICATOR_OFFLINELED, SBPS_NOBORDERS, 14);
	}

    // We need to resize the dialog to make room for control bars.
	// First, figure out how big the control bars are.
	CRect rcClientStart;
	CRect rcClientNow;
	GetClientRect(rcClientStart);
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0, reposQuery, rcClientNow);

    // Now move all the controls so they are in the same relative
	// position within the remaining client area as they would be
	// with no control bars.
	CPoint ptOffset(rcClientNow.left - rcClientStart.left, rcClientNow.top - rcClientStart.top); 

	CRect  rcChild;					
	CWnd* pwndChild = GetWindow(GW_CHILD);
	while (pwndChild)
	{                               
		pwndChild->GetWindowRect(rcChild);
		ScreenToClient(rcChild);
		rcChild.OffsetRect(ptOffset);
		pwndChild->MoveWindow(rcChild, FALSE);
		pwndChild = pwndChild->GetNextWindow();
	}

	// Adjust the dialog window dimensions
	CRect rcWindow;
	GetWindowRect(rcWindow);
	rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
	rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
	MoveWindow(rcWindow, FALSE);
	
	// And position the control bars
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
    return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : OnFTPUserConnected								*/
/* Description   : A user has connected to our server.				*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnFTPUserConnected(DWORD nThreadID, LPCTSTR lpszUser, LPCSTR lpszAddress)
{
	m_OnlineUsersPage.AddUser(nThreadID, lpszUser, lpszAddress);
}


/********************************************************************/
/*																	*/
/* Function name : OnFTPUserDisconnected							*/
/* Description   : A user has disconnected from our server.			*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnFTPUserDisconnected(DWORD nThreadID, LPCTSTR lpszUser)
{
	m_OnlineUsersPage.RemoveUser(nThreadID);
}


/********************************************************************/
/*																	*/
/* Function name : OnFTPStatusChange								*/		
/* Description   : FTP Status changed.								*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnFTPStatusChange(int nType, LPCTSTR lpszText)
{
	m_TracePage.AddTraceLine(lpszText);
}


/********************************************************************/
/*																	*/
/* Function name : OnFTPReceivedBytesChange							*/		
/* Description   : Number of received bytes has changed.			*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnFTPReceivedBytesChange(int nBytes) 
{
	m_StatisticsPage.SetValue(6, FormatSize(nBytes, 0));

	CString strStatus;
	strStatus.Format("%s received", FormatSize(nBytes, 0));
	m_wndStatusBar.SetPaneText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_DATA_RECEIVED), strStatus, TRUE);

	CClientDC dc(this);
	CSize size = dc.GetTextExtent(strStatus);
	m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_INDICATOR_DATA_RECEIVED), ID_INDICATOR_DATA_RECEIVED, SBPS_NORMAL, size.cx);
}


/********************************************************************/
/*																	*/
/* Function name : OnFTPSentBytesChange								*/		
/* Description   : Number of sent bytes has changed.				*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnFTPSentBytesChange(int nBytes)
{
	m_StatisticsPage.SetValue(7, FormatSize(nBytes, 0));

	CString strStatus;
	strStatus.Format("%s sent",  FormatSize(nBytes, 0));
	m_wndStatusBar.SetPaneText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_DATA_SEND), strStatus, TRUE);
	CClientDC dc(this);
	CSize size = dc.GetTextExtent(strStatus);
	m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_INDICATOR_DATA_SEND), ID_INDICATOR_DATA_SEND, SBPS_NORMAL, size.cx);
}


/********************************************************************/
/*																	*/
/* Function name : OnViewTrace										*/		
/* Description   : Handle menu selection.							*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnViewTrace() 
{
	ActivatePage(0);
}


/********************************************************************/
/*																	*/
/* Function name : OnViewTrace										*/		
/* Description   : Handle menu selection.							*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnViewUseraccounts() 
{
	ActivatePage(1);
}


/********************************************************************/
/*																	*/
/* Function name : OnViewConfiguration								*/		
/* Description   : Handle menu selection.							*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnViewConfiguration() 
{
	ActivatePage(2);
}


/********************************************************************/
/*																	*/
/* Function name : OnViewOnlineUsers								*/		
/* Description   : Handle menu selection.							*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnViewOnlineUsers() 
{
	ActivatePage(3);
}


/********************************************************************/
/*																	*/
/* Function name : OnViewStatistics									*/		
/* Description   : Handle menu selection.							*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnViewStatistics() 
{
	ActivatePage(4);
}


/********************************************************************/
/*																	*/
/* Function name : OnUpdateViewTrace								*/		
/* Description   : Update menu state of Trace item.					*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnUpdateViewTrace(CCmdUI* pCmdUI) 
{
	pCmdUI->SetRadio(m_TracePage.IsWindowVisible());	
}


/********************************************************************/
/*																	*/
/* Function name : OnUpdateViewUseraccounts							*/		
/* Description   : Update menu state of User Accounts item.			*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnUpdateViewUseraccounts(CCmdUI* pCmdUI) 
{
	pCmdUI->SetRadio(m_UserAccountPage.IsWindowVisible());		
}


/********************************************************************/
/*																	*/
/* Function name : OnUpdateViewOnlineUsers							*/		
/* Description   : Update menu state of Online Users item.			*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnUpdateViewOnlineUsers(CCmdUI* pCmdUI) 
{
	pCmdUI->SetRadio(m_OnlineUsersPage.IsWindowVisible());		
}


/********************************************************************/
/*																	*/
/* Function name : OnUpdateViewConfiguration						*/		
/* Description   : Update menu state of Configuration item.			*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnUpdateViewConfiguration(CCmdUI* pCmdUI) 
{
	pCmdUI->SetRadio(m_ConfigurationPage.IsWindowVisible());			
}


/********************************************************************/
/*																	*/
/* Function name : OnUpdateViewStatistics							*/		
/* Description   : Update menu state of Statistics item.			*/	
/*																	*/
/********************************************************************/
void CApplicationDlg::OnUpdateViewStatistics(CCmdUI* pCmdUI) 
{
	pCmdUI->SetRadio(m_StatisticsPage.IsWindowVisible());				
}


/********************************************************************/
/*																	*/
/* Function name : PreTranslateMessage								*/	
/* Description   : Needed to make tooltips work.					*/
/*																	*/
/********************************************************************/
BOOL CApplicationDlg::PreTranslateMessage(MSG* pMsg) 
{
	// enable tooltips
	if (m_hWnd)
    {
        if (IsWindow(m_ToolTipCtrl.m_hWnd))
			m_ToolTipCtrl.RelayEvent(pMsg);
    }
	
	return CDialogResize::PreTranslateMessage(pMsg);
}


/********************************************************************/
/*																	*/
/* Function name : OnToolTipText									*/	
/* Description   : Tooltip handler for this dialog.					*/
/*																	*/
/********************************************************************/
BOOL CApplicationDlg::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult)
{
    ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);

	// need to handle both ANSI and UNICODE versions of the message
	TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
	TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
	TCHAR szFullText[256];
	CString cstTipText;
	CString cstStatusText;

	UINT nID = pNMHDR->idFrom;
	if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
		pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
	{
		// idFrom is actually the HWND of the tool
		nID = ((UINT)(WORD)::GetDlgCtrlID((HWND)nID));
	}

	if (nID != 0) // will be zero on a separator
	{
		AfxLoadString(nID, szFullText);
			// this is the command id, not the button index
		AfxExtractSubString(cstTipText, szFullText, 1, '\n');
		AfxExtractSubString(cstStatusText, szFullText, 0, '\n');
	}

	// Non-UNICODE Strings only are shown in the tooltip window...
	if (pNMHDR->code == TTN_NEEDTEXTA)
		lstrcpyn(pTTTA->szText, cstTipText,
            (sizeof(pTTTA->szText)/sizeof(pTTTA->szText[0])));
	else
		_mbstowcsz(pTTTW->szText, cstTipText,
            (sizeof(pTTTW->szText)/sizeof(pTTTW->szText[0])));
	*pResult = 0;

	// bring the tooltip window above other popup windows
	::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);

    // message was handled
	return TRUE;    
}


/********************************************************************/
/*																	*/
/* Function name : SetOnlineLed										*/	
/* Description   : Turn online LED on/off.							*/
/*																	*/
/********************************************************************/
void CApplicationDlg::SetOnlineLed(BOOL bOnline)
{
	HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(),
				bOnline ? MAKEINTRESOURCE(IDI_LED_GREEN) : MAKEINTRESOURCE(IDI_LED_OFF),
				 IMAGE_ICON, 16, 16, LR_SHARED);
	m_wndStatusBar.GetStatusBarCtrl().SetIcon(m_wndStatusBar.CommandToIndex(ID_INDICATOR_ONLINELED), hIcon);
	m_wndStatusBar.GetStatusBarCtrl().Invalidate();
	m_wndStatusBar.GetStatusBarCtrl().UpdateWindow();
	DestroyIcon(hIcon);
}


/********************************************************************/
/*																	*/
/* Function name : SetOfflineLed									*/	
/* Description   : Turn offline LED on/off.							*/
/*																	*/
/********************************************************************/
void CApplicationDlg::SetOfflineLed(BOOL bOffline)
{
	HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(),
				bOffline ? MAKEINTRESOURCE(IDI_LED_RED) : MAKEINTRESOURCE(IDI_LED_OFF),
				 IMAGE_ICON, 16, 16, LR_SHARED);
	m_wndStatusBar.GetStatusBarCtrl().SetIcon(m_wndStatusBar.CommandToIndex(ID_INDICATOR_OFFLINELED), hIcon);
	m_wndStatusBar.GetStatusBarCtrl().Invalidate();
	m_wndStatusBar.GetStatusBarCtrl().UpdateWindow();
	DestroyIcon(hIcon);
}


/********************************************************************/
/*																	*/
/* Function name : OnUpdateApply									*/	
/* Description   : Update FTP server parameters.					*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnApply() 
{
	m_ConfigurationPage.UpdateData();
	theServer.SetPort(m_ConfigurationPage.m_nPort);
	theServer.SetMaxUsers(m_ConfigurationPage.m_nMaxUsers);
	theServer.SetTimeout(m_ConfigurationPage.m_nTimeout);
	theServer.SetWelcomeMessage(m_ConfigurationPage.m_strWelcomeMessage);
	theServer.SetGoodbyeMessage(m_ConfigurationPage.m_strGoodbyeMessage);

	OnFTPStatusChange(0, "FTP Server configuration updated.");
}


void CApplicationDlg::OnFTPStatisticChange(int nType, int nValue)
{
	m_StatisticsPage.SetValue(nType, nValue);
}


/********************************************************************/
/*																	*/
/* Function name : FormatSize										*/
/* Description   : Format size, the way explorer diplays it			*/
/*																	*/
/********************************************************************/
char* CApplicationDlg::FormatSize(DWORD dwSizeLow, DWORD dwSizeHigh)
{
	static char szBuff[100];

	unsigned __int64 nFileSize = ((unsigned __int64)(((DWORD)(dwSizeLow)) | 
								 ((unsigned __int64)((DWORD)(dwSizeHigh))) << 32));
	unsigned __int64 kb = 0;

	if (nFileSize > 1024)
	{
		kb = nFileSize / 1024;
		if (nFileSize % 1024)
			kb++;
	}

	// make it a string
	_ui64tot(kb, szBuff, 10);

	// add thousand seperators
	int nLength = lstrlen(szBuff);
	if (nLength > 3)
	{
		LPCTSTR ptr = szBuff;
		ptr += (nLength-1);

		char szTemp[100];

		LPTSTR ptrTemp = szTemp;
		for(int i=0; i<nLength; i++)
		{
			if (i && ((i % 3) == 0)) 
			{
				if (*ptrTemp != ',')
				{
					*ptrTemp = ',';
					ptrTemp = _tcsinc(ptrTemp);
				}
			}
			*ptrTemp = *ptr;
			ptrTemp = _tcsinc(ptrTemp);
			ptr = _tcsdec(szBuff, ptr);
		}
		// terminate string
		*ptrTemp = '\0';
		// reverse string
		_tcsrev(szTemp);
		lstrcpy(szBuff, szTemp);
	}
	// add 'KB' to it
	lstrcat(szBuff, " KB");
	return szBuff;
}


/********************************************************************/
/*																	*/
/* Function name : OnInitMenuPopup									*/
/* Description   : Enable/disable tray menu items					*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) 
{
	CDialogResize::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
	
	if (theServer.IsActive())
	{
		pPopupMenu->EnableMenuItem(ID_SERVER_START, MF_GRAYED);
		pPopupMenu->EnableMenuItem(ID_SERVER_STOP, MF_ENABLED);
	}
	else
	{
		pPopupMenu->EnableMenuItem(ID_SERVER_START, MF_ENABLED);
		pPopupMenu->EnableMenuItem(ID_SERVER_STOP, MF_GRAYED);
	}
}


/********************************************************************/
/*																	*/
/* Function name : OnHelpGetLatestVersion							*/
/* Description   : Check for updates on the website					*/
/*																	*/
/********************************************************************/
void CApplicationDlg::OnHelpGetLatestVersion() 
{
	// open URL in the browser.
	ShellExecute(NULL, "open", "http://www.pablosoftwaresolutions.com/html/quick__n_easy_ftp_server.html", NULL, NULL, SW_SHOWNORMAL);	
		
}

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

Share

About the Author

Pablo van der Meer
Web Developer
Netherlands Netherlands
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141223.1 | Last Updated 30 May 2005
Article Copyright 2002 by Pablo van der Meer
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid