📄 scemfimage.cpp
字号:
m_iAngle += 360;
ASSERT(m_iAngle>=0);
SCComputeFitZoom();
SCRefresh();
}
void CSCEMFImage::SCRotateRight()
{
m_iAngle += 90;
if (m_iAngle>=360)
m_iAngle -= 360;
ASSERT(m_iAngle>=0);
SCComputeFitZoom();
SCRefresh();
}
///
/// Show or hide scrollbars as necessary.
///
void CSCEMFImage::InitializeScrollBars(int width, int height)
{
RECT rClient;
SCROLLINFO ScrollInfo;
// Get windows client size.
GetClientRect(&rClient);
// If client size is equal to dib size, then add one to client size
// so that we don't show scroll bars.
// However, if client size is less than dib size, subtract scroll bar
// size form client size so that page size will be correct when
// scroll bars are shown.
if (rClient.bottom == height)
++rClient.bottom;
else if (rClient.bottom < height)
rClient.bottom -= GetSystemMetrics (SM_CYHSCROLL);
if (rClient.right == width)
++rClient.right;
else if (rClient.right < width)
rClient.right -= GetSystemMetrics (SM_CXVSCROLL);
// Initialize vertical scroll bar.
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_PAGE|SIF_RANGE;
ScrollInfo.nMin = 0;
ScrollInfo.nMax = height;
ScrollInfo.nPage = rClient.bottom;
SetScrollInfo(SB_VERT, &ScrollInfo, TRUE);
// Initialize horizontal scroll bar.
ScrollInfo.nMax = width;
ScrollInfo.nPage = rClient.right;
SetScrollInfo(SB_HORZ, &ScrollInfo, TRUE);
}
///
/// Resize the scrollbars' page information.
///
void CSCEMFImage::SizeScrollBars(int uiWindowWidth, int uiWindowHeight)
{
static BOOL m_bAdjusting = FALSE;
// Only size for valid windows and dib info.
// Don't SizeScrollBars if in process of adjusting them.
if (IsWindow(m_hWnd) && !m_bAdjusting)
{
int nScrollHeight = GetSystemMetrics (SM_CXVSCROLL);
int nScrollWidth = GetSystemMetrics (SM_CYHSCROLL);
SCROLLINFO VertScrollInfo;
SCROLLINFO HorzScrollInfo;
// Make sure that we don't get into an infinite loop when updating scroll bars.
m_bAdjusting = TRUE;
// Get current vertical scroll info.
VertScrollInfo.cbSize = sizeof(SCROLLINFO);
VertScrollInfo.fMask = SIF_ALL;
GetScrollInfo(SB_VERT, &VertScrollInfo);
// Get current horizontal scroll info.
HorzScrollInfo.cbSize = sizeof(SCROLLINFO);
HorzScrollInfo.fMask = SIF_ALL;
GetScrollInfo(SB_HORZ, &HorzScrollInfo);
// Update vertical scroll info.
VertScrollInfo.fMask = SIF_PAGE;
VertScrollInfo.nPage = uiWindowHeight;
SetScrollInfo(SB_VERT, &VertScrollInfo, TRUE);
// Update horizontal scroll info.
HorzScrollInfo.fMask = SIF_PAGE;
HorzScrollInfo.nPage = uiWindowWidth;
SetScrollInfo(SB_HORZ, &HorzScrollInfo, TRUE);
m_bAdjusting = FALSE;
}
}
///
/// Scroll in answer to a scrollbar event.
///
BOOL CSCEMFImage::ScrollChildWindow(int nScrollBar, UINT wScrollCode, int iCount /*=1*/)
{
int nPosition;
int nHorzScroll = 0;
int nVertScroll = 0;
SCROLLINFO ScrollInfo;
// Get current scroll information.
ZeroMemory(&ScrollInfo, sizeof(SCROLLINFO));
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_ALL;
if (!GetScrollInfo(nScrollBar, &ScrollInfo))
{
int error = GetLastError();
return FALSE;
}
nPosition = ScrollInfo.nPos;
// Modify scroll information based on requested
// scroll action.
switch (wScrollCode)
{
case SB_LINEDOWN:
ScrollInfo.nPos += SC_PIX_TXTLINE*iCount;
break;
case SB_LINEUP:
ScrollInfo.nPos -= SC_PIX_TXTLINE*iCount;
break;
case SB_PAGEDOWN:
ScrollInfo.nPos += ScrollInfo.nPage*iCount;
break;
case SB_PAGEUP:
ScrollInfo.nPos -= ScrollInfo.nPage*iCount;
break;
case SB_TOP:
ScrollInfo.nPos = ScrollInfo.nMin;
break;
case SB_BOTTOM:
ScrollInfo.nPos = ScrollInfo.nMax;
break;
// Don't do anything.
case SB_THUMBTRACK:
return TRUE;
case SB_THUMBPOSITION:
ScrollInfo.nPos = ScrollInfo.nTrackPos;
break;
case SB_ENDSCROLL:
default:
return FALSE;
}
// Make sure that scroll position is in range.
if (0 > ScrollInfo.nPos)
ScrollInfo.nPos = 0;
else if (ScrollInfo.nMax - (int)ScrollInfo.nPage + 1 < ScrollInfo.nPos)
ScrollInfo.nPos = ScrollInfo.nMax - ScrollInfo.nPage + 1;
// Set new scroll position.
ScrollInfo.fMask = SIF_POS;
SetScrollInfo(nScrollBar, &ScrollInfo, TRUE);
// Scroll window.
#if 0
// scroll position is integrated to scpaint
if (SB_VERT == nScrollBar)
nVertScroll = nPosition - ScrollInfo.nPos;
else
nHorzScroll = nPosition - ScrollInfo.nPos;
ScrollWindowEx(nHorzScroll, nVertScroll, NULL, NULL,
NULL, NULL, SW_INVALIDATE);
#endif
Invalidate();
UpdateWindow();
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////
// Scrolling events
//
void CSCEMFImage::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
ScrollChildWindow(SB_HORZ, nSBCode);
CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CSCEMFImage::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
ScrollChildWindow(SB_VERT, nSBCode);
CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}
//////////////////////////////////////////////////////////////////////////////////
// Page navigation events
//
void CSCEMFImage::SCGotoPage(int iPage)
{
if (!m_pEMFDoc || !m_pEMFDoc->SCGetNbPages())
return;
ASSERT(iPage>=1 && iPage<=(int)m_pEMFDoc->SCGetNbPages());
// load
m_hEmf = m_pEMFDoc->SCGetPageEMF(iPage-1);
m_iCurPage = iPage;
SCComputePageInfo(iPage);
if (m_iFitMode!=SC_FIT_NONE)
SCComputeFitZoom();
SCComputeRowsCols();
Invalidate();
}
void CSCEMFImage::SCGotoFirstPage()
{
SCComputeFitZoom();
SCGotoPage(1);
}
void CSCEMFImage::SCGotoPrevPage()
{
SCGotoPage(m_iCurPage-1);
}
void CSCEMFImage::SCGotoNextPage()
{
SCGotoPage(m_iCurPage+1);
}
void CSCEMFImage::SCGotoLastPage()
{
SCGotoPage(SCGetNumPages());
}
//////////////////////////////////////////////////////////////////////////////////
// Creation/background events
//
int CSCEMFImage::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
BOOL CSCEMFImage::OnEraseBkgnd(CDC* pDC)
{
return TRUE; // do not erase
//return CWnd::OnEraseBkgnd(pDC);
}
//////////////////////////////////////////////////////////////////////////////////
// Other utilities
//
void CSCEMFImage::SCGetPageBlackBox(int iPage, CRect& rcElems)
{
ASSERT(m_pEMFDoc);
ASSERT(iPage);
PSCEMFDocPage pDocPage = m_pEMFDoc->SCGetDocPage(iPage-1);
ASSERT(pDocPage);
pDocPage->SCGetPageBlackBox(rcElems);
}
void CSCEMFImage::SCGetPageSize(CSize& PgSize)
{
if (m_pEMFDoc && m_pEMFDoc->SCGetNbPages())
SCGetPageBlackBox((m_iCurPage) ? m_iCurPage: 1, m_rectPaper);
else
m_rectPaper.SetRectEmpty();
m_rectPaper.InflateRect(m_rectMargins.left, m_rectMargins.top, m_rectMargins.right, m_rectMargins.bottom);
// Note: the paper rectangle IS NOT rotated. It is considered as bound to the EMF.
// So it rotates only when the playing DC is rotated.
m_rectPaper.left = MulDiv(m_rectPaper.left, m_iCurZoom, SC_ZOOM100);
m_rectPaper.right = MulDiv(m_rectPaper.right, m_iCurZoom, SC_ZOOM100);
m_rectPaper.top = MulDiv(m_rectPaper.top, m_iCurZoom, SC_ZOOM100);
m_rectPaper.bottom = MulDiv(m_rectPaper.bottom, m_iCurZoom, SC_ZOOM100);
// Note: image dimensions ARE rotated
PgSize.cx = m_rectPaper.Width();
PgSize.cy = m_rectPaper.Height();
switch (m_iAngle)
{
case 90:
case 270:
{// rotate
SMC_ISWAP(PgSize.cx, PgSize.cy);
}
break;
}
}
// number rows and columns by row
void CSCEMFImage::SCComputeRowsCols()
{
CSize PgSize;
SCGetPageSize(PgSize); // current page or nothing
int iImgCx = PgSize.cx;
int iImgCy = PgSize.cy;
CRect rc;
GetClientRect(rc);
int iWndCx = rc.Width();
int iWndCy = rc.Height();
// try to set an y margin (for now, one row)
if (iImgCy<iWndCy)
m_iWorldCy = iWndCy;
else
m_iWorldCy = MIN_MARGIN*2 + iImgCy;
ASSERT(m_iWorldCy>=iWndCy);
// compute world dimensions for scrollbars
if (iImgCx<iWndCx)
m_iWorldCx = iWndCx;
else
m_iWorldCx = MIN_MARGIN*2 + iImgCx;
ASSERT(m_iWorldCx>=iWndCx);
// center
m_iPgPosX = (m_iWorldCx - iImgCx)/2;
m_iPgPosY = (m_iWorldCy - iImgCy)/2;
ASSERT(m_iPgPosX>=0);
ASSERT(m_iPgPosY>=0);
InitializeScrollBars(m_iWorldCx, m_iWorldCy);
}
void CSCEMFImage::SCComputeFitZoom()
{
if (!m_iCurPage || SC_FIT_NONE==m_iFitMode)
return;
// load page
m_hEmf = m_pEMFDoc->SCGetPageEMF(m_iCurPage-1);
if (!m_hEmf)
return;
// account for extra margins
CRect rcElems;
SCGetPageBlackBox(m_iCurPage, rcElems);
CSize sizeEMF(rcElems.Width() + m_rectMargins.left + m_rectMargins.right + MIN_MARGIN*2,
rcElems.Height() + m_rectMargins.top + m_rectMargins.bottom + MIN_MARGIN*2);
// Rotate
if ((90==m_iAngle || 270==m_iAngle))
{
SMC_ISWAP(sizeEMF.cx, sizeEMF.cy);
}
// Available client
CRect rc;
GetClientRect(rc);
int iWndCx = rc.Width();
int iWndCy = rc.Height();
#if 0
// TODO: take care of the vertical scrollbar, if it would show
if (SC_FIT_WIDTH==m_iFitMode)
{
// iWndCx -= GetSystemMetrics(SM_CXVSCROLL);
}
#endif
// scale
float fScale;
switch (m_iFitMode)
{
case SC_FIT_WIDTH:
fScale = float(iWndCx)/float(sizeEMF.cx);
break;
case SC_FIT_PAGE:
if (iWndCx>=iWndCy)
{// attempt keep y, and reduce x
fScale = float(iWndCy)/float(sizeEMF.cy);
if (fScale*sizeEMF.cx > iWndCx)
fScale = float(iWndCx)/float(sizeEMF.cx);
} else
{// attempt keep x, and reduce y
fScale = float(iWndCx)/float(sizeEMF.cx);
if (fScale*sizeEMF.cy > iWndCy)
fScale = float(iWndCy)/float(sizeEMF.cy);
}
break;
default:
ASSERT(0);
return;
}
m_iCurZoom = (int)(fScale*SC_ZOOM100);
if (m_iCurZoom<SC_MIN_ZOOM)
m_iCurZoom = SC_MIN_ZOOM;
else
if (m_iCurZoom>SC_MAX_ZOOM)
m_iCurZoom = SC_MAX_ZOOM;
}
void CSCEMFImage::SCComputePageInfo(int iPage)
{
ASSERT(m_pEMFDoc);
ASSERT(iPage>=1 && iPage<=(int)m_pEMFDoc->SCGetNbPages());
PSCEMFDocPage pDocPage = m_pEMFDoc->SCGetDocPage(iPage - 1);
ASSERT(pDocPage);
pDocPage->SCComputePageInfo(m_bReverseVideo, m_rectMargins);
}
/////////////////////////////////////////////////////////////////////////////
// CSCEMFImage printing
// Note: does not work!
void CSCEMFImage::SCPrintImage(CDC* pDC, CPrintInfo* pInfo, BOOL bFit/*=FALSE*/)
{
if (!pDC)
return;
if (!m_pEMFDoc || !m_pEMFDoc->SCGetNbPages())
return;
// paper in logical coordinates
CRect rcPaper = pInfo->m_rectDraw;
int xDest = rcPaper.left;
int yDest = rcPaper.top;
HDC hDC = pDC->m_hDC;
// We are going to seriously alter the DC (rotation, metafile playing, etc.).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -