📄 filetranscltview.cpp
字号:
// FileTransCltView.cpp : implementation of the CFileTransCltView class
//
#include "stdafx.h"
#include "FileTransClt.h"
#include "FileTransCltDoc.h"
#include "FileTransCltView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView
typedef struct{ //pakcet for socket
char packetType; //r:request rootdriver,d:directory f:file D:data
unsigned int length;
char content[2000];
}DATA_PACKET;
char* pDrives;
CString arrFiles[200];
CString savePath;
long fSize=0l,recvFSize=0l;
CString strIP;
bool thrFlag=false;
CCriticalSection critSection;
IMPLEMENT_DYNCREATE(CFileTransCltView, CFormView)
BEGIN_MESSAGE_MAP(CFileTransCltView, CFormView)
//{{AFX_MSG_MAP(CFileTransCltView)
ON_BN_CLICKED(IDC_CONNECT, OnConnect)
ON_NOTIFY(NM_DBLCLK, IDC_FILEBROWSE, OnDblclkFilebrowse)
ON_NOTIFY(TVN_SELCHANGED, IDC_FILEBROWSE, OnSelchangedFilebrowse)
ON_NOTIFY(NM_RCLICK, IDC_FILEBROWSE, OnRclickFilebrowse)
ON_COMMAND(IDC_SETPARAM, OnSetparam)
ON_COMMAND(ID_DOWNLOAD, OnDownload)
ON_COMMAND(ID_SAVEAS, OnSaveas)
ON_WM_TIMER()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView construction/destruction
CFileTransCltView::CFileTransCltView()
: CFormView(CFileTransCltView::IDD)
{
//{{AFX_DATA_INIT(CFileTransCltView)
m_fullPath = _T("");
//}}AFX_DATA_INIT
// TODO: add construction code here
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
WSACleanup( );
return;
}
}
CFileTransCltView::~CFileTransCltView()
{
//delete[] pDrives; //It will occur an assert failed!
}
void CFileTransCltView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFileTransCltView)
DDX_Control(pDX, IDC_FILEBROWSE, m_FileTreeBrowse);
DDX_Control(pDX, IDC_IPADDRESS, m_IPAddress);
DDX_Text(pDX, IDC_FULLPATH, m_fullPath);
DDX_Control(pDX, IDC_PROGCTRL, m_progCtrl);
//}}AFX_DATA_MAP
}
BOOL CFileTransCltView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CFormView::PreCreateWindow(cs);
}
void CFileTransCltView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
m_IPAddress.SetWindowText("127.0.0.1");
hCurrent=m_FileTreeBrowse.InsertItem("我的电脑",0,0,TVI_ROOT);
}
/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView printing
BOOL CFileTransCltView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CFileTransCltView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CFileTransCltView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
void CFileTransCltView::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/)
{
// TODO: add customized printing code here
}
/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView diagnostics
#ifdef _DEBUG
void CFileTransCltView::AssertValid() const
{
CFormView::AssertValid();
}
void CFileTransCltView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
CFileTransCltDoc* CFileTransCltView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFileTransCltDoc)));
return (CFileTransCltDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CFileTransCltView message handlers
void CFileTransCltView::OnConnect()
{
// TODO: Add your control notification handler code here
DWORD dwAddress;
m_IPAddress.GetAddress(dwAddress);
strIP.Format("%d.%d.%d.%d",
HIBYTE(HIWORD(dwAddress)),
LOBYTE(HIWORD(dwAddress)),
HIBYTE(LOWORD(dwAddress)),
LOBYTE(LOWORD(dwAddress))
);
DWORD dwThread;
DATA_PACKET requestPacket;
requestPacket.packetType='r';
::CreateThread(NULL,0,ThreadRequest,(LPVOID)&requestPacket,0,&dwThread);
m_fullPath="Connect succedd,and the root diretory is ready.";
UpdateData(false);
}
DWORD WINAPI CFileTransCltView::ThreadRequest(LPVOID lpParameter)
{
DATA_PACKET requestPacket=*(DATA_PACKET*)lpParameter;
SOCKET socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
sockaddr_in sin;
sin.sin_addr.S_un.S_addr=inet_addr(strIP);
sin.sin_family=AF_INET;
sin.sin_port=htons(1032);
if(::connect(socket,(sockaddr*)&sin,sizeof(sin))!=0)
{
AfxMessageBox("Request failure!");
return 0;
}
int thrInfo;
if( requestPacket.packetType=='D' ) //save download thead infomation
{
thrInfo=requestPacket.length;
thrFlag=true;
}
::send( socket,(char*)&requestPacket,sizeof(requestPacket),0 );
memset( requestPacket.content,0,sizeof(requestPacket.content) );
if( ::recv(socket,(char*)&requestPacket,sizeof(requestPacket),0) )
{
if( requestPacket.packetType=='r' )
{
int szBuffer=requestPacket.length;
pDrives=new char[2000]; //Make sure that allocate memery!
memcpy(pDrives,requestPacket.content,szBuffer); //Make sure that use memcpy()
}
if(requestPacket.packetType=='d' )
{
pDrives=new char[2000];
Memcpy( pDrives,requestPacket.content,sizeof(requestPacket.content) ); /* 2000 will take an error ?????*/
//char's pointer to CString Array
int i=0,j=0;
//Sleep(50);
//critSection.Lock();
while( i<requestPacket.length )
{
for(int k=0; pDrives[i]!='|' && i<requestPacket.length ; k++,i++ )
arrFiles[j].Insert(k,pDrives[i]);
i++;
j++;
}
//critSection.Unlock();
return 0;
}
if( requestPacket.packetType=='f' )
fSize=requestPacket.length;
//Write file
if( requestPacket.packetType=='D' )
{
//memset( pDrives,0,2000 );
Memcpy( pDrives,requestPacket.content,sizeof(requestPacket.content) );
FillInFile( socket,thrInfo,requestPacket.length,pDrives);
}
}
::closesocket(socket);
//pDrives=requestPacket.content; error
return 0;
}
void CFileTransCltView::OnDblclkFilebrowse(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
m_fullPath.Delete(0,8);
//Fill Tree Root with Logical drives
if( m_fullPath==""&&pDrives!=NULL )
{
while( *pDrives )
{
m_FileTreeBrowse.InsertItem( pDrives,hCurrent,TVI_LAST );
pDrives += strlen( pDrives ) + 1;
}
}
//request sub directory or files' name
if(m_fullPath!=""&&m_fullPath.Find('.')==-1)
{
m_fullPath.Delete(0,1); //strlen("我的电脑\") equal to 9 BYTE
//m_fullPath+='\0';
//MessageBox(m_fullPath);
DATA_PACKET dataPacket;
dataPacket.packetType='d';
dataPacket.length=m_fullPath.GetLength();
memcpy( dataPacket.content,m_fullPath,strlen(m_fullPath) );
::CreateThread(NULL,0,ThreadRequest,(LPVOID)&dataPacket,0,0);
while(arrFiles[0]=="")
Sleep(30);
CFileTransCltView::FillTree();
}
//DownLoad file which was clicked doubly
if(m_fullPath.Find('.')!=-1)
{
m_fullPath.Delete(0,1);
m_fullPath.Delete(2,1);
CFileTransCltView::DownloadFile(m_fullPath);
}
}
void CFileTransCltView::OnSelchangedFilebrowse(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
hCurrent=pNMTreeView->itemNew.hItem;
m_fullPath = m_FileTreeBrowse.GetFullPath( hCurrent );
UpdateData(false);
*pResult = 0;
}
void CFileTransCltView::FillTree()
{
int i=0;
while(i<200&&arrFiles[i]!="")
{
m_FileTreeBrowse.InsertItem( arrFiles[i],hCurrent,TVI_LAST );
i++;
}
//Clear the globle parameter of arrFile[i]
//memcpy( arrFiles,0,sizeof(arrFiles) ); //disable
for(int j=0;j<i;j++)
arrFiles[j]="";
}
void CFileTransCltView::OnRclickFilebrowse(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
/* First of all, It should judge the current path,if it's a drive or a directory,disable
the popup menu.Or else,it's a file path,enable the popup menu.
The problem here is that popup menu can set the item in tree focus,but not change the
item selected.In other words, the focus has been changed,but the selected item and
current path haven't been changed. Who know this, contact me please. Email:
tidge1982@yahoo.com.cn Thanks! */
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
hCurrent=pNMTreeView->itemNew.hItem;
m_FileTreeBrowse.SetItemState( hCurrent,TVIS_SELECTED,TVIS_SELECTED );
if(m_fullPath.Find('.')!=-1)
{
CPoint point;
GetCursorPos(&point);
if (point.x == -1 && point.y == -1)
{
//keystroke invocation
CRect rect;
GetClientRect(rect);
ClientToScreen(rect);
point = rect.TopLeft();
point.Offset(5, 5);
}
CMenu menu;
VERIFY(menu.LoadMenu(CG_IDR_POPUP_EXTN_TREE_CTRL));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
CWnd* pWndPopupOwner = this;
while (pWndPopupOwner->GetStyle() & WS_CHILD)
pWndPopupOwner = pWndPopupOwner->GetParent();
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
pWndPopupOwner);
}
*pResult = 0;
}
void CFileTransCltView::OnSetparam()
{
// TODO: Add your command handler code here
CSetParam setParam;
setParam.DoModal();
}
void CFileTransCltView::DownloadFile(CString fPath)
{
//Requet file size
DATA_PACKET dataPacket;
dataPacket.packetType='f';
dataPacket.length=strlen(m_fullPath);
memset( dataPacket.content,0,sizeof(dataPacket.content) );
memcpy( dataPacket.content,m_fullPath,strlen(m_fullPath) );
::CreateThread(NULL,0,ThreadRequest,(LPVOID)&dataPacket,0,0); // thread for request file size
while(fSize==0)
Sleep(30);
//download
CString subPath = m_FileTreeBrowse.GetSubPath(fPath);
CString tempPath = setParam.GetDefSavePath();
tempPath += '\\'+ subPath;
savePath.Format( "%s",tempPath ); // 'savePath' is a global parameter
dataPacket.packetType='D';
memcpy( dataPacket.content,fPath,strlen(fPath) ); // fPath is file path in server
int i = setParam.GetDefThrTotal(); // Download threads in total
for(int j=1;j<=i;j++)
{
dataPacket.length=j*100+i; // download thread index
::CreateThread(NULL,0,ThreadRequest,(LPVOID)&dataPacket,0,0);
while( !thrFlag ) // make sure the thread has been created.This is very important!!!
Sleep(50);
thrFlag = false;
}
m_progCtrl.SetRange( 0,100 );
m_progCtrl.SetPos( 0 );
SetTimer( 1,20,NULL ); // Calculate and display the progress in OnTimer();
// use sleep() will block the UI and no efficency!
}
void CFileTransCltView::FillInFile(SOCKET socket,int thrInfo,int packIndex,char* pPackCont)
{
int thrIndex = thrInfo/100;
int thrTotal = thrInfo-thrIndex*100;
int thrLength = fSize/thrTotal;
int bPoint = (thrIndex-1)*thrLength;
if( thrIndex == thrTotal )
thrLength = fSize-bPoint;
FILE *file;
if( (file = fopen( savePath, "ab" )) == NULL )
AfxMessageBox( "Open file occur an error\n" );
//fseek(file,bPoint,SEEK_SET);
int packTotal = thrLength/2000 +1;
int subTotal = packTotal;
DATA_PACKET dPacket;
while( subTotal>0 )
{
critSection.Lock(5000);
fseek( file,bPoint+(packIndex-1)*2000,SEEK_SET );
if( packIndex == packTotal ) //the last packet in thread,data maybe less than 2000B
{
int fLength = thrLength-(packTotal-1)*2000;
int errorcode=fwrite( pPackCont,1,fLength,file );
fflush(file);
recvFSize+=fLength;
}
else
{
fwrite( pPackCont,sizeof(char),2000,file );
fflush(file);
recvFSize+=2000;
}
critSection.Unlock();
subTotal--;
if( subTotal>0 )
{
if( recv( socket,(char*)&dPacket,sizeof(dPacket),0 ) != 0 )
{
packIndex = dPacket.length;
Memcpy( pPackCont,dPacket.content,sizeof(dPacket.content) );
}
}
else
{
if( recvFSize == fSize )
fclose(file);
return;
}
}
}
void CFileTransCltView::Memcpy(char *dest, char *sour, unsigned int num)
{
// Just for test.
// Actually,There is no need
for(int i=0;i<num;i++ )
dest[i]=sour[i];
}
void CFileTransCltView::OnDownload()
{
// TODO: Add your command handler code here
AfxMessageBox("disable!");
}
void CFileTransCltView::OnSaveas()
{
// TODO: Add your command handler code here
AfxMessageBox("disable!");
}
void CFileTransCltView::OnTimer(UINT nIDEvent)
{
// TODO: Calculate and display the download progress ;
if( fSize > recvFSize )
{
float progress = (float)recvFSize/(float)fSize*100 ;
m_fullPath.Format("Current progress %f",progress);
UpdateData(false);
m_progCtrl.SetPos( (int)progress );
}
else
{
recvFSize = 0; // clear for next time
m_progCtrl.SetPos( 100 ); // during the time, Maybe file has received all,but progress bar no time to do it.
m_fullPath.Format( "All are receive! The file has been save in %s.",savePath );
UpdateData(false);
KillTimer( 1 );
}
CFormView::OnTimer(nIDEvent);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -