183 个问题
如何使用OLE的API来绘制一个很大的Excel表格?
道政 吴
0
信誉分
- 有一张很大的Excel表格,行数超过了150行(如下图);
- 用户全选表格,然后复制(Ctrl+C),我编写了一个应用程序,在其中读取粘贴板的内容,并想通过OLE的API(如OleDraw)来绘制到HDC,最后用CImage保存为图片;
- 但是保存后的图片只能显示这个Excel表格的一部分内容(如下图);
当把粘贴板的内容粘贴通过选择性粘贴到 Office/Word中,显示正常(如下图);
- 当把粘贴板的内容粘贴通过选择性粘贴到 写字板(WordPad)中,写字板也只能展现一部分;
- 所以我想知道的是,是否有什么特殊的API调用来让整个OLE对象得到完整的绘制?
以下是我的程序代码:
#include <iostream>
#include <Windows.h>
#include <ole2.h>
#include <oleidl.h>
#include <comdef.h>
#include <atlimage.h>
#include <atlwin.h>
void DrawExcelFromClipboard()
{
if (FAILED(OleInitialize(NULL)))
{
fprintf(stderr, "Failed to init ole\n");
return;
}
IDataObject *pDataObj = NULL;
IOleObject *pOleObject = NULL;
IStorage *pStorage = NULL;
ILockBytes *pLockBytes = NULL;
if (SUCCEEDED(OleGetClipboard(&pDataObj)))
{
if (SUCCEEDED(CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes)) &&
SUCCEEDED(StgCreateDocfileOnILockBytes(pLockBytes,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
0, &pStorage)))
{
HRESULT hr = OleCreateFromData(pDataObj, IID_IOleObject, OLERENDER_DRAW,
NULL, NULL, pStorage, (void **)&pOleObject);
if (SUCCEEDED(hr))
{
SIZEL sz;
pOleObject->GetExtent(DVASPECT_CONTENT, &sz);
HDC hdcDesktop = ::GetDC(NULL);
int w = MulDiv(sz.cx, GetDeviceCaps(hdcDesktop, LOGPIXELSX), 2540);
int h = MulDiv(sz.cy, GetDeviceCaps(hdcDesktop, LOGPIXELSY), 2540);
::ReleaseDC(NULL, hdcDesktop);
CImage img;
img.Create(w, h, 32);
HDC hdc = img.GetDC();
RECT rc = {0, 0, w, h};
// frames
HBRUSH hBrush = CreateSolidBrush(RGB(240, 240, 240));
FillRect(hdc, &rc, hBrush);
DeleteObject(hBrush);
FrameRect(hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
InflateRect(&rc, -10, -10);
// SetMapMode(hdc, MM_TEXT);
if (1)
{
IViewObject2 *pView = NULL;
pOleObject->QueryInterface(IID_IViewObject2, (void **)&pView);
if (pView != NULL)
{
RECTL rcl;
rcl.left = rc.left;
rcl.right = rc.right;
rcl.top = rc.top;
rcl.bottom = rc.bottom;
hr = pView->Draw(DVASPECT_CONTENT,
-1,
NULL,
NULL,
NULL,
hdc,
&rcl,
NULL,
NULL,
0);
pView->Release();
}
}
else
{
hr = OleDraw(pOleObject, DVASPECT_CONTENT, hdc, &rc);
}
if (FAILED(hr))
{
fprintf(stderr, "Failed to draw ole\n");
}
else
{
if (!SUCCEEDED(img.Save(L"./ole.png", Gdiplus::ImageFormatPNG)))
{
fprintf(stderr, "Failed to save png\n");
}
}
img.ReleaseDC();
}
else
{
fprintf(stderr, "Failed to load ole\n");
}
}
}
else
{
fprintf(stderr, "No ole in clipboard\n");
}
CloseClipboard();
if (pDataObj)
pDataObj->Release();
if (pOleObject)
pOleObject->Release();
if (pStorage)
pStorage->Release();
if (pLockBytes)
pLockBytes->Release();
}
int main()
{
DrawExcelFromClipboard();
return 0;
}
开发人员技术 C++
登录以回答