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

📄 imageeditorview.cpp

📁 在mfc环境下实现的绘图板程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// ImageEditorView.cpp : CImageEditorView 类的实现
//

#include "stdafx.h"
#include "ImageEditor.h"
#include "ImageEditorDoc.h"
#include "DrawObject.h"
#include "ImageEditorView.h"
#include <math.h>
#include <atlenc.h>
#include "structure.h"
#include "MainFrm.h"
#include "ColorPaletteBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CImageEditorView

IMPLEMENT_DYNCREATE(CImageEditorView, CADMMScrollView)

BEGIN_MESSAGE_MAP(CImageEditorView, CADMMScrollView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CADMMScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CADMMScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CADMMScrollView::OnFilePrintPreview)

	ON_COMMAND_RANGE(ID_EDIT_SELECT, ID_EDIT_ROUND_RECT, OnSelectEditTool)
    ON_UPDATE_COMMAND_UI_RANGE(ID_EDIT_SELECT, ID_EDIT_ROUND_RECT, OnUpdateSelectEditTool)
	ON_WM_ERASEBKGND()
	ON_COMMAND(ID_FILE_OPEN, &CImageEditorView::OnFileOpen)
	ON_COMMAND(ID_FILE_SAVE, &CImageEditorView::OnFileSave)
	ON_COMMAND(ID_EDIT_CUT, &CImageEditorView::OnEditCut)
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	ON_COMMAND(ID_EDIT_UNDO, &CImageEditorView::OnEditUndo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, &CImageEditorView::OnUpdateEditUndo)
	ON_COMMAND(ID_EDIT_REDO, &CImageEditorView::OnEditRedo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, &CImageEditorView::OnUpdateEditRedo)
	ON_COMMAND(ID_EDIT_COPY, &CImageEditorView::OnEditCopy)
	
	ON_NOTIFY(NM_CLICK, IDW_COMBO, OnToolStyleChange)
	ON_COMMAND(ID_EDIT_PASTE, &CImageEditorView::OnEditPaste)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_MESSAGE(WM_HOTKEY,OnHotKey)
	ON_WM_SETCURSOR()
END_MESSAGE_MAP()


// CImageEditorView 构造/析构

CImageEditorView::CImageEditorView()
{
	m_nCurToolIndex = ID_EDIT_PEN;
	m_sizeCanvas.SetSize(12000,10000);
	m_fZoomScale = 1;
	
	m_pHistoryStack =new Stack(5);
	m_pCurObj = NULL;
	m_curMode = smNone;
	m_bCurrentObjectIsActive = FALSE;
	m_nDragHandle = 0;
	m_nCanvasHandle = 0;
	m_pEditBox = NULL;

	m_emLineWidth = 1;
	m_emBrushStyle = CDrawObject::MyPenStyle::psDot2;
	m_emShapeStyle = CDrawObject::ShapeStyle::styleFrameOnly;
}


CImageEditorView::~CImageEditorView()
{
	if(m_pHistoryStack)
	{
		delete m_pHistoryStack;
		m_pHistoryStack = NULL;
	}
	if (m_pCurObj)
	{
		delete m_pCurObj;
		m_pCurObj =NULL;
	}
	if (m_pEditBox)
	{
		delete m_pEditBox;
		m_pEditBox = NULL;
	}
}
void CImageEditorView::ShowEditBox(const CRect& rect, const CString& strText)
{
	CRect rectClient(rect);
	this->DocToClient(rectClient);
	if (m_pEditBox==NULL)
	{
		m_pEditBox = new CEdit;
		m_pEditBox->Create(ES_MULTILINE|ES_AUTOVSCROLL|WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER,rectClient, this, 1);
		m_fontEditBox.CreateFont(-1 * 12, 0, 0, 0, 20, 
						FALSE, FALSE, 0,
						ANSI_CHARSET, OUT_DEFAULT_PRECIS,
						CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
						DEFAULT_PITCH | FF_SWISS, _T("Arial")); 
		m_pEditBox->SetFont(&m_fontEditBox);
	}
	else
	{
		m_pEditBox->SetFont(&GetColorBar()->m_font);
		m_pEditBox->MoveWindow(rectClient);						
		m_pEditBox->ModifyStyle(NULL,WS_VISIBLE);
	}
	m_pEditBox->SetWindowText(strText);	
	int len = strText.GetLength();
	m_pEditBox->SetSel(len, len);
}
CColorPaletteBar* CImageEditorView::GetColorBar()
{
	return &((CMainFrame*)AfxGetMainWnd())->m_wndColorBar;
}

