⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 visdrawscrollview.cpp

📁 参数化车间设备资源绘制程序
💻 CPP
字号:
// VisDrawScrollView.cpp : 实现文件
//

#include "stdafx.h"
#include "VisDraw.h"
//#include "VisDrawScrollView.h"
#include ".\visdrawscrollview.h"


// CVisDrawScrollView

IMPLEMENT_DYNCREATE(CVisDrawScrollView, CScrollView)


CVisDrawScrollView::CVisDrawScrollView()
{
	m_bCenter = TRUE;

	m_bExtendX = FALSE;
	m_bExtendY = FALSE;
	m_Delta = 0;
	m_Center = CPoint(0, 0);
	m_Offset = CPoint(0, 0);
	m_Ratio = CSize(1, 1);
}

CVisDrawScrollView::~CVisDrawScrollView()
{
}


BEGIN_MESSAGE_MAP(CVisDrawScrollView, CScrollView)
	ON_WM_VSCROLL()
	ON_WM_HSCROLL()
	ON_WM_KEYDOWN()
END_MESSAGE_MAP()


// CVisDrawScrollView 绘图

void CVisDrawScrollView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: 在此添加绘制代码
}


// CVisDrawScrollView 诊断

#ifdef _DEBUG
void CVisDrawScrollView::AssertValid() const
{
	CScrollView::AssertValid();
}

void CVisDrawScrollView::Dump(CDumpContext& dc) const
{
	CScrollView::Dump(dc);
}
#endif //_DEBUG


// CVisDrawScrollView 消息处理程序


CSize CVisDrawScrollView::GetTotalSize() const
{
	// return the true total size (scroll view + offset)
	return m_TotalSize;
}


void CVisDrawScrollView::SetScrollSizes(int nMapMode, SIZE sizeTotal, const SIZE& sizePage, const SIZE& sizeLine)
{
	long cx, cy;

	// save total size
	ASSERT(sizeTotal.cx > 0 && sizeTotal.cy > 0);
	CSize TotalSize = sizeTotal;

	// compute document size in logical unit
	cx = sizeTotal.cx;
	cy = sizeTotal.cy;
	
	// scroll size can't be greater than 32768
	if (sizeTotal.cx > 32768) sizeTotal.cx = 32768;
	if (sizeTotal.cy > 32768) sizeTotal.cy = 32768;
	
	// calculate if BigScrollSize greater than ScrollSize
	cx -= sizeTotal.cx; m_bExtendX = (cx != 0);
	cy -= sizeTotal.cy; m_bExtendY = (cy != 0);

	// if first time, init client center and offset
	if (m_nMapMode == MM_NONE)
	{
		ASSERT(nMapMode > 0);
		int y = sizeTotal.cy / 2;
		if (nMapMode != MM_TEXT) y = -y;
		m_Center = CPoint(sizeTotal.cx / 2, y);
		m_Offset = CPoint(cx / 2, cy / 2);
		m_Ratio = TotalSize;
	}
	else SaveClientCenter();
	
	// to correct scroll position between DP and LP
	m_Delta = 0;
	if (nMapMode != MM_TEXT)
	{
		ASSERT(nMapMode > 0);
		CPoint point(1, 1);
		CWindowDC dc(NULL);
		dc.SetMapMode(nMapMode);
		dc.DPtoLP(&point);
		m_Delta = point.x;
	}

	SetRedraw(FALSE);
	CScrollView::SetScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine);
	m_TotalSize = TotalSize;
	RestoreClientCenter();
	SetRedraw(TRUE);
	Invalidate(TRUE);
	
}

//把设备坐标转化为逻辑坐标
void CVisDrawScrollView::ClientToDoc(CPoint& Point)
{	
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.DPtoLP(&Point);
	Point += m_Offset;
}

//把设备坐标转化为逻辑坐标
void CVisDrawScrollView::ClientToDocDraw(CPoint& Point)
{	
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.DPtoLP(&Point);	
}

//把设备矩形转化为逻辑矩形
void CVisDrawScrollView::ClientToDoc(CRect& rect)
{
	CPoint point = (m_nMapMode != MM_NONE) ? GetDeviceScrollPosition(): CPoint(0, 0);
	rect += point;
	if (m_nMapMode != MM_TEXT)
	{
		ASSERT(m_nMapMode > 0); // must be set
		CWindowDC dc(NULL);
		dc.SetMapMode(m_nMapMode);
		dc.DPtoLP(rect);
	}
	rect += m_Offset;
}

