#include "StdAfx.h"
#include <shlobj.h>
#include <afxres.h>
#include <CeFontDlg.h>
#include <CeFindFile.h>
#include <CeLabel.h>
#include <math.h>
#include "MainWnd.h"
#include "FtpViewRes.h"
#include "FtpTransDlg.h"
#include "ftpSite.h"
#include "OptDlg.h"
#include "PropertyDlg.h"
//#if defined(_WIN32_WCE_PSPC)
// #include <aygshell.h>
// #pragma comment(lib, "aygshell.lib")
//#endif
#if defined(_WIN32_WCE_POCKETPC)
static SHACTIVATEINFO s_saiDlgBox;
static SHACTIVATEINFO s_sai;
#endif
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)
{
CeString str;
TV_ITEM tvi;
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* pT)
{
SYSTEMTIME st;
BOOL bSuccess = ::FileTimeToSystemTime(&ft, &st);
if (! bSuccess || st.wYear > 9999)
{
sz[0] = 0;
}
else
{
int nSize = 0;
bool bToday = (pT && pT->wYear == st.wYear && pT->wMonth == st.wMonth && pT->wDay == st.wDay);
if (pT == NULL || !bToday)
nSize = ::GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_SHORTDATE, &st, NULL, sz, 32);
if (pT == NULL)
sz[nSize-1] = _T(' ');
if (pT == NULL || bToday)
::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:
CeChildMgr m_mgr;
public:
CeAboutDlg(): CeScrollDialog(IDD_ABOUT) {}
virtual BOOL OnInitDialog();
virtual void OnSize(UINT nType, int cx, int cy, bool& bHandled);
};
#define IDT_ANIM_ICON 100
BOOL CeAboutDlg::OnInitDialog()
{
BOOL bRet = CeScrollDialog::OnInitDialog();
m_mgr.Manage(GetDlgItem(IDC_NAME_STATIC), AL_ADJUST_SIZE);
#ifdef _WIN32_WCE_POCKETPC
// Create a Done button and size it.
SHINITDLGINFO shidi;
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
shidi.hDlg = m_hWnd;
SHInitDialog(&shidi);
#endif
// allow controls to be created
return bRet;
}
void CeAboutDlg::OnSize(UINT nType, int cx, int cy, bool& bHandled)
{
m_mgr.OnSize(nType, cx, cy);
CeScrollDialog::OnSize(nType, cx, cy, bHandled);
}
///////////////////////////////////////////////////////////////////////////////
//
// CeDropFileDlg = Dialog for querying the user as to thier intensions on
// dropping a file
//
///////////////////////////////////////////////////////////////////////////////
class CeDropFileDlg: public CeScrollDialog
{
private:
CeChildMgr m_mgr;
public:
int m_nWhich;
CeDropFileDlg(): CeScrollDialog(IDD_DROPFILE)
{ m_nWhich = IDCANCEL; }
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam, bool& bHandled);
virtual BOOL OnInitDialog();
virtual void OnSize(UINT nType, int cx, int cy, bool& bHandled);
virtual void OnOK();
virtual void OnSettingChange(WORD wFlag, LPCTSTR pszSection, bool& bHandled);
};
#define IDT_ANIM_ICON 100
BOOL CeDropFileDlg::OnInitDialog()
{
BOOL bRet = CeScrollDialog::OnInitDialog();
m_mgr.Manage(GetDlgItem(IDC_COPY), AL_ADJUST_WIDTH);
m_mgr.Manage(GetDlgItem(IDC_MOVE), AL_ADJUST_WIDTH);
m_mgr.Manage(GetDlgItem(IDC_SHORTCUT), AL_ADJUST_WIDTH);
m_mgr.Manage(GetDlgItem(IDCANCEL), AL_ADJUST_WIDTH);
#ifdef _WIN32_WCE_POCKETPC
// Create a Done button and size it.
SHINITDLGINFO shidi;
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
shidi.hDlg = m_hWnd;
SHInitDialog(&shidi);
#endif
// allow controls to be created
return bRet;
}
void CeDropFileDlg::OnSize(UINT nType, int cx, int cy, bool& bHandled)
{
m_mgr.OnSize(nType, cx, cy);
CeScrollDialog::OnSize(nType, cx, cy, bHandled);
}
void CeDropFileDlg::OnOK()
{
// m_nWhich = IDC_RADIOCOPY;
// for (int nID = IDC_RADIOCOPY; nID <= IDC_RADIOSHORTCUT; nID++)
// {
// if ((UINT)::SendMessage( GetDlgItem(nID), BM_GETCHECK, 0, 0 ))
// m_nWhich = nID; // id that matched
// }
CeScrollDialog::OnOK(); // call base class
}
BOOL CeDropFileDlg::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
m_nWhich = wId;
//default to handled
bHandled = true;
OnOK();
return FALSE;
}
void CeDropFileDlg::OnSettingChange( WORD wFlag, LPCTSTR pszSection, bool& bHandled )
{
#if defined(_WIN32_WCE_POCKETPC)
s_saiDlgBox.cbSize = sizeof s_saiDlgBox;
SHHandleWMSettingChange(m_hWnd, wFlag, (long) pszSection, &s_saiDlgBox);
bHandled = true;
#endif
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
CeMainWnd::CeMainWnd()
{
m_hFont = NULL;
m_hImages = NULL;
m_dwFontSize = 0;
m_hwndList = NULL;
m_hwndTree = NULL;
m_hwndLast = 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_CLOSE: DestroyWindow(); break;
case ID_TOOLS_OPTIONS: OnOptions(); break;
case ID_TOOLS_FONT: OnFont(); break;
// E_NOTIMPL
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::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))
{
MessageBox(m_ftpConn.GetFtpErrorReplyString(), 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();
HWND hwndFocus = m_hwndLast;
if (hwndFocus == m_hwndList)
{
int nSel;
if ((nSel = ListView_GetNextItem(m_hwndList, -1, LVNI_FOCUSED)) < 0)
{
if ((nSel = ListView_GetNextItem(m_hwndList, -1, LVIS_SELECTED)) < 0)
return;
}
CeString strFile;
LVITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = nSel;
lvi.iSubItem = 0;
lvi.pszText = strFile.GetBufferSetLength(64);
lvi.cchTextMax = 64;
ListView_GetItem(m_hwndList, &lvi);
strFile.ReleaseBuffer();
CeFileListItem *pItem = (CeFileListItem *) lvi.lParam;
if (pItem->m_dwAttrib & FILE_ATTRIBUTE_INROM)
{
MessageBox(L"Files in ROM cannot be removed.", L"ROM File",
MB_OK|MB_ICONINFORMATION);
return;
}
CeString strPrompt;
strPrompt.Format(_T("Are you sure you want to remove '%s'?"), (LPCTSTR)strFile);
if (IDYES != MessageBox(strPrompt, L"Confirm File Delete", MB_YESNO|MB_ICONINFORMATION))
return;
CeString strDir = m_strCurrentDirectory;
strDir += strFile;
if (m_bCurrentFtp)
{
if (! m_ftpConn.DeleteFile(strDir))
{
CeString str = m_ftpConn.GetFtpErrorReplyString();
MessageBox(str, _T("FTP delete failed!"), MB_OK|MB_ICONERROR);
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("\\") || str == _T("\\Windows\\"))
{
MessageBox(_T("Removing system files from the device won't work, sorry."),
_T("Remove file"), MB_ICONWARNING|MB_OK);
return;
}
int nResp = MessageBox(_T("Are you certain you wish to remove the selected directory?"),
str, MB_YESNO|MB_ICONINFORMATION);
if (nResp != IDYES)
return;
// remove the trailing "\"
CeString strDir((LPCTSTR)str, str.GetLength()-1);
if (bFtp)
{
if (m_ftpConn.DeleteDir(str))
{
TreeView_DeleteItem(m_hwndTree, hItem);
// refresh the list view....
}
else
{
MessageBox(m_ftpConn.GetFtpErrorReplyString(), _T("Remove Directory"), MB_OK|MB_ICONWARNING);
}
}
else
{
if (::RemoveDirectory(str))
{
TreeView_DeleteItem(m_hwndTree, hItem);
// refresh the list view....
}
else
{
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
{
CeString strErr;
strErr.Format(_T("Error number %lu occured while removing directory"), GetLastError());
MessageBox(strErr, _T("Remove Directory"), 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_OK|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, _T("Connect to FTP Site"), MB_OK|MB_ICONWARNING);
return;
}
else
{
if (! PopulateFilelist(hItem, m_ftpConn.GetRoot(), true))
{
// we will disconnect if we can't get a directory listing
// on an initial connection
m_ftpConn.Disconnect();
bConnect = FALSE;
return;
}
else
MessageBox(_T("Connection established."), NULL, MB_OK|MB_ICONINFORMATION);
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));
}
}
/*
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);
UINT uRet = dlg.DoModal(IDD_PROPERTY);
CeString strName = dlg.m_pageFtp.m_site.m_strName;
if (IDOK == uRet && ! 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) 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()
{
#if defined(_WIN32_WCE_POCKETPC)
#pragma comment(lib, "aygshell.lib")
SHMENUBARINFO mbi;
//set up menu bar structure
memset(&mbi, 0, sizeof(SHMENUBARINFO));
mbi.cbSize = sizeof(SHMENUBARINFO);
mbi.hwndParent = m_hWnd;
mbi.nToolBarId = IDM_MENUNEW;
mbi.hInstRes = g_hInst;
mbi.nBmpId = IDB_MENUNEW;
mbi.cBmpImages = 2;
mbi.dwFlags = 0; //SHCMBF_EMPTYBAR;
if (!SHCreateMenuBar(&mbi))
{
DWORD dw = GetLastError();
MessageBox(_T("SHCreateMenuBar Failed"), _T("Error"), MB_OK|MB_ICONERROR);
}
//m_hwndCmdBar = mbi.hwndMB;
#elif defined(_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(IDM_MENUNEW, 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 // _WIN32_WCE
}
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("Hidden")); g_options.m_bHidden = (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_bHidden, _T("Hidden"));
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)
if (m_cmdband)
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);
InitTree();
// Create the list 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 (m_cmdband && 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);
// set focus to the root of the tree
TreeView_SelectItem( m_hwndTree, TreeView_GetRoot(m_hwndTree) );
::SetFocus(m_hwndTree);
// Done
return TRUE;
}
void CeMainWnd::InitTree()
{
TreeView_DeleteAllItems(m_hwndTree);
// 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() || CeIsPocketPC() )
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() || CeIsPocketPC())
{
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);
}
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_bHidden = g_options.m_bHidden;
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();
RefreshList();
}
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_bHidden != dlg.m_bHidden)
{
g_options.m_bROM = dlg.m_bROM;
g_options.m_bHidden = dlg.m_bHidden;
RefreshList();
}
// 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)
{
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 = m_strCurrentDirectory;
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 || !m_strCurrentDirectory.Length())
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();
dlg.AddTaskProperty();
}
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();
dlg.AddTaskProperty();
}
}
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();
}
void CeMainWnd::OnSettingChange( WORD wFlag, LPCTSTR pszSection, bool& bHandled )
{
#if defined(_WIN32_WCE_POCKETPC)
s_sai.cbSize = sizeof s_sai;
SHHandleWMSettingChange(m_hWnd, wFlag, (long) pszSection, &s_sai);
bHandled = true;
#elif defined(_WIN32_WCE_PSPC)
switch (wFlag)
{
case SPI_SETSIPINFO:
{
SIPINFO si;
memset( &si, 0, sizeof( si ) );
si.cbSize = sizeof( si );
if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) )
{
MoveWindow(
si.rcVisibleDesktop.left,
si.rcVisibleDesktop.top,
si.rcVisibleDesktop.right - si.rcVisibleDesktop.left,
si.rcVisibleDesktop.bottom -
si.rcVisibleDesktop.top,
TRUE );
}
}
break;
default:
break;
}
#endif // _WIN32_PPC_
}
void CeMainWnd::OnSetFocus(HWND hWndOld)
{
::SetFocus(m_hwndLast);
TRACE0("SetFocus()\n");
}
#pragma comment(lib, "note_prj.lib")
LRESULT CeMainWnd::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
switch (uMsg)
{
// A bit of a a hack for simplicity, but it works for the most part
// it detects a change in the number of flash devices and uses that to
// know if it should refresh. It has the potential of being wrong if
// the power goes off and a flash card is changed and then re-powered
case WM_FTPVIEW_CARDNOTIFY:
{
extern int g_nFlashDevices;
int nFlash = 0;
CeFindFile ff;
if ( ff.FindFirstFlash() )
{
nFlash++;
for ( ; ff.FindNextFlash() ; )
nFlash++;
}
if (g_nFlashDevices != nFlash)
OnRefresh();
g_nFlashDevices = nFlash;
break;
}
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_SETFOCUS:
OnSetFocus((HWND) wParam);
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_SETFOCUS:
TRACE0("OnListViewNotify: SetFocus()\n");
m_hwndLast = m_hwndList;
break;
case NM_KILLFOCUS:
TRACE0("OnListViewNotify: KillFocus()\n");
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|MB_ICONERROR);
return FALSE;
}
}
else
{
if (! MoveFile(strOld, strNew))
{
CeString strErr;
strErr.Format(_T("Error %lu while renaming."), GetLastError());
MessageBox(strErr, _T("Rename failed!"), MB_OK|MB_ICONERROR);
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;
/*
Causes strange behaviour, need to work on this
case NM_CLICK:
{
//check with the tree control to see if we are on an item
LVHITTESTINFO lvht;
//lvht.flags = LVHT_ONITEM;
lvht.pt = pNMLV->ptAction;
::ScreenToClient(m_hwndList, &(lvht.pt));
int nItem = ListView_HitTest(m_hwndList,&lvht);
if ( nItem >= 0 )
{
ListView_SetItemState(m_hwndList, nItem, LVIS_FOCUSED|LVIS_SELECTED,
LVIS_FOCUSED|LVIS_SELECTED);
}
}
// fall through to execution
*/
/*
Conflicts with the drag and drop handling built in to the list
case GN_CONTEXTMENU:
{
TRACE0("OnListViewNotify: GN_CONTEXTMENU\n");
//check with the tree control to see if we are on an item
LVHITTESTINFO lvht;
lvht.flags = LVHT_ONITEM;
lvht.pt = pNMLV->ptAction;
int nItem = ListView_HitTest(m_hwndList,&lvht);
if ( nItem >= 0 )
{
ListView_SetItemState(m_hwndList, nItem, LVIS_FOCUSED|LVIS_SELECTED,
LVIS_FOCUSED|LVIS_SELECTED);
}
HMENU hMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_OPEN, _T("Open"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_PROPERTIES, _T("Properties"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_DELETE, _T("Delete"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_RENAME, _T("Rename"));
NMRGINFO* pnmhdr = (NMRGINFO*) pNMLV;
POINT point = pnmhdr->ptAction;
TrackPopupMenu(hMenu, TPM_RIGHTALIGN|TPM_TOPALIGN, point.x, point.y, 0, m_hWnd, NULL);
DestroyMenu(hMenu);
}
return FALSE;
*/
default:
TRACE2(_T("Unhandled WM_NOTIFY to LIST 0x%x or 0x%x:\n"), pNMLV->hdr.code,
(UINT) 0 - pNMLV->hdr.code);
break;
}
return 0;
}
void CeMainWnd::OnRefresh()
{
RefreshTree();
}
void CeMainWnd::RefreshTree()
{
InitTree();
RefreshList();
}
void CeMainWnd::RefreshList()
{
// 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_SETFOCUS:
TRACE0("OnTreeViewNotify: SetFocus()\n");
m_hwndLast = m_hwndTree;
break;
case NM_KILLFOCUS:
TRACE0("OnTreeViewNotify: KillFocus()\n");
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))
{
MessageBox(m_ftpConn.GetFtpErrorReplyString(), _T("FTP RENAME failed"), MB_OK|MB_ICONERROR);
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|MB_ICONERROR);
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;
case NM_CLICK:
TRACE0("NM_CLICK\n");
break;
/*
Conflicts with the drag and drop handling built in to the list
case GN_CONTEXTMENU:
{
TRACE0("OnTreeViewNotify: GN_CONTEXTMENU\n");
NMRGINFO* pnmhdr = (NMRGINFO*) pNMTV;
POINT point = pnmhdr->ptAction;
TV_HITTESTINFO hti;
hti.pt = point;
::ScreenToClient(m_hwndTree, &hti.pt);
HTREEITEM hHit = TreeView_HitTest(m_hwndTree, &hti);
// Build a standard popup, depending on the tree type
HTREEITEM hItem = TreeView_GetSelection(m_hwndTree);
if (! hItem || ! hHit)
return FALSE;
if (hItem != hHit)
{
TRACE0("OnTreeViewNotify: Item Changed\n");
TreeView_SelectItem(m_hwndTree, hHit);
hItem = hHit;
// Fix the list
OnRefresh();
}
HMENU hMenu = CreatePopupMenu();
eTreeNodeType eType = (eTreeNodeType) TreeView_GetLParam(m_hwndTree, hItem);
switch (eType)
{
case tntDesktop:
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_PROPERTIES, _T("Properties"));
break;
case tntDevice:
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_PROPERTIES, _T("Properties"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_ACTIONS_NEWSITE, _T("New Site..."));
break;
case tntLocalDir:
case tntFtpSiteDir:
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_PROPERTIES, _T("Properties"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_DELETE, _T("Delete"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_RENAME, _T("Rename"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_NEW_FOLDER, _T("New Folder"));
break;
case tntFtpSite:
if (! m_ftpConn.IsConnected())
{
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_PROPERTIES, _T("Properties"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_DELETE, _T("Delete"));
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_FILE_RENAME, _T("Rename"));
}
else
{
if (hItem == m_hConnected)
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_ACTIONS_DISCONNECT, _T("Disconnect"));
else
AppendMenu(hMenu, MF_STRING|MF_ENABLED, ID_ACTIONS_CONNECT, _T("Connect"));
}
break;
}
TrackPopupMenu(hMenu, TPM_RIGHTALIGN|TPM_TOPALIGN, point.x, point.y, 0, m_hWnd, NULL);
DestroyMenu(hMenu);
}
return FALSE;
*/
default:
TRACE2(_T("Unhandled WM_NOTIFY to TREE 0x%x or 0x%x:\n"), pNMTV->hdr.code,
(UINT) 0 - pNMTV->hdr.code);
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;
strDir += _T("\\");
}
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"), MB_OK|MB_ICONERROR);
if (! m_ftpConn.IsConnected())
// only disconnect if the server torched us, might only
// be a permissions error
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;
}
BOOL CeMainWnd::PopulateFilelist(HTREEITEM hItem, LPCTSTR szDir, bool bFtp)
{
if (NULL == m_hwndList)
return FALSE;
// Might take a while
CeWaitCursor wait;
CeString str(szDir);
ListView_DeleteAllItems(m_hwndList);
if (str.IsEmpty())
return TRUE;
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 TRUE;
::SendMessage(m_hwndList, WM_SETREDRAW, FALSE, 0);
int ii = 0;
do
{
if (ff.IsDirectory())
continue;
if (ff.IsInROM() && (! g_options.m_bROM))
continue;
if (! g_options.m_bHidden && (ff.IsHidden() || ff.IsSystem()))
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 FALSE;
LPARAM lp = TreeView_GetLParam(m_hwndTree, hItem);
if (lp == tntFtpSite && hItem != m_hConnected)
{
// a different FTP site, skip it
return TRUE;
}
::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|MB_ICONERROR);
return FALSE;
}
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);
return TRUE;
}
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;
SYSTEMTIME stToday;
GetLocalTime(&stToday);
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;
bool bIn = false;
for (int ii = 0; *lpsz != 0; lpsz++)
{
if (*lpsz == _T('"'))
{
bIn = !bIn;
}
else if (!bIn && _istspace(*lpsz))
{
// white space outside of quotes, end of link file name
break;
}
else
{
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, &stToday);
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);
CePoint ptScreen = 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 = ptScreen;
::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.
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);
}
//check with the tree control to see if we are on an item
LVHITTESTINFO lvht;
lvht.flags = LVHT_ONITEM;
lvht.pt = point;
::ScreenToClient(m_hwndList, &(lvht.pt));
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(ptScreen.x, ptScreen.y);
//lock the screen again
ImageList_DragEnter(HWND_DESKTOP, ptScreen.x, ptScreen.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|MB_ICONINFORMATION);
return;
}
/* Duplicate code ??
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))
{
MessageBox(m_ftpConn.GetFtpErrorReplyString(), _T("FTP RENAME failed"), MB_OK|MB_ICONERROR);
}
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)
{
CeDropFileDlg dlg;
if (IDOK == dlg.DoModal())
{
switch (dlg.m_nWhich)
{
case IDC_COPY:
// local destination and source, don't overrite existing
if (! ::CopyFile(strOld, strNew, FALSE))
{
CeString str;
str.Format(_T("Encountered error %lu while copying file %s"), GetLastError(), szFile);
MessageBox(str, _T("Copy failed"), MB_OK|MB_ICONERROR);
}
break;
case IDC_MOVE:
// local destination and source, don't overrite existing
if (! ::MoveFile(strOld, strNew))
{
CeString str;
str.Format(_T("Encountered error %lu while moving file %s"), GetLastError(), szFile);
MessageBox(str, _T("Move failed"), MB_OK|MB_ICONERROR);
}
else
{
// it should be gone...
ListView_DeleteItem(m_hwndList, m_dwDragItem);
}
break;
case IDC_SHORTCUT:
{
int n = strNew.ReverseFindIndex(_T('.'));
if (n >= 0)
strNew = CeString((LPCTSTR) strNew, n);
strNew += _T(".lnk");
strOld = _T('"');
strOld += m_strCurrentDirectory;
strOld += szFile;
strOld += _T('"');
if (! SHCreateShortcut((LPTSTR)(LPCTSTR)strNew, (LPTSTR)(LPCTSTR)strOld))
{
CeString str;
str.Format(_T("Encountered error %lu creating shortcut to file %s"), GetLastError(), szFile);
MessageBox(str, _T("Create Shortcut failed"), MB_OK|MB_ICONERROR);
}
}
break;
}
}
}
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);
}