远程客户端对话框的功能,主要涉及网络通信和树形目录显示

这段代码实现了一个远程客户端对话框的功能,主要涉及网络通信和树形目录显示。下面我将详细分析其编码逻辑:

1. SendCommandPacket 方法

这是核心的网络通信方法,负责发送命令包并处理响应:

int CRomoteClientDlg::SendCommandPacket(int nCmd, bool bAutoClose, BYTE* pData, size_t nLength)
{
    UpdateData();  // 更新对话框数据
    
    // 获取客户端Socket单例并初始化
    CClientSocket* pClient = CClientSocket::getInstance();
    bool ret = pClient->InitSocket(m_server_address, atoi((LPCTSTR)m_nPort));
    
    if (!ret) {
        AfxMessageBox("网络初始化失败!");
        return -1;
    }
    
    // 创建并发送命令包
    CPacket pack(nCmd, pData, nLength);
    ret = pClient->Send(pack);
    TRACE("send ret %d \r\n", ret);
    
    // 处理服务器响应
    int cmd = pClient->DealCommand();
    TRACE("ack:%d\r\n", cmd);
    
    // 根据参数决定是否自动关闭socket
    if (bAutoClose)
        pClient->CloseSocket();
        
    return cmd;
}
  1. 更新对话框数据

  2. 获取CClientSocket单例并初始化socket连接

  3. 创建命令包(包含命令号、数据和长度)

  4. 发送命令包到服务器

  5. 接收并处理服务器响应

  6. 根据bAutoClose参数决定是否关闭连接

  7. 返回服务器响应的命令号

2. OnBnClickedBtnFileinfo 方法

处理"文件信息"按钮点击事件,获取驱动器列表并显示在树形控件中:

void CRomoteClientDlg::OnBnClickedBtnFileinfo()
{
    // 发送命令1(获取驱动器列表)
    int ret = SendCommandPacket(1);
    if (ret == -1) {
        AfxMessageBox(_T("命令处理失败!!!"));
        return;
    }
    
    // 获取返回的驱动器列表数据
    CClientSocket* pClient = CClientSocket::getInstance();
    std::string drivers = pClient->GetPacket().strData;
    std::string dr;
    
    // 清空树形控件并逐个添加驱动器
    m_Tree.DeleteAllItems();
    for (size_t i = 0; i < drivers.size(); i++)
    {
        if (drivers[i] == ',') {
            dr += ":";
            m_Tree.InsertItem(dr.c_str(),TVI_ROOT,TVI_LAST);
            dr.clear();
            continue;
        }
        dr += drivers[i];
    }
}

逻辑流程:

  1. 发送命令1到服务器获取驱动器列表

  2. 检查返回结果是否成功

  3. 从socket包中获取驱动器字符串(格式如"C,D,E")

  4. 清空树形控件

  5. 解析驱动器字符串,逐个添加到树形控件的根节点下

3. GetPath 方法

根据树形控件中的选中项构建完整路径:

CString CRomoteClientDlg::GetPath(HTREEITEM hTree)
{
    CString strRet, strTmp;
    do {
        strTmp = m_Tree.GetItemText(hTree);  // 获取当前节点文本
        strRet = strTmp + '\\' + strRet;     // 拼接路径
        hTree = m_Tree.GetParentItem(hTree); // 获取父节点
    } while (hTree != NULL);                 // 直到根节点
    
    return strRet;
}

逻辑流程:

  1. 从指定树节点开始

  2. 循环获取当前节点文本和父节点

  3. 反向拼接路径字符串(从子节点到根节点)

  4. 返回完整路径字符串

4. OnNMDblclkTreeDir 方法

处理树形控件双击事件,获取选中目录的文件信息:

void CRomoteClientDlg::OnNMDblclkTreeDir(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0;
    
    // 获取鼠标位置和选中的树节点
    CPoint ptMouse;
    GetCursorPos(&ptMouse);
    m_Tree.ScreenToClient(&ptMouse);
    HTREEITEM hTreeSelected = m_Tree.HitTest(ptMouse,0);
    
    if (hTreeSelected == NULL)
        return;
        
    // 获取选中节点的完整路径
    CString strPath = GetPath(hTreeSelected);
    
    // 发送命令2(获取目录文件信息)
    SendCommandPacket(2, FALSE, (BYTE*)(LPCTSTR)strPath, strPath.GetLength());
    
    // 处理返回的文件信息
    PFILEINFO pInfo = (PFILEINFO)CClientSocket::getInstance()->GetPacket().Data();
    CClientSocket* pClient = CClientSocket::getInstance();
    
    // 如果文件信息有后续数据,继续接收
    if (pInfo->HasNext) {
        int cmd = pClient->DealCommand();
        TRACE("ack:%d\r\n", cmd);
        //TODO:处理收到的数据
    }
    
    pClient->CloseSocket();
}

逻辑流程:

  1. 获取鼠标位置并转换为树形控件坐标

  2. 检测双击的树节点

  3. 获取选中节点的完整路径

  4. 发送命令2(带路径参数)到服务器获取文件信息

  5. 接收并处理文件信息

  6. 检查是否有后续数据需要接收

  7. 关闭socket连接

整体设计特点

  1. 网络通信封装:使用SendCommandPacket方法封装了常用的网络操作,简化了其他方法的调用

  2. 单例模式:CClientSocket使用单例模式确保全局只有一个socket连接

  3. 树形控件交互:实现了路径获取和双击事件处理

  4. 命令驱动:使用不同的命令号(1,2等)区分不同的操作

  5. 错误处理:基本的错误检查和用户提示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值