Mfc实现多行连选以及多行不连选的多选复制操作

本文介绍了一种在列表视图中实现多行数据复制的方法,包括建立右键菜单、记录点击行号以及编写复制函数等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现在已经知道如何实现复制一行的做法。现实现多行复制,则需要拿到鼠标每次点击的行号。
任务:复制平扫信息中Z轴或者X轴列数据。(可多选,连选,不连续多选)

1.建立右键菜单并记录点击行号
void ScanDlg::OnRightclkListSubprocess(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    int index = pNMLV->iItem;

    POSITION pos = m_listUnitInfo->GetFirstSelectedItemPosition();//m_listUnitInfo为要处理的列表指针
    if (pos != NULL)
    {
        nFirstItem = m_listUnitInfo->GetNextSelectedItem(pos);//第一个被选中的的行号
        int nNextItem = 0;    //记下一个被选中的的行号
        nCheck.clear();//全局变量容器,在头文件时定义。每次重新选的时候先清空上一次遗留数据
        while (-1 != (nNextItem = m_listUnitInfo->GetNextSelectedItem(pos)))//两次点击选中连续多个(点一个按住shift键,然后再点一个作为结束)
        {
            nCheck.push_back(nNextItem);//存下被选中的第二、三、四...等行号(第一行是用nFirstItem记录的)
            nFinishItem = nNextItem;//把下一个置为最后一个,直到nNextItem为-1(没有下一个的时候>GetNextSelectedItem()函数会返回-1)    
        }    
    }
    if (index == -1)//没有被选中的
        return;
    HMENU hMenu = ::CreatePopupMenu();
    AppendMenu(hMenu, MF_STRING, 10001, _T("复制X轴数据"));
//    AppendMenu(hMenu, MF_STRING, 10002, _T("复制Y轴数据"));
    AppendMenu(hMenu, MF_STRING, 10003, _T("复制Z轴数据"));
    CPoint pt;
    GetCursorPos(&pt); //获得当前鼠标位置
    UINT Cmd = (UINT)::TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, m_hWnd, NULL);//弹出菜单

    switch (Cmd)//响应点击的菜单
    {
    case 10001:
        OnXCopyAisMsg();
        break;
    case 10002:
        break;
    case 10003:
        OnZCopyAisMsg();
        break;
    }
    *pResult = 0;
}


2.写复制函数
void ScanDlg::OnZCopyAisMsg()
{
    CString                strAisMsg;
    int                nItem;

    TCHAR                *pszData;
    HGLOBAL                hClipboardData;
    vector<int> nCopy;//写一个类型相同的容器来装被点击行号
    nCopy.clear();
    for (int j = 0; j < nCheck.size();j++)//遍历装着所有行号的容器,若是单击两下按住shift键连选的情况,则nCheck中所有值都是连续的且后一个比前一个大1
    {
        if (nCheck[j + 1] == nCheck[j] + 1)//有连续被选中(连续蓝色)的情况
        {
            //单击几下挨着但不连选的情况(单击一下后按住ctrl键继续单击别的进行选择时,有可能出现连续的且后一个比前一个大1数值)
            nCopy.push_back(nCheck[j]);//若出现则用容器记录下此行号,并且跳出if循环,继续看下面的是否连续且后一个比前一个大1数值,不是得话则会进else
            continue;

            //仅单击两下,全部连选的情况
            nItem = nFinishItem - nFirstItem + 1;
            for (int i = 0; i < nItem; i++)
            {
                strAisMsg += m_listUnitInfo->GetItemText(nFirstItem + i, 4) + _T("\n");
            }
            break;
        }
        else
        {
            nCopy.push_back(nCheck[j]);
            if (nCopy.size()<nCheck.size())
            {
                continue;
            }
            else
            {
                strAisMsg += m_listUnitInfo->GetItemText(nFirstItem, 4) + _T("\n");
                for (int i = 0; i < nCopy.size(); i++)
                {
                    strAisMsg += m_listUnitInfo->GetItemText(nCopy[i], 4) + _T("\n");
                }
            }
        }
    }

    //复制剪切板
    if (!strAisMsg.IsEmpty())
    {
        if (OpenClipboard())
        {
            EmptyClipboard();
            hClipboardData = GlobalAlloc(GMEM_DDESHARE, (strAisMsg.GetLength() + 1) * sizeof(TCHAR));
            if (hClipboardData)
            {
                pszData = (TCHAR *)GlobalLock(hClipboardData);
                _tcscpy(pszData, strAisMsg);
                GlobalUnlock(hClipboardData);
                SetClipboardData(CF_UNICODETEXT, hClipboardData);
            }

            CloseClipboard();
        }
    }

}

效果:

1.点击两下,按住shift,连续多选

2.不连续多选 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值