#include "StdAfx.h"
#include <shlobj.h>
#include "MainWnd.h"
#include "FtpViewRes.h"
#include "FtpTransDlg.h"
#include "ShortcutDlg.h"
#include "OptDlg.h"
#include "ftpSite.h"
#include "PropertyDlg.h"
#include "CeFontDlg.h"
#include "CeFindFile.h"
#include "CeLabel.h"
#include "afxres.h"
#include <math.h>
LISTSORTINFO g_sortinfo;
OPTIONS g_options;
CeArray<int> g_arColumns;
OSVERSIONINFO g_osvi = {sizeof(g_osvi)};
#define _WIN32_HR(err) HRESULT_FROM_WIN32(err)
static HRESULT (STDAPICALLTYPE *g_pfnVarDateFromStr)(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, DATE FAR* pdateOut) = NULL;
CeString TreeView_GetItemText(HWND hTree, HTREEITEM hItem)
{
TV_ITEM tvi;
CeString str;
tvi.mask = TVIF_TEXT | TVIF_HANDLE;
tvi.hItem = hItem;
tvi.pszText = str.GetBuffer(128);
tvi.cchTextMax = 128;
TreeView_GetItem(hTree, &tvi);
str.ReleaseBuffer();
return str;
}
LPARAM TreeView_GetLParam(HWND hTree, HTREEITEM hItem)
{
TV_ITEM tvi;
CeString str;
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hItem;
TreeView_GetItem(hTree, &tvi);
return tvi.lParam;
}
extern HINSTANCE g_hInst;
#define IDC_BAND 102
#define IDC_TREE 100
//#define IDC_LIST 101
#define IDC_MENU_BAND 201
#define IDC_BUTTON_BAND 202
enum eTreeNodeType
{
tntDesktop = 1,
tntDevice = 2,
tntFtpSite = 3,
tntLocalDir = 4,
tntFtpSiteDir = 5,
};
enum eImages
{
imFolderOpen = 0,
imFolderClose = 1,
imApp = 2,
imHeir = 3,
imDoc = 4,
imDesktop = 5,
imFtpSite = 6,
imFtpOpenFolder = 7,
imFtpClosedFolder = 8,
imPPC = 9,
imHPC = 10,
imHPCPro = 11,
imFlashOpen = 12,
imFlashClose = 13,
imDocUnknown = 14
};
BOOL LoadProc(FARPROC* pProc, LPCTSTR pszFuncName, LPCTSTR pszLibName)
{
HINSTANCE hInst = LoadLibrary(pszLibName);
if (NULL == hInst)
return FALSE;
return ((*pProc = GetProcAddress(hInst, pszFuncName)) != NULL);
}
void FormatDateTime(FILETIME ft, LPTSTR sz)
{
SYSTEMTIME st;
BOOL bSuccess = ::FileTimeToSystemTime(&ft, &st);
if (! bSuccess || st.wYear > 9999)
{
sz[0] = 0;
}
else
{
int nSize = ::GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_SHORTDATE,
&st, NULL, sz, 32);
sz[nSize-1] = _T(' ');
::GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS,
&st, NULL, sz + nSize, 32);
}
}
double NumDate(DATE dt)
{
// No problem if positive
if (dt >= 0)
return dt;
// If negative, must convert since negative dates not continuous
// (examples: -1.25 to -.75, -1.50 to -.50, -1.75 to -.25)
double temp = ceil(dt);
return temp - (dt - temp);
}
class CeFileListItem
{
public:
CeFileListItem(LPCTSTR lpsz, DWORD dwSize, DWORD dwAttrib, FILETIME ft, LPCTSTR lpszExt)
{
LPSTR sz = (LPSTR) &m_dwName;
// Little endian copy
sz[3] = (char) towupper(lpsz[0]);
sz[2] = (char) towupper(lpsz[1]);
sz[1] = (char) towupper(lpsz[2]);
sz[0] = (char) towupper(lpsz[3]);
m_dwSize = dwSize;
m_dwAttrib = dwAttrib;
m_ft = ft;
}
DWORD m_dwName;
DWORD m_dwSize;
DWORD m_dwAttrib;
FILETIME m_ft;
};
int CALLBACK CmpList(LPARAM lpOne, LPARAM lpTwo, LPARAM lpArg)
{
LISTSORTINFO* pSortInfo = (LISTSORTINFO *) lpArg;
int nResult = 0;
CeFileListItem *pItem = (CeFileListItem *) lpOne;
CeFileListItem *pItem2 = (CeFileListItem *) lpTwo;
//
// Attempt to sort my an easily accessable value,
// or if that isn't possible, use the column value
//
switch (pSortInfo->nColType)
{
case SORTCOL_NAME:
if (pItem->m_dwName != pItem2->m_dwName)
{
if (!pSortInfo->bAscending)
return pItem2->m_dwName - pItem->m_dwName;
else
return pItem->m_dwName - pItem2->m_dwName;
}
break;
case SORTCOL_SIZE:
if (!pSortInfo->bAscending)
return (int) pItem2->m_dwSize - pItem->m_dwSize;
else
return (int) pItem->m_dwSize - pItem2->m_dwSize;
case SORTCOL_DATE:
if (!pSortInfo->bAscending)
return (int) CompareFileTime(&pItem->m_ft, &pItem2->m_ft);
else
return (int) CompareFileTime(&pItem2->m_ft, &pItem->m_ft);
case SORTCOL_ATTRIB:
if (!pSortInfo->bAscending)
return (int) pItem2->m_dwAttrib - pItem->m_dwAttrib;
else
return (int) pItem->m_dwAttrib - pItem2->m_dwAttrib;
}
// Find the specified lParam
LV_FINDINFO fi;
// use LVFI_WRAP for cases where lpTwo represents a row before lpOne
fi.flags = LVFI_PARAM | LVFI_WRAP;
fi.lParam = lpOne;
int lFirstData = ListView_FindItem(pSortInfo->hwndList, -1, &fi);
fi.lParam = lpTwo;
// reduce searching time by setting the start row as lFirstData
int lSecondData = ListView_FindItem(pSortInfo->hwndList, lFirstData, &fi);
// because we are searching for LPARAM sent to us, FindItem() on
// these values should always be successful
ASSERT(lFirstData != -1);
ASSERT(lSecondData != -1);
// Go and lookup the lParam text
wchar_t szFirst[64], szSecond[64];
ListView_GetItemText(pSortInfo->hwndList, lFirstData, pSortInfo->nColumnNo, szFirst, 64);
ListView_GetItemText(pSortInfo->hwndList, lSecondData, pSortInfo->nColumnNo, szSecond, 64);
int nCompareValue = _tcsnicmp(szFirst, szSecond, 64);
return nCompareValue * ((pSortInfo->bAscending) ? 1: -1);
}
///////////////////////////////////////////////////////////////////////////////
//
// CeAboutDlg = Dialog for displaying information about the product
//
///////////////////////////////////////////////////////////////////////////////
class CeAboutDlg: public CeScrollDialog
{
private:
public:
CeAboutDlg(): CeScrollDialog(IDD_ABOUT) {}
virtual BOOL OnInitDialog();
};
#define IDT_ANIM_ICON 100
BOOL CeAboutDlg::OnInitDialog()
{
// allow controls to be created
return CeScrollDialog::OnInitDialog();
}
///////////////////////////////////////////////////////////////////////////////
/*
class CeConnectDlg: public CeDialog
{
public:
CeMainWnd* m_pMainWnd;
CeConnectDlg()
{
m_pMainWnd = NULL;
}
virtual BOOL OnInitDialog();
};
BOOL CeConnectDlg::OnInitDialog()
{
CeDialog::OnInitDialog();
HWND hList = GetDlgItem(IDC_ENTRIES);
LVCOLUMN col;
col.mask = LVCF_FMT | LVCF_TEXT;
col.fmt = LVCFMT_CENTER;
col.pszText = _T("Entries");
ListView_InsertColumn(hList, 0, &col);
RASENTRYNAME* pEntries = NULL;
int nEntries = CeRasEntry::GetAll(&pEntries);
if (nEntries > 0)
{
for (int ii = 0; ii < nEntries; ii++)
{
LVITEM item;
item.iItem = ii;
item.iSubItem = 0;
item.mask = LVIF_TEXT;
item.pszText = pEntries[ii].szEntryName;
ListView_InsertItem(hList, &item);
}
}
ListView_SetColumnWidth(hList, 0, LVSCW_AUTOSIZE_USEHEADER);
return TRUE;
}
*/
///////////////////////////////////////////////////////////////////////////////
CeMainWnd::CeMainWnd()
{
m_hFont = NULL;
m_hImages = NULL;
m_dwFontSize = 0;
m_hwndList = NULL;
m_hwndTree = NULL;
m_hConnected = NULL;
// Drag and drop info....
m_hDragImage = NULL;
m_bDragging = false;
m_hDropWnd = NULL;
m_ptDropPoint.x = 0;
m_ptDropPoint.y = 0;
m_dwDragItem = 0xffffffff;
m_dwDropItem = 0xffffffff;
memset(&m_nid, 0, sizeof m_nid);
}
BOOL CeMainWnd::OnCommand(WPARAM wParam, LPARAM lParam, bool& bHandled)
{
WORD wNotify = HIWORD(wParam); // notification code
WORD wId = LOWORD(wParam); // item, control, or accelerator identifier
HWND hwndCtl = (HWND) lParam; // handle of control
//default to handled
bHandled = false;
//menu commands
if (0 == wNotify)
{
// Parse the menu selections:
bHandled = true;
switch (wId)
{
case ID_FILE_OPEN: OnRun(); break;
case ID_FILE_PROPERTIES: OnProperties(); break;
case ID_FILE_DELETE: OnDelete(); break;
case ID_FILE_RENAME: OnRename(); break;
case ID_FILE_ABOUT: OnAbout(); break;
case ID_FILE_NEW_FOLDER: OnNewFolder(); break;
case ID_FILE_NEWSHORTCUT: OnNewShortcut(); break;
case ID_FILE_CLOSE: DestroyWindow(); break;
case ID_EDIT_OPTIONS: OnOptions(); break;
case ID_EDIT_FONT: OnFont(); break;
// E_NOTIMPL
case ID_EDIT_PASTEASSHORTCUT: break;
case ID_EDIT_PASTE: break;
case ID_EDIT_CUT: break;
case ID_EDIT_COPY: break;
case ID_ACTIONS_REFRESH: OnRefresh(); break;
case ID_ACTIONS_CONNECT: OnConnect(); break;
case ID_ACTIONS_DISCONNECT: OnDisconnect(); break;
case ID_ACTIONS_NEWSITE: OnNewSite(); break;
default:
bHandled = false;
break;
}
}
return 0;
}
void CeMainWnd::OnRun()
{
HWND hwndFocus = GetFocus();
if (hwndFocus != m_hwndList)
return;
if (m_bCurrentFtp || m_strCurrentDirectory.IsEmpty())
// nothing yet
return;
int nSel = ListView_GetNextItem(m_hwndList, -1, LVIS_SELECTED);
if (nSel < 0)
return;
TCHAR szFile[MAX_PATH];
ListView_GetItemText(m_hwndList, nSel, 1, szFile, MAX_PATH);
if (*szFile == 0)
{
// change directory, this is a folder
// ListView_GetItemText(m_hwndList, nSel, 0, szFile, MAX_PATH);
}
else
{
ListView_GetItemText(m_hwndList, nSel, 0, szFile, MAX_PATH);
Execute(m_strCurrentDirectory, szFile);
}
}
void CeMainWnd::OnRename()
{
HWND hwndFocus = GetFocus();
if (hwndFocus == m_hwndList)
{
int nSel = ListView_GetNextItem(m_hwndList, -1, LVIS_FOCUSED);
if (nSel >= 0)
ListView_EditLabel(m_hwndList, nSel);
}
else if (hwndFocus == m_hwndTree)
{
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
if (hItem != 0)
TreeView_EditLabel(m_hwndTree, hItem);
}
}
bool RecursiveRemoveDirectory(LPCTSTR lpszDir, bool bAndSubs = true)
{
CeString str;
str.Format(_T("%s*.*"), lpszDir);
CeFindFile ff;
if (! ff.FindFirst(str))
return true;
do
{
if (ff.IsDirectory())
{
RecursiveRemoveDirectory(ff.cFileName);
RemoveDirectory(ff.cFileName);
}
else
{
CeString strFile = lpszDir;
strFile += ff.cFileName;
DeleteFile(strFile);
}
}
while (ff.FindNext());
if (bAndSubs)
RemoveDirectory(ff.cFileName);
return true;
}
void CeMainWnd::OnEmptyRecycleBin()
{
RecursiveRemoveDirectory(_T("\\Recycled\\"), false);
}
void CeMainWnd::OnNewShortcut()
{
CeShortcutDlg dlg;
dlg.DoModal();
}
void CeMainWnd::OnNewFolder()
{
HWND hwndFocus = GetFocus();
// Check for focus and selection, otherwise forget it...
if (hwndFocus != m_hwndTree)
return;
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
if (NULL == hItem)
return;
eTreeNodeType eType = (eTreeNodeType) TreeView_GetLParam(m_hwndTree, hItem);
if (tntDesktop == eType || (tntFtpSite == eType && ! m_ftpConn.IsConnected()))
return;
bool bFtp;
CeString str = GetTreePath(hItem, bFtp);
str += _T("New Folder");
TreeView_Expand(m_hwndTree, hItem, TVE_EXPAND);
if (bFtp)
{
if (! m_ftpConn.CreateDir(str))
{
CeString strErr = m_ftpConn.GetFtpErrorReplyString();
MessageBox(strErr, str, MB_OK|MB_ICONWARNING);
}
}
else
{
if (! ::CreateDirectory(str, NULL))
{
MessageBox(_T("Unable to create directory!"), str, MB_OK|MB_ICONWARNING);
return;
}
}
// create the node off the root and enter edit mode
//
// initialize the tree
TVINSERTSTRUCT is;
is.hInsertAfter = TVI_SORT;
is.hParent = hItem;
is.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
is.item.pszText = _T("New Folder");
is.item.cChildren = 0;
if (bFtp)
{
is.item.lParam = tntFtpSiteDir;
is.item.iSelectedImage = imFtpOpenFolder;
is.item.iImage = imFtpClosedFolder;
}
else
{
is.item.lParam = tntLocalDir;
is.item.iSelectedImage = imFolderOpen;
is.item.iImage = imFolderClose;
}
// insert and edit...
TreeView_EditLabel(m_hwndTree, TreeView_InsertItem(m_hwndTree, &is) );
}
void CeMainWnd::OnDelete()
{
HWND hwndFocus = GetFocus();
if (hwndFocus == m_hwndList)
{
int nSel = ListView_GetNextItem(m_hwndList, -1, LVIS_SELECTED);
if (nSel < 0)
return;
CeString strFile;
ListView_GetItemText(m_hwndList, nSel, 0, strFile.GetBufferSetLength(64), 64);
strFile.ReleaseBuffer();
CeString strDir = m_strCurrentDirectory;
if (m_strCurrentDirectory[strDir.Length() - 1] != _T('\\'))
strDir += _T('\\');
strDir += strFile;
int nResp = MessageBox(_T("Are you certain you wish to remove the selected file?"),
strDir, MB_OKCANCEL);
if (nResp != IDOK)
return;
if (m_bCurrentFtp)
{
if (! m_ftpConn.DeleteFile(strDir))
{
CeString str = m_ftpConn.GetFtpErrorReplyString();
MessageBox(str, _T("FTP delete failed!"), MB_OK);
return;
}
}
else
{
if (! DeleteFile(strDir))
return;
}
ListView_DeleteItem(m_hwndList, nSel);
if (nSel > ListView_GetItemCount(m_hwndList))
nSel--;
::SetFocus(hwndFocus);
ListView_SetItemState(m_hwndList, nSel, LVIS_FOCUSED|LVIS_SELECTED,
LVIS_FOCUSED|LVIS_SELECTED);
}
else if (hwndFocus == m_hwndTree)
{
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
bool bFtp;
CeString str = GetTreePath(hItem, bFtp);
if (bFtp && str == _T("\\") && ! m_ftpConn.IsConnected())
{
// remove the ftp site from the data base
str = TreeView_GetItemText(m_hwndTree, hItem);
if (CeFtpSite::Remove(str))
TreeView_DeleteItem(m_hwndTree, hItem);
return;
}
if (str.IsEmpty() || str == _T("\\"))
{
MessageBox(_T("That's not something you can delete, sorry."),
_T("Error"), MB_ICONWARNING|MB_OK);
return;
}
int nResp = MessageBox(_T("Are you certain you wish to remove the selected directory?"),
str, MB_OKCANCEL);
if (nResp != IDOK)
return;
// remove the trailing "\"
str.GetBufferSetLength(str.GetLength()-1);
str.ReleaseBuffer();
if (bFtp)
{
if (m_ftpConn.DeleteDir(str))
{
TreeView_DeleteItem(m_hwndTree, hItem);
// refresh the list view....
}
else
{
CeString str = m_ftpConn.GetFtpErrorReplyString();
MessageBox(str, _T("FTP command failed!"), MB_OK|MB_ICONWARNING);
}
}
else
{
if (::RemoveDirectory(str))
{
TreeView_DeleteItem(m_hwndTree, hItem);
// refresh the list view....
}
else
{
CeString str;
if (ERROR_DIR_NOT_EMPTY == GetLastError())
{
MessageBox(_T("You must remove the files in this directory before you can remove it."),
_T("Error"), MB_ICONWARNING|MB_OK);
}
else
{
str.Format(_T("Error %lu remove directory"), GetLastError());
MessageBox(str, _T("Error"), MB_ICONWARNING|MB_OK);
}
}
}
}
}
void CeMainWnd::OnDisconnect()
{
if (m_ftpConn.IsConnected())
m_ftpConn.Disconnect();
if (NULL == m_hConnected)
return;
HTREEITEM hItem;
while (NULL != (hItem = TreeView_GetChild(m_hwndTree, m_hConnected)))
TreeView_DeleteItem(m_hwndTree, hItem);
TVITEM item;
item.hItem = m_hConnected;
item.mask = TVIF_STATE | TVIF_CHILDREN;
item.state = 0;
item.stateMask = TVIS_BOLD;
item.cChildren = 0;
TreeView_SetItem(m_hwndTree, &item);
// remove all the sun nodes and remove
TreeView_Expand(m_hwndTree, m_hConnected, TVE_COLLAPSERESET);
// clean out the file list
PopulateFilelist(m_hConnected, _T(""), true);
m_hConnected = NULL;
}
void CeMainWnd::OnConnect()
{
if (m_ftpConn.IsConnected())
{
MessageBox(_T("Already connected to an FTP site, this software currently supports a single connection"),
NULL, MB_ICONWARNING);
return;
}
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
TVITEM item;
TCHAR szBuf[64];
item.hItem = hItem;
item.mask = TVIF_PARAM | TVIF_TEXT;
item.pszText = szBuf;
item.cchTextMax = 64;
TreeView_GetItem(m_hwndTree, &item);
if (item.lParam != tntFtpSite)
return;
CeFtpSite site;
if (! site.Find(szBuf))
return;
BOOL bConnect;
{
m_ftpConn.SetPassive(site.m_bPassive);
CeWaitCursor wait;
if (site.m_bAnon)
bConnect = m_ftpConn.Connect(site.m_strAddress);
else
bConnect = m_ftpConn.Connect(site.m_strAddress, site.m_strUser, site.m_strPassword);
}
if (! bConnect)
{
CeString strErr = _T("Unable to establish a connection.\n");
strErr += m_ftpConn.GetFtpErrorReplyString();
MessageBox(strErr, NULL, MB_ICONWARNING);
return;
}
else
{
m_hConnected = hItem;
item.hItem = hItem;
item.mask = TVIF_STATE | TVIF_CHILDREN;
item.cChildren = I_CHILDRENCALLBACK;
item.state = TVIS_BOLD;
item.stateMask = TVIS_BOLD;
TreeView_SetItem(m_hwndTree, &item);
ASSERT(hItem != TreeView_GetRoot(m_hwndTree));
PopulateFilelist(hItem, m_ftpConn.GetRoot(), true);
MessageBox(_T("Connection established."));
}
}
/*
RasConnect()
{
// Dial up the network via RAS
// Get all available devices
//
// CeRasDevInfoArray arDevInfo;
// CeRasDevInfo::GetAll(arDevInfo);
// if (arDevInfo.GetSize() <= 0)
// {
// LogEvent(EVENT_ERROR, _T("No Remote Access devices configured."));
// throw Error(_T("No Remote Access devices configured."), IID_IWHCSRepository, REPOS_E_CONNECTION);
// }
//
// get all the available connections
RASCONN* pConn;
CeRasConn::GetAll(&pConn);
// Go through all the available lines and find one we can connect on
BOOL bFound = FALSE;
// for (int ii = 0; ! bFound && ii < arDevInfo.GetSize(); ii++)
// {
for (int jj = 0; ! bFound && jj < arConn.GetSize(); jj++)
{
if (! _tcscmp(arConn[jj].szDeviceName, arDevInfo[ii].szDeviceName))
{
// break out the the inner loop, we found
// the device active
break;
}
}
if (jj >= arConn.GetSize())
// not found with the other active connections
bFound = TRUE;
}
// if (! bFound)
{
// good generic error (actually no devices ready)
// throw Error(_T("No Remote Access devices available."), IID_IWHCSRepository,
// REPOS_E_DEVICE_UNAVAILABLE);
}
CeString strPhoneNumber("707-5772"), strAreaCode("612"), strCountryCode("1");
// Set up the RAS entry
CeRasEntry rasEntry(_T(""), strPhoneNumber, strAreaCode, strCountryCode);
if (! m_strHCSIPAddr.IsEmpty())
{
rasEntry.ipaddr = CRASEntry::StringToRASIP(m_strHCSIPAddr);
rasEntry.dwfOptions |= RASEO_SpecificIpAddr;
}
CeString strRASName("Desktop MAS");
// remove any conflicting entry
CeRasEntry ::Delete(strRASName);
// create our new entry
rasEntry.Set(strRASName, NULL);
// rasEntry.SetWin95(m_strRASName, "", bSpeaker);
// set up the dial out parameters
LPCTSTR szUser = _T("Kenny"), szPassword = _T("Fred");
CeRasDialParams rasParam(strRASName, szUser, szPassword);
CeRasConn rasConn;
rasConn.SetTimeout(150000U);
DWORD dwFlags = RDEOPT_UsePrefixSuffix | RDEOPT_IgnoreModemSpeaker;
// if (bSpeaker)
// dwFlags |= RDEOPT_SetModemSpeaker;
CeRasDialExt rasDialExt(dwFlags);
// dial
rasConn.Dial(&rasParam, TRUE, &rasDialExt);
// CRASPppIp PppIp;
// rasConn.GetProjectionInfo(&PppIp);
// m_strHCSIPAddr = PppIp.szIpAddress;
// if (m_strRCSIPAddr.IsEmpty())
// // use the overrride address of the PPP server
// m_strRCSIPAddr = PppIp.szServerIpAddress;
// CString str;
// str.Format("FMS IP: %s, RCS IP: %s", (LPCTSTR) m_strHCSIPAddr, (LPCTSTR) m_strRCSIPAddr);
}
*/
void CeMainWnd::OnNewSite()
{
CePropertyDlg dlg;
CeFtpSite site;
dlg.AddFtpSiteProperty(site);
if (IDOK == dlg.DoModal(IDD_PROPERTY) && ! site.m_strName.IsEmpty())
{
TVINSERTSTRUCT is;
is.hParent = TreeView_GetRoot(m_hwndTree);
is.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
is.item.pszText = (LPTSTR) (LPCTSTR) site.m_strName;
is.item.iImage = imFtpSite;
is.item.iSelectedImage = imFtpSite;
is.item.lParam = tntFtpSite;
CeString str;
HTREEITEM hAfter;
for (hAfter = TreeView_GetChild(m_hwndTree, is.hParent);
hAfter != NULL;
hAfter = TreeView_GetNextSibling(m_hwndTree, hAfter))
{
str = TreeView_GetItemText(m_hwndTree, hAfter);
if (str.CompareNoCase(site.m_strName))
{
hAfter = TreeView_GetPrevSibling(m_hwndTree, hAfter);
break;
}
}
is.hInsertAfter = hAfter;
TreeView_InsertItem(m_hwndTree, &is);
}
}
TCHAR* g_szSmallTips[] =
{
_T("Delete"),
_T("New Folder"),
_T("Properties"),
_T("Options"),
_T("Site Connect"),
_T("Site Disconnect"),
_T("About ftpView"),// no seperator skipping
};
TBBUTTON g_tb[] =
{
{0, ID_FILE_DELETE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{0, ID_FILE_NEW_FOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{0, ID_FILE_PROPERTIES, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
{0, ID_ACTIONS_CONNECT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{0, ID_ACTIONS_DISCONNECT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
};
void CeMainWnd::CreateBars()
{
#ifdef _WIN32_WCE
HIMAGELIST hImage = ImageList_LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_SEPERATORS), 16, 0, RGB(0,255,255));
m_cmdband.Create(m_hWnd, IDC_BAND, RBS_SMARTLABELS|RBS_VARHEIGHT|RBS_BANDBORDERS, hImage);
REBARBANDINFO rbbi[2];
memset(&rbbi, 0, sizeof rbbi);
// specific init
rbbi[0].cbSize = sizeof REBARBANDINFO;
rbbi[0].wID = IDC_MENU_BAND;
rbbi[0].fMask = RBBIM_ID|RBBIM_IMAGE|RBBIM_STYLE;
rbbi[0].fStyle = RBBS_NOGRIPPER;
rbbi[0].iImage = 0;
rbbi[1].cbSize = sizeof REBARBANDINFO;
rbbi[1].wID = IDC_BUTTON_BAND;
rbbi[1].fMask = RBBIM_ID|RBBIM_IMAGE;
rbbi[1].iImage = 1;
if (m_cmdband.AddBands(2, rbbi))
{
// Add the menu bar first
m_cmdband.GetCommandBar(0).InsertMenubar(IDR_MENU1, 0);
// Need: properties, del db, del record, ...
int nStd = m_cmdband.GetCommandBar(1).AddStdBitmap(IDB_STD_SMALL_COLOR);
int nView = m_cmdband.GetCommandBar(1).AddStdBitmap(IDB_VIEW_SMALL_COLOR);
int nLocal = m_cmdband.GetCommandBar(1).AddBitmap(IDB_HELP4, 1, 16, 16);
m_cmdband.GetCommandBar(1).AddBitmap(IDB_OPTIONS4, 1, 16, 16);
g_tb[0].iBitmap = nStd + STD_DELETE;
g_tb[1].iBitmap = nView + VIEW_NEWFOLDER;
g_tb[2].iBitmap = nStd + STD_PROPERTIES;
g_tb[4].iBitmap = nView + VIEW_NETCONNECT;
g_tb[5].iBitmap = nView + VIEW_NETDISCONNECT;
m_cmdband.GetCommandBar(1).AddButtons(sizeof(g_tb) / sizeof(TBBUTTON), g_tb);
// Add tooltips for the buttons we added
m_cmdband.GetCommandBar(1).AddToolTips(sizeof(g_szSmallTips)/sizeof(TCHAR*), (LPTSTR) g_szSmallTips);
}
#endif
}
void CeMainWnd::LoadOptions()
{
CeRegKey key;
key.Create(HKEY_LOCAL_MACHINE, _T("Software\\Magenic\\FtpView"));
DWORD bTmp;
key.QueryValue(bTmp, _T("SysIcons")); g_options.m_bUseSysIcons = (bTmp != 0);
key.QueryValue(bTmp, _T("TrayIcon")); g_options.m_bIconbar = (bTmp != 0);
key.QueryValue(bTmp, _T("Close")); g_options.m_bCloseButton = (bTmp != 0);
key.QueryValue(bTmp, _T("ROM")); g_options.m_bROM = (bTmp != 0);
key.QueryValue(bTmp, _T("ColType")); g_options.m_bCol_Type = (bTmp != 0);
key.QueryValue(bTmp, _T("ColDate")); g_options.m_bCol_Date = (bTmp != 0);
key.QueryValue(bTmp, _T("ColSize")); g_options.m_bCol_Size = (bTmp != 0);
key.QueryValue(bTmp, _T("ColAttrib")); g_options.m_bCol_Attrib = (bTmp != 0);
//Get the font back from the settings
LOGFONT lf;
DWORD dwByteCnt = sizeof(LOGFONT);
if (S_OK == key.QueryValue((BYTE*) &lf, _T("Font"), &dwByteCnt))
{
if (sizeof(LOGFONT) == dwByteCnt)
{
// create an initial font from the LOGFONT structure written
// out to the registry
HFONT hFont = ::CreateFontIndirect(&lf);
SetCtrlFont(hFont);
}
}
key.QueryValue(m_dwFontSize, _T("FontSize"));
}
void CeMainWnd::StoreOptions()
{
CeRegKey key;
key.Create(HKEY_LOCAL_MACHINE, _T("Software\\Magenic\\FtpView"));
if (NULL != m_hFont)
{
LOGFONT lf;
::GetObject((HGDIOBJ) m_hFont, sizeof LOGFONT, &lf);
DWORD dwByteCnt = sizeof(LOGFONT);
key.SetValue((BYTE*) &lf, sizeof LOGFONT, _T("Font"));
}
key.SetValue(m_dwFontSize, _T("FontSize"));
key.SetValue(g_options.m_bUseSysIcons, _T("SysIcons"));
key.SetValue(g_options.m_bIconbar, _T("TrayIcon"));
key.SetValue(g_options.m_bCloseButton, _T("Close"));
key.SetValue(g_options.m_bROM, _T("ROM"));
key.SetValue(g_options.m_bCol_Type, _T("ColType"));
key.SetValue(g_options.m_bCol_Date, _T("ColDate"));
key.SetValue(g_options.m_bCol_Size, _T("ColSize"));
key.SetValue(g_options.m_bCol_Attrib, _T("ColAttrib"));
}
BOOL CeMainWnd::OnCreate(LPCREATESTRUCT lpCS, bool& bHandled)
{
bHandled = true;
// get the version info
GetVersionEx(&g_osvi);
// Open the settings key
LoadOptions();
// Initialize our one automation function for 2.01 clients,
// the DLL will stay loaded "forever"
LoadProc((FARPROC*) &g_pfnVarDateFromStr, _T("VarDateFromStr"), _T(CEPLAT_WCE_OLEAUT32_DLL));
// Add the tool bars
CreateBars();
// adjust client to their size
CeRect rc;
GetClientRect(&rc);
#if defined(_WIN32_WCE)
rc.top += m_cmdband.Height();
#endif
CeRect rcTree, rcList;
GetWindowPlacements(rc, rcTree, rcList);
//
DWORD dwStyle = WS_VISIBLE | WS_CHILD |
TVS_HASBUTTONS |
TVS_HASLINES |
TVS_EDITLABELS |
TVS_NOTOOLTIPS |
TVS_SHOWSELALWAYS ;
m_hwndTree = CreateWindowEx(0 /*WS_EX_CLIENTEDGE*/,
WC_TREEVIEW, NULL, dwStyle,
rcTree.left, rcTree.top, rcTree.Width(), rcTree.Height(),
*this, (HMENU) IDC_TREE, g_hInst, NULL);
::SendMessage(m_hwndTree, WM_SETFONT, (WPARAM) m_hFont, TRUE);
// Create the image list
HIMAGELIST hImages;
hImages = ImageList_LoadImage(g_hInst, MAKEINTRESOURCE(IDB_IMAGELIST),
16, 0, RGB(255,255,255), IMAGE_BITMAP, 0);
TreeView_SetImageList(m_hwndTree, hImages, TVSIL_NORMAL);
TreeView_SetImageList(m_hwndTree, hImages, TVSIL_STATE);
m_hImages = ImageList_LoadImage(g_hInst, MAKEINTRESOURCE(IDB_IMAGELIST),
16, 0, RGB(255,255,255), IMAGE_BITMAP, 0);
// initialize the tree
TVINSERTSTRUCT is;
is.hInsertAfter = TVI_SORT;
is.hParent = TVI_ROOT;
is.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE;
if (CeIsPPC())
is.item.pszText = _T("My Palm");
else
is.item.pszText = _T("My Hand");
is.item.lParam = tntDesktop;
is.item.iSelectedImage = is.item.iImage = imDesktop;
HTREEITEM hRoot = TreeView_InsertItem(m_hwndTree, &is);
is.hParent = hRoot;
is.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_CHILDREN | TVIF_PARAM | TVIF_SELECTEDIMAGE;
is.hInsertAfter = TVI_FIRST;
is.item.cChildren = I_CHILDRENCALLBACK;
is.item.lParam = tntDevice;
is.item.pszText = _T("My Pocket PC");
if (CeIsPPC())
{
is.item.iSelectedImage = is.item.iImage = imPPC;
}
else if (CeIsHPCPro())
{
is.item.iSelectedImage = is.item.iImage = imHPCPro;
}
else
{
is.item.iSelectedImage = is.item.iImage = imHPC;
}
TreeView_InsertItem(m_hwndTree, &is);
PopulateFtpSites(hRoot);
TreeView_Expand(m_hwndTree, hRoot, TVE_EXPAND);
// Create the tree view
dwStyle = WS_VISIBLE | WS_CHILD |
LVS_EDITLABELS |
LVS_REPORT |
LVS_SINGLESEL ;
if (g_options.m_bUseSysIcons)
dwStyle |= LVS_SHAREIMAGELISTS;
m_hwndList = CreateWindowEx(0 /*WS_EX_CLIENTEDGE*/,
WC_LISTVIEW, NULL, dwStyle,
rcList.left, rcList.top, rcList.Width(), rcList.Height(),
*this, (HMENU) IDC_LIST, g_hInst, NULL);
::SendMessage(m_hwndList, WM_SETFONT, (WPARAM) m_hFont, TRUE);
// initialize sort list
g_sortinfo.hwndList = m_hwndList;
// causes weird effects with drag and drop
// ListView_SetExtendedListViewStyle(m_hwndList, LVS_EX_FULLROWSELECT);
// Add the columns
AddColumns();
// Set the image list
if (g_options.m_bUseSysIcons)
{
SHFILEINFO shinfo;
memset(&shinfo, 0, sizeof shinfo);
HIMAGELIST hSysImages = (HIMAGELIST) SHGetFileInfo(_T(".ZZZ"), 0, &shinfo, sizeof shinfo,
SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);
ListView_SetImageList(m_hwndList, hSysImages, LVSIL_SMALL);
}
else
{
ListView_SetImageList(m_hwndList, hImages, LVSIL_SMALL);
}
// Add Close button
if (g_options.m_bCloseButton)
{
m_cmdband.AddAdornments(0 /*CMDBAR_HELP*/, NULL);
}
// Set the panes
SetPanes(m_hwndTree, m_hwndList);
// Show or hide the icon bar
ShowIconBar(g_options.m_bIconbar);
// Done
return TRUE;
}
void CeMainWnd::AddColumns()
{
while (ListView_DeleteColumn(m_hwndList, 0))
;
int nCol = 0;
LVCOLUMN col;
col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
col.cx = 88;
col.pszText = _T("Name");
ListView_InsertColumn(m_hwndList, nCol++, &col);
int nColType;
g_arColumns.Add(nColType = SORTCOL_NAME);
if (g_options.m_bCol_Size)
{
col.fmt = LVCFMT_RIGHT;
col.cx = 60;
col.pszText = _T("Size");
ListView_InsertColumn(m_hwndList, nCol++, &col);
g_arColumns.Add(nColType = SORTCOL_SIZE);
}
if (g_options.m_bCol_Type)
{
col.fmt = LVCFMT_LEFT;
col.cx = 80;
col.pszText = _T("Type");
ListView_InsertColumn(m_hwndList, nCol++, &col);
g_arColumns.Add(nColType = SORTCOL_TYPE);
}
if (g_options.m_bCol_Date)
{
col.fmt = LVCFMT_LEFT;
col.cx = 90;
col.pszText = _T("Modified");
ListView_InsertColumn(m_hwndList, nCol++, &col);
g_arColumns.Add(nColType = SORTCOL_DATE);
}
if (g_options.m_bCol_Attrib)
{
col.fmt = LVCFMT_RIGHT;
col.cx = 40;
col.pszText = _T("Attributes");
ListView_InsertColumn(m_hwndList, nCol++, &col);
g_arColumns.Add(nColType = SORTCOL_ATTRIB);
}
}
void CeMainWnd::ShowIconBar(bool bShow)
{
// Set up the icon in the taskbar for bring us to the front
m_nid.cbSize = sizeof NOTIFYICONDATA;
m_nid.hWnd = m_hWnd;
m_nid.uID = IDI_APPICON;
m_nid.uFlags = NIF_MESSAGE | NIF_TIP;
m_nid.uCallbackMessage = WM_USER + 1000;
if (bShow)
{
m_nid.uFlags |= NIF_ICON;
m_nid.hIcon = (HICON) LoadImage(CeGetAppInstance(),
MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 16, 16, 0);
Shell_NotifyIcon(NIM_ADD, &m_nid);
}
else
{
Shell_NotifyIcon(NIM_DELETE, &m_nid);
}
}
void CeMainWnd::OnOptions()
{
CeOptionsDlg dlg;
dlg.m_bSysIcons = g_options.m_bUseSysIcons;
dlg.m_bClose = g_options.m_bCloseButton;
dlg.m_bIconbar = g_options.m_bIconbar;
dlg.m_bROM = g_options.m_bROM;
dlg.m_bCol_Type = g_options.m_bCol_Type;
dlg.m_bCol_Size = g_options.m_bCol_Size;
dlg.m_bCol_Date = g_options.m_bCol_Date;
dlg.m_bCol_Attrib = g_options.m_bCol_Attrib;
if (IDOK == dlg.DoModal())
{
if (g_options.m_bCol_Type != dlg.m_bCol_Type ||
g_options.m_bCol_Size != dlg.m_bCol_Size ||
g_options.m_bCol_Date != dlg.m_bCol_Date ||
g_options.m_bCol_Attrib != dlg.m_bCol_Attrib)
{
g_options.m_bCol_Type = dlg.m_bCol_Type;
g_options.m_bCol_Size = dlg.m_bCol_Size;
g_options.m_bCol_Date = dlg.m_bCol_Date;
g_options.m_bCol_Attrib = dlg.m_bCol_Attrib;
AddColumns();
OnRefresh();
}
if (g_options.m_bIconbar != dlg.m_bIconbar)
{
g_options.m_bIconbar = dlg.m_bIconbar;
// Show or hide the icon bar
ShowIconBar(g_options.m_bIconbar);
}
if (g_options.m_bROM != dlg.m_bROM)
{
g_options.m_bROM = dlg.m_bROM;
OnRefresh();
}
// must be done after restart
g_options.m_bUseSysIcons = dlg.m_bSysIcons;
g_options.m_bCloseButton = dlg.m_bClose;
}
}
void CeMainWnd::OnFont()
{
LOGFONT logfont;
if (NULL == m_hFont)
{
m_dwFontSize = 9;
GetObject(GetStockObject(SYSTEM_FONT), sizeof LOGFONT, &logfont);
}
else
{
GetObject(m_hFont, sizeof LOGFONT, &logfont);
}
CeFontDlg dlg(m_dwFontSize, &logfont);
if (IDOK == dlg.DoModal(IDD_FONTDLG))
{
SetCtrlFont(dlg.m_hFont);
m_dwFontSize = dlg.m_nPointSize;
}
}
void CeMainWnd::SetCtrlFont(HFONT hFont)
{
if (m_hFont)
::DeleteObject(m_hFont);
if (NULL == hFont)
{
m_hFont = NULL;
return;
}
LOGFONT logfont;
GetObject(hFont, sizeof logfont, &logfont);
m_hFont = ::CreateFontIndirect(&logfont);
::SendMessage(m_hwndTree, WM_SETFONT, (WPARAM) m_hFont, TRUE);
::SendMessage(m_hwndList, WM_SETFONT, (WPARAM) m_hFont, TRUE);
}
void CeMainWnd::OnAbout()
{
CeAboutDlg dlg;
dlg.DoModal();
}
void CeMainWnd::OnProperties()
{
HWND hwndFocus = GetFocus();
WIN32_FIND_DATA fd;
CePropertyDlg dlg;
CeString strFullName;
CeString strName;
if (hwndFocus == m_hwndList)
{
strFullName = m_strCurrentDirectory;
int nSel = ListView_GetNextItem(m_hwndList, -1, LVIS_SELECTED);
if (nSel < 0)
// list has focus but no selection, go away
return;
ListView_GetItemText(m_hwndList, nSel, 0, strName.GetBufferSetLength(64), 64);
strName.ReleaseBuffer();
strFullName += strName;
if (m_bCurrentFtp)
{
m_ftpConn.GetFileInfo(strFullName, fd);
}
else
{
CeFindFile ff;
if (ff.FindFirst(strFullName))
fd = ff;
}
dlg.AddFileProperty(m_strCurrentDirectory, fd, !m_bCurrentFtp);
}
else if (hwndFocus == m_hwndTree)
{
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
if (NULL == hItem)
return;
strFullName = CeString((LPCTSTR) m_strCurrentDirectory, m_strCurrentDirectory.Length() - 1);
strName = TreeView_GetItemText(m_hwndTree, hItem);
eTreeNodeType eType = (eTreeNodeType) TreeView_GetLParam(m_hwndTree, hItem);
if (tntFtpSite == eType)
{
// edit the ftp site properties
CeFtpSite site;
if (! site.Find(strName))
return;
dlg.AddFtpSiteProperty(site);
}
else if (tntDesktop == eType)
{
dlg.AddSystemProperty();
}
else if (tntFtpSiteDir == eType)
{
memset(&fd, 0, sizeof fd);
fd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
dlg.AddFileProperty(strFullName, fd, false);
}
else if (tntLocalDir == eType)
{
bool bPath;
HTREEITEM hParent = TreeView_GetParent(m_hwndTree, hItem);
CeString strTmp = GetTreePath(hParent, bPath);
CeFindFile ff;
if (ff.FindFirst(strFullName))
fd = ff;
dlg.AddFileProperty(strTmp, fd, true);
}
else if (tntDevice == eType)
{
dlg.AddSystemProperty();
}
}
else
{
// focus is gone somewhere
return;
}
if (IDOK == dlg.DoModal(IDD_PROPERTY))
{
if (hwndFocus == m_hwndList)
{
// refresh the current list item
int nSel = ListView_GetNextItem(m_hwndList, -1, LVIS_SELECTED);
ListView_DeleteItem(m_hwndList, nSel);
InsertFile(m_strCurrentDirectory, &dlg.m_pageFile.m_finddata, FALSE, nSel);
ListView_SetItemState(m_hwndList, nSel, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
}
else
{
// tree had focus, copy new name if there was one
}
}
// place focus back on the previous location
::SetFocus(hwndFocus);
}
void CeMainWnd::OnDestroy(bool& bHandled)
{
StoreOptions();
// Remove the icon in the taskbar for bring us to the front
Shell_NotifyIcon(NIM_DELETE, &m_nid);
bHandled = true;
PostQuitMessage(0);
}
void CeMainWnd::OnClose(bool& bHandled)
{
bHandled = true;
if (m_ftpConn.IsConnected())
m_ftpConn.Disconnect();
DestroyWindow();
}
LRESULT CeMainWnd::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
switch (uMsg)
{
case WM_HELP:
{
// PROCESS_INFORMATION pi;
// ::CreateProcess(_T("peghelp.exe"), _T("file:BeamEx.htc"),
// NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
// CloseHandle(pi.hProcess);
// CloseHandle(pi.hThread);
}
break;
case WM_USER + 1000:
{
bHandled = true;
if (lParam == WM_LBUTTONUP || lParam == WM_LBUTTONDBLCLK)
{
SetForegroundWindow (m_hWnd);
}
else if (lParam == WM_LBUTTONDOWN)
{
;
}
}
}
return 1;
}
LRESULT CeMainWnd::OnNotify(int nCtrlId, LPNMHDR pNMH, bool& bHandled)
{
bHandled = false;
LRESULT bRet = FALSE; // default
if (IDC_TREE == nCtrlId)
{
bRet = OnTreeViewNotify((LPNMTREEVIEW) pNMH);
bHandled = true;
}
else if (IDC_LIST == nCtrlId)
{
bRet = OnListViewNotify((NMLISTVIEW*) pNMH);
bHandled = true;
}
else if (IDC_BAND == nCtrlId)
{
if (pNMH->code == RBN_HEIGHTCHANGE)
{
CeRect rc;
GetClientRect(&rc);
rc.top += m_cmdband.Height();
CeRect rcTree, rcList;
GetWindowPlacements(rc, rcTree, rcList);
::MoveWindow(m_hwndList, rcList.left, rcList.top,
rcList.Width(), rcList.Height(), TRUE);
::MoveWindow(m_hwndTree, rcTree.left, rcTree.top,
rcTree.Width(), rcTree.Height(), TRUE);
//TRACE0("Size Change\n");
}
}
return bRet;
}
LRESULT CeMainWnd::OnListViewNotify(NMLISTVIEW* pNMLV)
{
LV_DISPINFO* pDI = (LV_DISPINFO *) pNMLV;
NMKEY* pNMK = (NMKEY*) pNMLV;
switch (pNMLV->hdr.code)
{
case NM_KEYDOWN:
// here for future ab(use) currently not sent by this control (ala 2.11)
if (pNMK->wVKey == VK_DELETE)
OnDelete();
else if (pNMK->wVKey == VK_RETURN)
OnRun();
break;
case NM_DBLCLK:
OnRun();
break;
case LVN_BEGINDRAG:
// Notifies the tree view control's parent window that a drag
// and drop operation is being initiated.
OnBeginDragList(pNMLV);
return 0;
case LVN_COLUMNCLICK:
OnColumnClick(pNMLV);
break;
case LVN_ENDLABELEDIT:
{
// rename the current list entry
if (NULL == pDI->item.pszText)
// cancelled
return FALSE;
//get the old file name
CeString strFile;
ListView_GetItemText(m_hwndList, pDI->item.iItem, 0, strFile.GetBuffer(120), 120);
strFile.ReleaseBuffer();
CeString strOld = m_strCurrentDirectory;
CeString strNew = m_strCurrentDirectory;
strNew += pDI->item.pszText;
strOld += strFile;
if (m_bCurrentFtp)
{
if (! m_ftpConn.RenameFile(strOld, strNew))
{
CeString strErr = m_ftpConn.GetFtpErrorReplyString();
MessageBox(strErr, _T("FTP rename failed!"), MB_OK);
return FALSE;
}
}
else
{
if (! MoveFile(strOld, strNew))
{
CeString strErr;
strErr.Format(_T("Error %lu while renaming."), GetLastError());
MessageBox(strErr, _T("Rename failed!"), MB_OK);
return FALSE;
}
}
WIN32_FIND_DATA fd;
if (m_bCurrentFtp)
{
m_ftpConn.GetFileInfo(strNew, fd);
}
else
{
CeFindFile ff;
if (ff.FindFirst(strNew))
fd = ff;
}
//
// Update
int nSel = ListView_GetNextItem(m_hwndList, -1, LVIS_SELECTED);
ListView_DeleteItem(m_hwndList, nSel);
InsertFile(m_strCurrentDirectory, &fd, FALSE, nSel);
ListView_SetItemState(m_hwndList, nSel, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
}
break;
case LVN_BEGINLABELEDIT:
return FALSE;
}
return 0;
}
void CeMainWnd::OnRefresh()
{
// Create a directory name going backward using the path, and determine
// if the selected node is on an FTP site
bool bFtp;
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
CeString strDir = GetTreePath(hItem, bFtp);
PopulateFilelist(hItem, strDir, bFtp);
}
BOOL CeMainWnd::Execute(LPCTSTR lpszDir, LPCTSTR lpszFile)
{
if (0 == *lpszDir)
return FALSE;
CeString str(lpszDir);
if (str[str.Length() - 1] != _T('\\'))
str += _T('\\');
str += lpszFile;
SHELLEXECUTEINFO sei;
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof sei;
sei.nShow = SW_SHOWNORMAL;
sei.lpVerb = _T("open");
sei.fMask = 0; // Allow function to put up an error SEE_MASK_FLAG_NO_UI;
sei.lpFile = str;
return ShellExecuteEx(&sei);
}
LRESULT CeMainWnd::OnTreeViewNotify(NMTREEVIEW* pNMTV)
{
bool bFtp;
HTREEITEM hRoot = TreeView_GetRoot(m_hwndTree);
switch (pNMTV->hdr.code)
{
case NM_KEYDOWN:
{
// here for future ab(use) currently not sent by this control (ala 2.11)
NMKEY* pNMK = (NMKEY*) pNMTV;
if (pNMK->wVKey == VK_DELETE)
OnDelete();
else if (pNMK->wVKey == VK_RETURN)
OnRun();
}
break;
case NM_DBLCLK:
{
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
eTreeNodeType eType = (eTreeNodeType) TreeView_GetLParam(m_hwndTree, hItem);
switch (eType)
{
case tntFtpSite:
if (m_ftpConn.IsConnected() && hItem == m_hConnected)
OnDisconnect();
else
OnConnect();
break;
}
}
break;
case TVN_BEGINDRAG:
// a drag operation has been initiated.
OnBeginDragTree(pNMTV);
return FALSE;
case TVN_BEGINLABELEDIT:
{
// an edit operation has been initiated.
TV_DISPINFO* pTVDI = (TV_DISPINFO*) pNMTV;
bool bFtp;
CeString strDir = GetTreePath(pTVDI->item.hItem, bFtp);
if (strDir.IsEmpty() || (strDir == _T("\\") && ! bFtp))
// don't allow renaming the roots...
return TRUE;
}
return FALSE;
case TVN_ENDLABELEDIT:
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*) pNMTV;
if (pTVDI->item.pszText == NULL || *pTVDI->item.pszText == 0)
return TRUE;
bool bFtp;
HTREEITEM hParent = TreeView_GetParent(m_hwndTree, pTVDI->item.hItem);
CeString strDir = GetTreePath(hParent, bFtp);
CeString strNew = strDir;
CeString strOld = strDir;
strNew += pTVDI->item.pszText;
strOld += TreeView_GetItemText(m_hwndTree, pTVDI->item.hItem);
if (pTVDI->item.lParam == tntFtpSite || bFtp)
{
if (strDir.IsEmpty())
{
if (strNew.IsEmpty() || strOld.IsEmpty())
// ignore
return TRUE;
if (! CeFtpSite::Rename(strOld, strNew))
//
return FALSE;
}
else if (! m_ftpConn.RenameFile(strOld, strNew))
{
CeString str = m_ftpConn.GetFtpErrorReplyString();
MessageBox(str, _T("FTP rename failed!"), MB_OK);
return FALSE;
}
return TRUE;
}
else
{
if (! MoveFile(strOld, strNew))
{
CeString strErr;
strErr.Format(_T("Error %lu while renaming."), GetLastError());
MessageBox(strErr, _T("Rename failed!"), MB_OK);
return FALSE;
}
else
return TRUE;
}
}
return FALSE;
case TVN_SELCHANGED:
if (pNMTV->action == TVC_BYKEYBOARD || pNMTV->action == TVC_BYMOUSE)
{
//TRACE0("Tree item changed\n");
// Create a directory name going backward using the path, and determine
// if the selected node is on an FTP site
CeString strDir = GetTreePath(pNMTV->itemNew.hItem, bFtp);
PopulateFilelist(pNMTV->itemNew.hItem, strDir, bFtp);
}
break;
case TVN_GETDISPINFO:
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*) pNMTV;
//TRACE0("Tree item dispinfo request\n");
if (pTVDI->item.mask & TVIF_CHILDREN)
pTVDI->item.cChildren = I_CHILDRENCALLBACK;
}
break;
// A directory node has been collapsed. Now we can remove the child items
// from the node.
case TVN_ITEMEXPANDED:
if (pNMTV->action == TVE_COLLAPSE)
{
// Now actually remove the child items within this directory
if (pNMTV->itemNew.lParam == tntDesktop)
// skip the root all items there are added manually
return 0;
//TRACE0("Tree item collapsed\n");
//HTREEITEM hItem;
//while (NULL != (hItem = TreeView_GetChild(m_hwndTree, pNMTV->itemNew.hItem)))
// TreeView_DeleteItem(m_hwndTree, hItem);
HTREEITEM hSel = TreeView_GetSelection(m_hwndTree);
// Create a directory name going backward using the path, and determine
// if the selected node is on an FTP site
bool bFtp;
CeString strDir = GetTreePath(hSel, bFtp);
PopulateFilelist(hSel, strDir, bFtp);
}
break;
// A node is expanding or collapsing. We need to update the folder
// images to reflect either a closed or open folder depending on it's
// new state.
case TVN_ITEMEXPANDING:
if (pNMTV->action == TVE_COLLAPSE || pNMTV->action == TVE_COLLAPSERESET)
{
if (pNMTV->itemNew.hItem == hRoot)
// skip the root all items there are added manually
return 1;
//TRACE0("Tree item collapsing\n");
}
else
{
//TRACE0("Item expanding\n");
if (pNMTV->itemNew.hItem == TreeView_GetRoot(m_hwndTree))
// skip the root all items there are added manually
return 0;
if (! (pNMTV->itemNew.state & TVIS_EXPANDEDONCE))
{
// one time addition
//TRACE0("Item expanding\n");
//
// Create a directory name going backward using the path
//
CeString strDir = GetTreePath(pNMTV->itemNew.hItem, bFtp);
BOOL bSubs = PopulateDirectory(pNMTV->itemNew.hItem, strDir, bFtp);
// Retrieve the image from the current item
pNMTV->itemNew.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
TreeView_GetItem(m_hwndTree, &(pNMTV->itemNew));
pNMTV->itemNew.mask = TVIF_CHILDREN;
pNMTV->itemNew.cChildren = bSubs ? 1: 0;
TreeView_SetItem(m_hwndTree, &(pNMTV->itemNew));
}
}
break;
}
return 0;
}
CeString CeMainWnd::GetTreePath(HTREEITEM hDir, bool& bFtp)
{
// assume failure
bFtp = false;
TVITEM tvi;
TCHAR szBuf[MAX_PATH];
tvi.mask = TVIF_TEXT | TVIF_PARAM;
tvi.pszText = szBuf;
tvi.cchTextMax = MAX_PATH;
tvi.hItem = hDir;
CeString strDir;
CeString strTmp;
while (TreeView_GetItem(m_hwndTree, &tvi) && tvi.lParam != tntDesktop)
{
if (tvi.lParam == tntFtpSite)
bFtp = true;
if (tvi.lParam == tntLocalDir || tvi.lParam == tntFtpSiteDir)
{
strTmp = tvi.pszText;
strTmp += _T("\\");
strDir = strTmp + strDir;
}
else if (tvi.lParam == tntFtpSite || tvi.lParam == tntDevice)
{
strTmp = _T("\\");
strDir = strTmp + strDir;
}
// the NEXT node up the tree
tvi.hItem = TreeView_GetParent(m_hwndTree, tvi.hItem);
TreeView_GetItem(m_hwndTree, &tvi);
}
if (strDir.IsEmpty())
{
LPITEMIDLIST lppidl = NULL;
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &lppidl);
SHGetPathFromIDList(lppidl, szBuf);
strDir = szBuf;
}
return strDir;
}
BOOL CeMainWnd::PopulateFtpSites(HTREEITEM hRoot)
{
BOOL bAdded = FALSE;
// might take a while...
CeWaitCursor wait;
CeDb db;
if (! CeFtpSite::Open(db))
return bAdded;
CeDbRecord rec;
for (CEOID oidRec = db.SeekFirst(); 0 != oidRec; oidRec = db.SeekNext())
{
if (!db.ReadRec(rec))
continue;
// Get the site name
CeString str;
rec.GetIdVal(SITE_NAME, str);
TCHAR szBuf[64];
TVITEM tvi;
tvi.pszText = szBuf;
tvi.cchTextMax = 64;
HTREEITEM hItem = NULL, hLast = NULL;
for (hItem = TreeView_GetChild(m_hwndTree, hRoot); NULL != hItem; )
{
tvi.hItem = hItem;
tvi.mask = TVIF_TEXT | TVIF_PARAM;
TreeView_GetItem(m_hwndTree, &tvi);
if (tvi.lParam == tntFtpSite && str >= tvi.pszText)
// insert after THIS item
break;
hLast = hItem;
hItem = TreeView_GetNextSibling(m_hwndTree, hItem);
}
//
// initialize the tree
//
TVINSERTSTRUCT is;
is.hInsertAfter = hItem ? hItem : TVI_LAST;
is.hParent = hRoot;
is.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_CHILDREN | TVIF_PARAM | TVIF_SELECTEDIMAGE;
is.item.pszText = (LPTSTR) (LPCTSTR) str;
is.item.cChildren = 0;
is.item.lParam = tntFtpSite;
is.item.iSelectedImage = imFtpSite;
is.item.iImage = imFtpSite;
TreeView_InsertItem(m_hwndTree, &is);
bAdded = TRUE;
}
return bAdded;
}
BOOL CeMainWnd::PopulateDirectory(HTREEITEM hItem, LPCTSTR szDir, bool bFtp)
{
BOOL bAdded = FALSE;
// Might take a while
CeWaitCursor wait;
if (bFtp)
{
CeString str(szDir);
for (int ii = 0; ii < str.GetLength(); ii++)
{
if (_T('\\') == str[ii])
str[ii] = _T('/');
}
if (! m_ftpConn.SetCurDir(str))
{
CeString str = m_ftpConn.GetFtpErrorReplyString();
MessageBox(str, _T("FTP Server"));
OnDisconnect();
return FALSE;
}
CeFileAttrArray files;
m_ftpConn.GetFileList(files);
for (ii = 0; ii < files.GetCount(); ii++)
{
if (! (files[ii].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
continue;
if (_tcscmp(files[ii].cFileName, _T(".")) == 0 || _tcscmp(files[ii].cFileName, _T("..")) == 0)
// skip up and same directory
continue;
//
// initialize the tree
//
TVINSERTSTRUCT is;
is.hInsertAfter = TVI_SORT;
is.hParent = hItem;
is.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_CHILDREN | TVIF_PARAM | TVIF_SELECTEDIMAGE;
is.item.pszText = files[ii].cFileName;
is.item.cChildren = I_CHILDRENCALLBACK;
is.item.lParam = tntFtpSiteDir;
is.item.iSelectedImage = imFtpOpenFolder;
is.item.iImage = imFtpClosedFolder;
TreeView_InsertItem(m_hwndTree, &is);
bAdded = TRUE;
}
}
else
{
CeString str(szDir);
CeFindFile ff;
if (str[str.Length()-1] != _T('\\'))
str += _T("\\*.*");
else
str += _T("*.*");
if (! ff.FindFirst(str))
// no files
return FALSE;
do
{
if (ff.IsDirectory())
{
//
// initialize the tree
//
TVINSERTSTRUCT is;
is.hInsertAfter = TVI_SORT;
is.hParent = hItem;
is.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
is.item.pszText = ff.cFileName;
is.item.cChildren = I_CHILDRENCALLBACK;
is.item.lParam = tntLocalDir;
is.item.iSelectedImage = ff.IsStorageCard() ? imFlashOpen: imFolderOpen;
is.item.iImage = ff.IsStorageCard() ? imFlashClose: imFolderClose;
TreeView_InsertItem(m_hwndTree, &is);
bAdded = TRUE;
}
}
while (ff.FindNext());
}
return bAdded;
}
void CeMainWnd::PopulateFilelist(HTREEITEM hItem, LPCTSTR szDir, bool bFtp)
{
if (NULL == m_hwndList)
return;
// Might take a while
CeWaitCursor wait;
CeString str(szDir);
ListView_DeleteAllItems(m_hwndList);
if (str.IsEmpty())
return;
m_strCurrentDirectory = szDir;
m_bCurrentFtp = bFtp;
if (! bFtp)
{
if (str[str.Length()-1] != _T('\\'))
str += _T("\\*.*");
else
str += _T("*.*");
CeFindFile ff;
if (! ff.FindFirst(str))
// no files
return;
::SendMessage(m_hwndList, WM_SETREDRAW, FALSE, 0);
int ii = 0;
do
{
if (ff.IsDirectory())
continue;
if (ff.IsInROM() && (! g_options.m_bROM))
continue;
InsertFile(szDir, &ff, bFtp, ii++);
}
while (ff.FindNext());
::SendMessage(m_hwndList, WM_SETREDRAW, TRUE, 0);
}
else
{
if (! m_ftpConn.IsConnected())
// selected an FTP site, but we aren't connected
return;
LPARAM lp = TreeView_GetLParam(m_hwndTree, hItem);
if (lp == tntFtpSite && hItem != m_hConnected)
{
// a different FTP site, skip it
return;
}
CeWaitCursor wait;
::SendMessage(m_hwndList, WM_SETREDRAW, FALSE, 0);
CeFileAttrArray files;
if (! m_ftpConn.GetFileList(files, szDir))
{
CeString str = m_ftpConn.GetFtpErrorReplyString();
MessageBox(str, _T("FTP directory failed!"), MB_OK);
}
else
{
for (int ii = 0; ii < files.GetCount(); ii++)
if (! (files[ii].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
InsertFile(szDir, &files[ii], bFtp, ii);
}
::SendMessage(m_hwndList, WM_SETREDRAW, TRUE, 0);
}
// resort
// for speed, don't sort, if the user clicks a column, then it will sort
//ListView_SortItems(m_hwndList, CmpList, (LPARAM) &m_sortinfo);
g_sortinfo.bAscending = true;
g_sortinfo.nColumnNo = -1;
// select the first item
ListView_SetItemState(m_hwndList, 0, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
}
BOOL GetShFileInfo(LPCTSTR lpszName, DWORD dwAttrib, SHFILEINFO & shinfo, int nFlags, bool bLocal)
{
memset(&shinfo, 0, sizeof(SHFILEINFO));
DWORD dwVersion = g_osvi.dwMajorVersion * 100 + g_osvi.dwMinorVersion;
if (g_options.m_bUseSysIcons && dwVersion > 201)
{
// after version 2.01, this actually worked
if ( ::SHGetFileInfo(lpszName, dwAttrib, &shinfo, sizeof(SHFILEINFO), nFlags))
return S_OK;
// continue on failure
}
// 2.01 version of SHGetFileInfo() is broken, implement our own
LPCTSTR lpsz = _tcsrchr(lpszName, _T('\\'));
if (NULL != lpsz)
_tcscpy(shinfo.szDisplayName, lpsz+1);
else
_tcscpy(shinfo.szDisplayName, lpszName);
if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)
{
_tcscpy(shinfo.szTypeName, _T("Folder"));
shinfo.hIcon = LoadIcon(CeGetAppInstance(), MAKEINTRESOURCE(IDI_FOLDER));
}
else if (NULL != (lpsz = _tcsrchr(lpszName, _T('.'))))
{
HRESULT hr = S_OK;
// extract the extension
TCHAR szTmp[MAX_PATH];
_tcsncpy(szTmp, lpsz, MAX_PATH);
szTmp[MAX_PATH] = 0;
// open the registry key
CeRegKey key;
if (SUCCEEDED(hr))
hr = _WIN32_HR(key.Open(HKEY_CLASSES_ROOT, szTmp, KEY_READ));
DWORD dwCnt;
if (SUCCEEDED(hr))
// open file type key
hr = _WIN32_HR(key.QueryValue(szTmp, _T(""), &(dwCnt = MAX_PATH)));
key.Close();
if (SUCCEEDED(hr))
// open file type key
hr = _WIN32_HR(key.Open(HKEY_CLASSES_ROOT, szTmp, KEY_READ));
if (SUCCEEDED(hr))
// open file type key
hr = _WIN32_HR(key.QueryValue(szTmp, _T(""), &(dwCnt = MAX_PATH)));
key.Close();
if (SUCCEEDED(hr))
{
// type name from registry
_tcscpy(shinfo.szTypeName, szTmp);
shinfo.iIcon = imDoc;
}
else
{
if (_tcsicmp(lpsz, _T(".lnk")) == 0)
{
_tcscpy(shinfo.szTypeName, _T("Shortcut"));
}
else
{
// type name from extention
_tcscpy(shinfo.szTypeName, lpsz+1);
_tcscat(shinfo.szTypeName, _T(" File"));
shinfo.iIcon = imDocUnknown;
}
}
if (nFlags & SHGFI_ICON)
{
if (_tcsicmp(lpsz, _T(".exe")) == 0)
{
if (! (nFlags & SHGFI_SMALLICON))
shinfo.hIcon = LoadIcon(CeGetAppInstance(), MAKEINTRESOURCE(IDI_EXE));
shinfo.iIcon = imApp;
}
else
{
if (! (nFlags & SHGFI_SMALLICON))
shinfo.hIcon = LoadIcon(CeGetAppInstance(), MAKEINTRESOURCE(IDI_FILE));
}
}
}
else
{
_tcscpy(shinfo.szTypeName, _T("File"));
if (nFlags & SHGFI_ICON)
{
if (! (nFlags & SHGFI_SMALLICON))
shinfo.hIcon = LoadIcon(CeGetAppInstance(), MAKEINTRESOURCE(IDI_FILE));
shinfo.iIcon = imDocUnknown;
}
}
return S_OK;
}
void CeMainWnd::InsertFile(LPCTSTR szDir, WIN32_FIND_DATA* pFD, bool bFtp, int iInsertItem)
{
CeString str;
SHFILEINFO shinfo;
UINT nFlags =
SHGFI_SYSICONINDEX | // Icon index
SHGFI_ICON |
SHGFI_SMALLICON | // Small icon
SHGFI_TYPENAME | // type name (e.g., CPP File)
SHGFI_DISPLAYNAME; // display name (no extension)
if (bFtp)
{
nFlags |= SHGFI_USEFILEATTRIBUTES;
GetShFileInfo(pFD->cFileName, pFD->dwFileAttributes, shinfo, nFlags, ! bFtp);
}
else
{
str = szDir;
str += pFD->cFileName;
GetShFileInfo(str, pFD->dwFileAttributes, shinfo, nFlags, ! bFtp);
}
DWORD dwVersion = g_osvi.dwMajorVersion * 100 + g_osvi.dwMinorVersion;
int iIcon = shinfo.iIcon;
if (! bFtp && dwVersion > 201 && !_tcscmp(shinfo.szTypeName, _T("Shortcut")))
{
TCHAR szTarget[128];
// This call always returns an extra character, handle it
if (::SHGetShortcutTarget(str, szTarget, 128))
{
LPTSTR lpsz = szTarget;
for (int ii = 0; *lpsz != 0; lpsz++)
{
if (*lpsz == _T('"'))
continue;
if (_istspace(*lpsz))
break;
szTarget[ii] = *lpsz;
ii++;
}
szTarget[ii] = 0;
nFlags =
SHGFI_SYSICONINDEX | //
SHGFI_ICON | //
SHGFI_SMALLICON | // Small icon
SHGFI_TYPENAME | // type name (e.g., CPP File)
SHGFI_DISPLAYNAME; // display name (no extension)
if (szTarget[0] != _T('\\'))
// use atributes when not a full path
nFlags |= SHGFI_USEFILEATTRIBUTES;
memset(&shinfo, 0, sizeof shinfo);
GetShFileInfo(szTarget, 0, shinfo, nFlags, true);
iIcon = shinfo.iIcon;
}
}
LVITEM item;
int nSubItem = 0;
if (iInsertItem < 0)
item.iItem = ListView_GetItemCount(m_hwndList);
else
item.iItem = iInsertItem;
// Name/Icon
item.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
item.pszText = pFD->cFileName;
item.iImage = iIcon;
item.iSubItem = nSubItem++;
item.lParam = (DWORD) new CeFileListItem(pFD->cFileName, pFD->nFileSizeLow,
pFD->dwFileAttributes, pFD->ftLastWriteTime, _T("Type"));
item.iItem = ListView_InsertItem(m_hwndList, &item);
TCHAR szTmp[256];
if (g_options.m_bCol_Size)
{
// Size
if (pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
szTmp[0] = 0;
else
wsprintf(szTmp, _T("%lu"), pFD->nFileSizeLow);
item.mask = LVIF_TEXT;
item.pszText = szTmp;
item.iSubItem = nSubItem++;
ListView_SetItem(m_hwndList, &item);
}
if (g_options.m_bCol_Type)
{
// Type
item.mask = LVIF_TEXT;
item.pszText = (LPTSTR) (LPCTSTR) shinfo.szTypeName;
item.iSubItem = nSubItem++;
ListView_SetItem(m_hwndList, &item);
}
if (g_options.m_bCol_Date)
{
// Modified
FILETIME ft = pFD->ftLastWriteTime;
if (! bFtp)
// need to convert time to local displayable format
FileTimeToLocalFileTime(&ft, &ft);
FormatDateTime(ft, szTmp);
item.mask = LVIF_TEXT;
item.pszText = szTmp;
item.iSubItem = nSubItem++;
ListView_SetItem(m_hwndList, &item);
}
if (g_options.m_bCol_Attrib)
{
// Attributes
int ii = 0;
if (pFD->dwFileAttributes & FILE_ATTRIBUTE_READONLY) szTmp[ii++] = _T('R');
if (pFD->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) szTmp[ii++] = _T('H');
if (pFD->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) szTmp[ii++] = _T('S');
if (pFD->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) szTmp[ii++] = _T('A');
if (pFD->dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) szTmp[ii++] = _T('C');
if (pFD->dwFileAttributes & FILE_ATTRIBUTE_INROM) szTmp[ii++] = _T('M');
if (pFD->dwFileAttributes & FILE_ATTRIBUTE_ROMMODULE) szTmp[ii++] = _T('X');
szTmp[ii] = 0;
item.mask = LVIF_TEXT;
item.pszText = szTmp;
item.iSubItem = nSubItem++;
ListView_SetItem(m_hwndList, &item);
}
}
void CeMainWnd::OnColumnClick(NMLISTVIEW *pLV)
{
ASSERT(pLV->iItem == -1);
// Might take a while
CeWaitCursor wait;
g_sortinfo.nColType = g_arColumns[ pLV->iSubItem ];
if (pLV->iSubItem == g_sortinfo.nColumnNo)
// invert the sort
g_sortinfo.bAscending = ! g_sortinfo.bAscending;
else
{
// new sort on this column
g_sortinfo.bAscending = true;
g_sortinfo.nColumnNo = pLV->iSubItem;
}
ListView_SortItems(m_hwndList, CmpList, (LPARAM) &g_sortinfo);
}
LRESULT CeMainWnd::OnBeginDragTree(NMTREEVIEW* pNMTV)
{
TRACE0("Beginning to Drag the image!!!!\n");
/* This first pass will be limited to dragging from the
Listview to the tree view. This allows file to be moved, which is
all that this aplication is intending to do.
At some point though, this could be expanded if moving directories is something
we want to do.
//SET THE FLAGS INDICATING A DRAG IN PROGRESS
m_bDragging = true;
m_dwDragItem = (DWORD) pNMTV->itemNew.hItem;
m_dwDropItem = 0xffffffff;
m_hDragImage = TreeView_CreateDragImage(m_hwndTree, (HTREEITEM) m_dwDragItem);
ImageList_BeginDrag(m_hDragImage, 0, 8, 8);
if (! ImageList_DragEnter(HWND_DESKTOP, pNMTV->ptDrag.x, pNMTV->ptDrag.y))
TRACE0("Drag Enter failed!");
//CAPTURE ALL MOUSE MESSAGES IN CASE THE USER DRAGS OUTSIDE OF THE VIEW
SetCapture();
*/
return 0;
}
LRESULT CeMainWnd::OnBeginDragList(NMLISTVIEW* pNMLV)
{
TRACE0("Beginning to Drag the image!!!!\n");
//SET THE FLAGS INDICATING A DRAG IN PROGRESS
m_bDragging = true; // yes, we are dragging
m_dwDragItem = pNMLV->iItem; // this is the item to drag
m_dwDropItem = 0xffffffff; // no drop yet, clear it
//CREATE A DRAG IMAGE FROM THE CENTER POINT OF THE ITEM IMAGE
POINT pt; pt.x = 8; pt.y = 8;
m_hDragImage = ListView_CreateDragImage(m_hwndList, m_dwDragItem, &pt);
ImageList_BeginDrag(m_hDragImage, 0, 8, 8);
ImageList_DragEnter(HWND_DESKTOP, pNMLV->ptAction.x, pNMLV->ptAction.y);
//CAPTURE ALL MOUSE MESSAGES IN CASE THE USER DRAGS OUTSIDE OF THE VIEW
SetCapture();
return 0;
}
void CeMainWnd::OnMouseMove( UINT nFlags, POINT point, bool& bHandled )
{
if (m_bDragging)
{
m_ptDropPoint = point;
//unlock window and allow updates to occur
ImageList_DragLeave(HWND_DESKTOP);
ClientToScreen(&m_ptDropPoint);
//CONVERT THE DROP POINT TO CLIENT CO-ORDIANTES
m_hDropWnd = ::WindowFromPoint(m_ptDropPoint);
::ScreenToClient(m_hDropWnd, &m_ptDropPoint);
if (m_hwndTree == m_hDropWnd)
{
//check with the tree control to see if we are on an item
TVHITTESTINFO tvht;
tvht.flags = TVHT_ONITEM;
tvht.pt.x = point.x;
tvht.pt.y = point.y;
::ScreenToClient(m_hwndTree, &(tvht.pt));
m_dwDropItem = (DWORD) TreeView_HitTest(m_hwndTree, &tvht);
if (NULL != m_dwDropItem)
//if we had a hit, then drop highlite the item
TreeView_Select(m_hwndTree, m_dwDropItem, TVGN_DROPHILITE);
}
else if (m_hwndList == m_hDropWnd)
{
/*
Nothing at this juncture. THe user can only drop in the tree at this point.
//check with the tree control to see if we are on an item
LVHITTESTINFO lvht;
lvht.flags = LVHT_ONITEM;
lvht.pt.x = point.x;
lvht.pt.y = point.y;
::ScreenToClient(m_hwndList, &(lvht.pt));
int nItem = -1;
while (-1 != (nItem = ListView_GetNextItem(m_hwndList, nItem, LVIS_DROPHILITED)))
{
//if we had a hit, then drop highlite the item
ListView_SetItemState(m_hwndList, nItem, 0, LVIS_DROPHILITED);
}
m_dwDropItem = ListView_HitTest(m_hwndList,&lvht);
if (m_dwDropItem >= 0)
{
//if we had a hit, then drop highlite the item
ListView_SetItemState(m_hwndList, m_dwDropItem, LVIS_DROPHILITED, LVIS_DROPHILITED);
}
*/
}
//paint the image in the new location
ImageList_DragMove(m_ptDropPoint.x, m_ptDropPoint.y);
//lock the screen again
ImageList_DragEnter(HWND_DESKTOP, point.x, point.y) ;
}
CeSplitFrame::OnMouseMove(nFlags, point, bHandled);
}
void CeMainWnd::OnLButtonUp( UINT nFlags, POINT point, bool& bHandled )
{
if (m_bDragging)
{
//RELEASE THE MOUSE CAPTURE AND END THE DRAGGING
::ReleaseCapture();
m_bDragging = FALSE;
ImageList_DragLeave(HWND_DESKTOP);
ImageList_EndDrag();
//GET THE WINDOW UNDER THE DROP POINT
POINT pt = point;
ClientToScreen(&pt);
m_hDropWnd = ::WindowFromPoint(pt);
//DROP THE ITEM ON THE LIST
if (m_hDropWnd == m_hwndList)
{
// Only drops
MessageBox(_T("You can only drop files onto a folder in the tree."),
_T("Info"), MB_OK);
}
else if (m_hDropWnd == m_hwndTree)
{
// drop the list item into the tree item
TreeView_SelectDropTarget(m_hwndTree, NULL);
// Originally selected the destination, but now leave the selection
// TreeView_SelectItem(m_hwndTree, (HTREEITEM) m_dwDropItem);
}
// always make this call in case we floated over it at some point
TreeView_SelectDropTarget(m_hwndTree, NULL);
// Now copy the file to the drop target...
bool bFtp;
// PArt of the original code mentioned above...
//CeString strNew = GetTreePath(TreeView_GetSelection(m_hwndTree), bFtp);
CeString strNew = GetTreePath((HTREEITEM) m_dwDropItem, bFtp);
CeString strOld = m_strCurrentDirectory;
TCHAR szFile[MAX_PATH];
LV_ITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = m_dwDragItem;
lvi.iSubItem = 0;
lvi.pszText = szFile;
lvi.cchTextMax = MAX_PATH;
ListView_GetItem(m_hwndList, &lvi);
strOld += szFile;
strNew += szFile;
if (bFtp)
{
if (m_bCurrentFtp)
{
// remote source and destination
if (! m_ftpConn.RenameFile(strOld,strNew))
{
CeString str = m_ftpConn.GetFtpErrorReplyString();
MessageBox(str, _T("FTP rename failed!"), MB_OK);
}
else
{
ListView_DeleteItem(m_hwndList, m_dwDragItem);
}
}
else if (strOld != strNew)
{
// Local source, remote destination
CeFtpTransferDlg dlg(&m_ftpConn, strOld, strNew,
((CeFileListItem*) lvi.lParam)->m_dwSize, true);
dlg.DoModal();
}
else
return;
}
else
{
if (m_bCurrentFtp)
{
// local destination, remote source
CeFtpTransferDlg dlg(&m_ftpConn, strOld, strNew,
((CeFileListItem*) lvi.lParam)->m_dwSize, false);
dlg.DoModal();
}
else if (strOld != strNew)
{
// local destination and source
if (! ::CopyFile(strOld, strNew, FALSE))
{
MessageBox(_T("Copy failed"), _T("Copy failed"), MB_OK);
}
}
else
return;
}
/*
// Drop messes up current list directory, re-sync
// Old-code no longer change to destination...
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
m_strCurrentDirectory = GetTreePath(hItem, m_bCurrentFtp);
PopulateFilelist(hItem, m_strCurrentDirectory, m_bCurrentFtp);
*/
::SetFocus(m_hwndTree);
}
CeSplitFrame::OnLButtonUp(nFlags, point, bHandled);
}