📄 imageeditorview.cpp
字号:
// 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 + -