BOOL CImageEditorView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CADMMScrollView::PreCreateWindow(cs);
}

// CImageEditorView 绘制

void CImageEditorView::OnDraw(CDC* pDC)
{
	CRect rcClient;
	this->GetClientRect(rcClient);
	pDC->DPtoLP(&rcClient);

	CDC dcMem;
	dcMem.CreateCompatibleDC(pDC); 
	CUtility::PrepareDC(dcMem.m_hDC,m_fZoomScale);
	CBitmap bmp;
	CSize bmpSize(rcClient.Width(),rcClient.Height());
	dcMem.LPtoDP(&bmpSize);
	bmp.CreateCompatibleBitmap(pDC,bmpSize.cx,bmpSize.cy);
	dcMem.SelectObject(&bmp);  

	CPoint ptTopLeft(rcClient.left,rcClient.top);
	dcMem.LPtoDP(&ptTopLeft);
	dcMem.OffsetViewportOrg(-ptTopLeft.x,-ptTopLeft.y);

	//绘制	
	DoDraw(&dcMem,TRUE);
	DrawCanvasTracker(&dcMem);
	//贴到屏幕
	pDC->BitBlt(rcClient.left,rcClient.top,rcClient.Width(),rcClient.Height(),&dcMem,rcClient.left,rcClient.top,SRCCOPY);
	dcMem.DeleteDC();
}
void CImageEditorView::DoDraw(CDC *pDC, BOOL bToScreen)
{
	if (!m_imgCurent.IsNull()) 
		m_imgCurent.Detach();

	HBITMAP hBmp = m_pHistoryStack->GetCurrent();
	if (hBmp)	
	{
		m_imgCurent.Attach(hBmp);
		CSize sizePic; //图片的大小 pix Unit

		if (bToScreen) //如果是从bmp显示到屏幕 则大小以bmp为准
		{
			sizePic.SetSize(m_imgCurent.GetWidth(),m_imgCurent.GetHeight());
			CSize sizeTemp(m_sizeCanvas);
			pDC->LPtoDP(&sizeTemp);
			if (sizeTemp!=sizePic)
			{
				m_sizeCanvas = sizePic;
				pDC->DPtoLP(&m_sizeCanvas);
				m_sizeCanvas.SetSize(m_sizeCanvas.cx*m_fZoomScale, m_sizeCanvas.cy*m_fZoomScale);
			}
 
			DrawBackGround(pDC);	
		}
		else //否则以屏幕画布大小为准
		{
			sizePic = m_sizeCanvas;
			pDC->LPtoDP(&sizePic);

			//如果将画布拖大 则用背景填充
			if (m_imgCurent.GetWidth()<sizePic.cx || m_imgCurent.GetHeight()<sizePic.cy)
			{
				CSize sizeReal(m_imgCurent.GetWidth(),m_imgCurent.GetHeight());
				pDC->DPtoLP(&sizeReal);

				CRect  rect1(sizeReal.cx, 0, m_sizeCanvas.cx, m_sizeCanvas.cy);
				pDC->FillRect(&rect1,&CBrush(GetColorBar()->m_colorBack));

				CRect  rect2(0, sizeReal.cy, m_sizeCanvas.cx, m_sizeCanvas.cy);
				pDC->FillRect(&rect2,&CBrush(GetColorBar()->m_colorBack));
			}
		}

		m_imgCurent.StretchBlt(pDC->GetSafeHdc(),
							   0,0,m_sizeCanvas.cx,m_sizeCanvas.cy,
							   0,0,sizePic.cx,sizePic.cy,
							   SRCCOPY);
	}
	//
	if (m_pCurObj)
	{
		m_pCurObj->DrawSelf(pDC);
		if (m_bCurrentObjectIsActive)
			m_pCurObj->DrawTracker(pDC);
	}
}
void CImageEditorView::OnInitialUpdate()
{
	CADMMScrollView::OnInitialUpdate();

	CSize sizeTotal;
	sizeTotal.cx = sizeTotal.cy = 20000;
	SetScrollSizes(MM_ISOTROPIC, sizeTotal);
	CreatDefaultImage();
}