//把设备矩形转化为逻辑矩形
void CVisDrawScrollView::ClientToDocDraw(CRect& rect)
{
	CPoint point = (m_nMapMode != MM_NONE) ? GetDeviceScrollPosition(): CPoint(0, 0);
	rect += point;
	if (m_nMapMode != MM_TEXT)
	{
		ASSERT(m_nMapMode > 0); // must be set
		CWindowDC dc(NULL);
		dc.SetMapMode(m_nMapMode);
		dc.DPtoLP(rect);
	}
	
}

//把逻辑坐标转化为设备坐标
void CVisDrawScrollView::DocToClient(CPoint& point)
{
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.LPtoDP(&point);
//	point -= m_Offset;
}

//把矩形逻辑矩形转化为设备矩形
void CVisDrawScrollView::DocToClient(CRect& rect)
{
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.LPtoDP(rect);

	rect.NormalizeRect();

//	rect -= m_Offset;
}

CPoint CVisDrawScrollView::GetLogPosition(CPoint Point) const
{
	// return the true point position (scroll view + offset)
	CPoint point = (m_nMapMode != MM_NONE) ? GetDeviceScrollPosition(): CPoint(0, 0);
	Point += point;
	if (m_nMapMode != MM_TEXT)
	{
		ASSERT(m_nMapMode > 0); // must be set
		CWindowDC dc(NULL);
		dc.SetMapMode(m_nMapMode);
		dc.DPtoLP(&Point);
	}
	Point += m_Offset;

	return Point;
}

//把矩形设备坐标转化为逻辑坐标

void CVisDrawScrollView::GetLogPosition(CRect &rect)
{
	// return the true point position (scroll view + offset)
	CPoint point = (m_nMapMode != MM_NONE) ? GetDeviceScrollPosition(): CPoint(0, 0);
	rect += point;
	if (m_nMapMode != MM_TEXT)
	{
		ASSERT(m_nMapMode > 0); // must be set
		CWindowDC dc(NULL);
		dc.SetMapMode(m_nMapMode);
		dc.DPtoLP(rect);
	}
	rect += m_Offset;
}

CPoint CVisDrawScrollView::GetDeviceScrollPosition() const
{
	CPoint pt(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT));
	ASSERT(pt.x >= 0 && pt.y >= 0);

	if (m_bCenter)
	{
		CRect rect;
		GetClientRect(&rect);

		// if client area is larger than total device size,
		// the scroll positions are overridden to place origin such that
		// output is centered in the window
		// GetDeviceScrollPosition() must reflect this

		if (m_totalDev.cx < rect.Width())
			pt.x = -((rect.Width() - m_totalDev.cx) / 2);
		if (m_totalDev.cy < rect.Height())
			pt.y = -((rect.Height() - m_totalDev.cy) / 2);
	}

	return pt;
}


//获取设备坐标原点
CPoint CVisDrawScrollView::GetDeviceOrg() const
{
	
	CPoint pointOrg = GetDeviceScrollPosition();
	if (pointOrg.x > 0) pointOrg.x = 0;
	if (pointOrg.y > 0) pointOrg.y = 0;
	pointOrg.x = abs(pointOrg.x);
	pointOrg.y = abs(pointOrg.y);
	return pointOrg;
}
 
//得到客户区矩形逻辑坐标

void CVisDrawScrollView::GetLogClientRect(CRect *pRect) const
{
	// return the true client rectangle (scroll view + offset)
	
	GetClientRect(pRect);
	CPoint point = (m_nMapMode != MM_NONE) ? GetDeviceScrollPosition(): CPoint(0, 0);
	pRect->OffsetRect(point.x, point.y);
	if (m_nMapMode != MM_TEXT)
	{
		ASSERT(m_nMapMode > 0); // must be set
		CWindowDC dc(NULL);
		dc.SetMapMode(m_nMapMode);
		dc.DPtoLP(pRect);
	}
	pRect->OffsetRect(m_Offset);
}

CPoint CVisDrawScrollView::GetLogClientCenter() const
{
	// return the true client center (scroll view + offset)
	CRect rect;
	GetLogClientRect(&rect);
	return rect.CenterPoint();
}

void CVisDrawScrollView::SaveClientCenter()
{
	// save client center and scale factor
	m_Center = GetLogClientCenter();
	m_Ratio  = m_TotalSize;
}

void CVisDrawScrollView::RestoreClientCenter()
{
	// update client center with scale and restore center
	m_Center.x = MulDiv(m_Center.x, m_TotalSize.cx, m_Ratio.cx);
	m_Center.y = MulDiv(m_Center.y, m_TotalSize.cy, m_Ratio.cy);
	CenterOnPoint(m_Center);
}

