我现在做了一个类似飞鸽传书的程序,实现两台电脑上可以互相传送文件,聊天的功能,现在我想在传文件的过程中加入进度条用来显示传输的进度和接收的进度,请问如何来实现呢???注: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;可以吗?
各位帮帮小弟,解决了马上给分。

解决方案 »

  1.   

    pTransferDlg->m_mySendProg.SetPos(SEND_BUFFER_SIZE*i);
    试一下
      

  2.   

    该段代码你自己参考一下~~`
    //发送文件线程
    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;
    }
      

  3.   

    具体你可以参考网上的程序MyQQ~~
      

  4.   

    谢谢楼上两位to:  snowbirdfly(专心搞好嵌入式~~~) 
       pDlg->m_Progress.SetRange32(0,myFileInfo.fileLength);
       pDlg->m_Progress.SetPos(temp);
    我参考了这两句,问题还是在传的过程中显示不出进度条来,是不是我在静态成员函里用 CTransferDlg *pTransferDlg = new CTransferDlg不可以啊?
      

  5.   

    奇怪了
    你在CTransferDlg *pTransferDlg = new CTransferDlg;之后没有用DoModal();,那个对话框能显示出来吗?还是你这个对话框一早就有的阿。
      

  6.   

    问题还是在传的过程中显示不出进度条来?
    CTransferDlg本身就是在该类里面,写自身的成员函数没有必要在new了~~
    直接用this就可以了~~
      

  7.   

    我觉得楼主是想
    CTransferDlg *pTransferDlg = (CTransferDlg*) lpParameter;
    这样吧
      

  8.   

    谢谢大家的帮助,刚刚吃饭去了,我的static  DWORD WINAPI SendFileProc(LPVOID lpParameter);
    static  DWORD WINAPI RecvFileProc(LPVOID lpParameter);是CTransferDlg类的静态线程函数,用this指针不可以吧?
      

  9.   

    各位,我在CTransferDlg *pTransferDlg = new CTransferDlg;后边添加pTransferDlg->Create(IDD_TRANSFER_DIALOG);现在传文件时是可以出现进度条,但会出现两个一样的对话框,而且是在第二个对话框里出现进度条的,这个对话矿是我刚刚在SendFileProc创建的,我要怎么改使它在原来的对话矿出现呢?
      

  10.   

    SendFileProc既然是CTransferDlg的线程函数,那应该是这样调用吧
    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);   ..........................  } }
      

  11.   

    首先设置进度条的长度 为你要发送文件的大小。
    SetRange32(0,fiellength);
     每次发送一定字节后就在进度条上显示
    SetPos(SendLength);
      

  12.   

    static DWORD WINAPI RecvFileProc(LPVOID lpParameter);是CTransferDlg类的静态线程函数
    请问如何得到对话框的指针呢?
    如果能得到对话矿的指针,问题也就可以解决了。
    谢谢各位!
      

  13.   

    我在上面不是告诉你了吗
    AfxBeginThread (SendFileProc,this);
     CTransferDlg *pTransferDlg = (CTransferDlg*) lpParameter;  /////得到对话框指针
    真是郁闷阿
      

  14.   

    关键是我的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.
      

  15.   

    你是用什么创建新线程的,把代码贴出来看一下吧。
    如果是用AfxBeginThread,你的静态函数要改成这样static UINT RecvFileProc(LPVOID lpParameter);如果你的程序是这样:当用户单击对话框的某个按钮,就开始传送文件,那就吧AfxBeginThread (SendFileProc,this)放在你单击按钮的事件中吧,它就会创建一个新的线程的了,希望你明白吧。
      

  16.   

    void CTransferDlg::OnBtnSendFile() 
    {
    // 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;
    }
      

  17.   


    非常感谢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);
       ..........................  } }   
    想通过获得对话框的举柄,在转化为获得对话矿的指针,为什么实现不了啊?
      

  18.   

    不用这么复杂吧
    你就是想将一个参数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);   ..........................  }
      

  19.   

    非常感谢lshddd()
    现在可以了。