void CImageEditorView::UpdateViewSize()
{
	CSize sizeNew(m_totalLog);
	//if (sizeNew.cx<m_sizeCanvas.cx*m_fZoomScale) 
		sizeNew.cx = m_sizeCanvas.cx*m_fZoomScale+1000;

	//if (sizeNew.cy<m_sizeCanvas.cy*m_fZoomScale)
		sizeNew.cy = m_sizeCanvas.cy*m_fZoomScale+1000;

	if (sizeNew!=m_totalLog)
		this->SetScrollSizes(MM_ISOTROPIC, sizeNew);
}


BOOL CImageEditorView::CreatDefaultImage(void)
{
	CSize size(m_sizeCanvas);
	this->DocToClient(size);
	
	HBITMAP      hBmp;
	CClientDC	dc(this);
	CDC 		memDC;
	CBitmap     bitmap;

	CBitmap *pOldBitmap;
	memDC.CreateCompatibleDC(&dc);
	bitmap.CreateCompatibleBitmap(&dc, size.cx,size.cy);
	pOldBitmap = memDC.SelectObject(&bitmap);
	memDC.FillRect(&CRect(0,0,size.cx,size.cy),&CBrush(RGB(255,255,255)));
	hBmp=(HBITMAP)bitmap.GetSafeHandle();	
	memDC.SelectObject(pOldBitmap);
	bitmap.Detach();

	if (hBmp)
	{	
		InitHistory(hBmp);
		return TRUE;
	}
	return FALSE;
}

HBITMAP CImageEditorView::CanvasToBmp(void)
{
	HBITMAP      hBmp;
	CClientDC	dc(this);
	CDC 		memDC;
	CBitmap     bitmap;

	CSize size(m_sizeCanvas.cx/m_fZoomScale,m_sizeCanvas.cy/m_fZoomScale);
	this->DocToClient(size);

	CBitmap *pOldBitmap;
	memDC.CreateCompatibleDC(&dc);
	bitmap.CreateCompatibleBitmap(&dc, size.cx,size.cy);
	pOldBitmap = memDC.SelectObject(&bitmap);
	CUtility::PrepareDC(memDC.m_hDC);
	this->DoDraw(&memDC);
	hBmp=(HBITMAP)bitmap.GetSafeHandle();	
	memDC.SelectObject(pOldBitmap);
	bitmap.Detach();
	return hBmp;
}

// CImageEditorView 打印

BOOL CImageEditorView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void CImageEditorView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void CImageEditorView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}


// CImageEditorView 诊断

#ifdef _DEBUG
void CImageEditorView::AssertValid() const
{
	CADMMScrollView::AssertValid();
}

void CImageEditorView::Dump(CDumpContext& dc) const
{
	CADMMScrollView::Dump(dc);
}

CImageEditorDoc* CImageEditorView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CImageEditorDoc)));
	return (CImageEditorDoc*)m_pDocument;
}
#endif //_DEBUG


// CImageEditorView 消息处理程序

void CImageEditorView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
	CADMMScrollView::OnPrepareDC(pDC, pInfo);
	pDC->SetViewportExt((int)(m_XLogPix*m_fZoomScale),(int)(m_YLogPix*m_fZoomScale));	
}

void CImageEditorView::OnSelectEditTool(UINT id)
{
	m_nCurToolIndex = id;
	((CMainFrame*)AfxGetMainWnd())->OnChangeTool(id);

	SetInitState();
	if (m_pCurObj!=NULL)
	{
		this->InvalidateObj(m_pCurObj);
		RecordHistory();
	}
}
void CImageEditorView::SetInitState()
{
	m_curMode = smNone;
	HidenEditBox();
	m_bCurrentObjectIsActive = FALSE;
}
void CImageEditorView::OnUpdateSelectEditTool(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(pCmdUI->m_nID == m_nCurToolIndex);
}
BOOL CImageEditorView::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

