CreateFile时正确得到了hCom句柄,但在WriteFile时却是句柄无效,写不进去,问题I出在那里啊?源程序如下,帮忙看一下,谢谢 HANDLE hCom;
DWORD dwError;
DCB dcb;
COMMTIMEOUTS TimeOuts;
hCom=CreateFile("COM3",           //文件名
GENERIC_READ | GENERIC_WRITE, // 允许读和写 
0,                            // 独占方式
NULL, 
OPEN_EXISTING,                 //打开而不是创建
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // 重叠方式
NULL
);

if(hCom == INVALID_HANDLE_VALUE)
{
dwError=GetLastError( );// 处理错误
}
SetupComm( hCom, 1024, 1024);//缓冲区的大小为1024

TimeOuts. ReadIntervalTimeout=1000; 
TimeOuts.ReadTotalTimeoutMultiplier=500; 
TimeOuts.ReadTotalTimeoutConstant=5000; 
TimeOuts.WriteTotalTimeoutMultiplier=500; 
TimeOuts.WriteTotalTimeoutConstant=5000;

SetCommTimeouts(hCom, &TimeOuts); // 设置超时

GetCommState(hCom, &dcb);
dcb.BaudRate=2400; // 波特率为2400
dcb.ByteSize=8; // 每个字符有8位
dcb.Parity=NOPARITY; //无校验
dcb.StopBits=ONESTOPBIT; //一个停止位
SetCommState(hCom, &dcb);

char buf[20]="ATDT823\r";
int i=strlen(buf);
DWORD dwBytesWritten;
OVERLAPPED write_os; BOOL bRtn=WriteFile(hCom,buf,i,&dwBytesWritten,&write_os);
if(!bRtn)
{
dwError=GetLastError();
}

