PDF元素的移动、拉伸参考rect的实现,这里我们主要看看PDF的绘制部分代码
我这边的做法是先将PDF页面生成一张图片,然后跟图片控件一样进行贴图展示。
关于PDF的解析这边使用了第三方开源库mupdf
库导入:
#include "../mupdf/include/mupdf/fitz.h"
#include "../mupdf/include/mupdf/pdf.h"
#ifdef _DEBUG
#pragma comment(lib,"../mupdf/lib/x64/Debug/libmupdf.lib")
#else
#pragma comment(lib,"../mupdf/lib/x64/Release/libmupdf.lib")
#endif
PDF解析、以及图片绘制如下:
#pragma once
#include "CEleBase.h"
class CElePDF : public CEleBase
{
DEF_SOBJECT(SWindow, L"ele_pdf")
public:
CElePDF();
~CElePDF();
public:
void OnPaint(IRenderTarget* pRT);
protected:
LRESULT OnCreate(LPVOID);
void OnLButtonDown(UINT nFlags, SOUI::CPoint point);
void OnLButtonUp(UINT nFlags, SOUI::CPoint point);
void OnMouseMove(UINT nFlags, SOUI::CPoint point);
void OnLButtonDblClk(UINT nFlags, SOUI::CPoint point);
void OnRButtonUp(UINT nFlags, CPoint point);
protected:
SOUI_MSG_MAP_BEGIN()
MSG_WM_CREATE(OnCreate)
MSG_WM_PAINT_EX(OnPaint)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
MSG_WM_LBUTTONUP(OnLButtonUp)
MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
MSG_WM_RBUTTONUP(OnRButtonUp)
MSG_WM_MOUSEMOVE(OnMouseMove)
SOUI_MSG_MAP_END()
private:
CPoint m_ptDown;
EcPosType m_curEcPosType;
};
#include "stdafx.h"
#include "CElePDF.h"
CElePDF::CElePDF()
{
//
}
CElePDF::~CElePDF()
{
//
}
void CElePDF::OnPaint(IRenderTarget* pRT)
{
SetMsgHandled(FALSE);
pRT->SetAntiAlias(TRUE);
CRect rcWindow = GetWindowRect();
SStringW sstrPath = L"test.pdf";
std::string strUTF8Path = S_CW2A(sstrPath, CP_UTF8);
fz_context* ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
fz_register_document_handlers(ctx);
fz_document* doc = fz_open_document(ctx, strUTF8Path.c_str());
int nCount = fz_count_pages(ctx, doc);
//设置缩放
double dXDPI = 100.0;
double dYDPI = 100.0;
float xZoom = dXDPI / 72;
float yZoom = dYDPI / 72;
fz_matrix ctm = fz_scale(xZoom, yZoom);
fz_pixmap* pix = NULL;
int nPageIndex = 0;
pix = fz_new_pixmap_from_page_number(ctx, doc, nPageIndex, ctm, fz_device_rgb(ctx), 0);
//直接读取pix中的像素值没搞明白,这里暂时先保存成一个本地图片吧
fz_save_pixmap_as_png(ctx, pix, "pdf2image.png");
fz_drop_pixmap(ctx, pix);
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
SStringW sstrPicPath = L"pdf2image.png";
SAutoRefPtr<IBitmap> pBmp = SResLoadFromFile::LoadImage(sstrPicPath);
DWORD mode = MAKELONG(EM_STRETCH, kNone_FilterLevel);
if (pBmp)
{
CRect rcSrc(0, 0, pBmp->Width(), pBmp->Height());
pRT->DrawBitmapEx(rcWindow, pBmp, &rcSrc, mode, 255);
pBmp->Release();
}
else
{
//image load failed
}
//...
}
LRESULT CElePDF::OnCreate(LPVOID)
{
SetMsgHandled(FALSE);
//生成元素ID
std::string strUUID = CGlobalUnits::GetInstance()->GenerateUUID();
m_strUUID = strUUID;
return __super::OnCreate(NULL);
}
void CElePDF::OnLButtonDown(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
SetCapture();
//...
}
void CElePDF::OnLButtonUp(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
ReleaseCapture();
//...
}
void CElePDF::OnMouseMove(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
//...
}
void CElePDF::OnLButtonDblClk(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
}
void CElePDF::OnRButtonUp(UINT nFlags, CPoint point)
{
SetMsgHandled(FALSE);
}
控件使用:
先注册,再在容器中创建元素
m_theApp->RegisterWindowClass<CElePDF>();
CElePDF* pEle = (CElePDF*)SApplication::getSingleton().CreateWindowByName(L"ele_pdf");
SASSERT(pEle);
SApplication::getSingleton().SetSwndDefAttr(pEle);
this->InsertChild(pEle);
pEle->SSendMessage(WM_CREATE);
CPoint ptReal(point);
ptReal.x -= rcContainer.left;
ptReal.y -= rcContainer.top;
SStringT sstrRectPos;
sstrRectPos.Format(_T("%d,%d,@%d,@%d"), ptReal.x, ptReal.y, 200, 200);
pEle->SetAttribute(L"pos", sstrRectPos);
//将位置、长宽等信息转为毫米
CPoint ptRB(ptReal.x + 200, ptReal.y + 200);
pEle->m_ptLT = ptReal;
pEle->m_ptRB = ptRB;
以上就是PDF控件的实现以及使用。
效果如下:
源PDF文件: