Files
SimpleRemoter/server/2015Remote/FileManagerDlg.cpp
2026-04-19 22:55:21 +02:00

3223 lines
109 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// FileManagerDlg.cpp : implementation file
//
#include "stdafx.h"
#include "2015Remote.h"
#include "FileManagerDlg.h"
#include "FileTransferModeDlg.h"
#include "InputDlg.h"
#include "ZstdArchive.h"
#include "2015RemoteDlg.h"
#include <Shlobj.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static UINT indicators[] = {
ID_SEPARATOR, // status line indicator
ID_SEPARATOR,
ID_SEPARATOR
};
#define MAX_SEND_BUFFER 65535
#define MAX_RECV_BUFFER 65535
typedef struct {
LVITEM* plvi;
CString sCol2;
} lvItem, *plvItem;
/////////////////////////////////////////////////////////////////////////////
// CFileManagerDlg dialog
float GetScreenScalingFactor()
{
HDC hdc = GetDC(NULL); // 获取屏幕设备上下文
int dpiX = GetDeviceCaps(hdc, LOGPIXELSX); // 获取水平 DPI
ReleaseDC(NULL, hdc);
// 缩放比例 = DPI / 标准 DPI96
return dpiX / 96.0f;
}
CFileManagerDlg::CFileManagerDlg(CWnd* pParent, Server* pIOCPServer, ClientContext *pContext)
: DialogBase(CFileManagerDlg::IDD, pParent, pIOCPServer, pContext, IDI_ICON_FATHER)
{
m_fScalingFactor = GetScreenScalingFactor();
//{{AFX_DATA_INIT(CFileManagerDlg)
//}}AFX_DATA_INIT
m_bIsClosed = false;
m_ProgressCtrl = NULL;
// 保存远程驱动器列表
memset(m_bRemoteDriveList, 0, sizeof(m_bRemoteDriveList));
PBYTE pSrc = m_ContextObject->m_DeCompressionBuffer.GetBuffer(1);
int length = m_ContextObject->m_DeCompressionBuffer.GetBufferLen() - 1;
if (length > 0)
memcpy(m_bRemoteDriveList, pSrc, length);
m_nTransferMode = TRANSFER_MODE_NORMAL;
m_nOperatingFileLength = 0;
m_nCounter = 0;
m_bIsStop = false;
m_hRecvFile = INVALID_HANDLE_VALUE;
m_bSearching = false;
m_bSearchStopped = false;
m_nSearchResultCount = 0;
m_dwSearchStartTime = 0;
m_bLocalSearching = false;
m_bLocalSearchStopped = false;
m_nLocalSearchResultCount = 0;
m_dwLocalSearchStartTime = 0;
m_hLocalSearchThread = NULL;
}
void CFileManagerDlg::DoDataExchange(CDataExchange* pDX)
{
__super::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFileManagerDlg)
DDX_Control(pDX, IDC_REMOTE_PATH, m_Remote_Directory_ComboBox);
DDX_Control(pDX, IDC_LOCAL_PATH, m_Local_Directory_ComboBox);
DDX_Control(pDX, IDC_LIST_REMOTE, m_list_remote);
DDX_Control(pDX, IDC_LIST_LOCAL, m_list_local);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CFileManagerDlg, CDialog)
//{{AFX_MSG_MAP(CFileManagerDlg)
ON_WM_QUERYDRAGICON()
ON_WM_SIZE()
ON_NOTIFY(NM_DBLCLK, IDC_LIST_LOCAL, OnDblclkListLocal)
ON_NOTIFY(LVN_BEGINDRAG, IDC_LIST_LOCAL, OnBegindragListLocal)
ON_NOTIFY(LVN_BEGINDRAG, IDC_LIST_REMOTE, OnBegindragListRemote)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_WM_TIMER()
ON_WM_CLOSE()
ON_NOTIFY(NM_DBLCLK, IDC_LIST_REMOTE, OnDblclkListRemote)
ON_COMMAND(IDT_LOCAL_PREV, OnLocalPrev)
ON_COMMAND(IDT_REMOTE_PREV, OnRemotePrev)
ON_COMMAND(IDT_LOCAL_VIEW, OnLocalView)
ON_COMMAND(IDM_LOCAL_LIST, OnLocalList)
ON_COMMAND(IDM_LOCAL_REPORT, OnLocalReport)
ON_COMMAND(IDM_LOCAL_BIGICON, OnLocalBigicon)
ON_COMMAND(IDM_LOCAL_SMALLICON, OnLocalSmallicon)
ON_COMMAND(IDM_REMOTE_BIGICON, OnRemoteBigicon)
ON_COMMAND(IDM_REMOTE_LIST, OnRemoteList)
ON_COMMAND(IDM_REMOTE_REPORT, OnRemoteReport)
ON_COMMAND(IDM_REMOTE_SMALLICON, OnRemoteSmallicon)
ON_COMMAND(IDT_REMOTE_VIEW, OnRemoteView)
ON_UPDATE_COMMAND_UI(IDT_LOCAL_STOP, OnUpdateLocalStop)
ON_UPDATE_COMMAND_UI(IDT_REMOTE_STOP, OnUpdateRemoteStop)
ON_UPDATE_COMMAND_UI(IDT_LOCAL_PREV, OnUpdateLocalPrev)
ON_UPDATE_COMMAND_UI(IDT_REMOTE_PREV, OnUpdateRemotePrev)
ON_UPDATE_COMMAND_UI(IDT_LOCAL_COPY, OnUpdateLocalCopy)
ON_UPDATE_COMMAND_UI(IDT_REMOTE_COPY, OnUpdateRemoteCopy)
ON_UPDATE_COMMAND_UI(IDT_REMOTE_DELETE, OnUpdateRemoteDelete)
ON_UPDATE_COMMAND_UI(IDT_REMOTE_NEWFOLDER, OnUpdateRemoteNewfolder)
ON_UPDATE_COMMAND_UI(IDT_LOCAL_DELETE, OnUpdateLocalDelete)
ON_UPDATE_COMMAND_UI(IDT_LOCAL_NEWFOLDER, OnUpdateLocalNewfolder)
ON_UPDATE_COMMAND_UI(IDT_LOCAL_SEARCH, OnUpdateLocalSearch)
ON_UPDATE_COMMAND_UI(IDT_REMOTE_SEARCH, OnUpdateRemoteSearch)
ON_COMMAND(IDT_REMOTE_COPY, OnRemoteCopy)
ON_COMMAND(IDT_LOCAL_COPY, OnLocalCopy)
ON_COMMAND(IDT_LOCAL_DELETE, OnLocalDelete)
ON_COMMAND(IDT_REMOTE_DELETE, OnRemoteDelete)
ON_COMMAND(IDT_REMOTE_STOP, OnRemoteStop)
ON_COMMAND(IDT_LOCAL_STOP, OnLocalStop)
ON_COMMAND(IDT_LOCAL_NEWFOLDER, OnLocalNewfolder)
ON_COMMAND(IDT_REMOTE_NEWFOLDER, OnRemoteNewfolder)
ON_COMMAND(IDT_LOCAL_DESKTOP, OnLocalDesktop)
ON_COMMAND(IDT_LOCAL_DOWNLOADS, OnLocalDownloads)
ON_COMMAND(IDT_LOCAL_HOME, OnLocalHome)
ON_COMMAND(IDT_LOCAL_SEARCH, OnLocalSearch)
ON_COMMAND(IDT_REMOTE_DESKTOP, OnRemoteDesktop)
ON_COMMAND(IDT_REMOTE_DOWNLOADS, OnRemoteDownloads)
ON_COMMAND(IDT_REMOTE_HOME, OnRemoteHome)
ON_COMMAND(IDT_REMOTE_SEARCH, OnRemoteSearch)
ON_COMMAND(IDM_TRANSFER, OnTransfer)
ON_COMMAND(IDM_RENAME, OnRename)
ON_NOTIFY(LVN_ENDLABELEDIT, IDC_LIST_LOCAL, OnEndlabeleditListLocal)
ON_NOTIFY(LVN_ENDLABELEDIT, IDC_LIST_REMOTE, OnEndlabeleditListRemote)
ON_COMMAND(IDM_DELETE, OnDelete)
ON_COMMAND(IDM_NEWFOLDER, OnNewfolder)
ON_COMMAND(IDM_REFRESH, OnRefresh)
ON_COMMAND(IDM_LOCAL_OPEN, OnLocalOpen)
ON_COMMAND(IDM_REMOTE_OPEN_SHOW, OnRemoteOpenShow)
ON_COMMAND(IDM_REMOTE_OPEN_HIDE, OnRemoteOpenHide)
ON_NOTIFY(NM_RCLICK, IDC_LIST_LOCAL, OnRclickListLocal)
ON_NOTIFY(NM_RCLICK, IDC_LIST_REMOTE, OnRclickListRemote)
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)
ON_MESSAGE(WM_LOCAL_SEARCH_DONE, OnLocalSearchDone)
ON_MESSAGE(WM_LOCAL_SEARCH_PROGRESS, OnLocalSearchProgress)
//}}AFX_MSG_MAP
ON_COMMAND(ID_FILEMANGER_COMPRESS, &CFileManagerDlg::OnFilemangerCompress)
ON_COMMAND(ID_FILEMANGER_UNCOMPRESS, &CFileManagerDlg::OnFilemangerUncompress)
ON_COMMAND(IDM_TRANSFER_S, &CFileManagerDlg::OnTransferV2ToRemote)
ON_COMMAND(IDM_TRANSFER_R, &CFileManagerDlg::OnTransferV2ToLocal)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFileManagerDlg message handlers
int GetIconIndex_(LPCTSTR lpFileName, DWORD dwFileAttributes)
{
SHFILEINFO sfi = {};
if (dwFileAttributes == INVALID_FILE_ATTRIBUTES)
dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
else
dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
SHGetFileInfo
(
lpFileName,
dwFileAttributes,
&sfi,
sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES
);
return sfi.iIcon;
}
int GetIconIndex(LPCTSTR lpFileName, DWORD dwFileAttributes)
{
VLDGlobalDisable();
// 代码中排除: Windows.Storage.dll 内部缓存,不是代码泄漏,是误报。
int index = GetIconIndex_(lpFileName, dwFileAttributes);
VLDGlobalEnable();
return index;
}
BOOL CFileManagerDlg::OnInitDialog()
{
__super::OnInitDialog();
// 多语言翻译 - Static控件
SetDlgItemText(IDC_STATIC_LOCAL, _TR("本地"));
SetDlgItemText(IDC_STATIC_REMOTE, _TR("远程"));
// TODO: Add extra initialization here
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
RECT rect;
GetClientRect(&rect);
/*为真彩工具条添加的代码*/
// 一定要定义工具栏ID不然RepositionBars会重置工具栏的位置
// ID 定义在AFX_IDW_CONTROLBAR_FIRST AFX_IDW_CONTROLBAR_LAST
// 本地工具条 CBRS_TOP 会在工具条上产生一条线
if (!m_wndToolBar_Local.Create(this, WS_CHILD |
WS_VISIBLE | CBRS_ALIGN_ANY | CBRS_TOOLTIPS | CBRS_FLYBY, ID_LOCAL_TOOLBAR)
||!m_wndToolBar_Local.LoadToolBar(IDR_TOOLBAR1)) {
TRACE0("Failed to create toolbar ");
return -1; //Failed to create
}
m_wndToolBar_Local.ModifyStyle(0, TBSTYLE_FLAT); //Fix for WinXP
m_wndToolBar_Local.LoadTrueColorToolBar
(
24, //加载真彩工具条
IDB_TOOLBAR_ENABLE,
IDB_TOOLBAR_ENABLE,
IDB_TOOLBAR_DISABLE
);
// 添加下拉按钮
m_wndToolBar_Local.AddDropDownButton(this, IDT_LOCAL_VIEW, IDR_LOCAL_VIEW);
if (!m_wndToolBar_Remote.Create(this, WS_CHILD |
WS_VISIBLE | CBRS_ALIGN_ANY | CBRS_TOOLTIPS | CBRS_FLYBY, ID_REMOTE_TOOLBAR)
||!m_wndToolBar_Remote.LoadToolBar(IDR_TOOLBAR2)) {
TRACE0("Failed to create toolbar ");
return -1; //Failed to create
}
m_wndToolBar_Remote.ModifyStyle(0, TBSTYLE_FLAT); //Fix for WinXP
m_wndToolBar_Remote.LoadTrueColorToolBar
(
24, //加载真彩工具条
IDB_TOOLBAR_ENABLE,
IDB_TOOLBAR_ENABLE,
IDB_TOOLBAR_DISABLE
);
// 添加下拉按钮
m_wndToolBar_Remote.AddDropDownButton(this, IDT_REMOTE_VIEW, IDR_REMOTE_VIEW);
//显示工具栏
UpdateWindowsPos();
// 设置标题
CString str;
str.FormatL("%s - 文件管理",m_IPAddress);
SetWindowText(str);
// 为列表视图设置ImageList
m_list_local.SetImageList(&(THIS_APP->m_pImageList_Large), LVSIL_NORMAL);
m_list_local.SetImageList(&(THIS_APP->m_pImageList_Small), LVSIL_SMALL);
// 创建带进度条的状态栏
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT))) {
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_wndStatusBar.SetPaneInfo(0, m_wndStatusBar.GetItemID(0), SBPS_STRETCH, NULL);
m_wndStatusBar.SetPaneInfo(1, m_wndStatusBar.GetItemID(1), SBPS_NORMAL, 120);
m_wndStatusBar.SetPaneInfo(2, m_wndStatusBar.GetItemID(2), SBPS_NORMAL, 50);
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); //显示状态栏
m_wndStatusBar.GetItemRect(1, &rect);
m_ProgressCtrl = new CProgressCtrl;
m_ProgressCtrl->Create(PBS_SMOOTH | WS_VISIBLE, rect, &m_wndStatusBar, 1);
m_ProgressCtrl->SetRange(0, 100); //设置进度条范围
m_ProgressCtrl->SetPos(20); //设置进度条当前位置
m_list_local.ModifyStyle(FALSE, LVS_REPORT);
m_list_remote.ModifyStyle(FALSE, LVS_REPORT);
FixedLocalDriveList();
FixedRemoteDriveList();
/////////////////////////////////////////////
//// Set up initial variables
m_bDragging = false;
m_nDragIndex = -1;
m_nDropIndex = -1;
CoInitialize(NULL);
SHAutoComplete(GetDlgItem(IDC_LOCAL_PATH)->GetWindow(GW_CHILD)->m_hWnd, SHACF_FILESYSTEM);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CFileManagerDlg::OnSize(UINT nType, int cx, int cy)
{
__super::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
// 状态栏还没有创建
if (m_wndStatusBar.m_hWnd == NULL)
return;
// 定位状态栏
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); //显示工具栏
RECT rect;
m_wndStatusBar.GetItemRect(1, &rect);
m_ProgressCtrl->MoveWindow(&rect);
UpdateWindowsPos();
}
void CFileManagerDlg::UpdateWindowsPos()
{
RECT rect;
GetClientRect(&rect);
int cx = rect.right - rect.left;
int cy = rect.bottom - rect.top;
GetDlgItem(IDC_LIST_LOCAL)->MoveWindow(0, 36, cx, (cy - 100) / 2);
GetDlgItem(IDC_LIST_REMOTE)->MoveWindow(0, (cy / 2) + 28, cx, (cy - 100) / 2);
GetDlgItem(IDC_STATIC_LOCAL)->MoveWindow(10, 10, 25 * m_fScalingFactor, 20);
GetDlgItem(IDC_STATIC_REMOTE)->MoveWindow(10, cy / 2, 25 * m_fScalingFactor, 20);
GetDlgItem(IDC_LOCAL_PATH)->MoveWindow(56, 5, 210, 12);
GetDlgItem(IDC_REMOTE_PATH)->MoveWindow(56, (cy / 2) - 4, 210, 12);
//显示工具栏
m_wndToolBar_Local.MoveWindow(268, 0, (rect.right - 268), 48);
m_wndToolBar_Remote.MoveWindow(268, (rect.bottom / 2 - 10), (rect.right - 268), 48);
}
void CFileManagerDlg::FixedLocalDriveList()
{
// 停止正在进行的本地搜索
if (m_bLocalSearching) {
m_bLocalSearching = false;
m_bLocalSearchStopped = true;
}
char DriveString[256];
char *pDrive = NULL;
m_list_local.DeleteAllItems();
while(m_list_local.DeleteColumn(0) != 0);
m_list_local.InsertColumnL(0, "名称", LVCFMT_LEFT, 200);
m_list_local.InsertColumnL(1, "类型", LVCFMT_LEFT, 100);
m_list_local.InsertColumnL(2, "总大小", LVCFMT_LEFT, 100);
m_list_local.InsertColumnL(3, "可用空间", LVCFMT_LEFT, 115);
GetLogicalDriveStrings(sizeof(DriveString), DriveString);
pDrive = DriveString;
char FileSystem[MAX_PATH];
unsigned __int64 HDAmount = 0;
unsigned __int64 HDFreeSpace = 0;
unsigned long AmntMB = 0; // 总大小
unsigned long FreeMB = 0; // 剩余空间
for (int i = 0; *pDrive != '\0'; i++, pDrive += lstrlen(pDrive) + 1) {
// 得到磁盘相关信息
memset(FileSystem, 0, sizeof(FileSystem));
// 得到文件系统信息及大小
GetVolumeInformation(pDrive, NULL, 0, NULL, NULL, NULL, FileSystem, MAX_PATH);
int nFileSystemLen = lstrlen(FileSystem) + 1;
if (GetDiskFreeSpaceEx(pDrive, (PULARGE_INTEGER)&HDFreeSpace, (PULARGE_INTEGER)&HDAmount, NULL)) {
AmntMB = HDAmount / 1024 / 1024;
FreeMB = HDFreeSpace / 1024 / 1024;
} else {
AmntMB = 0;
FreeMB = 0;
}
int nItem = m_list_local.InsertItem(i, pDrive, GetIconIndex(pDrive, GetFileAttributes(pDrive)));
m_list_local.SetItemData(nItem, 1);
if (lstrlen(FileSystem) == 0) {
SHFILEINFO sfi = {};
SHGetFileInfo(pDrive, FILE_ATTRIBUTE_NORMAL, &sfi,sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
m_list_local.SetItemText(nItem, 1, sfi.szTypeName);
} else {
m_list_local.SetItemText(nItem, 1, FileSystem);
}
CString str;
str.FormatL("%10.1f GB", (float)AmntMB / 1024);
m_list_local.SetItemText(nItem, 2, str);
str.FormatL("%10.1f GB", (float)FreeMB / 1024);
m_list_local.SetItemText(nItem, 3, str);
}
// 重置本地当前路径
m_Local_Path = "";
m_Local_Directory_ComboBox.ResetContent();
ShowMessage(_TRF("本地:装载目录 %s 完成"), m_Local_Path);
}
void CFileManagerDlg::OnDblclkListLocal(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
if (m_list_local.GetSelectedCount() == 0 || m_list_local.GetItemData(m_list_local.GetSelectionMark()) != 1)
return;
FixedLocalFileList();
*pResult = 0;
}
void CFileManagerDlg::FixedLocalFileList(CString directory)
{
// 导航时停止正在进行的本地搜索
if (m_bLocalSearching) {
m_bLocalSearching = false;
m_bLocalSearchStopped = true;
}
if (directory.GetLength() == 0) {
int nItem = m_list_local.GetSelectionMark();
// 如果有选中的,是目录
if (nItem != -1) {
if (m_list_local.GetItemData(nItem) == 1) {
directory = m_list_local.GetItemText(nItem, 0);
}
}
// 从组合框里得到路径
else {
m_Local_Directory_ComboBox.GetWindowText(m_Local_Path);
}
}
// 得到父目录
if (directory == "..") {
m_Local_Path = GetParentDirectory(m_Local_Path);
}
// 刷新当前用
else if (directory != ".") {
m_Local_Path += directory;
if(m_Local_Path.Right(1) != "\\")
m_Local_Path += "\\";
}
// 是驱动器的根目录,返回磁盘列表
if (m_Local_Path.GetLength() == 0) {
FixedLocalDriveList();
return;
}
m_Local_Directory_ComboBox.InsertStringL(0, m_Local_Path);
m_Local_Directory_ComboBox.SetCurSel(0);
// 重建标题
m_list_local.DeleteAllItems();
while(m_list_local.DeleteColumn(0) != 0);
m_list_local.InsertColumnL(0, "名称", LVCFMT_LEFT, 200);
m_list_local.InsertColumnL(1, "大小", LVCFMT_LEFT, 100);
m_list_local.InsertColumnL(2, "类型", LVCFMT_LEFT, 100);
m_list_local.InsertColumnL(3, "修改日期", LVCFMT_LEFT, 115);
int nItemIndex = 0;
m_list_local.SetItemData
(
m_list_local.InsertItem(nItemIndex++, "..", GetIconIndex(NULL, FILE_ATTRIBUTE_DIRECTORY)),
1
);
// i 为 0 时列目录i 为 1时列文件
for (int i = 0; i < 2; ++i) {
CFileFind file;
BOOL bContinue;
bContinue = file.FindFile(m_Local_Path + "*.*");
while (bContinue) {
bContinue = file.FindNextFile();
if (file.IsDots())
continue;
bool bIsInsert = !file.IsDirectory() == i;
if (!bIsInsert)
continue;
int nItem = m_list_local.InsertItem(nItemIndex++, file.GetFileName(),
GetIconIndex(file.GetFileName(), GetFileAttributes(file.GetFilePath())));
m_list_local.SetItemData(nItem, file.IsDirectory());
SHFILEINFO sfi = {};
SHGetFileInfo(file.GetFileName(), FILE_ATTRIBUTE_NORMAL, &sfi,sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
m_list_local.SetItemText(nItem, 2, sfi.szTypeName);
CString str;
str.FormatL("%10d KB", file.GetLength() / 1024 + (file.GetLength() % 1024 ? 1 : 0));
m_list_local.SetItemText(nItem, 1, str);
CTime time;
file.GetLastWriteTime(time);
m_list_local.SetItemText(nItem, 3, time.FormatL("%Y-%m-%d %H:%M"));
}
}
ShowMessage(_TRF("本地:装载目录 %s 完成"), m_Local_Path);
}
void CFileManagerDlg::DropItemOnList(CListCtrl* pDragList, CListCtrl* pDropList)
{
//This routine performs the actual drop of the item dragged.
//It simply grabs the info from the Drag list (pDragList)
// and puts that info into the list dropped on (pDropList).
//Send: pDragList = pointer to CListCtrl we dragged from,
// pDropList = pointer to CListCtrl we are dropping on.
//Return: nothing.
////Variables
// Unhilight the drop target
if(pDragList == pDropList) { //we are return
return;
} //EO if(pDragList...
pDropList->SetItemState(m_nDropIndex, 0, LVIS_DROPHILITED);
if ((CWnd *)pDropList == &m_list_local) {
OnRemoteCopy();
} else if ((CWnd *)pDropList == &m_list_remote) {
OnLocalCopy();
} else {
// 见鬼了
return;
}
// 重置
m_nDropIndex = -1;
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CFileManagerDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CFileManagerDlg::OnBegindragListLocal(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
//// Save the index of the item being dragged in m_nDragIndex
//// This will be used later for retrieving the info dragged
m_nDragIndex = pNMListView->iItem;
if (!m_list_local.GetItemText(m_nDragIndex, 0).Compare(".."))
return;
//We will call delete later (in LButtonUp) to clean this up
if(m_list_local.GetSelectedCount() > 1) //more than 1 item in list is selected
m_hCursor = THIS_APP->LoadCursor(IDC_CURSOR_MDRAG);
else
m_hCursor = THIS_APP->LoadCursor(IDC_CURSOR_DRAG);
ASSERT(m_hCursor); //make sure it was created
//// Change the cursor to the drag image
//// (still must perform DragMove() in OnMouseMove() to show it moving)
//// Set dragging flag and others
m_bDragging = TRUE; //we are in a drag and drop operation
m_nDropIndex = -1; //we don't have a drop index yet
m_pDragList = &m_list_local; //make note of which list we are dragging from
m_pDropWnd = &m_list_local; //at present the drag list is the drop list
//// Capture all mouse messages
SetCapture();
*pResult = 0;
}
void CFileManagerDlg::OnBegindragListRemote(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
//// Save the index of the item being dragged in m_nDragIndex
//// This will be used later for retrieving the info dragged
m_nDragIndex = pNMListView->iItem;
if (!m_list_local.GetItemText(m_nDragIndex, 0).Compare(".."))
return;
//We will call delete later (in LButtonUp) to clean this up
if(m_list_remote.GetSelectedCount() > 1) //more than 1 item in list is selected
m_hCursor = THIS_APP->LoadCursor(IDC_CURSOR_MDRAG);
else
m_hCursor = THIS_APP->LoadCursor(IDC_CURSOR_DRAG);
ASSERT(m_hCursor); //make sure it was created
//// Change the cursor to the drag image
//// (still must perform DragMove() in OnMouseMove() to show it moving)
//// Set dragging flag and others
m_bDragging = TRUE; //we are in a drag and drop operation
m_nDropIndex = -1; //we don't have a drop index yet
m_pDragList = &m_list_remote; //make note of which list we are dragging from
m_pDropWnd = &m_list_remote; //at present the drag list is the drop list
//// Capture all mouse messages
SetCapture ();
*pResult = 0;
}
void CFileManagerDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//While the mouse is moving, this routine is called.
//This routine will redraw the drag image at the present
// mouse location to display the dragging.
//Also, while over a CListCtrl, this routine will highlight
// the item we are hovering over.
//// If we are in a drag/drop procedure (m_bDragging is true)
if (m_bDragging) {
//SetClassLong(m_list_local.m_hWnd, GCL_HCURSOR, (LONG)THIS_APP->LoadCursor(IDC_DRAG));
//// Move the drag image
CPoint pt(point); //get our current mouse coordinates
ClientToScreen(&pt); //convert to screen coordinates
//// Get the CWnd pointer of the window that is under the mouse cursor
CWnd* pDropWnd = WindowFromPoint (pt);
ASSERT(pDropWnd); //make sure we have a window
//// If we drag outside current window we need to adjust the highlights displayed
if (pDropWnd != m_pDropWnd) {
if (m_nDropIndex != -1) { //If we drag over the CListCtrl header, turn off the hover highlight
TRACE("m_nDropIndex is -1\n");
CListCtrl* pList = (CListCtrl*)m_pDropWnd;
VERIFY (pList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED));
// redraw item
VERIFY (pList->RedrawItems (m_nDropIndex, m_nDropIndex));
pList->UpdateWindow ();
m_nDropIndex = -1;
}
}
// Save current window pointer as the CListCtrl we are dropping onto
m_pDropWnd = pDropWnd;
// Convert from screen coordinates to drop target client coordinates
pDropWnd->ScreenToClient(&pt);
//If we are hovering over a CListCtrl we need to adjust the highlights
if(pDropWnd->IsKindOf(RUNTIME_CLASS (CListCtrl))) {
//Note that we can drop here
SetCursor(m_hCursor);
if (m_pDropWnd->m_hWnd == m_pDragList->m_hWnd)
return;
UINT uFlags;
CListCtrl* pList = (CListCtrl*)pDropWnd;
// Turn off hilight for previous drop target
pList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED);
// Redraw previous item
pList->RedrawItems (m_nDropIndex, m_nDropIndex);
// Get the item that is below cursor
m_nDropIndex = ((CListCtrl*)pDropWnd)->HitTest(pt, &uFlags);
if (m_nDropIndex != -1) {
// Highlight it
pList->SetItemState(m_nDropIndex, LVIS_DROPHILITED, LVIS_DROPHILITED);
// Redraw item
pList->RedrawItems(m_nDropIndex, m_nDropIndex);
pList->UpdateWindow();
}
} else {
//If we are not hovering over a CListCtrl, change the cursor
// to note that we cannot drop here
SetCursor(LoadCursor(NULL, IDC_NO));
}
}
__super::OnMouseMove(nFlags, point);
}
void CFileManagerDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//This routine is the end of the drag/drop operation.
//When the button is released, we are to drop the item.
//There are a few things we need to do to clean up and
// finalize the drop:
// 1) Release the mouse capture
// 2) Set m_bDragging to false to signify we are not dragging
// 3) Actually drop the item (we call a separate function to do that)
//If we are in a drag and drop operation (otherwise we don't do anything)
if (m_bDragging) {
// Release mouse capture, so that other controls can get control/messages
ReleaseCapture();
// Note that we are NOT in a drag operation
m_bDragging = FALSE;
CPoint pt (point); //Get current mouse coordinates
ClientToScreen (&pt); //Convert to screen coordinates
// Get the CWnd pointer of the window that is under the mouse cursor
CWnd* pDropWnd = WindowFromPoint (pt);
ASSERT (pDropWnd); //make sure we have a window pointer
// If window is CListCtrl, we perform the drop
if (pDropWnd->IsKindOf (RUNTIME_CLASS (CListCtrl))) {
m_pDropList = (CListCtrl*)pDropWnd; //Set pointer to the list we are dropping on
DropItemOnList(m_pDragList, m_pDropList); //Call routine to perform the actual drop
}
}
__super::OnLButtonUp(nFlags, point);
}
BOOL CFileManagerDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_KEYDOWN) {
if (pMsg->wParam == VK_ESCAPE)
return true;
if (pMsg->wParam == VK_RETURN) {
if (
pMsg->hwnd == m_list_local.m_hWnd ||
pMsg->hwnd == ((CEdit*)m_Local_Directory_ComboBox.GetWindow(GW_CHILD))->m_hWnd
) {
FixedLocalFileList();
} else if
(
pMsg->hwnd == m_list_remote.m_hWnd ||
pMsg->hwnd == ((CEdit*)m_Remote_Directory_ComboBox.GetWindow(GW_CHILD))->m_hWnd
) {
GetRemoteFileList();
}
return TRUE;
}
}
// 单击除了窗口标题栏以外的区域使窗口移动
if (pMsg->message == WM_LBUTTONDOWN && pMsg->hwnd == m_hWnd) {
pMsg->message = WM_NCLBUTTONDOWN;
pMsg->wParam = HTCAPTION;
}
/*
UINT CFileManagerDlg::OnNcHitTest (Cpoint point )
{
UINT nHitTest =Cdialog: : OnNcHitTest (point )
return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest
}
上述技术有两点不利之处,
其一是在窗口的客户区域双击时,窗口将极大;
其二, 它不适合包含几个视窗的主框窗口。
*/
if(m_wndToolBar_Local.IsWindowVisible()) {
CWnd* pWndParent = m_wndToolBar_Local.GetParent();
m_wndToolBar_Local.OnUpdateCmdUI((CFrameWnd*)this, TRUE);
}
if(m_wndToolBar_Remote.IsWindowVisible()) {
CWnd* pWndParent = m_wndToolBar_Remote.GetParent();
m_wndToolBar_Remote.OnUpdateCmdUI((CFrameWnd*)this, TRUE);
}
return __super::PreTranslateMessage(pMsg);
}
void CFileManagerDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
m_ProgressCtrl->StepIt();
__super::OnTimer(nIDEvent);
}
void CFileManagerDlg::FixedRemoteDriveList()
{
// 加载系统统图标列表 设置驱动器图标列表
HIMAGELIST hImageListLarge = NULL;
HIMAGELIST hImageListSmall = NULL;
Shell_GetImageLists(&hImageListLarge, &hImageListSmall);
ListView_SetImageList(m_list_remote.m_hWnd, hImageListLarge, LVSIL_NORMAL);
ListView_SetImageList(m_list_remote.m_hWnd, hImageListSmall, LVSIL_SMALL);
m_list_remote.DeleteAllItems();
// 重建Column
while(m_list_remote.DeleteColumn(0) != 0);
m_list_remote.InsertColumnL(0, "名称", LVCFMT_LEFT, 200);
m_list_remote.InsertColumnL(1, "类型", LVCFMT_LEFT, 100);
m_list_remote.InsertColumnL(2, "总大小", LVCFMT_LEFT, 100);
m_list_remote.InsertColumnL(3, "可用空间", LVCFMT_LEFT, 115);
char *pDrive = NULL;
pDrive = (char *)m_bRemoteDriveList;
unsigned long AmntMB = 0; // 总大小
unsigned long FreeMB = 0; // 剩余空间
//char VolName[MAX_PATH];
//char FileSystem[MAX_PATH];
/*
6 DRIVE_FLOPPY
7 DRIVE_REMOVABLE
8 DRIVE_FIXED
9 DRIVE_REMOTE
10 DRIVE_REMOTE_DISCONNECT
11 DRIVE_CDROM
*/
int nIconIndex = -1;
for (int i = 0; pDrive[i] != '\0';) {
if (pDrive[i] == 'A' || pDrive[i] == 'B') {
nIconIndex = 6;
} else {
switch (pDrive[i + 1]) {
case DRIVE_REMOVABLE:
nIconIndex = 7;
break;
case DRIVE_FIXED:
nIconIndex = 8;
break;
case DRIVE_REMOTE:
nIconIndex = 9;
break;
case DRIVE_CDROM:
nIconIndex = 11;
break;
default:
nIconIndex = 8;
break;
}
}
CString str;
str.FormatL("%c:\\", pDrive[i]);
int nItem = m_list_remote.InsertItem(i, str, nIconIndex);
m_list_remote.SetItemData(nItem, 1);
memcpy(&AmntMB, pDrive + i + 2, 4);
memcpy(&FreeMB, pDrive + i + 6, 4);
str.FormatL("%10.1f GB", (float)AmntMB / 1024);
m_list_remote.SetItemText(nItem, 2, str);
str.FormatL("%10.1f GB", (float)FreeMB / 1024);
m_list_remote.SetItemText(nItem, 3, str);
i += 10;
char *lpFileSystemName = NULL;
char *lpTypeName = NULL;
lpTypeName = pDrive + i;
i += lstrlen(pDrive + i) + 1;
lpFileSystemName = pDrive + i;
// 磁盘类型, 为空就显示磁盘名称
if (lstrlen(lpFileSystemName) == 0) {
m_list_remote.SetItemText(nItem, 1, lpTypeName);
} else {
m_list_remote.SetItemText(nItem, 1, lpFileSystemName);
}
i += lstrlen(pDrive + i) + 1;
}
// 重置远程当前路径
m_Remote_Path = "";
m_Remote_Directory_ComboBox.ResetContent();
ShowMessage(_TRF("远程:装载目录 %s 完成"), m_Remote_Path);
}
void CFileManagerDlg::OnClose()
{
CancelIO();
// 等待数据处理完毕
if (IsProcessing()) {
ShowWindow(SW_HIDE);
return;
}
CoUninitialize();
DialogBase::OnClose();
}
CString CFileManagerDlg::GetParentDirectory(CString strPath)
{
CString strCurPath = strPath;
int Index = strCurPath.ReverseFind('\\');
if (Index == -1) {
return strCurPath;
}
CString str = strCurPath.Left(Index);
Index = str.ReverseFind('\\');
if (Index == -1) {
strCurPath = "";
return strCurPath;
}
strCurPath = str.Left(Index);
if(strCurPath.Right(1) != "\\")
strCurPath += "\\";
return strCurPath;
}
void CFileManagerDlg::OnReceiveComplete()
{
switch (m_ContextObject->m_DeCompressionBuffer.GetBuffer(0)[0]) {
case TOKEN_FILE_LIST: // 文件列表
try {
FixedRemoteFileList
(
m_ContextObject->m_DeCompressionBuffer.GetBuffer(0),
m_ContextObject->m_DeCompressionBuffer.GetBufferLen() - 1
);
} catch (CMemoryException* e) {
char err[256];
e->GetErrorMessage(err, sizeof(err));
Mprintf("[ERROR] CMemoryException: %s\n", err);
} catch (CFileException* e) {
char err[256];
e->GetErrorMessage(err, sizeof(err));
Mprintf("[ERROR] CFileException: %s\n", err);
} catch (CException* e) {
char err[256];
e->GetErrorMessage(err, sizeof(err));
Mprintf("[ERROR] CException: %s\n", err);
} catch (...) {
Mprintf("[ERROR] Other exception\n");
}
break;
case TOKEN_FILE_SIZE: // 传输文件时的第一个数据包,文件大小,及文件名
CreateLocalRecvFile();
break;
case TOKEN_FILE_DATA: // 文件内容
WriteLocalRecvFile();
break;
case TOKEN_TRANSFER_FINISH: // 传输完成
EndLocalRecvFile();
break;
case TOKEN_CREATEFOLDER_FINISH:
GetRemoteFileList(".");
break;
case TOKEN_DELETE_FINISH:
EndRemoteDeleteFile();
break;
case TOKEN_GET_TRANSFER_MODE:
SendTransferMode();
break;
case TOKEN_DATA_CONTINUE:
SendFileData();
break;
case TOKEN_RENAME_FINISH:
// 刷新远程文件列表
GetRemoteFileList(".");
break;
case TOKEN_SEARCH_FILE_LIST: // 搜索结果列表
if (m_bSearchStopped) break; // 已停止,丢弃在途数据
try {
FixedRemoteSearchFileList
(
m_ContextObject->m_DeCompressionBuffer.GetBuffer(0),
m_ContextObject->m_DeCompressionBuffer.GetBufferLen() - 1
);
} catch (...) {
Mprintf("[ERROR] Search list exception\n");
}
break;
case TOKEN_SEARCH_FILE_FINISH: // 搜索完成
if (m_bSearchStopped) {
m_bSearchStopped = false; // 收到结束标记,重置停止标志
break;
}
m_bSearching = false;
m_list_remote.EnableWindow(TRUE);
{
DWORD dwElapsed = (GetTickCount() - m_dwSearchStartTime) / 1000;
ShowMessage(_TRF("搜索 \"%s\" 在 %s 完成,共 %d 个结果 (耗时 %d秒)"), m_strSearchName, m_strSearchPath, m_nSearchResultCount, dwElapsed);
}
break;
default:
SendException();
break;
}
}
void CFileManagerDlg::GetRemoteFileList(CString directory)
{
// 导航到目录时停止正在进行的远程搜索
if (m_bSearching) {
BYTE bStop = COMMAND_FILES_SEARCH_STOP;
m_ContextObject->Send2Client(&bStop, 1);
m_bSearching = false;
m_bSearchStopped = true; // 丢弃在途搜索数据
}
if (directory.GetLength() == 0) {
int nItem = m_list_remote.GetSelectionMark();
// 如果有选中的,是目录
if (nItem != -1) {
if (m_list_remote.GetItemData(nItem) == 1) {
directory = m_list_remote.GetItemText(nItem, 0);
}
}
// 从组合框里得到路径
else {
m_Remote_Directory_ComboBox.GetWindowText(m_Remote_Path);
}
}
// 得到父目录
if (directory == "..") {
m_Remote_Path = GetParentDirectory(m_Remote_Path);
} else if (directory != ".") {
m_Remote_Path += directory;
if(m_Remote_Path.Right(1) != "\\")
m_Remote_Path += "\\";
}
// 是驱动器的根目录,返回磁盘列表
if (m_Remote_Path.GetLength() == 0) {
FixedRemoteDriveList();
return;
}
// 发送数据前清空缓冲区
int PacketSize = m_Remote_Path.GetLength() + 2;
BYTE *bPacket = (BYTE *)LocalAlloc(LPTR, PacketSize);
bPacket[0] = COMMAND_LIST_FILES;
memcpy(bPacket + 1, m_Remote_Path.GetBuffer(0), PacketSize - 1);
m_ContextObject->Send2Client(bPacket, PacketSize);
LocalFree(bPacket);
m_Remote_Directory_ComboBox.InsertStringL(0, m_Remote_Path);
m_Remote_Directory_ComboBox.SetCurSel(0);
// 得到返回数据前禁窗口
m_list_remote.EnableWindow(FALSE);
m_ProgressCtrl->SetPos(0);
}
void CFileManagerDlg::OnDblclkListRemote(NMHDR* pNMHDR, LRESULT* pResult)
{
if (m_list_remote.GetSelectedCount() == 0 || m_list_remote.GetItemData(m_list_remote.GetSelectionMark()) != 1)
return;
// TODO: Add your control notification handler code here
GetRemoteFileList();
*pResult = 0;
}
void CFileManagerDlg::FixedRemoteFileList(BYTE *pbBuffer, DWORD dwBufferLen)
{
// 重新设置ImageList
SHFILEINFO sfi = {};
HIMAGELIST hImageListLarge = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi,sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
HIMAGELIST hImageListSmall = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi,sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
ListView_SetImageList(m_list_remote.m_hWnd, hImageListLarge, LVSIL_NORMAL);
ListView_SetImageList(m_list_remote.m_hWnd, hImageListSmall, LVSIL_SMALL);
// 重建标题
m_list_remote.DeleteAllItems();
while(m_list_remote.DeleteColumn(0) != 0);
m_list_remote.InsertColumnL(0, "名称", LVCFMT_LEFT, 200);
m_list_remote.InsertColumnL(1, "大小", LVCFMT_LEFT, 100);
m_list_remote.InsertColumnL(2, "类型", LVCFMT_LEFT, 100);
m_list_remote.InsertColumnL(3, "修改日期", LVCFMT_LEFT, 115);
int nItemIndex = 0;
m_list_remote.SetItemData
(
m_list_remote.InsertItem(nItemIndex++, "..", GetIconIndex(NULL, FILE_ATTRIBUTE_DIRECTORY)),
1
);
/*
ListView 消除闪烁
更新数据前用SetRedraw(FALSE)
更新后调用SetRedraw(TRUE)
*/
m_list_remote.SetRedraw(FALSE);
if (dwBufferLen != 0) {
//
for (int i = 0; i < 2; ++i) {
// 跳过Token共5字节
char *pList = (char *)(pbBuffer + 1);
for(char *pBase = pList; pList - pBase < dwBufferLen - 1;) {
char *pszFileName = NULL;
DWORD dwFileSizeHigh = 0; // 文件高字节大小
DWORD dwFileSizeLow = 0; // 文件低字节大小
int nItem = 0;
bool bIsInsert = false;
FILETIME ftm_strReceiveLocalFileTime;
int nType = *pList ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
// i 为 0 时列目录i为1时列文件
bIsInsert = !(nType == FILE_ATTRIBUTE_DIRECTORY) == i;
pszFileName = ++pList;
if (bIsInsert) {
nItem = m_list_remote.InsertItem(nItemIndex++, pszFileName, GetIconIndex(pszFileName, nType));
m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
SHFILEINFO sfi = {};
SHGetFileInfo(pszFileName, FILE_ATTRIBUTE_NORMAL | nType, &sfi,sizeof(SHFILEINFO), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
m_list_remote.SetItemText(nItem, 2, sfi.szTypeName);
}
// 得到文件大小
pList += lstrlen(pszFileName) + 1;
if (bIsInsert) {
memcpy(&dwFileSizeHigh, pList, 4);
memcpy(&dwFileSizeLow, pList + 4, 4);
CString strSize;
strSize.FormatL("%10d KB", (dwFileSizeHigh * (MAXDWORD+long long(1))) / 1024 + dwFileSizeLow / 1024 + (dwFileSizeLow % 1024 ? 1 : 0));
m_list_remote.SetItemText(nItem, 1, strSize);
memcpy(&ftm_strReceiveLocalFileTime, pList + 8, sizeof(FILETIME));
CTime time(ftm_strReceiveLocalFileTime);
m_list_remote.SetItemText(nItem, 3, time.FormatL("%Y-%m-%d %H:%M"));
}
pList += 16;
}
}
}
m_list_remote.SetRedraw(TRUE);
// 恢复窗口
m_list_remote.EnableWindow(TRUE);
ShowMessage(_TRF("远程:装载目录 %s 完成"), m_Remote_Path);
}
void CFileManagerDlg::FixedRemoteSearchFileList(BYTE *pbBuffer, DWORD dwBufferLen)
{
// 第一批结果到达时,初始化搜索列表
if (!m_bSearching) {
m_bSearching = true;
m_nSearchResultCount = 0;
m_IconCache.clear();
// 预缓存文件夹图标
m_IconCache["*folder*"] = GetIconIndex(NULL, FILE_ATTRIBUTE_DIRECTORY);
// 重新设置ImageList
SHFILEINFO sfi = {};
HIMAGELIST hImageListLarge = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
HIMAGELIST hImageListSmall = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
ListView_SetImageList(m_list_remote.m_hWnd, hImageListLarge, LVSIL_NORMAL);
ListView_SetImageList(m_list_remote.m_hWnd, hImageListSmall, LVSIL_SMALL);
// 重建标题 (搜索模式: 名称、大小、修改日期、路径)
m_list_remote.DeleteAllItems();
while (m_list_remote.DeleteColumn(0) != 0);
m_list_remote.InsertColumnL(0, "名称", LVCFMT_LEFT, 180);
m_list_remote.InsertColumnL(1, "大小", LVCFMT_LEFT, 90);
m_list_remote.InsertColumnL(2, "修改日期", LVCFMT_LEFT, 115);
m_list_remote.InsertColumnL(3, "路径", LVCFMT_LEFT, 220);
}
m_list_remote.SetRedraw(FALSE);
if (dwBufferLen != 0) {
char *pList = (char *)(pbBuffer + 1);
for (char *pBase = pList; pList - pBase < (int)(dwBufferLen - 1);) {
int nType = *pList ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
char *pszFullPath = ++pList;
// 从完整路径中提取文件名
CString csFullPath(pszFullPath);
int nPos = csFullPath.ReverseFind('\\');
CString csFileName = (nPos >= 0) ? csFullPath.Right(csFullPath.GetLength() - nPos - 1) : csFullPath;
CString csDir = (nPos >= 0) ? csFullPath.Left(nPos) : "";
// 按扩展名缓存图标避免重复调用SHGetFileInfo
int nIcon;
if (nType == FILE_ATTRIBUTE_DIRECTORY) {
nIcon = m_IconCache["*folder*"];
} else {
CString csExt;
int nDot = csFileName.ReverseFind('.');
csExt = (nDot >= 0) ? csFileName.Mid(nDot) : "*noext*";
csExt.MakeLower();
auto it = m_IconCache.find((LPCSTR)csExt);
if (it != m_IconCache.end()) {
nIcon = it->second;
} else {
nIcon = GetIconIndex((LPCSTR)csExt, nType);
m_IconCache[(LPCSTR)csExt] = nIcon;
}
}
int nItem = m_list_remote.InsertItem(m_nSearchResultCount, csFileName, nIcon);
m_list_remote.SetItemData(nItem, nType == FILE_ATTRIBUTE_DIRECTORY);
pList += lstrlen(pszFullPath) + 1;
// 文件大小
DWORD dwFileSizeHigh = 0, dwFileSizeLow = 0;
memcpy(&dwFileSizeHigh, pList, 4);
memcpy(&dwFileSizeLow, pList + 4, 4);
CString strSize;
strSize.FormatL("%10d KB", (dwFileSizeHigh * (MAXDWORD + long long(1))) / 1024 + dwFileSizeLow / 1024 + (dwFileSizeLow % 1024 ? 1 : 0));
m_list_remote.SetItemText(nItem, 1, strSize);
// 修改日期
FILETIME ftLastWrite;
memcpy(&ftLastWrite, pList + 8, sizeof(FILETIME));
CTime time(ftLastWrite);
m_list_remote.SetItemText(nItem, 2, time.FormatL("%Y-%m-%d %H:%M"));
// 路径
m_list_remote.SetItemText(nItem, 3, csDir);
pList += 16;
m_nSearchResultCount++;
}
}
m_list_remote.SetRedraw(TRUE);
DWORD dwElapsed = (GetTickCount() - m_dwSearchStartTime) / 1000;
ShowMessage(_TRF("搜索 \"%s\" 在 %s ... 已找到 %d 个 (%d秒)"), m_strSearchName, m_strSearchPath, m_nSearchResultCount, dwElapsed);
}
void CFileManagerDlg::ShowMessage(const char *lpFmt, ...)
{
char *buff = new char[1024];
va_list arglist;
va_start( arglist, lpFmt );
memset(buff, 0, 1024);
vsprintf(buff, lpFmt, arglist);
// fix: 多线程操作控件引发崩溃的问题
// m_wndStatusBar.SetPaneText(0, buff);
// msg 第1个参数为缓存大小,第2个参数为缓存指针
SendMessage(WM_MY_MESSAGE, 1024, (LPARAM)buff);
va_end( arglist );
}
void CFileManagerDlg::OnLocalPrev()
{
// TODO: Add your command handler code here
FixedLocalFileList("..");
}
void CFileManagerDlg::OnRemotePrev()
{
// TODO: Add your command handler code here
GetRemoteFileList("..");
}
void CFileManagerDlg::OnLocalDesktop()
{
char path[MAX_PATH];
if (SHGetSpecialFolderPathA(m_hWnd, path, CSIDL_DESKTOPDIRECTORY, FALSE)) {
m_Local_Path = path;
if (m_Local_Path.Right(1) != "\\")
m_Local_Path += "\\";
FixedLocalFileList(".");
}
}
void CFileManagerDlg::OnLocalDownloads()
{
char path[MAX_PATH];
if (SHGetSpecialFolderPathA(m_hWnd, path, CSIDL_PROFILE, FALSE)) {
m_Local_Path.Format("%s\\Downloads\\", path);
FixedLocalFileList(".");
}
}
void CFileManagerDlg::OnLocalHome()
{
char path[MAX_PATH];
if (SHGetSpecialFolderPathA(m_hWnd, path, CSIDL_PROFILE, FALSE)) {
m_Local_Path = path;
if (m_Local_Path.Right(1) != "\\")
m_Local_Path += "\\";
FixedLocalFileList(".");
}
}
// 通配符匹配 (支持 * 和 ?, 大小写不敏感)
bool CFileManagerDlg::WildcardMatch(LPCTSTR pattern, LPCTSTR str)
{
while (*pattern) {
if (*pattern == '*') {
pattern++;
if (!*pattern) return true;
while (*str) {
if (WildcardMatch(pattern, str)) return true;
str++;
}
return false;
} else if (*pattern == '?') {
if (!*str) return false;
pattern++;
str++;
} else {
if (tolower((unsigned char)*pattern) != tolower((unsigned char)*str)) return false;
pattern++;
str++;
}
}
return *str == '\0';
}
#define LOCAL_SEARCH_MAX_DEPTH 32
#define LOCAL_SEARCH_MAX_RESULTS 10000
struct LocalSearchContext {
CFileManagerDlg *pDlg;
CString searchPath;
CString searchName;
};
static bool LocalShouldSkipDirectory(DWORD dwAttributes)
{
if ((dwAttributes & FILE_ATTRIBUTE_HIDDEN) && (dwAttributes & FILE_ATTRIBUTE_SYSTEM))
return true;
if (dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
return true;
return false;
}
DWORD WINAPI CFileManagerDlg::LocalSearchThreadProc(LPVOID lpParam)
{
LocalSearchContext *pCtx = (LocalSearchContext *)lpParam;
pCtx->pDlg->LocalSearchWorker();
delete pCtx;
return 0;
}
void CFileManagerDlg::LocalSearchWorker()
{
char szPattern[MAX_PATH];
if (m_strLocalSearchName.Find('*') < 0 && m_strLocalSearchName.Find('?') < 0)
wsprintf(szPattern, "*%s*", (LPCSTR)m_strLocalSearchName);
else
lstrcpy(szPattern, (LPCSTR)m_strLocalSearchName);
struct SearchDir {
CString path;
int depth;
};
std::vector<SearchDir> dirStack;
dirStack.push_back({m_strLocalSearchPath, 0});
auto *pResults = new std::vector<LocalSearchItem>();
DWORD dwLastProgressTime = GetTickCount();
int nLastProgressCount = 0;
while (!dirStack.empty() && m_bLocalSearching && (int)pResults->size() < LOCAL_SEARCH_MAX_RESULTS) {
SearchDir cur = dirStack.back();
dirStack.pop_back();
if (cur.depth > LOCAL_SEARCH_MAX_DEPTH) continue;
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile(cur.path + "*.*", &fd);
if (hFind == INVALID_HANDLE_VALUE) continue;
std::vector<SearchDir> subdirs;
do {
if (!m_bLocalSearching) break;
if (strcmp(fd.cFileName, ".") == 0 || strcmp(fd.cFileName, "..") == 0) continue;
BOOL bIsDir = fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if (WildcardMatch(szPattern, fd.cFileName) && (int)pResults->size() < LOCAL_SEARCH_MAX_RESULTS) {
LocalSearchItem item;
item.fileName = fd.cFileName;
item.dir = cur.path;
item.bIsDir = bIsDir;
int nDot = item.fileName.ReverseFind('.');
item.ext = bIsDir ? "*folder*" : ((nDot >= 0) ? item.fileName.Mid(nDot) : "*noext*");
item.ext.MakeLower();
item.sizeHigh = fd.nFileSizeHigh;
item.sizeLow = fd.nFileSizeLow;
item.ftWrite = fd.ftLastWriteTime;
pResults->push_back(item);
}
if (bIsDir && !LocalShouldSkipDirectory(fd.dwFileAttributes))
subdirs.push_back({cur.path + fd.cFileName + "\\", cur.depth + 1});
} while (FindNextFile(hFind, &fd));
FindClose(hFind);
for (int i = (int)subdirs.size() - 1; i >= 0; i--)
dirStack.push_back(subdirs[i]);
// 数量增加500+或距上次更新超过2秒则更新进度
int nCount = (int)pResults->size();
DWORD dwNow = GetTickCount();
if (nCount - nLastProgressCount >= 500 || (nCount > nLastProgressCount && dwNow - dwLastProgressTime >= 2000)) {
::PostMessage(m_hWnd, WM_LOCAL_SEARCH_PROGRESS, (WPARAM)nCount, 0);
nLastProgressCount = nCount;
dwLastProgressTime = dwNow;
}
}
// 搜索完成将所有结果一次性发送给UI线程
// wParam: 1=正常完成, 0=被停止
BOOL bCompleted = dirStack.empty() || (int)pResults->size() >= LOCAL_SEARCH_MAX_RESULTS;
::SendMessage(m_hWnd, WM_LOCAL_SEARCH_DONE, bCompleted, (LPARAM)pResults);
}
LRESULT CFileManagerDlg::OnLocalSearchProgress(WPARAM wParam, LPARAM lParam)
{
if (!m_bLocalSearching || m_bLocalSearchStopped) return 0;
DWORD dwElapsed = (GetTickCount() - m_dwLocalSearchStartTime) / 1000;
ShowMessage(_TRF("搜索 \"%s\" 在 %s ... 已找到 %d 个 (%d秒)"),
m_strLocalSearchName, m_strLocalSearchPath, (int)wParam, dwElapsed);
return 0;
}
LRESULT CFileManagerDlg::OnLocalSearchDone(WPARAM wParam, LPARAM lParam)
{
auto *pResults = (std::vector<LocalSearchItem> *)lParam;
// 搜索被停止或已导航离开,丢弃结果
if (m_bLocalSearchStopped) {
delete pResults;
return 0;
}
// 插入所有结果
m_list_local.SetRedraw(FALSE);
for (size_t i = 0; i < pResults->size(); i++) {
const LocalSearchItem &item = (*pResults)[i];
int nType = item.bIsDir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
int nIcon;
auto it = m_LocalIconCache.find((LPCSTR)item.ext);
if (it != m_LocalIconCache.end()) {
nIcon = it->second;
} else {
nIcon = GetIconIndex((LPCSTR)item.ext, nType);
m_LocalIconCache[(LPCSTR)item.ext] = nIcon;
}
int nItem = m_list_local.InsertItem(m_nLocalSearchResultCount, item.fileName, nIcon);
m_list_local.SetItemData(nItem, item.bIsDir ? 1 : 0);
CString strSize;
__int64 fileSize = ((__int64)item.sizeHigh << 32) | item.sizeLow;
strSize.Format("%10d KB", (int)(fileSize / 1024 + (fileSize % 1024 ? 1 : 0)));
m_list_local.SetItemText(nItem, 1, strSize);
CTime time(item.ftWrite);
m_list_local.SetItemText(nItem, 2, time.Format("%Y-%m-%d %H:%M"));
CString dir = item.dir;
if (dir.GetLength() > 3 && dir.Right(1) == "\\")
dir = dir.Left(dir.GetLength() - 1);
m_list_local.SetItemText(nItem, 3, dir);
m_nLocalSearchResultCount++;
}
m_list_local.SetRedraw(TRUE);
DWORD dwElapsed = (GetTickCount() - m_dwLocalSearchStartTime) / 1000;
if (wParam) // 正常完成
ShowMessage(_TRF("搜索 \"%s\" 在 %s 完成,共 %d 个结果 (耗时 %d秒)"),
m_strLocalSearchName, m_strLocalSearchPath, m_nLocalSearchResultCount, dwElapsed);
else // 被停止
ShowMessage(_TRF("搜索 \"%s\" 在 %s 已停止,共 %d 个结果 (耗时 %d秒)"),
m_strLocalSearchName, m_strLocalSearchPath, m_nLocalSearchResultCount, dwElapsed);
m_bLocalSearching = false;
m_list_local.EnableWindow(TRUE);
delete pResults;
return 0;
}
void CFileManagerDlg::OnLocalSearch()
{
CInputDlg dlg(this);
dlg.Init(_TR("搜索文件"), _TR("请输入搜索关键词"));
if (dlg.DoModal() == IDOK && !dlg.m_str.IsEmpty()) {
if (m_Local_Path.GetLength() == 0)
return;
// 停止远程搜索
if (m_bSearching) {
m_bSearchStopped = true;
m_bSearching = false;
m_list_remote.EnableWindow(TRUE);
BYTE bStop = COMMAND_FILES_SEARCH_STOP;
m_ContextObject->Send2Client(&bStop, 1);
}
// 停止上一次本地搜索
if (m_bLocalSearching) {
m_bLocalSearching = false;
m_bLocalSearchStopped = true;
}
// 等待旧线程结束 (同时处理消息避免SendMessage死锁)
if (m_hLocalSearchThread) {
while (MsgWaitForMultipleObjects(1, &m_hLocalSearchThread, FALSE, 5000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1) {
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CloseHandle(m_hLocalSearchThread);
m_hLocalSearchThread = NULL;
}
// 重置状态
m_bLocalSearching = true;
m_bLocalSearchStopped = false;
m_nLocalSearchResultCount = 0;
m_dwLocalSearchStartTime = GetTickCount();
m_strLocalSearchPath = m_Local_Path;
m_strLocalSearchName = dlg.m_str;
m_LocalIconCache.clear();
m_LocalIconCache["*folder*"] = GetIconIndex(NULL, FILE_ATTRIBUTE_DIRECTORY);
// 初始化列表列 (搜索模式: 名称、大小、修改日期、路径)
SHFILEINFO sfi = {};
HIMAGELIST hImageListLarge = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
HIMAGELIST hImageListSmall = (HIMAGELIST)SHGetFileInfo(NULL, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
ListView_SetImageList(m_list_local.m_hWnd, hImageListLarge, LVSIL_NORMAL);
ListView_SetImageList(m_list_local.m_hWnd, hImageListSmall, LVSIL_SMALL);
m_list_local.DeleteAllItems();
while (m_list_local.DeleteColumn(0) != 0);
m_list_local.InsertColumnL(0, "名称", LVCFMT_LEFT, 180);
m_list_local.InsertColumnL(1, "大小", LVCFMT_LEFT, 90);
m_list_local.InsertColumnL(2, "修改日期", LVCFMT_LEFT, 115);
m_list_local.InsertColumnL(3, "路径", LVCFMT_LEFT, 220);
m_list_local.EnableWindow(FALSE);
ShowMessage(_TRF("正在搜索 \"%s\" 在 %s ..."), m_strLocalSearchName, m_strLocalSearchPath);
// 启动搜索线程
LocalSearchContext *pCtx = new LocalSearchContext;
pCtx->pDlg = this;
m_hLocalSearchThread = CreateThread(NULL, 0, LocalSearchThreadProc, (LPVOID)pCtx, 0, NULL);
}
}
void CFileManagerDlg::OnRemoteDesktop()
{
m_Remote_Path = "%USERPROFILE%\\Desktop\\";
GetRemoteFileList(".");
}
void CFileManagerDlg::OnRemoteDownloads()
{
m_Remote_Path = "%USERPROFILE%\\Downloads\\";
GetRemoteFileList(".");
}
void CFileManagerDlg::OnRemoteHome()
{
m_Remote_Path = "%USERPROFILE%\\";
GetRemoteFileList(".");
}
void CFileManagerDlg::OnRemoteSearch()
{
// 停止本地搜索
if (m_bLocalSearching) {
m_bLocalSearching = false;
m_bLocalSearchStopped = true;
m_list_local.EnableWindow(TRUE);
}
// 如果正在远程搜索,先停止
if (m_bSearching) {
BYTE bStop = COMMAND_FILES_SEARCH_STOP;
m_ContextObject->Send2Client(&bStop, 1);
m_bSearching = false;
}
CInputDlg dlg(this);
dlg.Init(_TR("搜索文件"), _TR("请输入搜索关键词"));
if (dlg.DoModal() == IDOK && !dlg.m_str.IsEmpty()) {
if (m_Remote_Path.GetLength() == 0)
return;
// 重置搜索状态 (m_bSearching 将在第一个 TOKEN_SEARCH_FILE_LIST 到达时设为 true)
m_bSearching = false;
m_bSearchStopped = false;
m_nSearchResultCount = 0;
m_dwSearchStartTime = GetTickCount();
// 构建搜索数据包: [COMMAND_SEARCH_FILE][SearchPath\0][SearchFileName\0]
CString searchPath = m_Remote_Path;
CString searchName = dlg.m_str;
m_strSearchPath = searchPath;
m_strSearchName = searchName;
int nPathLen = searchPath.GetLength() + 1;
int nNameLen = searchName.GetLength() + 1;
int nPacketSize = 1 + nPathLen + nNameLen;
BYTE *bPacket = (BYTE *)LocalAlloc(LPTR, nPacketSize);
bPacket[0] = COMMAND_SEARCH_FILE;
memcpy(bPacket + 1, searchPath.GetBuffer(0), nPathLen);
memcpy(bPacket + 1 + nPathLen, searchName.GetBuffer(0), nNameLen);
m_ContextObject->Send2Client(bPacket, nPacketSize);
LocalFree(bPacket);
m_list_remote.EnableWindow(FALSE);
ShowMessage(_TRF("正在搜索 %s ..."), searchName);
}
}
void CFileManagerDlg::OnLocalView()
{
// TODO: Add your command handler code here
m_list_local.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
}
// 在工具栏上显示ToolTip
BOOL CFileManagerDlg::OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{
ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
//让上一层的边框窗口优先处理该消息
if (GetRoutingFrame() != NULL)
return FALSE;
//分ANSI and UNICODE两个处理版本
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
TCHAR szFullText[256];
CString strTipText;
UINT_PTR nID = pNMHDR->idFrom;
//如果idFrom是一个子窗口则得到其ID。
if (
pNMHDR->code == TTN_NEEDTEXTA
&& (pTTTA->uFlags & TTF_IDISHWND)
|| pNMHDR->code == TTN_NEEDTEXTW
&& (pTTTW->uFlags & TTF_IDISHWND)
) {
//idFrom是工具条的句柄
nID = ::GetDlgCtrlID((HWND)nID);
}
if (nID != 0) { //若是0为一分隔栏不是按钮
//得到nID对应的字符串
AfxLoadString(nID, szFullText);
//从上面得到的字符串中取出Tooltip使用的文本
AfxExtractSubString(strTipText, szFullText, 1, '\n');
}
//复制分离出的文本
#ifndef _UNICODE
if (pNMHDR->code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA->szText, strTipText, sizeof(pTTTA->szText));
else
_mbstowcsz(pTTTW->szText, strTipText, sizeof(pTTTW->szText));
#else
if (pNMHDR->code == TTN_NEEDTEXTA)
_wcstombsz(pTTTA->szText, strTipText, sizeof(pTTTA->szText));
else
lstrcpyn(pTTTW->szText, strTipText, sizeof(pTTTW->szText));
#endif
*pResult = 0;
//显示Tooltip窗口
::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
return TRUE; //消息处理完毕
}
//////////////////////////////////以下为工具栏响应处理//////////////////////////////////////////
void CFileManagerDlg::OnLocalList()
{
// TODO: Add your command handler code here
m_list_local.ModifyStyle(LVS_TYPEMASK, LVS_LIST);
}
void CFileManagerDlg::OnLocalReport()
{
// TODO: Add your command handler code here
m_list_local.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
}
void CFileManagerDlg::OnLocalBigicon()
{
// TODO: Add your command handler code here
m_list_local.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
}
void CFileManagerDlg::OnLocalSmallicon()
{
// TODO: Add your command handler code here
m_list_local.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);
}
void CFileManagerDlg::OnRemoteList()
{
// TODO: Add your command handler code here
m_list_remote.ModifyStyle(LVS_TYPEMASK, LVS_LIST);
}
void CFileManagerDlg::OnRemoteReport()
{
// TODO: Add your command handler code here
m_list_remote.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
}
void CFileManagerDlg::OnRemoteBigicon()
{
// TODO: Add your command handler code here
m_list_remote.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
}
void CFileManagerDlg::OnRemoteSmallicon()
{
// TODO: Add your command handler code here
m_list_remote.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);
}
void CFileManagerDlg::OnRemoteView()
{
// TODO: Add your command handler code here
m_list_remote.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
}
// 为根目录时禁用向上按钮
void CFileManagerDlg::OnUpdateLocalPrev(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_Local_Path.GetLength() && m_list_local.IsWindowEnabled());
}
void CFileManagerDlg::OnUpdateLocalDelete(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
// 不是根目录并且选择项目大于0
pCmdUI->Enable(m_Local_Path.GetLength() && m_list_local.GetSelectedCount() && m_list_local.IsWindowEnabled());
}
void CFileManagerDlg::OnUpdateLocalNewfolder(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_Local_Path.GetLength() && m_list_local.IsWindowEnabled());
}
void CFileManagerDlg::OnUpdateLocalSearch(CCmdUI* pCmdUI)
{
// 有本地路径、列表可用、且没有搜索正在进行
pCmdUI->Enable(m_Local_Path.GetLength() && m_list_local.IsWindowEnabled() && !m_bLocalSearching && !m_bSearching);
}
void CFileManagerDlg::OnUpdateRemoteSearch(CCmdUI* pCmdUI)
{
// 有远程路径、列表可用、且没有搜索正在进行
pCmdUI->Enable(m_Remote_Path.GetLength() && m_list_remote.IsWindowEnabled() && !m_bSearching && !m_bLocalSearching);
}
void CFileManagerDlg::OnUpdateLocalCopy(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable
(
m_list_local.IsWindowEnabled()
&& (m_Remote_Path.GetLength() || m_list_remote.GetSelectedCount()) // 远程路径为空,或者有选择
&& m_list_local.GetSelectedCount()// 本地路径为空,或者有选择
);
}
void CFileManagerDlg::OnUpdateLocalStop(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable((!m_list_local.IsWindowEnabled() && m_bIsUpload) || m_bLocalSearching);
}
void CFileManagerDlg::OnUpdateRemotePrev(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_Remote_Path.GetLength() && m_list_remote.IsWindowEnabled());
}
void CFileManagerDlg::OnUpdateRemoteCopy(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
// 不是根目录并且选择项目大于0
pCmdUI->Enable
(
m_list_remote.IsWindowEnabled()
&& (m_Local_Path.GetLength() || m_list_local.GetSelectedCount()) // 本地路径为空,或者有选择
&& m_list_remote.GetSelectedCount() // 远程路径为空,或者有选择
);
}
void CFileManagerDlg::OnUpdateRemoteDelete(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
// 不是根目录并且选择项目大于0
pCmdUI->Enable(m_Remote_Path.GetLength() && m_list_remote.GetSelectedCount() && m_list_remote.IsWindowEnabled());
}
void CFileManagerDlg::OnUpdateRemoteNewfolder(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_Remote_Path.GetLength() && m_list_remote.IsWindowEnabled());
}
void CFileManagerDlg::OnUpdateRemoteStop(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable((!m_list_remote.IsWindowEnabled() && !m_bIsUpload) || m_bSearching);
}
bool CFileManagerDlg::FixedUploadDirectory(LPCTSTR lpPathName)
{
char lpszFilter[MAX_PATH];
char *lpszSlash = NULL;
memset(lpszFilter, 0, sizeof(lpszFilter));
if (lpPathName[lstrlen(lpPathName) - 1] != '\\')
lpszSlash = "\\";
else
lpszSlash = "";
wsprintf(lpszFilter, "%s%s*.*", lpPathName, lpszSlash);
WIN32_FIND_DATA wfd;
HANDLE hFind = FindFirstFile(lpszFilter, &wfd);
if (hFind == INVALID_HANDLE_VALUE) // 如果没有找到或查找失败
return FALSE;
do {
if (wfd.cFileName[0] == '.')
continue; // 过滤这两个目录
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
char strDirectory[MAX_PATH];
wsprintf(strDirectory, "%s%s%s", lpPathName, lpszSlash, wfd.cFileName);
FixedUploadDirectory(strDirectory); // 如果找到的是目录,则进入此目录进行递归
} else {
CString file;
file.FormatL("%s%s%s", lpPathName, lpszSlash, wfd.cFileName);
//Mprintf("send file %s\n",strFile);
m_Remote_Upload_Job.AddTail(file);
// 对文件进行操作
}
} while (FindNextFile(hFind, &wfd));
FindClose(hFind); // 关闭查找句柄
return true;
}
void CFileManagerDlg::EnableControl(BOOL bEnable)
{
m_list_local.EnableWindow(bEnable);
m_list_remote.EnableWindow(bEnable);
m_Local_Directory_ComboBox.EnableWindow(bEnable);
m_Remote_Directory_ComboBox.EnableWindow(bEnable);
}
void CFileManagerDlg::OnLocalCopy()
{
m_bIsUpload = true;
// TODO: Add your command handler code here
// TODO: Add your command handler code here
// 如果Drag的找到Drop到了哪个文件夹
if (m_nDropIndex != -1 && m_pDropList->GetItemData(m_nDropIndex))
m_hCopyDestFolder = m_pDropList->GetItemText(m_nDropIndex, 0);
// 重置上传任务列表
m_Remote_Upload_Job.RemoveAll();
POSITION pos = m_list_local.GetFirstSelectedItemPosition(); //iterator for the CListCtrl
while(pos) { //so long as we have a valid POSITION, we keep iterating
int nItem = m_list_local.GetNextSelectedItem(pos);
CString file = m_Local_Path + m_list_local.GetItemText(nItem, 0);
// 如果是目录
if (m_list_local.GetItemData(nItem)) {
file += '\\';
FixedUploadDirectory(file.GetBuffer(0));
} else {
// 添加到上传任务列表中去
m_Remote_Upload_Job.AddTail(file);
}
} //EO while(pos) -- at this point we have deleted the moving items and stored them in memory
if (m_Remote_Upload_Job.IsEmpty()) {
MessageBoxAPI_L(m_hWnd, "文件夹为空", "警告", MB_OK|MB_ICONWARNING);
return;
}
EnableControl(FALSE);
SendUploadJob();
}
void CFileManagerDlg::OnLocalCompress()
{
std::vector<std::string> paths;
POSITION pos = m_list_local.GetFirstSelectedItemPosition();
while (pos) {
int nItem = m_list_local.GetNextSelectedItem(pos);
CString file = m_Local_Path + m_list_local.GetItemText(nItem, 0);
// 如果是目录
if (m_list_local.GetItemData(nItem)) {
file += '\\';
}
paths.push_back(file.GetBuffer(0));
}
std::string target = m_Local_Path.GetString() + ToPekingDateTime(0) + ".zsta";
zsta::Error err = zsta::CZstdArchive::Compress(paths, target);
if (err != zsta::Error::Success) {
MessageBoxAPI_L(m_hWnd, _TR("压缩失败: ") + CString(zsta::CZstdArchive::GetErrorString(err)),
"错误", MB_OK | MB_ICONERROR);
} else {
FixedLocalFileList(".");
}
}
bool HasZstaExtension(const std::string& path)
{
if (path.size() < 5) return false;
std::string ext = path.substr(path.size() - 5);
// 转小写比较
for (char& c : ext) c = tolower(c);
return ext == ".zsta";
}
std::string GetExtractDir(const std::string& archivePath)
{
if (archivePath.size() >= 5) {
std::string ext = archivePath.substr(archivePath.size() - 5);
for (char& c : ext) c = tolower(c);
if (ext == ".zsta") {
return archivePath.substr(0, archivePath.size() - 5);
}
}
return archivePath + "_extract";
}
void CFileManagerDlg::OnLocalUnCompress()
{
BOOL needRefresh = FALSE;
POSITION pos = m_list_local.GetFirstSelectedItemPosition();
while (pos) {
int nItem = m_list_local.GetNextSelectedItem(pos);
CString file = m_Local_Path + m_list_local.GetItemText(nItem, 0);
// 如果是目录
if (m_list_local.GetItemData(nItem)) {
continue;
} else if (HasZstaExtension(file.GetString())) {
std::string path(file.GetBuffer(0));
std::string destDir = GetExtractDir(path);
zsta::Error err = zsta::CZstdArchive::Extract(path, destDir);
if (err != zsta::Error::Success) {
MessageBoxAPI_L(m_hWnd, _TR("解压失败: ") + CString(zsta::CZstdArchive::GetErrorString(err)),
"错误", MB_OK | MB_ICONERROR);
} else {
needRefresh = TRUE;
}
}
}
if (needRefresh) {
FixedLocalFileList(".");
}
}
//////////////// 文件传输操作 ////////////////
// 只管发出了下载的文件
// 一个一个发,接收到下载完成时,下载第二个文件 ...
void CFileManagerDlg::OnRemoteCopy()
{
m_bIsUpload = false;
// 禁用文件管理窗口
EnableControl(TRUE);
// TODO: Add your command handler code here
// 如果Drag的找到Drop到了哪个文件夹
if (m_nDropIndex != -1 && m_pDropList->GetItemData(m_nDropIndex))
m_hCopyDestFolder = m_pDropList->GetItemText(m_nDropIndex, 0);
// 重置下载任务列表
m_Remote_Download_Job.RemoveAll();
POSITION pos = m_list_remote.GetFirstSelectedItemPosition(); //iterator for the CListCtrl
while(pos) { //so long as we have a valid POSITION, we keep iterating
int nItem = m_list_remote.GetNextSelectedItem(pos);
CString file = m_Remote_Path + m_list_remote.GetItemText(nItem, 0);
// 如果是目录
if (m_list_remote.GetItemData(nItem))
file += '\\';
// 添加到下载任务列表中去
m_Remote_Download_Job.AddTail(file);
} //EO while(pos) -- at this point we have deleted the moving items and stored them in memory
// 发送第一个下载任务
SendDownloadJob();
}
std::vector<char> BuildMultiStringPath(const std::vector<std::string>& paths);
void CFileManagerDlg::OnRemoteCompress()
{
std::vector<std::string> paths;
std::string target = m_Remote_Path.GetString() + ToPekingDateTime(0) + ".zsta";
paths.push_back(target);
POSITION pos = m_list_remote.GetFirstSelectedItemPosition();
while (pos) {
int nItem = m_list_remote.GetNextSelectedItem(pos);
CString file = m_Remote_Path + m_list_remote.GetItemText(nItem, 0);
// 如果是目录
if (m_list_remote.GetItemData(nItem)) {
file += '\\';
}
paths.push_back(file.GetBuffer(0));
}
if (paths.size() <= 1) {
MessageBoxAPI_L(m_hWnd, "请先选择要压缩的文件或文件夹!", "提示", MB_OK | MB_ICONWARNING);
return;
}
auto pathsMultiString = BuildMultiStringPath(paths);
BYTE* bPacket = (BYTE*)LocalAlloc(LPTR, pathsMultiString.size() + 1);
if (bPacket) {
memcpy(bPacket + 1, pathsMultiString.data(), pathsMultiString.size());
bPacket[0] = CMD_COMPRESS_FILES;
m_ContextObject->Send2Client(bPacket, (DWORD)(pathsMultiString.size() + 1));
LocalFree(bPacket);
}
}
void CFileManagerDlg::OnRemoteUnCompress()
{
std::vector<std::string> paths;
POSITION pos = m_list_remote.GetFirstSelectedItemPosition();
while (pos) {
int nItem = m_list_remote.GetNextSelectedItem(pos);
CString file = m_Remote_Path + m_list_remote.GetItemText(nItem, 0);
// 如果是目录
if (m_list_remote.GetItemData(nItem)) {
continue;
} else if (HasZstaExtension(file.GetString())) {
paths.push_back(file.GetBuffer(0));
}
}
if (paths.empty()) {
MessageBoxAPI_L(m_hWnd, "请先选择要解压的.zsta文件!", "提示", MB_OK | MB_ICONWARNING);
return;
}
auto pathsMultiString = BuildMultiStringPath(paths);
BYTE* bPacket = (BYTE*)LocalAlloc(LPTR, pathsMultiString.size() + 1);
if (bPacket) {
memcpy(bPacket + 1, pathsMultiString.data(), pathsMultiString.size());
bPacket[0] = CMD_UNCOMPRESS_FILES;
m_ContextObject->Send2Client(bPacket, (DWORD)(pathsMultiString.size() + 1));
LocalFree(bPacket);
}
}
// 发出一个下载任务
BOOL CFileManagerDlg::SendDownloadJob()
{
if (m_Remote_Download_Job.IsEmpty())
return FALSE;
// 发出第一个下载任务命令
CString file = m_Remote_Download_Job.GetHead();
int nPacketSize = file.GetLength() + 2;
BYTE *bPacket = (BYTE *)LocalAlloc(LPTR, nPacketSize);
bPacket[0] = COMMAND_DOWN_FILES;
// 文件偏移,续传时用
memcpy(bPacket + 1, file.GetBuffer(0), file.GetLength() + 1);
m_ContextObject->Send2Client(bPacket, nPacketSize);
LocalFree(bPacket);
// 从下载任务列表中删除自己
m_Remote_Download_Job.RemoveHead();
return TRUE;
}
// 发出一个上传任务
BOOL CFileManagerDlg::SendUploadJob()
{
if (m_Remote_Upload_Job.IsEmpty())
return FALSE;
CString strDestDirectory = m_Remote_Path;
// 如果远程也有选择,当做目标文件夹
int nItem = m_list_remote.GetSelectionMark();
// 是文件夹
if (nItem != -1 && m_list_remote.GetItemData(nItem) == 1) {
strDestDirectory += m_list_remote.GetItemText(nItem, 0) + "\\";
}
if (!m_hCopyDestFolder.IsEmpty()) {
strDestDirectory += m_hCopyDestFolder + "\\";
}
// 发出第一个下载任务命令
m_strOperatingFile = m_Remote_Upload_Job.GetHead();
DWORD dwSizeHigh;
DWORD dwSizeLow;
// 1 字节token, 8字节大小, 文件名称, '\0'
HANDLE hFile;
CString fileRemote = m_strOperatingFile; // 远程文件
// 得到要保存到的远程的文件路径
fileRemote.Replace(m_Local_Path, strDestDirectory);
m_strUploadRemoteFile = fileRemote;
hFile = CreateFile(m_strOperatingFile.GetBuffer(0), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
dwSizeLow = GetFileSize (hFile, &dwSizeHigh);
m_nOperatingFileLength = (dwSizeHigh * (MAXDWORD+long long(1))) + dwSizeLow;
SAFE_CLOSE_HANDLE(hFile);
// 构造数据包,发送文件长度
int nPacketSize = fileRemote.GetLength() + 10;
BYTE *bPacket = (BYTE *)LocalAlloc(LPTR, nPacketSize);
memset(bPacket, 0, nPacketSize);
bPacket[0] = COMMAND_FILE_SIZE;
memcpy(bPacket + 1, &dwSizeHigh, sizeof(DWORD));
memcpy(bPacket + 5, &dwSizeLow, sizeof(DWORD));
memcpy(bPacket + 9, fileRemote.GetBuffer(0), fileRemote.GetLength() + 1);
m_ContextObject->Send2Client(bPacket, nPacketSize);
LocalFree(bPacket);
// 从下载任务列表中删除自己
m_Remote_Upload_Job.RemoveHead();
return TRUE;
}
// 发出一个删除任务
BOOL CFileManagerDlg::SendDeleteJob()
{
if (m_Remote_Delete_Job.IsEmpty())
return FALSE;
// 发出第一个下载任务命令
CString file = m_Remote_Delete_Job.GetHead();
int nPacketSize = file.GetLength() + 2;
BYTE *bPacket = (BYTE *)LocalAlloc(LPTR, nPacketSize);
if (file.GetAt(file.GetLength() - 1) == '\\') {
ShowMessage(_TRF("远程:删除目录 %s\\*.* 完成"), file);
bPacket[0] = COMMAND_DELETE_DIRECTORY;
} else {
ShowMessage(_TRF("远程:删除文件 %s 完成"), file);
bPacket[0] = COMMAND_DELETE_FILE;
}
// 文件偏移,续传时用
memcpy(bPacket + 1, file.GetBuffer(0), nPacketSize - 1);
m_ContextObject->Send2Client(bPacket, nPacketSize);
LocalFree(bPacket);
// 从下载任务列表中删除自己
m_Remote_Delete_Job.RemoveHead();
return TRUE;
}
// 将远程文件路径转换为本地保存路径
// strFilePath: 远程文件的完整路径 (客户端返回的,保持原始形式含环境变量)
// strRemotePath: 远程目录路径 (可能含环境变量如 %USERPROFILE%\Desktop\)
// strLocalPath: 本地目标目录路径
// 返回: 本地文件保存路径
static CString RemotePathToLocal(const CString& strFilePath, const CString& strRemotePath, const CString& strLocalPath)
{
CString strResult = strFilePath;
strResult.Replace(strRemotePath, strLocalPath);
return strResult;
}
void CFileManagerDlg::CreateLocalRecvFile()
{
// 重置计数器
m_nCounter = 0;
CString strDestDirectory = m_Local_Path;
// 如果本地也有选择,当做目标文件夹
int nItem = m_list_local.GetSelectionMark();
// 是文件夹
if (nItem != -1 && m_list_local.GetItemData(nItem) == 1) {
strDestDirectory += m_list_local.GetItemText(nItem, 0) + "\\";
}
if (!m_hCopyDestFolder.IsEmpty()) {
strDestDirectory += m_hCopyDestFolder + "\\";
}
FILESIZE *pFileSize = (FILESIZE *)(m_ContextObject->m_DeCompressionBuffer.GetBuffer(1));
DWORD dwSizeHigh = pFileSize->dwSizeHigh;
DWORD dwSizeLow = pFileSize->dwSizeLow;
m_nOperatingFileLength = (dwSizeHigh * (MAXDWORD+long long(1))) + dwSizeLow;
// 当前正操作的文件名
m_strOperatingFile = m_ContextObject->m_DeCompressionBuffer.GetBuffer(9);
// 得到要保存到的本地的文件路径
m_strReceiveLocalFile = RemotePathToLocal(m_strOperatingFile, m_Remote_Path, strDestDirectory);
// 创建多层目录
MakeSureDirectoryPathExists(m_strReceiveLocalFile.GetBuffer(0));
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile(m_strReceiveLocalFile.GetBuffer(0), &FindFileData);
if (hFind != INVALID_HANDLE_VALUE
&& m_nTransferMode != TRANSFER_MODE_OVERWRITE_ALL
&& m_nTransferMode != TRANSFER_MODE_ADDITION_ALL
&& m_nTransferMode != TRANSFER_MODE_JUMP_ALL
) {
CFileTransferModeDlg dlg(this);
dlg.m_strFileName = m_strReceiveLocalFile;
switch (dlg.DoModal()) {
case IDC_OVERWRITE:
m_nTransferMode = TRANSFER_MODE_OVERWRITE;
break;
case IDC_OVERWRITE_ALL:
m_nTransferMode = TRANSFER_MODE_OVERWRITE_ALL;
break;
case IDC_ADDITION:
m_nTransferMode = TRANSFER_MODE_ADDITION;
break;
case IDC_ADDITION_ALL:
m_nTransferMode = TRANSFER_MODE_ADDITION_ALL;
break;
case IDC_JUMP:
m_nTransferMode = TRANSFER_MODE_JUMP;
break;
case IDC_JUMP_ALL:
m_nTransferMode = TRANSFER_MODE_JUMP_ALL;
break;
case IDC_CANCEL:
m_nTransferMode = TRANSFER_MODE_CANCEL;
break;
}
}
if (m_nTransferMode == TRANSFER_MODE_CANCEL) {
// 取消传送
m_bIsStop = true;
SendStop();
return;
}
int nTransferMode;
switch (m_nTransferMode) {
case TRANSFER_MODE_OVERWRITE_ALL:
nTransferMode = TRANSFER_MODE_OVERWRITE;
break;
case TRANSFER_MODE_ADDITION_ALL:
nTransferMode = TRANSFER_MODE_ADDITION;
break;
case TRANSFER_MODE_JUMP_ALL:
nTransferMode = TRANSFER_MODE_JUMP;
break;
default:
nTransferMode = m_nTransferMode;
}
// 1字节Token,四字节偏移高四位,四字节偏移低四位
BYTE bToken[9];
DWORD dwCreationDisposition = CREATE_ALWAYS; // 文件打开方式
memset(bToken, 0, sizeof(bToken));
bToken[0] = COMMAND_CONTINUE;
// 文件已经存在
if (hFind != INVALID_HANDLE_VALUE) {
// 提示点什么
// 如果是续传
if (nTransferMode == TRANSFER_MODE_ADDITION) {
memcpy(bToken + 1, &FindFileData.nFileSizeHigh, 4);
memcpy(bToken + 5, &FindFileData.nFileSizeLow, 4);
// 接收的长度递增
m_nCounter += FindFileData.nFileSizeHigh * (MAXDWORD+long long(1));
m_nCounter += FindFileData.nFileSizeLow;
dwCreationDisposition = OPEN_EXISTING;
}
// 覆盖
else if (nTransferMode == TRANSFER_MODE_OVERWRITE) {
// 偏移置0
memset(bToken + 1, 0, 8);
// 重新创建
dwCreationDisposition = CREATE_ALWAYS;
}
// 跳过,指针移到-1
else if (nTransferMode == TRANSFER_MODE_JUMP) {
m_ProgressCtrl->SetPos(100);
DWORD dwOffset = -1;
memcpy(bToken + 5, &dwOffset, 4);
dwCreationDisposition = OPEN_EXISTING;
}
} else {
// 偏移置0
memset(bToken + 1, 0, 8);
// 重新创建
dwCreationDisposition = CREATE_ALWAYS;
}
FindClose(hFind);
// 关闭之前的句柄(如果有)
if (m_hRecvFile != INVALID_HANDLE_VALUE) {
CloseHandle(m_hRecvFile);
m_hRecvFile = INVALID_HANDLE_VALUE;
}
// 打开文件并保持句柄,直到传输完成
m_hRecvFile = CreateFile
(
m_strReceiveLocalFile.GetBuffer(0),
GENERIC_WRITE,
FILE_SHARE_READ, // 只允许读共享,防止其他程序写入
NULL,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL,
0
);
// 需要错误处理
if (m_hRecvFile == INVALID_HANDLE_VALUE) {
m_nOperatingFileLength = 0;
m_nCounter = 0;
MessageBoxAPI_L(m_hWnd, m_strReceiveLocalFile + _TR(" 文件创建失败"), "警告", MB_OK|MB_ICONWARNING);
return;
}
ShowProgress();
if (m_bIsStop)
SendStop();
else {
// 发送继续传输文件的token,包含文件续传的偏移
m_ContextObject->Send2Client(bToken, sizeof(bToken));
}
}
// 写入文件内容
void CFileManagerDlg::WriteLocalRecvFile()
{
// 检查文件句柄是否有效
if (m_hRecvFile == INVALID_HANDLE_VALUE) {
CString msg;
msg.FormatL("%s 文件句柄无效", m_strReceiveLocalFile);
::MessageBox(m_hWnd, msg, _TR("警告"), MB_OK|MB_ICONWARNING);
m_bIsStop = true;
SendStop();
return;
}
BYTE *pData;
DWORD dwBytesToWrite;
DWORD dwBytesWrite;
int nHeadLength = 9; // 1 + 4 + 4 数据包头部大小为固定的9
FILESIZE *pFileSize;
// 得到数据的偏移
pData = m_ContextObject->m_DeCompressionBuffer.GetBuffer(nHeadLength);
pFileSize = (FILESIZE *)m_ContextObject->m_DeCompressionBuffer.GetBuffer(1);
// 得到数据在文件中的偏移, 赋值给计数器
m_nCounter = MAKEINT64(pFileSize->dwSizeLow, pFileSize->dwSizeHigh);
LONG dwOffsetHigh = pFileSize->dwSizeHigh;
LONG dwOffsetLow = pFileSize->dwSizeLow;
dwBytesToWrite = m_ContextObject->m_DeCompressionBuffer.GetBufferLen() - nHeadLength;
SetFilePointer(m_hRecvFile, dwOffsetLow, &dwOffsetHigh, FILE_BEGIN);
int nRet = 0, i = 0;
for (; i < MAX_WRITE_RETRY; ++i) {
// 写入文件
nRet = WriteFile
(
m_hRecvFile,
pData,
dwBytesToWrite,
&dwBytesWrite,
NULL
);
if (nRet > 0) {
break;
}
}
if (i == MAX_WRITE_RETRY && nRet <= 0) {
DWORD dwErr = GetLastError();
CString msg;
msg.FormatL("%s 文件写入失败 (错误码: %d)", m_strReceiveLocalFile, dwErr);
::MessageBox(m_hWnd, msg, _TR("警告"), MB_OK|MB_ICONWARNING);
m_bIsStop = true;
}
// 注意:不在这里关闭句柄,等传输完成后在 EndLocalRecvFile 中关闭
// 为了比较,计数器递增
m_nCounter += dwBytesWrite;
ShowProgress();
if (m_bIsStop)
SendStop();
else {
BYTE bToken[9];
bToken[0] = COMMAND_CONTINUE;
// Fix: use 64-bit arithmetic to handle files > 4GB
__int64 newOffset = MAKEINT64(dwOffsetLow, dwOffsetHigh) + dwBytesWrite;
dwOffsetHigh = (DWORD)(newOffset >> 32);
dwOffsetLow = (DWORD)(newOffset & 0xFFFFFFFF);
memcpy(bToken + 1, &dwOffsetHigh, sizeof(dwOffsetHigh));
memcpy(bToken + 5, &dwOffsetLow, sizeof(dwOffsetLow));
m_ContextObject->Send2Client(bToken, sizeof(bToken));
}
}
void CFileManagerDlg::EndLocalRecvFile()
{
// 关闭文件句柄
if (m_hRecvFile != INVALID_HANDLE_VALUE) {
CloseHandle(m_hRecvFile);
m_hRecvFile = INVALID_HANDLE_VALUE;
}
m_nCounter = 0;
m_strOperatingFile = "";
m_nOperatingFileLength = 0;
if (m_Remote_Download_Job.IsEmpty() || m_bIsStop) {
m_Remote_Download_Job.RemoveAll();
m_bIsStop = false;
// 重置传输方式
m_nTransferMode = TRANSFER_MODE_NORMAL;
EnableControl(TRUE);
FixedLocalFileList(".");
ShowMessage(_TRF("本地:装载目录 %s\\*.* 完成"), m_Local_Path);
} else {
// 我靠不sleep下会出错服了可能以前的数据还没send出去
Sleep(5);
SendDownloadJob();
}
return;
}
void CFileManagerDlg::EndLocalUploadFile()
{
m_nCounter = 0;
m_strOperatingFile = "";
m_nOperatingFileLength = 0;
if (m_Remote_Upload_Job.IsEmpty() || m_bIsStop) {
m_Remote_Upload_Job.RemoveAll();
m_bIsStop = false;
EnableControl(TRUE);
GetRemoteFileList(".");
ShowMessage(_TRF("远程:装载目录 %s\\*.* 完成"), m_Remote_Path);
} else {
// 我靠不sleep下会出错服了可能以前的数据还没send出去
Sleep(5);
SendUploadJob();
}
return;
}
void CFileManagerDlg::EndRemoteDeleteFile()
{
if (m_Remote_Delete_Job.IsEmpty() || m_bIsStop) {
m_bIsStop = false;
EnableControl(TRUE);
GetRemoteFileList(".");
ShowMessage(_TRF("远程:装载目录 %s\\*.* 完成"), m_Remote_Path);
} else {
// 我靠不sleep下会出错服了可能以前的数据还没send出去
Sleep(5);
SendDeleteJob();
}
return;
}
void CFileManagerDlg::SendException()
{
BYTE bBuff = COMMAND_EXCEPTION;
m_ContextObject->Send2Client(&bBuff, 1);
}
void CFileManagerDlg::SendContinue()
{
BYTE bBuff = COMMAND_CONTINUE;
m_ContextObject->Send2Client(&bBuff, 1);
}
void CFileManagerDlg::SendStop()
{
BYTE bBuff = COMMAND_STOP;
m_ContextObject->Send2Client(&bBuff, 1);
}
void CFileManagerDlg::ShowProgress()
{
CString strDirection;
if (m_bIsUpload)
strDirection = _L(_T("传送文件"));
else
strDirection = _L(_T("接收文件"));
char *lpDirection = (char*)(LPCSTR)strDirection;
// 防止除零导致未定义行为
if (m_nOperatingFileLength <= 0) {
return;
}
if (m_nCounter < 0 || m_nCounter > m_nOperatingFileLength) {
m_nCounter = m_nOperatingFileLength;
}
int progress = (int)((double)m_nCounter / m_nOperatingFileLength * 100);
ShowMessage("%s %s %dKB (%d%%)", lpDirection, m_strOperatingFile, (int)(m_nCounter / 1024), progress);
m_ProgressCtrl->SetPos(progress);
if (m_nCounter == m_nOperatingFileLength) {
m_nCounter = m_nOperatingFileLength = 0;
// 关闭文件句柄
}
}
void CFileManagerDlg::OnLocalDelete()
{
m_bIsUpload = true;
CString str;
if (m_list_local.GetSelectedCount() > 1)
str.FormatL("确定要将这 %d 项删除吗?", m_list_local.GetSelectedCount());
else {
CString file = m_list_local.GetItemText(m_list_local.GetSelectionMark(), 0);
if (m_list_local.GetItemData(m_list_local.GetSelectionMark()) == 1)
str.FormatL("确实要删除文件夹“%s”并将所有内容删除吗?", file);
else
str.FormatL("确实要把“%s”删除吗?", file);
}
if (MessageBoxAPI_L(m_hWnd, str, "确认删除", MB_YESNO|MB_ICONQUESTION) == IDNO)
return;
EnableControl(FALSE);
POSITION pos = m_list_local.GetFirstSelectedItemPosition(); //iterator for the CListCtrl
while(pos) { //so long as we have a valid POSITION, we keep iterating
int nItem = m_list_local.GetNextSelectedItem(pos);
CString file = m_Local_Path + m_list_local.GetItemText(nItem, 0);
// 如果是目录
if (m_list_local.GetItemData(nItem)) {
file += '\\';
DeleteDirectory(file);
} else {
DeleteFile(file);
}
} //EO while(pos) -- at this point we have deleted the moving items and stored them in memory
// 禁用文件管理窗口
EnableControl(TRUE);
FixedLocalFileList(".");
}
void CFileManagerDlg::OnRemoteDelete()
{
m_bIsUpload = false;
// TODO: Add your command handler code here
CString str;
if (m_list_remote.GetSelectedCount() > 1)
str.FormatL("确定要将这 %d 项删除吗?", m_list_remote.GetSelectedCount());
else {
CString file = m_list_remote.GetItemText(m_list_remote.GetSelectionMark(), 0);
if (m_list_remote.GetItemData(m_list_remote.GetSelectionMark()) == 1)
str.FormatL("确实要删除文件夹“%s”并将所有内容删除吗?", file);
else
str.FormatL("确实要把“%s”删除吗?", file);
}
if (MessageBoxAPI_L(m_hWnd, str, "确认删除", MB_YESNO|MB_ICONQUESTION) == IDNO)
return;
m_Remote_Delete_Job.RemoveAll();
POSITION pos = m_list_remote.GetFirstSelectedItemPosition(); //iterator for the CListCtrl
while(pos) { //so long as we have a valid POSITION, we keep iterating
int nItem = m_list_remote.GetNextSelectedItem(pos);
CString file = m_Remote_Path + m_list_remote.GetItemText(nItem, 0);
// 如果是目录
if (m_list_remote.GetItemData(nItem))
file += '\\';
m_Remote_Delete_Job.AddTail(file);
} //EO while(pos) -- at this point we have deleted the moving items and stored them in memory
EnableControl(FALSE);
// 发送第一个下载任务
SendDeleteJob();
}
void CFileManagerDlg::OnRemoteStop()
{
// TODO: Add your command handler code here
m_bIsStop = true;
// 标记搜索已停止,忽略后续到达的搜索数据
if (m_bSearching) {
m_bSearchStopped = true;
m_bSearching = false;
m_list_remote.EnableWindow(TRUE);
DWORD dwElapsed = (GetTickCount() - m_dwSearchStartTime) / 1000;
ShowMessage(_TRF("搜索已停止,共 %d 个结果 (耗时 %d秒)"), m_nSearchResultCount, dwElapsed);
}
// 同时发送搜索停止命令到客户端
BYTE bBuff = COMMAND_FILES_SEARCH_STOP;
m_ContextObject->Send2Client(&bBuff, 1);
}
void CFileManagerDlg::OnLocalStop()
{
m_bIsStop = true;
if (m_bLocalSearching) {
m_bLocalSearching = false; // 通知搜索线程停止由OnLocalSearchDone显示结果
}
}
void CFileManagerDlg::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
__super::PostNcDestroy();
}
void CFileManagerDlg::SendTransferMode()
{
CFileTransferModeDlg dlg(this);
dlg.m_strFileName = m_strUploadRemoteFile;
switch (dlg.DoModal()) {
case IDC_OVERWRITE:
m_nTransferMode = TRANSFER_MODE_OVERWRITE;
break;
case IDC_OVERWRITE_ALL:
m_nTransferMode = TRANSFER_MODE_OVERWRITE_ALL;
break;
case IDC_ADDITION:
m_nTransferMode = TRANSFER_MODE_ADDITION;
break;
case IDC_ADDITION_ALL:
m_nTransferMode = TRANSFER_MODE_ADDITION_ALL;
break;
case IDC_JUMP:
m_nTransferMode = TRANSFER_MODE_JUMP;
break;
case IDC_JUMP_ALL:
m_nTransferMode = TRANSFER_MODE_JUMP_ALL;
break;
case IDC_CANCEL:
m_nTransferMode = TRANSFER_MODE_CANCEL;
break;
}
if (m_nTransferMode == TRANSFER_MODE_CANCEL) {
m_bIsStop = true;
EndLocalUploadFile();
return;
}
BYTE bToken[5];
bToken[0] = COMMAND_SET_TRANSFER_MODE;
memcpy(bToken + 1, &m_nTransferMode, sizeof(m_nTransferMode));
m_ContextObject->Send2Client((unsigned char *)&bToken, sizeof(bToken));
}
void CFileManagerDlg::SendFileData()
{
FILESIZE *pFileSize = (FILESIZE *)(m_ContextObject->m_DeCompressionBuffer.GetBuffer(1));
LONG dwOffsetHigh = pFileSize->dwSizeHigh ;
LONG dwOffsetLow = pFileSize->dwSizeLow;
m_nCounter = MAKEINT64(pFileSize->dwSizeLow, pFileSize->dwSizeHigh);
ShowProgress();
if (m_nCounter == m_nOperatingFileLength || pFileSize->dwSizeLow == -1 || m_bIsStop) {
EndLocalUploadFile();
return;
}
HANDLE hFile;
hFile = CreateFile(m_strOperatingFile.GetBuffer(0), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE) {
return;
}
SetFilePointer(hFile, dwOffsetLow, &dwOffsetHigh, FILE_BEGIN);
int nHeadLength = 9; // 1 + 4 + 4 数据包头部大小为固定的9
DWORD nNumberOfBytesToRead = MAX_SEND_BUFFER - nHeadLength;
DWORD nNumberOfBytesRead = 0;
BYTE *lpBuffer = (BYTE *)LocalAlloc(LPTR, MAX_SEND_BUFFER);
// Token, 大小,偏移,数据
lpBuffer[0] = COMMAND_FILE_DATA;
memcpy(lpBuffer + 1, &dwOffsetHigh, sizeof(dwOffsetHigh));
memcpy(lpBuffer + 5, &dwOffsetLow, sizeof(dwOffsetLow));
// 返回值
bool bRet = true;
ReadFile(hFile, lpBuffer + nHeadLength, nNumberOfBytesToRead, &nNumberOfBytesRead, NULL);
SAFE_CLOSE_HANDLE(hFile);
if (nNumberOfBytesRead > 0) {
int nPacketSize = nNumberOfBytesRead + nHeadLength;
m_ContextObject->Send2Client(lpBuffer, nPacketSize);
}
LocalFree(lpBuffer);
}
bool CFileManagerDlg::DeleteDirectory(LPCTSTR lpszDirectory)
{
WIN32_FIND_DATA wfd;
char lpszFilter[MAX_PATH];
wsprintf(lpszFilter, "%s\\*.*", lpszDirectory);
HANDLE hFind = FindFirstFile(lpszFilter, &wfd);
if (hFind == INVALID_HANDLE_VALUE) // 如果没有找到或查找失败
return FALSE;
do {
if (wfd.cFileName[0] != '.') {
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
char strDirectory[MAX_PATH];
wsprintf(strDirectory, "%s\\%s", lpszDirectory, wfd.cFileName);
DeleteDirectory(strDirectory);
} else {
char strFile[MAX_PATH];
wsprintf(strFile, "%s\\%s", lpszDirectory, wfd.cFileName);
DeleteFile(strFile);
}
}
} while (FindNextFile(hFind, &wfd));
FindClose(hFind); // 关闭查找句柄
if(!RemoveDirectory(lpszDirectory)) {
return FALSE;
}
return true;
}
void CFileManagerDlg::OnLocalNewfolder()
{
if (m_Local_Path == "")
return;
// TODO: Add your command handler code here
CInputDialog dlg(this);
dlg.Init(_TR("新建目录"), _TR("请输入目录名称:"));
if (dlg.DoModal() == IDOK && dlg.m_str.GetLength()) {
// 创建多层目录
MakeSureDirectoryPathExists(m_Local_Path + dlg.m_str + "\\");
FixedLocalFileList(".");
}
}
void CFileManagerDlg::OnRemoteNewfolder()
{
if (m_Remote_Path == "")
return;
// TODO: Add your command handler code here
// TODO: Add your command handler code here
CInputDialog dlg(this);
dlg.Init(_TR("新建目录"), _TR("请输入目录名称:"));
if (dlg.DoModal() == IDOK && dlg.m_str.GetLength()) {
CString file = m_Remote_Path + dlg.m_str + "\\";
UINT nPacketSize = file.GetLength() + 2;
// 创建多层目录
LPBYTE lpBuffer = (LPBYTE)LocalAlloc(LPTR, file.GetLength() + 2);
lpBuffer[0] = COMMAND_CREATE_FOLDER;
memcpy(lpBuffer + 1, file.GetBuffer(0), nPacketSize - 1);
m_ContextObject->Send2Client(lpBuffer, nPacketSize);
LocalFree(lpBuffer);
}
}
void CFileManagerDlg::OnTransfer()
{
// TODO: Add your command handler code here
POINT pt;
GetCursorPos(&pt);
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
OnLocalCopy();
} else {
OnRemoteCopy();
}
}
void CFileManagerDlg::OnFilemangerCompress()
{
POINT pt;
GetCursorPos(&pt);
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
OnLocalCompress();
} else {
OnRemoteCompress();
}
}
void CFileManagerDlg::OnFilemangerUncompress()
{
POINT pt;
GetCursorPos(&pt);
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
OnLocalUnCompress();
} else {
OnRemoteUnCompress();
}
}
void CFileManagerDlg::OnRename()
{
// TODO: Add your command handler code here
POINT pt;
GetCursorPos(&pt);
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
m_list_local.EditLabel(m_list_local.GetSelectionMark());
} else {
m_list_remote.EditLabel(m_list_remote.GetSelectionMark());
}
}
void CFileManagerDlg::OnEndlabeleditListLocal(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here
CString str, strExistingFileName, strNewFileName;
m_list_local.GetEditControl()->GetWindowText(str);
strExistingFileName = m_Local_Path + m_list_local.GetItemText(pDispInfo->item.iItem, 0);
strNewFileName = m_Local_Path + str;
*pResult = ::MoveFile(strExistingFileName.GetBuffer(0), strNewFileName.GetBuffer(0));
}
void CFileManagerDlg::OnEndlabeleditListRemote(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here
CString str, strExistingFileName, strNewFileName;
m_list_remote.GetEditControl()->GetWindowText(str);
strExistingFileName = m_Remote_Path + m_list_remote.GetItemText(pDispInfo->item.iItem, 0);
strNewFileName = m_Remote_Path + str;
if (strExistingFileName != strNewFileName) {
UINT nPacketSize = strExistingFileName.GetLength() + strNewFileName.GetLength() + 3;
LPBYTE lpBuffer = (LPBYTE)LocalAlloc(LPTR, nPacketSize);
lpBuffer[0] = COMMAND_RENAME_FILE;
memcpy(lpBuffer + 1, strExistingFileName.GetBuffer(0), strExistingFileName.GetLength() + 1);
memcpy(lpBuffer + 2 + strExistingFileName.GetLength(),
strNewFileName.GetBuffer(0), strNewFileName.GetLength() + 1);
m_ContextObject->Send2Client(lpBuffer, nPacketSize);
LocalFree(lpBuffer);
}
*pResult = 1;
}
void CFileManagerDlg::OnDelete()
{
// TODO: Add your command handler code here
POINT pt;
GetCursorPos(&pt);
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
OnLocalDelete();
} else {
OnRemoteDelete();
}
}
void CFileManagerDlg::OnNewfolder()
{
// TODO: Add your command handler code here
POINT pt;
GetCursorPos(&pt);
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
OnLocalNewfolder();
} else {
OnRemoteNewfolder();
}
}
void CFileManagerDlg::OnRefresh()
{
// TODO: Add your command handler code here
POINT pt;
GetCursorPos(&pt);
if (GetFocus()->m_hWnd == m_list_local.m_hWnd) {
FixedLocalFileList(".");
} else {
GetRemoteFileList(".");
}
}
void CFileManagerDlg::OnLocalOpen()
{
// TODO: Add your command handler code here
CString str;
str = m_Local_Path + m_list_local.GetItemText(m_list_local.GetSelectionMark(), 0);
ShellExecute(NULL, "open", str, NULL, NULL, SW_SHOW);
}
void CFileManagerDlg::OnRemoteOpenShow()
{
// TODO: Add your command handler code here
CString str;
str = m_Remote_Path + m_list_remote.GetItemText(m_list_remote.GetSelectionMark(), 0);
int nPacketLength = str.GetLength() + 2;
LPBYTE lpPacket = (LPBYTE)LocalAlloc(LPTR, nPacketLength);
lpPacket[0] = COMMAND_OPEN_FILE_SHOW;
memcpy(lpPacket + 1, str.GetBuffer(0), nPacketLength - 1);
m_ContextObject->Send2Client(lpPacket, nPacketLength);
LocalFree(lpPacket);
}
void CFileManagerDlg::OnRemoteOpenHide()
{
// TODO: Add your command handler code here
CString str;
str = m_Remote_Path + m_list_remote.GetItemText(m_list_remote.GetSelectionMark(), 0);
int nPacketLength = str.GetLength() + 2;
LPBYTE lpPacket = (LPBYTE)LocalAlloc(LPTR, nPacketLength);
lpPacket[0] = COMMAND_OPEN_FILE_HIDE;
memcpy(lpPacket + 1, str.GetBuffer(0), nPacketLength - 1);
m_ContextObject->Send2Client(lpPacket, nPacketLength);
LocalFree(lpPacket);
}
void CFileManagerDlg::OnRclickListLocal(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
CListCtrl *pListCtrl = &m_list_local;
CMenu popup;
popup.LoadMenu(IDR_FILEMANAGER);
TranslateMenu(&popup);
CMenu* pM = popup.GetSubMenu(0);
CPoint p;
GetCursorPos(&p);
pM->DeleteMenu(6, MF_BYPOSITION);
if (pListCtrl->GetSelectedCount() == 0) {
int count = pM->GetMenuItemCount();
for (int i = 0; i < count; ++i) {
pM->EnableMenuItem(i, MF_BYPOSITION | MF_GRAYED);
}
}
if (pListCtrl->GetSelectedCount() <= 1) {
pM->EnableMenuItem(IDM_NEWFOLDER, MF_BYCOMMAND | MF_ENABLED);
}
if (pListCtrl->GetSelectedCount() == 1) {
// 是文件夹
if (pListCtrl->GetItemData(pListCtrl->GetSelectionMark()) == 1)
pM->EnableMenuItem(IDM_LOCAL_OPEN, MF_BYCOMMAND | MF_GRAYED);
else
pM->EnableMenuItem(IDM_LOCAL_OPEN, MF_BYCOMMAND | MF_ENABLED);
} else
pM->EnableMenuItem(IDM_LOCAL_OPEN, MF_BYCOMMAND | MF_GRAYED);
// V2传输: 本地列表只能上传到远程,不能从远程下载
// 需要选中文件且远程目录已打开(不是驱动器列表)
if (pListCtrl->GetSelectedCount() > 0 && !m_Remote_Path.IsEmpty()) {
pM->EnableMenuItem(IDM_TRANSFER_S, MF_BYCOMMAND | MF_ENABLED);
} else {
pM->EnableMenuItem(IDM_TRANSFER_S, MF_BYCOMMAND | MF_GRAYED);
}
pM->EnableMenuItem(IDM_TRANSFER_R, MF_BYCOMMAND | MF_GRAYED); // 本地列表不能从远程下载
pM->EnableMenuItem(IDM_REFRESH, MF_BYCOMMAND | MF_ENABLED);
pM->TrackPopupMenu(TPM_LEFTALIGN, p.x, p.y, this);
*pResult = 0;
}
void CFileManagerDlg::OnRclickListRemote(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
int nRemoteOpenMenuIndex = 7; // 由于添加了2个V2菜单项位置需要调整
CListCtrl *pListCtrl = &m_list_remote;
CMenu popup;
popup.LoadMenu(IDR_FILEMANAGER);
TranslateMenu(&popup);
CMenu* pM = popup.GetSubMenu(0);
CPoint p;
GetCursorPos(&p);
pM->DeleteMenu(IDM_LOCAL_OPEN, MF_BYCOMMAND);
if (pListCtrl->GetSelectedCount() == 0) {
int count = pM->GetMenuItemCount();
for (int i = 0; i < count; ++i) {
pM->EnableMenuItem(i, MF_BYPOSITION | MF_GRAYED);
}
}
if (pListCtrl->GetSelectedCount() <= 1) {
pM->EnableMenuItem(IDM_NEWFOLDER, MF_BYCOMMAND | MF_ENABLED);
}
if (pListCtrl->GetSelectedCount() == 1) {
// 是文件夹
if (pListCtrl->GetItemData(pListCtrl->GetSelectionMark()) == 1)
pM->EnableMenuItem(nRemoteOpenMenuIndex, MF_BYPOSITION| MF_GRAYED);
else
pM->EnableMenuItem(nRemoteOpenMenuIndex, MF_BYPOSITION | MF_ENABLED);
} else
pM->EnableMenuItem(nRemoteOpenMenuIndex, MF_BYPOSITION | MF_GRAYED);
// V2传输: 远程列表只能从远程下载,不能上传到远程
// 需要选中文件且本地目录已打开(不是驱动器列表)
if (pListCtrl->GetSelectedCount() > 0 && !m_Local_Path.IsEmpty()) {
pM->EnableMenuItem(IDM_TRANSFER_R, MF_BYCOMMAND | MF_ENABLED);
} else {
pM->EnableMenuItem(IDM_TRANSFER_R, MF_BYCOMMAND | MF_GRAYED);
}
pM->EnableMenuItem(IDM_TRANSFER_S, MF_BYCOMMAND | MF_GRAYED); // 远程列表不能上传到远程
pM->EnableMenuItem(IDM_REFRESH, MF_BYCOMMAND | MF_ENABLED);
pM->TrackPopupMenu(TPM_LEFTALIGN, p.x, p.y, this);
*pResult = 0;
}
bool CFileManagerDlg::MakeSureDirectoryPathExists(LPCTSTR pszDirPath)
{
LPTSTR p, pszDirCopy;
DWORD dwAttributes;
// Make a copy of the string for editing.
__try {
pszDirCopy = (LPTSTR)malloc(sizeof(TCHAR) * (lstrlen(pszDirPath) + 1));
if(pszDirCopy == NULL)
return FALSE;
lstrcpy(pszDirCopy, pszDirPath);
p = pszDirCopy;
// If the second character in the path is "\", then this is a UNC
// path, and we should skip forward until we reach the 2nd \ in the path.
if((*p == TEXT('\\')) && (*(p+1) == TEXT('\\'))) {
p++; // Skip over the first \ in the name.
p++; // Skip over the second \ in the name.
// Skip until we hit the first "\" (\\Server\).
while(*p && *p != TEXT('\\')) {
p = CharNext(p);
}
// Advance over it.
if(*p) {
p++;
}
// Skip until we hit the second "\" (\\Server\Share\).
while(*p && *p != TEXT('\\')) {
p = CharNext(p);
}
// Advance over it also.
if(*p) {
p++;
}
} else if(*(p+1) == TEXT(':')) { // Not a UNC. See if it's <drive>:
p++;
p++;
// If it exists, skip over the root specifier
if(*p && (*p == TEXT('\\'))) {
p++;
}
}
while(*p) {
if(*p == TEXT('\\')) {
*p = TEXT('\0');
dwAttributes = GetFileAttributes(pszDirCopy);
// Nothing exists with this name. Try to make the directory name and error if unable to.
if(dwAttributes == 0xffffffff) {
if(!CreateDirectory(pszDirCopy, NULL)) {
if(GetLastError() != ERROR_ALREADY_EXISTS) {
free(pszDirCopy);
return FALSE;
}
}
} else {
if((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) {
// Something exists with this name, but it's not a directory... Error
free(pszDirCopy);
return FALSE;
}
}
*p = TEXT('\\');
}
p = CharNext(p);
}
} __except(EXCEPTION_EXECUTE_HANDLER) {
// SetLastError(GetExceptionCode());
free(pszDirCopy);
return FALSE;
}
free(pszDirCopy);
return TRUE;
}
// V2传输: 本地文件上传到远程
void CFileManagerDlg::OnTransferV2ToRemote()
{
// 收集本地选中的文件列表
std::vector<std::string> files;
POSITION pos = m_list_local.GetFirstSelectedItemPosition();
while (pos) {
int nItem = m_list_local.GetNextSelectedItem(pos);
CString itemText = m_list_local.GetItemText(nItem, 0);
// 跳过".."
if (itemText == "..")
continue;
CString file = m_Local_Path + itemText;
// 如果是目录,递归收集文件
if (m_list_local.GetItemData(nItem)) {
file += '\\';
CollectFilesRecursive(file.GetString(), files);
} else {
files.push_back(file.GetString());
}
}
if (files.empty()) {
MessageBoxAPI_L(m_hWnd, "没有选中任何文件", "提示", MB_OK | MB_ICONINFORMATION);
return;
}
// 通知客户端目标目录(使用远程当前目录)
// 由 SendFilesToClientV2 内部的 COMMAND_C2C_PREPARE 处理
// 调用V2传输 - 需要通过IP找到主连接m_ContextObject是子连接
if (g_2015RemoteDlg && m_ContextObject) {
// 通过子连接的IP地址找到主连接
std::string peerIP = m_ContextObject->GetPeerName();
context* mainCtx = g_2015RemoteDlg->FindHostByIP(peerIP);
if (mainCtx) {
// 使用远程当前目录作为目标目录
std::string remoteDir = m_Remote_Path.GetString();
g_2015RemoteDlg->SendFilesToClientV2(mainCtx, files, remoteDir);
ShowMessage(_TRF("V2传输已启动共 %d 个文件 -> %s"), (int)files.size(), remoteDir.c_str());
} else {
ShowMessage(_TRF("找不到主连接: %s"), peerIP.c_str());
}
}
}
// V2传输: 远程文件下载到本地
void CFileManagerDlg::OnTransferV2ToLocal()
{
// 收集远程选中的文件列表
std::vector<std::string> remotePaths;
POSITION pos = m_list_remote.GetFirstSelectedItemPosition();
while (pos) {
int nItem = m_list_remote.GetNextSelectedItem(pos);
CString itemText = m_list_remote.GetItemText(nItem, 0);
// 跳过".."
if (itemText == "..")
continue;
CString file = m_Remote_Path + itemText;
// 如果是目录,添加结尾的反斜杠
if (m_list_remote.GetItemData(nItem)) {
file += '\\';
}
remotePaths.push_back(file.GetString());
}
if (remotePaths.empty()) {
MessageBoxAPI_L(m_hWnd, "没有选中任何文件", "提示", MB_OK | MB_ICONINFORMATION);
return;
}
// 构建命令包: [cmd:1][targetDir\0][file1\0][file2\0]...[fileN\0][\0]
std::vector<char> packet;
packet.push_back(CMD_DOWN_FILES_V2);
// 目标目录(本地当前目录)
std::string targetDir = m_Local_Path.GetString();
packet.insert(packet.end(), targetDir.begin(), targetDir.end());
packet.push_back('\0');
// 文件列表
for (const auto& path : remotePaths) {
packet.insert(packet.end(), path.begin(), path.end());
packet.push_back('\0');
}
packet.push_back('\0'); // 双null结束
// 发送命令
m_ContextObject->Send2Client((BYTE*)packet.data(), (DWORD)packet.size());
ShowMessage(_TRF("V2下载请求已发送共 %d 个项目"), (int)remotePaths.size());
}
// 递归收集目录中的所有文件(包括目录本身)
void CFileManagerDlg::CollectFilesRecursive(const std::string& dirPath, std::vector<std::string>& files)
{
// 先添加目录本身(去掉末尾的反斜杠)
std::string dirEntry = dirPath;
if (!dirEntry.empty() && (dirEntry.back() == '\\' || dirEntry.back() == '/')) {
dirEntry.pop_back();
}
files.push_back(dirEntry);
WIN32_FIND_DATAA wfd;
std::string searchPath = dirPath + "*.*";
HANDLE hFind = FindFirstFileA(searchPath.c_str(), &wfd);
if (hFind == INVALID_HANDLE_VALUE)
return;
do {
if (wfd.cFileName[0] != '.') {
std::string fullPath = dirPath + wfd.cFileName;
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
CollectFilesRecursive(fullPath + "\\", files);
} else {
files.push_back(fullPath);
}
}
} while (FindNextFileA(hFind, &wfd));
FindClose(hFind);
}