void CVisDrawScrollView::CenterOnPoint(CPoint ptCenter)
{
	// save scroll position & offset
	CPoint savePosition = CScrollView::GetScrollPosition();
	CPoint saveOffset = m_Offset;
	
	CRect rect;	GetClientRect(&rect);
	CPoint Center = rect.CenterPoint();
	if (m_nMapMode != MM_TEXT)
	{
		ASSERT(m_nMapMode > 0); // must be set
		CWindowDC dc(NULL);
		dc.SetMapMode(m_nMapMode);
		dc.DPtoLP(&Center);
	}

	// reverse direction
	if (m_nMapMode != MM_TEXT)
	{
		ptCenter.y = -ptCenter.y;
		Center.y = -Center.y;
	}

	CPoint Position(ptCenter.x - Center.x, ptCenter.y - Center.y);

	if (m_bExtendX)		// BigScrollSize < ScrollSize
	{
		// window is left over
		if (ptCenter.x < Center.x)
		{
			Position.x = 0;
			m_Offset.x = 0;
		}
		// page is left over
		else if (ptCenter.x < 16384)
		{
			Position.x = (int)(ptCenter.x - Center.x);
			m_Offset.x = 0;
		}
		// window is right over
		else if (ptCenter.x + Center.x > m_TotalSize.cx)
		{
			Position.x = (int)(32768 - 2 * Center.x);
			m_Offset.x = m_TotalSize.cx - 32768;
		}
		// page is right over
		else if (ptCenter.x + 16384 > m_TotalSize.cx)
		{
			Position.x = (int)(32768 - Center.x - m_TotalSize.cx + ptCenter.x);
			m_Offset.x = m_TotalSize.cx - 32768;
		}
		// page is centered
		else
		{
			Position.x = (int)(16384 - Center.x);
			m_Offset.x = ptCenter.x - 16384;
		}
	}
	else m_Offset.x = 0;

	if (m_bExtendY)		// BigScrollSize < ScrollSize
	{
		// window is top over
		if (ptCenter.y < Center.y)
		{
			Position.y = 0;
			m_Offset.y = 0;
		}
		// page is top over
		else if (ptCenter.y < 16384)
		{
			Position.y = (int)(ptCenter.y - Center.y);
			m_Offset.y = 0;
		}
		// window is bottom over
		else if (ptCenter.y + Center.y > m_TotalSize.cy)
		{
			Position.y = (int)(32768 - 2 * Center.y);
			m_Offset.y = m_TotalSize.cy - 32768;
		}
		// page is bottom over
		else if (ptCenter.y + 16384 > m_TotalSize.cy)
		{
			Position.y = (int)(32768 - Center.y - m_TotalSize.cy + ptCenter.y);
			m_Offset.y = m_TotalSize.cy - 32768;
		}
		// page is centered
		else
		{
			Position.y = (int)(16384 - Center.y);
			m_Offset.y = ptCenter.y - 16384;
		}
	}
	else m_Offset.y = 0;

	// reverse direction
	if (m_nMapMode != MM_TEXT)
	{
		ptCenter.y = -ptCenter.y;
		Position.y = -Position.y;
		m_Offset.y = -m_Offset.y;
	}

	
	if (Position != savePosition)
	{
		CScrollView::ScrollToPosition(Position);
	}
	
	// if offset change, scroll window
	if (saveOffset != m_Offset)
	{
		CSize sizeScroll(saveOffset.x - m_Offset.x, saveOffset.y - m_Offset.y);
		if (m_nMapMode != MM_TEXT)
		{
			ASSERT(m_nMapMode > 0); // must be set
			CWindowDC dc(NULL);
			dc.SetMapMode(m_nMapMode);
			dc.LPtoDP(&sizeScroll);
		}
		ScrollWindow(sizeScroll.cx, -sizeScroll.cy);
	}

	SaveClientCenter();
}


CPoint CVisDrawScrollView::GetScrollPosition() const
{
	// return the true scroll position (scroll view + offset)
	CPoint point = CScrollView::GetScrollPosition();
	point += m_Offset;
	return point;
}

void CVisDrawScrollView::ScrollToPosition(POINT Point)
{
	CRect rect;
	GetLogClientRect(&rect);
	Point.x += rect.Width() / 2;
	Point.y += rect.Height() / 2;
	// use center on point to scroll to, new offset will be calculated
	CenterOnPoint(Point);
}