void CImageEditorView::DrawBackGround(CDC *pDC)
{
	CRect rcClient;
	this->GetClientRect(rcClient);
	pDC->DPtoLP(&rcClient);
	CBrush brush(RGB(128, 128, 128));
	pDC->FillRect(&rcClient,&brush);
	brush.DeleteObject(); 
}
void CImageEditorView::OnFileOpen()
{
	CString strFilter;// = _T("Bitmap image|*.bmp|JPEG image|*.jpg|GIF image|*.gif|PNG image|*.png||");
	CSimpleArray<GUID> aguidFileTypes;
	HRESULT hResult;

	hResult = m_imgCurent.GetExporterFilterString(strFilter,aguidFileTypes);
	if (FAILED(hResult)) 
	{
		CString fmt;
		fmt.Format(_T("GetExporterFilter failed:\n%x - %s"), hResult, _com_error(hResult).ErrorMessage());
		::AfxMessageBox(fmt);
		return;
	}

	CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
	if (dlg.DoModal()==IDOK)
	{
		m_imgCurent.Destroy();
		hResult = m_imgCurent.Load(dlg.GetFileName());
		if (FAILED(hResult)) 
		{
			CString fmt;
			fmt.Format(_T("Load image failed:\n%x - %s"), hResult, _com_error(hResult).ErrorMessage());
			::AfxMessageBox(fmt);
			return;
		}
		m_sizeCanvas.SetSize(m_imgCurent.GetWidth(),m_imgCurent.GetHeight());
		this->ClientToDoc(m_sizeCanvas);
		InitHistory(m_imgCurent.Detach());
		UpdateViewSize();
		this->Invalidate();
	}
}

void CImageEditorView::OnFileSave()
{
	CString strFilter = _T("Bitmap image|*.bmp|JPEG image|*.jpg|GIF image|*.gif|PNG image|*.png||");
	CFileDialog dlg(FALSE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
	if (dlg.DoModal()==IDOK)
	{
		CString strFileName;
		CString strExtension;
		strFileName = dlg.m_ofn.lpstrFile;

		// add the file extension if the user didn't supply one
		if (dlg.m_ofn.nFileExtension == 0) 
		{
			switch (dlg.m_ofn.nFilterIndex)
			{
			case 1:
				strExtension = "bmp";
				break;
			case 2:
				strExtension = "jpg";
				break;
			case 3:
				strExtension = "gif";
				break;
			case 4:
				strExtension = "png";
				break;
			default:
				break;
			}

			strFileName = strFileName + '.' + strExtension;

		}

		// the extension on the file name will determine the file type that is saved
		HRESULT hResult = m_imgCurent.Save(strFileName);
		if (FAILED(hResult)) {
			CString fmt;
			fmt.Format(_T("Save image failed:\n%x - %s"), hResult, _com_error(hResult).ErrorMessage());
			::AfxMessageBox(fmt);
			return;
		}
	}
}

// 坐标转换
// =======================================================================================================
//
void CImageEditorView::ClientToDoc(CPoint& point)
{
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.DPtoLP(&point);
}

void CImageEditorView::ClientToDoc(CRect& rect)
{
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.DPtoLP(rect);
}

void CImageEditorView::ClientToDoc(CSize& size)
{
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.DPtoLP(&size);
}
void CImageEditorView::DocToClient(CPoint& point)
{
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.LPtoDP(&point);
}

void CImageEditorView::DocToClient(CRect& rect)
{
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.LPtoDP(rect);
	rect.NormalizeRect();
}
void CImageEditorView::DocToClient(CSize& size)
{
	CClientDC dc(this);
	OnPrepareDC(&dc, NULL);
	dc.LPtoDP(&size);
}

void CImageEditorView::SetZoomScale(float fValue)
{
	if (fValue<1)
		fValue = 1;
	else if (fValue>8)
		fValue = 8;

	if (fabs(m_fZoomScale - fValue)>0.000001)

⌨️ 快捷键说明

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