解决方案 »

  1.   

    你定义的DCB结构可以直接用,不要加&
      

  2.   

    DCB dcb;
            COMMTIMEOUTS CommTimeOuts;
            BOOL fSuccess;
            hCom = CreateFile(FormMain->ComboBox1->Text.c_str(),
                    GENERIC_READ | GENERIC_WRITE,
                    0,    //必须
                    NULL, //无安全属性
                    OPEN_EXISTING, //必须用OPEN_EXISTING
                    FILE_FLAG_OVERLAPPED,  //重叠I/O操作
                    NULL  //对通信设备必须是NULL
                    );
            if (hCom == INVALID_HANDLE_VALUE) {
                    MessageBox(NULL,"打开通信设备文件失败!","错        误",MB_OK);
            return false;
            }        if(!SetupComm(hCom,BLOCK_LENGTH,BLOCK_LENGTH))
            {
                    MessageBox(NULL,"设置串行口内部输入、输出缓冲区长度操作异常!","错误",MB_OK);
            return false;
            }        fSuccess = GetCommState(hCom, &dcb);
            if (!fSuccess) {
                    MessageBox(NULL,"获取通信设备控制块数据结构操作异常!","错误",MB_OK);
            return false;
            }
            //填充要改变的串行口控制(配置)块数据结构的有关成员
            dcb.DCBlength=sizeof(DCB);
            //dcb.BaudRate=9600;
            dcb.Parity=1;
            dcb.ByteSize=8;
            dcb.StopBits=2;
            BuildCommDCB("9600,N,8,1",&dcb);
        
            dcb.fInX =  true;
            dcb.fOutX =  true;
            dcb.XonLim =  1;
            dcb.XoffLim =  1;        //回写DCB数据块
            fSuccess = SetCommState(hCom, &dcb);
            if (!fSuccess) {
                    MessageBox(NULL,"设置通信设备控制块数据结构操作异常!","错误",MB_OK);
            return false;
            }
            //清除接收缓冲区
            PurgeComm(hCom,PURGE_RXCLEAR);
            GetCommTimeouts(hCom, &CommTimeOuts);
                CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
            CommTimeOuts.WriteTotalTimeoutConstant = 5000;         SetCommTimeouts(hCom, &CommTimeOuts);
                memset(&osRead, 0, sizeof(OVERLAPPED));
                    memset(&osWrite, 0, sizeof(OVERLAPPED));
                    osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
                osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);        BufferOffset=0;
            return true;还要对重叠操作的数据结构初始化,建立信号态。
      

  3.   

    如果你用的是2000的话,设一下write_os.offset和write_os.offsethigh都为零
      

  4.   

    osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);还有将osWrite.offset和osWrite.offsehigh设为零。
      

  5.   

    估计是你的OVERLAPPED的成员变量hEvent没有初始化吧
    write_os.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    然后看看行不行
      

  6.   

    // 打开串行口并建立辅助工作线程
    BOOL CNcfileCtrlDlg::OpenConnection()
    {
    COMMTIMEOUTS TimeOuts;
    m_hTermWnd = GetSafeHwnd();
    if(m_bConnected)
    return FALSE;
    m_hCom = CreateFile(m_sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
                          NULL); // 重叠方式
    if(m_hCom == INVALID_HANDLE_VALUE)
    return FALSE;
    SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);
    // SetCommMask(m_hCom, EV_RXCHAR);/////////////////////////////////////////////////////////////////////
    //测试代码
    // DWORD lpEvtMask;
    // GetCommMask(m_hCom,&lpEvtMask);
    // if(lpEvtMask & EV_RXCHAR == EV_RXCHAR)
    // AfxMessageBox("EV_RXCHAR!");
    // SetCommMask(m_hCom,0);
    // GetCommMask(m_hCom,&lpEvtMask);
    // if(lpEvtMask & EV_RXCHAR == EV_RXCHAR)
    // AfxMessageBox("EV_RXCHAR!");
    // else
    // AfxMessageBox("NO EV_RXCHAR!");
    //////////////////////////////////////////////////////////////////// // 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作
    TimeOuts.ReadIntervalTimeout = MAXDWORD; 
        TimeOuts.ReadTotalTimeoutMultiplier = 0; 
    TimeOuts.ReadTotalTimeoutConstant = 0; 
    /* 设置写超时以指定WriteComm成员函数中的
        GetOverlappedResult函数的等待时间*/
    TimeOuts.WriteTotalTimeoutMultiplier = 50; 
    TimeOuts.WriteTotalTimeoutConstant = 2000;
    SetCommTimeouts(m_hCom, &TimeOuts);
    if(ConfigConnection())
    {
    m_pThread = AfxBeginThread(CommProc, this, THREAD_PRIORITY_NORMAL, 
    0, CREATE_SUSPENDED, NULL); // 创建并挂起接收线程
    if(m_pThread == NULL)
    {
    MessageBox("创建接收数据线程失败!","警告", MB_ICONWARNING | MB_OK);
    CloseHandle(m_hCom);
    return FALSE;
    } ReceiveThread = TRUE;
    m_bConnected = TRUE;
    }
    else
    {
    CloseHandle(m_hCom);
    return FALSE;
    }
    return TRUE;
    }// 结束工作者线程,关闭串行口
    void CNcfileCtrlDlg::CloseConnection()
    {
    // 结束事件监视线程
    if(!m_bConnected) return;
    m_bConnected = FALSE; // 结束CommProc线程中WaitSingleObject函数的等待
    SetEvent(m_hPostMsgEvent);  // 结束CommProc线程中WaitCommEvent的等待
    SetCommMask(m_hCom, 0);  if(ReceiveThread)//判断接收线程是否退出
    {
    if(!TerminateThread(m_pThread->m_hThread,0))
    MessageBox("终止接收数据线程失败!","警告", MB_ICONWARNING | MB_OK);
    }
    if(BeginThread)      //判断发送线程是否退出
    {
    if(!TerminateThread(m_pThreadT->m_hThread,0))
    MessageBox("终止发送数据线程失败!","警告", MB_ICONWARNING | MB_OK);
    } if(EventThread)      //判断事件监视线程是否退出
    {
    if(!TerminateThread(m_pThreadEvent->m_hThread,0))
    MessageBox("终止事件监视线程失败!","警告", MB_ICONWARNING | MB_OK);
    } CloseHandle(m_hCom);
    }
    // 从串行口输入缓冲区(m_hCom通信设备)中读入指定数量的字符
    DWORD CNcfileCtrlDlg::ReadComm(char *buf, DWORD dwLength)
    {
    DWORD length = 0;
    COMSTAT ComStat; // 串口设备状态结构
    DWORD dwErrorFlags;
    ClearCommError(m_hCom,&dwErrorFlags,&ComStat); // 读取串口设备的当前状态
    length = min(dwLength, ComStat.cbInQue); // 应该读取的数据长度
    ReadFile(m_hCom,buf,length,&length,&m_osRead); // 读取数据
    return length;
    }// 将指定数量的字符从串行口输出,在调用该函数时,实际dwLength都为1
    DWORD CNcfileCtrlDlg::WriteComm(char* buf, DWORD dwLength)
    {
    BOOL fState;
    DWORD length = dwLength;  //成功写入缓冲区的字符数
    COMSTAT ComStat;
    DWORD dwErrorFlags;
    ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
    fState = WriteFile(m_hCom,buf,dwLength,&length,&m_osWrite);
    if(!fState){
    if(GetLastError() == ERROR_IO_PENDING)   //写操作被挂起
    {
    if(!GetOverlappedResult(m_hCom,&m_osWrite,&length,TRUE)) //写操作没有成功完成
    {
    MessageBox("发送代码出现错误!","错误", MB_ICONERROR | MB_OK);
    }
    }
    else
    length = 0;
    } return length;
    }
    // 配置串行口
    BOOL CNcfileCtrlDlg::ConfigConnection()
    {
    DCB dcb;
    if(!GetCommState(m_hCom, &dcb)) // 获取缺省的dcb结构的值
    return FALSE; dcb.fOutX = 0;
    dcb.fInX = 0;
    dcb.fOutxCtsFlow = 0;
    dcb.fOutxDsrFlow = 0;
    dcb.fBinary = TRUE;
    dcb.BaudRate = m_nBaud; // 波特率
    dcb.ByteSize = m_nDataBits; // 每字节位数
    dcb.fParity = TRUE;
    switch(m_nParity) // 校验设置
    {
    case 0: dcb.Parity = NOPARITY;
    break;
    case 1: dcb.Parity = ODDPARITY;
    break;
    case 2: dcb.Parity = EVENPARITY;
    break;
    case 3: dcb.Parity = MARKPARITY;
    break;
            case 4: dcb.Parity = SPACEPARITY;
    break;
    default:;
    }
    switch(m_nStopBits) // 停止位
    {
    case 0: dcb.StopBits = ONESTOPBIT;
    break;
    // case 1: dcb.StopBits = ONE5STOPBITS;
    // break;
    case 1: dcb.StopBits = TWOSTOPBITS;
    break;
    default:;
    }
    // 硬件流控制设置

        if (m_bRts)
    dcb.fRtsControl = RTS_CONTROL_HANDSHAKE ;
    else
    dcb.fRtsControl = RTS_CONTROL_ENABLE ;
    // XON/XOFF流控制设置,软件流控制
    if (m_bXon)
    {
    dcb.fInX = dcb.fOutX = 1;
    dcb.XonChar = XON;
    dcb.XoffChar = XOFF;
    dcb.XonLim = 50;
    dcb.XoffLim = 50;
    }
        //硬件流控制设置
    if (m_bDsr)
    dcb.fDtrControl = DTR_CONTROL_HANDSHAKE ;
    else
    dcb.fDtrControl = DTR_CONTROL_ENABLE ; //输出流信号监控
    if(m_bOutxCtsFlow)
    dcb.fOutxCtsFlow = 1;
    if(m_bOutxDsrFlow)
    dcb.fOutxDsrFlow = 1; return SetCommState(m_hCom, &dcb);
    }void CNcfileCtrlDlg::OnQuery() 
    {
    BeginWaitCursor();
    UpdateData();
    pPartSet = new CPartSet;
    pNcprogramSet = new CNcprogramSet; if(m_PartDrawCode == "")
    {
    MessageBox("零件图号不能为空,请输入!!!","提示", MB_ICONINFORMATION | MB_OK);
    return;
    }
    else
    {
    /* CString tempSqlStr;
    tempSqlStr="select PROCESS_ROUTE.* from PROCESS_ROUTE,NC_PROGRAM_LIB where NC_PROGRAM_LIB.NC_PROGRAM_NAME=PROCESS_ROUTE.NC_PROGRAM_NAME and PROCESS_ROUTE.DRAWING_NUMBER='";// 
    tempSqlStr+=m_PartDrawCode;
    tempSqlStr+="'";
    if(!pProcessSet->IsOpen() && !pPartSet->IsOpen())
    {
    pProcessSet->Open(AFX_DB_USE_DEFAULT_TYPE,tempSqlStr,CRecordset::none);
    pPartSet->Open(AFX_DB_USE_DEFAULT_TYPE,tempSqlStr,CRecordset::none);
    }*/
    if(!pPartSet->IsOpen())
    pPartSet->Open();
    pPartSet->MoveFirst();
    while(!pPartSet->IsEOF())
    {
    if(pPartSet->m_PART_DRAW_CODE == m_PartDrawCode)
    {
    m_partname = pPartSet->m_PART_NAME;
    UpdateData(false);
    }
    pPartSet->MoveNext();
    }
    if(m_partname == "")
    {
    MessageBox("输入的零件图号不存在或错误,请核实!","警告",MB_ICONWARNING | MB_OK);
    }
    pPartSet->Close(); 
    if(!pNcprogramSet->IsOpen ())
    pNcprogramSet->Open ();
    m_cOperationCode.ResetContent();
            pNcprogramSet->MoveFirst ();
    while(!pNcprogramSet->IsEOF())
    {
                if(pNcprogramSet->m_PART_DRAW_CODE == m_PartDrawCode)
    {
    m_cOperationCode.AddString(pNcprogramSet->m_OPERATION_NO);
    m_cOperationCode.GetLBText(0,m_sOperationCode);
    UpdateData(false);
    }
    pNcprogramSet->MoveNext();
    }
    pNcprogramSet->Close();
    }
    m_sNcFile = "";
    m_sProgramCode = "";
    m_sState = "";
    m_sVersion = "";
    m_sStart = "";
    m_sEnd = "";
    UpdateData(false);
    EndWaitCursor();
    }
      

  7.   

    // 打开串行口并建立辅助工作线程
    BOOL CNcfileCtrlDlg::OpenConnection()
    {
    COMMTIMEOUTS TimeOuts;
    m_hTermWnd = GetSafeHwnd();
    if(m_bConnected)
    return FALSE;
    m_hCom = CreateFile(m_sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
                          NULL); // 重叠方式
    if(m_hCom == INVALID_HANDLE_VALUE)
    return FALSE;
    SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);
    // SetCommMask(m_hCom, EV_RXCHAR);/////////////////////////////////////////////////////////////////////
    //测试代码
    // DWORD lpEvtMask;
    // GetCommMask(m_hCom,&lpEvtMask);
    // if(lpEvtMask & EV_RXCHAR == EV_RXCHAR)
    // AfxMessageBox("EV_RXCHAR!");
    // SetCommMask(m_hCom,0);
    // GetCommMask(m_hCom,&lpEvtMask);
    // if(lpEvtMask & EV_RXCHAR == EV_RXCHAR)
    // AfxMessageBox("EV_RXCHAR!");
    // else
    // AfxMessageBox("NO EV_RXCHAR!");
    //////////////////////////////////////////////////////////////////// // 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作
    TimeOuts.ReadIntervalTimeout = MAXDWORD; 
        TimeOuts.ReadTotalTimeoutMultiplier = 0; 
    TimeOuts.ReadTotalTimeoutConstant = 0; 
    /* 设置写超时以指定WriteComm成员函数中的
        GetOverlappedResult函数的等待时间*/
    TimeOuts.WriteTotalTimeoutMultiplier = 50; 
    TimeOuts.WriteTotalTimeoutConstant = 2000;
    SetCommTimeouts(m_hCom, &TimeOuts);
    if(ConfigConnection())
    {
    m_pThread = AfxBeginThread(CommProc, this, THREAD_PRIORITY_NORMAL, 
    0, CREATE_SUSPENDED, NULL); // 创建并挂起接收线程
    if(m_pThread == NULL)
    {
    MessageBox("创建接收数据线程失败!","警告", MB_ICONWARNING | MB_OK);
    CloseHandle(m_hCom);
    return FALSE;
    } ReceiveThread = TRUE;
    m_bConnected = TRUE;
    }
    else
    {
    CloseHandle(m_hCom);
    return FALSE;
    }
    return TRUE;
    }// 结束工作者线程,关闭串行口
    void CNcfileCtrlDlg::CloseConnection()
    {
    // 结束事件监视线程
    if(!m_bConnected) return;
    m_bConnected = FALSE; // 结束CommProc线程中WaitSingleObject函数的等待
    SetEvent(m_hPostMsgEvent);  // 结束CommProc线程中WaitCommEvent的等待
    SetCommMask(m_hCom, 0);  if(ReceiveThread)//判断接收线程是否退出
    {
    if(!TerminateThread(m_pThread->m_hThread,0))
    MessageBox("终止接收数据线程失败!","警告", MB_ICONWARNING | MB_OK);
    }
    if(BeginThread)      //判断发送线程是否退出
    {
    if(!TerminateThread(m_pThreadT->m_hThread,0))
    MessageBox("终止发送数据线程失败!","警告", MB_ICONWARNING | MB_OK);
    } if(EventThread)      //判断事件监视线程是否退出
    {
    if(!TerminateThread(m_pThreadEvent->m_hThread,0))
    MessageBox("终止事件监视线程失败!","警告", MB_ICONWARNING | MB_OK);
    } CloseHandle(m_hCom);
    }
    // 从串行口输入缓冲区(m_hCom通信设备)中读入指定数量的字符
    DWORD CNcfileCtrlDlg::ReadComm(char *buf, DWORD dwLength)
    {
    DWORD length = 0;
    COMSTAT ComStat; // 串口设备状态结构
    DWORD dwErrorFlags;
    ClearCommError(m_hCom,&dwErrorFlags,&ComStat); // 读取串口设备的当前状态
    length = min(dwLength, ComStat.cbInQue); // 应该读取的数据长度
    ReadFile(m_hCom,buf,length,&length,&m_osRead); // 读取数据
    return length;
    }// 将指定数量的字符从串行口输出,在调用该函数时,实际dwLength都为1
    DWORD CNcfileCtrlDlg::WriteComm(char* buf, DWORD dwLength)
    {
    BOOL fState;
    DWORD length = dwLength;  //成功写入缓冲区的字符数
    COMSTAT ComStat;
    DWORD dwErrorFlags;
    ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
    fState = WriteFile(m_hCom,buf,dwLength,&length,&m_osWrite);
    if(!fState){
    if(GetLastError() == ERROR_IO_PENDING)   //写操作被挂起
    {
    if(!GetOverlappedResult(m_hCom,&m_osWrite,&length,TRUE)) //写操作没有成功完成
    {
    MessageBox("发送代码出现错误!","错误", MB_ICONERROR | MB_OK);
    }
    }
    else
    length = 0;
    } return length;
    }
    // 配置串行口
    BOOL CNcfileCtrlDlg::ConfigConnection()
    {
    DCB dcb;
    if(!GetCommState(m_hCom, &dcb)) // 获取缺省的dcb结构的值
    return FALSE; dcb.fOutX = 0;
    dcb.fInX = 0;
    dcb.fOutxCtsFlow = 0;
    dcb.fOutxDsrFlow = 0;
    dcb.fBinary = TRUE;
    dcb.BaudRate = m_nBaud; // 波特率
    dcb.ByteSize = m_nDataBits; // 每字节位数
    dcb.fParity = TRUE;
    switch(m_nParity) // 校验设置
    {
    case 0: dcb.Parity = NOPARITY;
    break;
    case 1: dcb.Parity = ODDPARITY;
    break;
    case 2: dcb.Parity = EVENPARITY;
    break;
    case 3: dcb.Parity = MARKPARITY;
    break;
            case 4: dcb.Parity = SPACEPARITY;
    break;
    default:;
    }
    switch(m_nStopBits) // 停止位
    {
    case 0: dcb.StopBits = ONESTOPBIT;
    break;
    // case 1: dcb.StopBits = ONE5STOPBITS;
    // break;
    case 1: dcb.StopBits = TWOSTOPBITS;
    break;
    default:;
    }
    // 硬件流控制设置

        if (m_bRts)
    dcb.fRtsControl = RTS_CONTROL_HANDSHAKE ;
    else
    dcb.fRtsControl = RTS_CONTROL_ENABLE ;
    // XON/XOFF流控制设置,软件流控制
    if (m_bXon)
    {
    dcb.fInX = dcb.fOutX = 1;
    dcb.XonChar = XON;
    dcb.XoffChar = XOFF;
    dcb.XonLim = 50;
    dcb.XoffLim = 50;
    }
        //硬件流控制设置
    if (m_bDsr)
    dcb.fDtrControl = DTR_CONTROL_HANDSHAKE ;
    else
    dcb.fDtrControl = DTR_CONTROL_ENABLE ; //输出流信号监控
    if(m_bOutxCtsFlow)
    dcb.fOutxCtsFlow = 1;
    if(m_bOutxDsrFlow)
    dcb.fOutxDsrFlow = 1; return SetCommState(m_hCom, &dcb);
    }void CNcfileCtrlDlg::OnQuery() 
    {
    BeginWaitCursor();
    UpdateData();
    pPartSet = new CPartSet;
    pNcprogramSet = new CNcprogramSet; if(m_PartDrawCode == "")
    {
    MessageBox("零件图号不能为空,请输入!!!","提示", MB_ICONINFORMATION | MB_OK);
    return;
    }
    else
    {
    /* CString tempSqlStr;
    tempSqlStr="select PROCESS_ROUTE.* from PROCESS_ROUTE,NC_PROGRAM_LIB where NC_PROGRAM_LIB.NC_PROGRAM_NAME=PROCESS_ROUTE.NC_PROGRAM_NAME and PROCESS_ROUTE.DRAWING_NUMBER='";// 
    tempSqlStr+=m_PartDrawCode;
    tempSqlStr+="'";
    if(!pProcessSet->IsOpen() && !pPartSet->IsOpen())
    {
    pProcessSet->Open(AFX_DB_USE_DEFAULT_TYPE,tempSqlStr,CRecordset::none);
    pPartSet->Open(AFX_DB_USE_DEFAULT_TYPE,tempSqlStr,CRecordset::none);
    }*/
    if(!pPartSet->IsOpen())
    pPartSet->Open();
    pPartSet->MoveFirst();
    while(!pPartSet->IsEOF())
    {
    if(pPartSet->m_PART_DRAW_CODE == m_PartDrawCode)
    {
    m_partname = pPartSet->m_PART_NAME;
    UpdateData(false);
    }
    pPartSet->MoveNext();
    }
    if(m_partname == "")
    {
    MessageBox("输入的零件图号不存在或错误,请核实!","警告",MB_ICONWARNING | MB_OK);
    }
    pPartSet->Close(); 
    if(!pNcprogramSet->IsOpen ())
    pNcprogramSet->Open ();
    m_cOperationCode.ResetContent();
            pNcprogramSet->MoveFirst ();
    while(!pNcprogramSet->IsEOF())
    {
                if(pNcprogramSet->m_PART_DRAW_CODE == m_PartDrawCode)
    {
    m_cOperationCode.AddString(pNcprogramSet->m_OPERATION_NO);
    m_cOperationCode.GetLBText(0,m_sOperationCode);
    UpdateData(false);
    }
    pNcprogramSet->MoveNext();
    }
    pNcprogramSet->Close();
    }
    m_sNcFile = "";
    m_sProgramCode = "";
    m_sState = "";
    m_sVersion = "";
    m_sStart = "";
    m_sEnd = "";
    UpdateData(false);
    EndWaitCursor();
    }