void CVisDrawScrollView::SetScaleToFitSize(SIZE sizeTotal)
{
	// do not use CScrollView::SetScaleToFit();
	// this function change the size of the view !
	CSize sizeClient, sizeSb;
	GetTrueClientSize(sizeClient, sizeSb);
	if (m_nMapMode != MM_TEXT)
	{
		ASSERT(m_nMapMode > 0); // must be set
		CWindowDC dc(NULL);
		dc.SetMapMode(m_nMapMode);
		dc.DPtoLP(&sizeClient);
	}
	if (sizeClient.cy < MulDiv(sizeTotal.cy, sizeClient.cx, sizeTotal.cx))
	{
		// add 1% to eliminate scroll bars
		sizeTotal.cy = MulDiv(sizeTotal.cy, 101, 100);
		sizeTotal.cx = MulDiv(sizeTotal.cx, sizeClient.cy, sizeTotal.cy);
		sizeTotal.cy = sizeClient.cy;
	}
	else
	{
		// add 1% to eliminate scroll bars
		sizeTotal.cx = MulDiv(sizeTotal.cx, 101, 100);
		sizeTotal.cx = sizeClient.cx;
		sizeTotal.cy = MulDiv(sizeTotal.cy, sizeClient.cx, sizeTotal.cx);
	}
	SetScrollSizes(m_nMapMode, sizeTotal);
}


void CVisDrawScrollView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	if (m_bExtendY && nSBCode != SB_ENDSCROLL)
	{
		CPoint ScrollPos = CScrollView::GetScrollPosition();
		CRect rect; GetLogClientRect(&rect);
		int Height = rect.Height();

		// reverse direction
		if (m_nMapMode != MM_TEXT)
		{
			ScrollPos.y = -ScrollPos.y;
			Height = -Height;
			m_Offset.y = -m_Offset.y;
		}

		CClientDC dc(this);
		dc.SetMapMode(m_nMapMode);

		SIZE size;
		switch (nSBCode)
		{
			case SB_LINEUP:
			case SB_LINEDOWN:
				size = m_lineDev;
				break;
			case SB_PAGEUP:
			case SB_PAGEDOWN:
				size = m_pageDev;
				break;
			default:
				size.cx = size.cy = 0;
		}
		dc.DPtoLP(&size);

		// on top
		if (ScrollPos.y == 0)
		{
			m_Offset.y -= size.cy;
			if (m_Offset.y < 0)
			{
				MessageBeep(MB_ICONEXCLAMATION);
				m_Offset.y = 0;
			}
			Invalidate(TRUE);
		}
		// on bottom
		else if (ScrollPos.y >= 32768 - Height - m_Delta)
		{
			m_Offset.y += size.cy;
			if (m_Offset.y > m_TotalSize.cy - 32768)
			{
				MessageBeep(MB_ICONEXCLAMATION);
				m_Offset.y = m_TotalSize.cy - 32768;
			}
			Invalidate(TRUE);
		}

		// reverse direction
		if (m_nMapMode != MM_TEXT)
			m_Offset.y = -m_Offset.y;
	}
	CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
	SaveClientCenter();
}

void CVisDrawScrollView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	if (m_bExtendX && nSBCode != SB_ENDSCROLL)
	{
		CPoint ScrollPos = CScrollView::GetScrollPosition();
		CRect rect; GetLogClientRect(&rect);
		int Width = rect.Width();

		CClientDC dc(this);
		dc.SetMapMode(m_nMapMode);

		SIZE size;
		switch (nSBCode)
		{
			case SB_LINELEFT:
			case SB_LINERIGHT:
				size = m_lineDev;
				break;
			case SB_PAGELEFT:
			case SB_PAGERIGHT:
				size = m_pageDev;
				break;
			default:
				size.cx = size.cy = 0;
		}
		dc.DPtoLP(&size);
    
		// left side
		if (ScrollPos.x == 0)
		{
			m_Offset.x -= size.cx;
			if (m_Offset.x < 0)
			{
				MessageBeep(MB_ICONEXCLAMATION);
				m_Offset.x = 0;
			}
			Invalidate(TRUE);
		}
		// right side
		else if (ScrollPos.x >= 32768 - Width - m_Delta)
		{
			m_Offset.x += size.cx;
			if (m_Offset.x > m_TotalSize.cx - 32768)
			{
				MessageBeep(MB_ICONEXCLAMATION);
				m_Offset.x = m_TotalSize.cx - 32768;
			}
			Invalidate(TRUE);
		}
	}
	CScrollView::OnHScroll(nSBCode, nPos, pScrollBar);
	SaveClientCenter();
}

void CVisDrawScrollView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	switch(nChar)
	{
	case VK_LEFT:
		SendMessage(WM_HSCROLL,SB_LINEUP);
		break;
		
	case VK_RIGHT:
		SendMessage(WM_HSCROLL,SB_LINEDOWN);
		break;

	case VK_UP:
		SendMessage(WM_VSCROLL,SB_LINEUP);
		break;

	case VK_DOWN:
		SendMessage(WM_VSCROLL,SB_LINEDOWN);
		break;
	}

	CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CVisDrawScrollView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
	// TODO: 在此添加专用代码和/或调用基类

	CScrollView::OnPrepareDC(pDC, pInfo);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -