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;
}
發佈了21 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章