在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;
}