我现在做了一个类似飞鸽传书的程序,实现两台电脑上可以互相传送文件,聊天的功能,现在我想在传文件的过程中加入进度条用来显示传输的进度和接收的进度,请问如何来实现呢???注:1. static DWORD WINAPI SendFileProc(LPVOID lpParameter);是CTransferDlg类的静态成员函数,用来发送文件;
2.static DWORD WINAPI RecvFileProc(LPVOID lpParameter);是CTransferDlg类的静态成员函数,用来接收文件;我在对话框里加了一个进度条控件,用m_mySendProg关联变量,
加入以下的代码:(发送端)
DWORD WINAPI CTransferDlg::SendFileProc(LPVOID lpParameter)
{
...................
CTransferDlg *pTransferDlg = new CTransferDlg;
pTransferDlg->m_mySendProg.SetRange32(0,myFile.GetLength());
pTransferDlg->m_mySendProg.SetPos(0);
int i =0;
while(..)//传送文件过程
{
i++;
...............
pTransferDlg->m_mySendProg.SetStep(SEND_BUFFER_SIZE*i);
.......................... } }
为什么这样不行啊,请问在静态成员函里用 CTransferDlg *pTransferDlg = new CTransferDlg;可以吗?
各位帮帮小弟,解决了马上给分。
2.static DWORD WINAPI RecvFileProc(LPVOID lpParameter);是CTransferDlg类的静态成员函数,用来接收文件;我在对话框里加了一个进度条控件,用m_mySendProg关联变量,
加入以下的代码:(发送端)
DWORD WINAPI CTransferDlg::SendFileProc(LPVOID lpParameter)
{
...................
CTransferDlg *pTransferDlg = new CTransferDlg;
pTransferDlg->m_mySendProg.SetRange32(0,myFile.GetLength());
pTransferDlg->m_mySendProg.SetPos(0);
int i =0;
while(..)//传送文件过程
{
i++;
...............
pTransferDlg->m_mySendProg.SetStep(SEND_BUFFER_SIZE*i);
.......................... } }
为什么这样不行啊,请问在静态成员函里用 CTransferDlg *pTransferDlg = new CTransferDlg;可以吗?
各位帮帮小弟,解决了马上给分。
试一下
//发送文件线程
UINT _SendFileThread(LPVOID lparam)
{
CMyQQDlg *pDlg=(CMyQQDlg *)lparam;
if(pDlg->StopServer==true) return -1;
CSocket sockClient;
sockClient.Create();
CString ip;
pDlg->m_You_IP.GetWindowText(ip);
sockClient.Connect(ip, PORT+pDlg->m_client);
//首先发送标记F为文件,2
int end=0;
end=sockClient.Send("F",FLAG);
///////////////////////////////////////////////////////////////////发送标志是否成功
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendFileThread Send错误!"+pDlg->GetError(GetLastError()));
return -1;
}
else if(end!=2)
{
AfxMessageBox("文件头错误");
return -1;
}
///////////////////////////////////////////////////////////////////
CFile myFile;
FILEINFO myFileInfo;
if(!myFile.Open(pDlg->m_fileName, CFile::modeRead | CFile::typeBinary))
return -1;
myFileInfo.fileLength=myFile.GetLength(); //得到文件大小
strcpy(myFileInfo.fileName,myFile.GetFileName());//得到文件名称
sockClient.Send(&myFileInfo,sizeof(myFileInfo)); //发送文件信息
pDlg->m_Progress.SetRange32(0,myFileInfo.fileLength);
myFile.Seek(0,CFile::begin);
char m_buf[SIZEFILE]={0};
CString strError;
int num=0;
end=0;
int temp=0;
pDlg->GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(true);
for(;;)
{
if(pDlg->FileWork==false)
{
pDlg->FileWork=true;
pDlg->GetDlgItem(IDCANCEL)->EnableWindow(false);
pDlg->GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false);
}
num=myFile.Read(m_buf, SIZEFILE);
if(num==0) break;
end=sockClient.Send(m_buf, num);
temp+=end;
pDlg->m_Progress.SetPos(temp);
if(pDlg->FileStop==true)
{
pDlg->FileStop=false;
pDlg->FileWork=false;
break;
}
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendFileThread Send错误!"+pDlg->GetError(GetLastError()));
break;
}
}
pDlg->m_Progress.SetPos(0);
CString strLocalName;
pDlg->GetLocalHostName(strLocalName);
CString strLocalIP;
pDlg->GetIpAddress(strLocalName,strLocalIP);
if(temp==myFileInfo.fileLength)
pDlg->AddMsgList(strLocalIP+"->"+strLocalName,"文件发送成功");
else
pDlg->AddMsgList(strLocalIP+"->"+strLocalName,"文件发送失败");
myFile.Close();
sockClient.Close();
pDlg->FileWork=false;
pDlg->GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
pDlg->GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(false); pDlg->GetDlgItem(IDCANCEL)->EnableWindow(true);
pDlg->GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
return 0;
}
//保存文件~~~
int CMyQQDlg::SaveYouFile(CSocket &recSo, SOCKADDR_IN &client)//接受文件
{
CString fname;
CFileDialog dlg(false); //另存文件
FILEINFO myFileInfo;
recSo.Receive(&myFileInfo,sizeof(FILEINFO));
int fileLength=myFileInfo.fileLength;
CString strfileIp,strfileName,strfileLength;
strfileIp.Format(inet_ntoa(client.sin_addr));
strfileName.Format(myFileInfo.fileName);
strfileLength.Format("%f",myFileInfo.fileLength/1024.0);
CString title="文件"+strfileName+" 大小"+strfileLength+"KB "+"来在"+strfileIp+" 是否接受";
dlg.m_ofn.lpstrTitle=title;//标题条
char fileme[500]={0};//必须足够大小
strcpy(fileme,strfileIp+strfileName);
dlg.m_ofn.lpstrFile=fileme; //文件名称
if(dlg.DoModal()==IDOK)
{
fname=dlg.GetPathName(); //得到文件名名称、路径
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_SHOW);
}
else
{
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(false);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
GetDlgItem(IDCANCEL)->EnableWindow(true);
recSo.Close();
return 0;
}
char buf[SIZEFILE]={0};
CFile f(fname,CFile::modeCreate|CFile::modeWrite); //存文件
m_Progress.SetRange32(0,fileLength);
int n=0; //接受的字节数 0表示结束
int temp=0;
GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(true);
GetDlgItem(IDCANCEL)->EnableWindow(false);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false);
for(;;)
{
n=recSo.Receive(buf,SIZEFILE); //接受
if(n==0) //0表示结束
break; //接受完毕
f.Write(buf,n);
temp+=n;
m_Progress.SetPos(temp);
if(FileWork==false) FileWork=true;
if(FileStop==true)
{
FileStop=false;
FileWork=false;
break ;
}
}
f.Close();
m_Progress.SetPos(0);
if(temp==fileLength)
AddMsgList(inet_ntoa(client.sin_addr),"文件接受成功");
else
AddMsgList(inet_ntoa(client.sin_addr),"文件接受失败");
FileWork=false;
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(false);
GetDlgItem(IDCANCEL)->EnableWindow(true);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
return 0;
}
pDlg->m_Progress.SetRange32(0,myFileInfo.fileLength);
pDlg->m_Progress.SetPos(temp);
我参考了这两句,问题还是在传的过程中显示不出进度条来,是不是我在静态成员函里用 CTransferDlg *pTransferDlg = new CTransferDlg不可以啊?
你在CTransferDlg *pTransferDlg = new CTransferDlg;之后没有用DoModal();,那个对话框能显示出来吗?还是你这个对话框一早就有的阿。
CTransferDlg本身就是在该类里面,写自身的成员函数没有必要在new了~~
直接用this就可以了~~
CTransferDlg *pTransferDlg = (CTransferDlg*) lpParameter;
这样吧
static DWORD WINAPI RecvFileProc(LPVOID lpParameter);是CTransferDlg类的静态线程函数,用this指针不可以吧?
AfxBeginThread (SendFileProc,this);这样在线程函数函数中要修给CTransferDlg中的控件,应该这样写DWORD WINAPI CTransferDlg::SendFileProc(LPVOID lpParameter)
{
...................
CTransferDlg *pTransferDlg = (CTransferDlg*) lpParameter; /////得到对话框指针 pTransferDlg->m_mySendProg.SetRange(0,myFile.GetLength());
pTransferDlg->m_mySendProg.SetPos(0);
int i =0;
while(..)//传送文件过程
{
i++;
...............
pTransferDlg->m_mySendProg.SetPos(SEND_BUFFER_SIZE*i); .......................... } }
SetRange32(0,fiellength);
每次发送一定字节后就在进度条上显示
SetPos(SendLength);
请问如何得到对话框的指针呢?
如果能得到对话矿的指针,问题也就可以解决了。
谢谢各位!
AfxBeginThread (SendFileProc,this);
CTransferDlg *pTransferDlg = (CTransferDlg*) lpParameter; /////得到对话框指针
真是郁闷阿
这个是试用期的任务,还望各位多帮忙。
AfxBeginThread (SendFileProc,this);应该放哪里啊?
还有有这样的一个错误:
D:\Program Files\Microsoft Visual Studio\MyProjects\9.12\Transfer\TransferDlg.cpp(491) : error C2665: 'AfxBeginThread' : none of the 2 overloads can convert parameter 1 from type 'unsigned long (void *)'
Error executing cl.exe.
如果是用AfxBeginThread,你的静态函数要改成这样static UINT RecvFileProc(LPVOID lpParameter);如果你的程序是这样:当用户单击对话框的某个按钮,就开始传送文件,那就吧AfxBeginThread (SendFileProc,this)放在你单击按钮的事件中吧,它就会创建一个新的线程的了,希望你明白吧。
{
// TODO: Add your control notification handler code here CString string;
POSITION pos = m_listCtrl.GetFirstSelectedItemPosition();
if (pos)
{
int nItem = m_listCtrl.GetNextSelectedItem(pos);
string = m_listCtrl.GetItemText(nItem,3);
}
DWORD dwIP;
dwIP = inet_addr(string);
if(bOpenFile)
{
SENDPARAM *pSendFileParam = new SENDPARAM ;
pSendFileParam->m_dwIP = dwIP;
/ HANDLE hSendFileThread = CreateThread(NULL, 0, SendFileProc, (LPVOID)pSendFileParam,
0, NULL);
// AfxBeginThread (SendFileProc,this);
CloseHandle(hSendFileThread);
}
}
#define SEND_BUFFER_SIZE 1024
DWORD WINAPI CTransferDlg::SendFileProc(LPVOID lpParameter)
{ DWORD dwIP = ((SENDPARAM*)lpParameter)->m_dwIP;
HWND hwnd = ((SENDPARAM*)lpParameter)->hwnd;
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(7000);
addrSrv.sin_addr.S_un.S_addr = dwIP;
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
if(SOCKET_ERROR == connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))
{
AfxMessageBox("Connect fail!");
return 0;
}
CString fileName;
fileName = myFile.GetFileName();
send(sockClient, fileName, fileName.GetLength(), 0);
char Recvstr[2];
memset(Recvstr, 0, 2);
recv(sockClient,Recvstr,2,0);
if(CString(Recvstr) == "N")
return 0;
CString strLength;
UINT fileLength;
fileLength = myFile.GetLength();
strLength.Format("%d", fileLength);
send(sockClient, strLength, strLength.GetLength(), 0);
// now send the file's data
Sleep(1000);
char sendData[SEND_BUFFER_SIZE];
memset(sendData, 0, SEND_BUFFER_SIZE);
UINT LeftToSend = myFile.GetLength();
do
{
ZeroMemory(sendData,SEND_BUFFER_SIZE);//Çå¿Õ»º³åÆ÷
int sendThisTime, doneSoFar, buffOffset;
sendThisTime = myFile.Read(sendData, SEND_BUFFER_SIZE);
buffOffset = 0;
do
{
doneSoFar = send(sockClient, sendData + buffOffset, sendThisTime,0);
buffOffset += doneSoFar;
sendThisTime -= doneSoFar;
LeftToSend -= doneSoFar;
}
while ( sendThisTime > 0 );
}
while(LeftToSend >0); Sleep(1000); myFile.Close();
closesocket(sockClient);
AfxMessageBox("Send Success!");
return 1;
}
非常感谢lshddd() ( )我现在改为这样了:
struct SENDPARAM
{
DWORD m_dwIP;
HWND hwnd;
};void CTransferDlg::OnBtnSendFile()
{ ..........................
SENDPARAM *pSendFileParam = new SENDPARAM ;
pSendFileParam->m_dwIP = dwIP;
pSendFileParam->hwnd = m_hWnd;(加了这一句)
HANDLE hSendFileThread = CreateThread(NULL, 0, SendFileProc, (LPVOID)pSendFileParam,
0, NULL);
//AfxBeginThread (SendFileProc,this);
CloseHandle(hSendFileThread);
..............................
}DWORD WINAPI CTransferDlg::SendFileProc(LPVOID lpParameter)
{
................
HWND hwnd = ((SENDPARAM*)lpParameter)->hwnd;
................ CTransferDlg *pTransferDlg =(CTransferDlg *)FromHandle(hwnd);
pTransferDlg->m_SendFilePrgo.SetRange32(0,fileLength);
pTransferDlg->m_SendFilePrgo.SetPos(0);
............
int i =0;
while(..)//传送文件过程
{
i++;
...............
pTransferDlg->m_mySendProg.SetStep(SEND_BUFFER_SIZE*i);
.......................... } }
想通过获得对话框的举柄,在转化为获得对话矿的指针,为什么实现不了啊?
你就是想将一个参数DWORD m_dwIP和一个对话框指针dlg传给线程函数而已吧。那可以这样做啊,将DWORD m_dwIP设为对话框类的一个成员变量,然后你传递参数的时候就直接写成 CreateThread(NULL, 0, SendFileProc, this,0, NULL);而在线程函数中要访问m_dwIP就可以这样写
CTransferDlg *pTransferDlg = (CTransferDlg*) lpParameter; /////首先得到对话框指针DWORD dwIP = pTransferDlg->m_dwIP; ////////////////然后访问对话框类中的变量
////////////////其他操作 pTransferDlg->m_mySendProg.SetRange(0,myFile.GetLength());
pTransferDlg->m_mySendProg.SetPos(0);
int i =0;
while(..)//传送文件过程
{
i++;
...............
pTransferDlg->m_mySendProg.SetPos(SEND_BUFFER_SIZE*i); .......................... }
现在可以了。