VC 操作word部分代码(利用剪切板取得Word中的图片,ClipBoard, Addpicture)

在32位WIN7 VS2012环境下测试通过,在64位WIN7 VS2013环境下GlobalLock和GlobalSize函数返回NULL,具体参见注释

// 读取给定文件名的Doc文档中的数据
BOOL CWordOperator::ReadInDataFromDoc(CString strFileName)
{
    // 读取Config文件,获得需要读取的单元格坐标
    LoadConfig();

    // COM相关变量
    COleVariant vTrue((short)TRUE);
    COleVariant vFalse((short)FALSE);
    COleVariant vOpt((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

    // Word相关变量
    CApplication wordApp;   // 在对象继承结构中是最顶层的对象,可以通过它的方法访问别的工作类型的对象(本例主要是word)
    CDocuments docs;        // 代表所有打开的文档对象
    CDocument0 doc;         // 单一文件
    CSelection selection;   // 选择区域
    CRange rangeWord;       // 文档区域
    CTables0 tables;        // 所有表格
    CTable0 table;          // 单一表格
    CCell cell;             // 单元格
    CnlineShapes shapes;    // 图片集合
    CnlineShape shape;      // 图片

    // 启动Word程序
    if (!wordApp.CreateDispatch(_T("word.application"))) // 启动Word
    {
        AfxMessageBox(_T("无法启动Word"));
        return FALSE;
    }

    // 设置Word不可见
    wordApp.put_Visible(FALSE);

    // 打开指定Doc
    docs = wordApp.get_Documents();
    doc = docs.Open(COleVariant(strFileName), vFalse, vTrue, vFalse, vOpt, vOpt,
        vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt);
    if (!doc)   // 打开失败
    {
        AfxMessageBox(_T("无法打开文件"));
        return FALSE;
    }

    // 获得选择焦点
    selection = wordApp.get_Selection();

    // 获得表格
    tables = doc.get_Tables();
    table = tables.Item(1); // 索引从1开始

    // 根据XML中定义的节点中的行列进行读取
//  for each (DocCellData data in m_lstDocDatas)
    for (std::list<DocCellData>::iterator it = m_lstDocDatas.begin();
        it != m_lstDocDatas.end(); it++)
    {
        DocCellData& data = *it;
        // 根据节点中设定的行列获得单元格
        cell = table.Cell(data.nRowIndex, data.nColIndex);
        if (!cell)  // 错误提示
        {
            CString strErr;
            strErr.Format(_T("%s指定的%d行%d列的单元格不存在"), data.strXMLName,
                &data.nRowIndex, &data.nColIndex);
            AfxMessageBox(strErr);
            break;
        }
        // 取得单元格内容
        rangeWord = cell.get_Range();
        // 判断类型
        switch (data.type)
        {
        case TextType:  // 文本类型
            data.strValue = rangeWord.get_Text();
//          OpenClipboard(NULL);
//          // 清除剪切板内容
//          EmptyClipboard();
//          // 不关闭则复制操作不起作用,无法复制到剪切板里
//          CloseClipboard();
//          rangeWord.Copy();
//          OpenClipboard(NULL);
//          if (true)
//          {
//              HGLOBAL hClipBoard = ::GetClipboardData(CF_TEXT);
//              void* pMem = ::GlobalLock(hClipBoard);
//              n = GlobalSize(hClipBoard);
//              CString str((char*)pMem);
//          }
            break;
        case PicType:   // 图片类型
            // 取得所有图片集合
            shapes = rangeWord.get_InlineShapes();
            if (shapes.get_Count()) // 存在图片
            {
                // 利用剪切板获得图片
                // 取得第一张图
                shape = shapes.Item(1);
                shape.Select();
                // 复制到剪切板
                selection = wordApp.get_Selection();

                // 打开剪切板(占用状态,此时进行复制粘贴等操作将无效果)
                ::OpenClipboard(NULL);
                // 清除剪切板内容
                ::EmptyClipboard();
                // 不关闭则复制操作不起作用,无法复制到剪切板里
                ::CloseClipboard();
                selection.CopyAsPicture();

                // 32位WIN7下VS2012可以运行
                // 打开剪切板,并且剪切板里存在图片
//              if (::IsClipboardFormatAvailable(CF_DIB) &&
//                     ::OpenClipboard(NULL))
//              {
//                  // 取得剪切板中的图片数据
//                  HGLOBAL hClipBoard = ::GetClipboardData(CF_DIB);
//                  // 锁定内存位置吗,以防系统将内存页移位
//                  LPVOID pMem = ::GlobalLock(hClipBoard);
// 
//                  // 如果存在图片,则进行复制
//                  if (pMem)
//                  {
//                      // 取得位图大小
//                      data.nPicSize = ::GlobalSize(hClipBoard);
//                      // 复制到结构中
//                      data.pBmp = new BYTE[data.nPicSize];
//                      memcpy(data.pBmp, pMem, data.nPicSize);
//                      // 解锁内存
//                      ::GlobalUnlock(hClipBoard);
//                  }
//                  else
//                  {
//                      data.nPicSize = 0;
//                  }
//                  //关闭剪贴板,释放剪贴板资源的占用权
//                  ::CloseClipboard();
//              }

                // 64位WIN7下VS2013可以运行
                if (::IsClipboardFormatAvailable(CF_ENHMETAFILE) &&
                    ::OpenClipboard(NULL))
                {
                    // 首先生成EMF图片文件并存储
                    CString strTempBmp(GetAppPath());
                    strTempBmp += EMFFILENAME;  // 指定存储路径
                    HANDLE hClipBoard = ::GetClipboardData(CF_ENHMETAFILE); // 从剪切板读取EMF格式内容(其它格式读不出来)
                    HENHMETAFILE hTempBmp =
                        ::CopyEnhMetaFile((HENHMETAFILE)hClipBoard, strTempBmp);    // 存成文件
                    // 关闭剪切板,释放剪贴板资源的占用权
                    ::CloseClipboard();
                    if (hTempBmp)   // 图片存在
                    {
                        // 释放内存
                        DeleteEnhMetaFile(hTempBmp);
                        // 读入内存
                        CFile emfFile(strTempBmp, CFile::modeRead); // 取得emf文件
                        data.nPicSize = emfFile.GetLength();    // 取得文件大小(再加一)
                        data.pBmp = new BYTE[data.nPicSize + 1];    // 分配内存
                        emfFile.Read(data.pBmp, data.nPicSize); // 读入
                        data.pBmp[data.nPicSize] = 0;   // 将最后一位置为结束位
                        emfFile.Close();    // 关闭emf文件
                        emfFile.Remove(strTempBmp); // 删除emf文件
                        // 打开剪切板(占用状态,此时进行复制粘贴等操作将无效果)
                        ::OpenClipboard(NULL);
                        // 清除剪切板内容
                        ::EmptyClipboard();
                        // 不关闭则复制操作不起作用,无法复制到剪切板里
                        ::CloseClipboard();
                    }
                }
            }
            break;
        default:
            break;
        }
    }

    // 关闭文档
    doc.Close(vFalse, vOpt, vOpt);
    // 退出Word
    wordApp.Quit(vFalse, vOpt, vOpt);

    return TRUE;
}
// 根据数据生成Doc文档
BOOL CWordOperator::WriteOutDocByData(CString strFileName)
{
    // COM相关变量
    COleVariant vTrue((short)TRUE);
    COleVariant vFalse((short)FALSE);
    COleVariant vOpt((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

    // Word相关变量
    CApplication wordApp;   // 在对象继承结构中是最顶层的对象,可以通过它的方法访问别的工作类型的对象(本例主要是word)
    CDocuments docs;        // 代表所有打开的文档对象
    CDocument0 doc;         // 单一文件
    CSelection selection;   // 选择区域
    CRange rangeWord;       // 文档区域
    CTables0 tables;        // 所有表格
    CTable0 table;          // 单一表格
    CCell cell;             // 单元格
    CnlineShapes shapes;    // 图片集合
    CnlineShape shape;      // 图片

    // 启动Word程序
    if (!wordApp.CreateDispatch(_T("word.application"))) // 启动Word
    {
        AfxMessageBox(_T("无法启动Word"));
        return FALSE;
    }

    // 设置Word不可见
    wordApp.put_Visible(TRUE);

    // 打开指定Doc
    docs = wordApp.get_Documents();
    CComVariant Template("");
    CComVariant NewTemplate(false), DocumentType(0), Visible;
    docs.Add(&Template, &NewTemplate, &DocumentType, &Visible);
    doc = docs.Item(&CComVariant(1));
    if (!doc)   // 打开失败
    {
        AfxMessageBox(_T("无法创建文件"));
        return FALSE;
    }

    // 获得选择焦点
    selection = wordApp.get_Selection();
    rangeWord = selection.get_Range();

    // 获得表格
    tables = doc.get_Tables();
    tables.Add(rangeWord, 10, 10, vOpt, vOpt);
    table = tables.Item(1); // 索引从1开始

    // 根据节点中设定的行列获得单元格
    cell = table.Cell(1, 1);
    // 根据XML中定义的节点中的行列进行读取
    for each (DocCellData data in m_lstDocDatas)
    {
        // 取得单元格内容
        rangeWord = cell.get_Range();
        cell.Select();
        // 判断类型
        switch (data.type)
        {
        case TextType:  // 文本类型
            rangeWord.put_Text(data.strValue);
            break;
        case PicType:   // 图片类型
            // 64位WIN7下VS2013调试通过
            if (TRUE)   // 跳过switch的语法检查
            {
                // 先存成文件
                CString strTempBmpFileName(GetAppPath());
                strTempBmpFileName += EMFFILENAME;  // 生成路径
                // 创建emf文件
                CFile emfFile(strTempBmpFileName,
                    CFile::modeCreate | CFile::modeReadWrite);
                emfFile.Write(data.pBmp, data.nPicSize);    // 写入位图
                emfFile.Close();    // 关闭文件
                // 将图片插入到文档
                rangeWord.Select();
                shapes = selection.get_InlineShapes();  // 得到图片集合
                // 插入emf图片
                shapes.AddPicture(strTempBmpFileName, vFalse, vTrue,
                    &_variant_t(rangeWord));
                // 删除emf文件
                emfFile.Remove(strTempBmpFileName);
            }

            // 32位WIN7下VS2012调试通过
//          // 打开剪切板(占用状态,此时进行复制粘贴等操作将无效果)
//          ::OpenClipboard(NULL);
//          // 清除剪切板内容
//          ::EmptyClipboard();
//          // 不关闭则复制操作不起作用,无法复制到剪切板里
//          ::CloseClipboard();
// 
//          if (::OpenClipboard(NULL))
//          {
//                 // 申请全局内存来存放BMP,以便交给剪切板
//              HGLOBAL hClipBoard = ::GlobalAlloc(GMEM_MOVEABLE, data.nPicSize);
//                 // 锁定内存地址
//              LPVOID pMem = ::GlobalLock(hClipBoard);
//                 // 复制位图
//              memcpy(pMem, data.pBmp, data.nPicSize);
//                 // 解锁内存
//              ::GlobalUnlock(hClipBoard);
//                 // 将位图设置到剪切板中
//              ::SetClipboardData(CF_DIB, hClipBoard);
//                 // 关闭剪切板
//              ::CloseClipboard();
//              rangeWord.Paste();
//              rangeWord.Paste();
//          }
//          //关闭剪贴板,释放剪贴板资源的占用权
//          ::CloseClipboard();
            break;
        default:
            break;
        }

        cell = cell.get_Next();
    }

    // 保存文档
    doc.Save();
    // 关闭文档
    doc.Close(vTrue, vOpt, vOpt);
    // 退出Word
    wordApp.Quit(vTrue, vOpt, vOpt);

    return TRUE;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值