📄 drawvw.cpp
字号:
// drawvw.cpp : implementation of the CDrawView class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include <afxpriv.h>
#include "drawcli.h"
#include "drawdoc.h"
#include "drawobj.h"
#include "cntritem.h"
#include "drawvw.h"
#include "drawobj.h"
#include "drawtool.h"
#include "mainfrm.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
// private clipboard format (list of Draw objects)
CLIPFORMAT CDrawView::m_cfDraw = (CLIPFORMAT)
::RegisterClipboardFormat(_T("MFC Draw Sample"));
CLIPFORMAT CDrawView::m_cfObjectDescriptor = NULL;
/////////////////////////////////////////////////////////////////////////////
// CDrawView
IMPLEMENT_DYNCREATE(CDrawView, CScrollView)
BEGIN_MESSAGE_MAP(CDrawView, CScrollView)
//{{AFX_MSG_MAP(CDrawView)
ON_COMMAND(ID_OLE_INSERT_NEW, OnInsertObject)
ON_COMMAND(ID_CANCEL_EDIT, OnCancelEdit)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDBLCLK()
ON_COMMAND(ID_DRAW_SELECT, OnDrawSelect)
ON_COMMAND(ID_DRAW_ROUNDRECT, OnDrawRoundRect)
ON_COMMAND(ID_DRAW_RECT, OnDrawRect)
ON_COMMAND(ID_DRAW_LINE, OnDrawLine)
ON_COMMAND(ID_DRAW_ELLIPSE, OnDrawEllipse)
ON_UPDATE_COMMAND_UI(ID_DRAW_ELLIPSE, OnUpdateDrawEllipse)
ON_UPDATE_COMMAND_UI(ID_DRAW_LINE, OnUpdateDrawLine)
ON_UPDATE_COMMAND_UI(ID_DRAW_RECT, OnUpdateDrawRect)
ON_UPDATE_COMMAND_UI(ID_DRAW_ROUNDRECT, OnUpdateDrawRoundRect)
ON_UPDATE_COMMAND_UI(ID_DRAW_SELECT, OnUpdateDrawSelect)
ON_UPDATE_COMMAND_UI(ID_OBJECT_MOVEBACK, OnUpdateSingleSelect)
ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateAnySelect)
ON_COMMAND(ID_DRAW_POLYGON, OnDrawPolygon)
ON_UPDATE_COMMAND_UI(ID_DRAW_POLYGON, OnUpdateDrawPolygon)
ON_WM_SIZE()
ON_COMMAND(ID_VIEW_GRID, OnViewGrid)
ON_UPDATE_COMMAND_UI(ID_VIEW_GRID, OnUpdateViewGrid)
ON_WM_ERASEBKGND()
ON_COMMAND(ID_OBJECT_FILLCOLOR, OnObjectFillColor)
ON_COMMAND(ID_OBJECT_LINECOLOR, OnObjectLineColor)
ON_COMMAND(ID_OBJECT_MOVEBACK, OnObjectMoveBack)
ON_COMMAND(ID_OBJECT_MOVEFORWARD, OnObjectMoveForward)
ON_COMMAND(ID_OBJECT_MOVETOBACK, OnObjectMoveToBack)
ON_COMMAND(ID_OBJECT_MOVETOFRONT, OnObjectMoveToFront)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
ON_WM_SETFOCUS()
ON_COMMAND(ID_VIEW_SHOWOBJECTS, OnViewShowObjects)
ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWOBJECTS, OnUpdateViewShowObjects)
ON_COMMAND(ID_EDIT_PROPERTIES, OnEditProperties)
ON_UPDATE_COMMAND_UI(ID_EDIT_PROPERTIES, OnUpdateEditProperties)
ON_WM_DESTROY()
ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll)
ON_WM_CREATE()
ON_UPDATE_COMMAND_UI(ID_OBJECT_MOVEFORWARD, OnUpdateSingleSelect)
ON_UPDATE_COMMAND_UI(ID_OBJECT_MOVETOBACK, OnUpdateSingleSelect)
ON_UPDATE_COMMAND_UI(ID_OBJECT_MOVETOFRONT, OnUpdateSingleSelect)
ON_WM_CONTEXTMENU()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDrawView construction/destruction
CDrawView::CDrawView()
{
m_bGrid = TRUE;
m_gridColor = RGB(0, 0, 128);
m_bActive = FALSE;
// new
if( m_cfObjectDescriptor == NULL )
m_cfObjectDescriptor = (CLIPFORMAT)::RegisterClipboardFormat(_T("Object Descriptor") );
m_prevDropEffect = DROPEFFECT_NONE;
// end new
}
CDrawView::~CDrawView()
{
}
BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs)
{
ASSERT(cs.style & WS_CHILD);
if (cs.lpszClass == NULL)
cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS);
return TRUE;
}
void CDrawView::OnActivateView(BOOL bActivate,CView* pActiveView,CView* pDeactiveView)
{
CView::OnActivateView(bActivate, pActiveView, pDeactiveView);
// invalidate selections when active status changes
if (m_bActive != bActivate)
{
if (bActivate) // if becoming active update as if active
m_bActive = bActivate;
if (!m_selection.IsEmpty())
OnUpdate(NULL, HINT_UPDATE_SELECTION, NULL);
m_bActive = bActivate;
}
}
/////////////////////////////////////////////////////////////////////////////
// CDrawView drawing
void CDrawView::InvalObj(CDrawObj* pObj)
{
CRect rect = pObj->m_position;
DocToClient(rect);
if (m_bActive && IsSelected(pObj))
{
rect.left -= 4;
rect.top -= 5;
rect.right += 5;
rect.bottom += 4;
}
rect.InflateRect(1, 1); // handles CDrawOleObj objects
InvalidateRect(rect, FALSE);
}
void CDrawView::OnUpdate(CView* , LPARAM lHint, CObject* pHint)
{
switch (lHint)
{
case HINT_UPDATE_WINDOW: // redraw entire window
Invalidate(FALSE);
break;
case HINT_UPDATE_DRAWOBJ: // a single object has changed
InvalObj((CDrawObj*)pHint);
break;
case HINT_UPDATE_SELECTION: // an entire selection has changed
{
CDrawObjList* pList = pHint != NULL ?
(CDrawObjList*)pHint : &m_selection;
POSITION pos = pList->GetHeadPosition();
while (pos != NULL)
InvalObj(pList->GetNext(pos));
}
break;
case HINT_DELETE_SELECTION: // an entire selection has been removed
if (pHint != &m_selection)
{
CDrawObjList* pList = (CDrawObjList*)pHint;
POSITION pos = pList->GetHeadPosition();
while (pos != NULL)
{
CDrawObj* pObj = pList->GetNext(pos);
InvalObj(pObj);
Remove(pObj); // remove it from this view's selection
}
}
break;
case HINT_UPDATE_OLE_ITEMS:
{
CDrawDoc* pDoc = GetDocument();
POSITION pos = pDoc->GetObjects()->GetHeadPosition();
while (pos != NULL)
{
CDrawObj* pObj = pDoc->GetObjects()->GetNext(pos);
if (pObj->IsKindOf(RUNTIME_CLASS(CDrawOleObj)))
InvalObj(pObj);
}
}
break;
default:
ASSERT(FALSE);
break;
}
}
void CDrawView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
CScrollView::OnPrepareDC(pDC, pInfo);
// mapping mode is MM_ANISOTROPIC
// these extents setup a mode similar to MM_LOENGLISH
// MM_LOENGLISH is in .01 physical inches
// these extents provide .01 logical inches
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX),
pDC->GetDeviceCaps(LOGPIXELSY));
pDC->SetWindowExt(100, -100);
// set the origin of the coordinate system to the center of the page
CPoint ptOrg;
ptOrg.x = GetDocument()->GetSize().cx / 2;
ptOrg.y = GetDocument()->GetSize().cy / 2;
// ptOrg is in logical coordinates
pDC->OffsetWindowOrg(-ptOrg.x,ptOrg.y);
}
BOOL CDrawView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll)
{
// do the scroll
if (!CScrollView::OnScrollBy(sizeScroll, bDoScroll))
return FALSE;
// update the position of any in-place active item
if (bDoScroll)
{
UpdateActiveItem();
UpdateWindow();
}
return TRUE;
}
void CDrawView::OnDraw(CDC* pDC)
{
CDrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CDC dc;
CDC* pDrawDC = pDC;
CBitmap bitmap;
CBitmap* pOldBitmap;
// only paint the rect that needs repainting
CRect client;
pDC->GetClipBox(client);
CRect rect = client;
DocToClient(rect);
if (!pDC->IsPrinting())
{
// draw to offscreen bitmap for fast looking repaints
if (dc.CreateCompatibleDC(pDC))
{
if (bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()))
{
OnPrepareDC(&dc, NULL);
pDrawDC = &dc;
// offset origin more because bitmap is just piece of the whole drawing
dc.OffsetViewportOrg(-rect.left, -rect.top);
pOldBitmap = dc.SelectObject(&bitmap);
dc.SetBrushOrg(rect.left % 8, rect.top % 8);
// might as well clip to the same rectangle
dc.IntersectClipRect(client);
}
}
}
// paint background
CBrush brush;
if (!brush.CreateSolidBrush(pDoc->GetPaperColor()))
return;
brush.UnrealizeObject();
pDrawDC->FillRect(client, &brush);
if (!pDC->IsPrinting() && m_bGrid)
DrawGrid(pDrawDC);//
pDoc->Draw(pDrawDC, this);
if (pDrawDC != pDC)
{
pDC->SetViewportOrg(0, 0);
pDC->SetWindowOrg(0,0);
pDC->SetMapMode(MM_TEXT);
dc.SetViewportOrg(0, 0);
dc.SetWindowOrg(0,0);
dc.SetMapMode(MM_TEXT);
pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
&dc, 0, 0, SRCCOPY);
dc.SelectObject(pOldBitmap);
}
//*/
}
void CDrawView::Remove(CDrawObj* pObj)
{
POSITION pos = m_selection.Find(pObj);
if (pos != NULL)
m_selection.RemoveAt(pos);
}
void CDrawView::PasteNative(COleDataObject& dataObject)
{
// get file refering to clipboard data
CFile* pFile = dataObject.GetFileData(m_cfDraw);
if (pFile == NULL)
return;
// connect the file to the archive
CArchive ar(pFile, CArchive::load);
TRY
{
ar.m_pDocument = GetDocument(); // set back-pointer in archive
// read the selection
m_selection.Serialize(ar);
}
CATCH_ALL(e)
{
ar.Close();
delete pFile;
THROW_LAST();
}
END_CATCH_ALL
ar.Close();
delete pFile;
}
void CDrawView::PasteEmbedded(COleDataObject& dataObject, CPoint point )
{
BeginWaitCursor();
// paste embedded
CDrawOleObj* pObj = new CDrawOleObj(GetInitialPosition());
ASSERT_VALID(pObj);
CDrawItem* pItem = new CDrawItem(GetDocument(), pObj);
ASSERT_VALID(pItem);
pObj->m_pClientItem = pItem;
TRY
{
if (!pItem->CreateFromData(&dataObject) &&
!pItem->CreateStaticFromData(&dataObject))
{
AfxThrowMemoryException(); // any exception will do
}
// add the object to the document
GetDocument()->Add(pObj);
m_selection.AddTail(pObj);
ClientToDoc( point );
pObj->MoveTo( CRect( point, pObj->m_extent ), this );
// try to get initial presentation data
pItem->UpdateLink();
pItem->UpdateExtent();
}
CATCH_ALL(e)
{
// clean up item
pItem->Delete();
pObj->m_pClientItem = NULL;
GetDocument()->Remove(pObj);
pObj->Remove();
AfxMessageBox(IDP_FAILED_TO_CREATE);
}
END_CATCH_ALL
EndWaitCursor();
}
void CDrawView::DrawGrid(CDC* pDC)
{
CDrawDoc* pDoc = GetDocument();
COLORREF oldBkColor = pDC->SetBkColor(pDoc->GetPaperColor());
CRect rect;
rect.left = -pDoc->GetSize().cx / 2;
rect.top = -pDoc->GetSize().cy / 2;
rect.right = rect.left + pDoc->GetSize().cx;
rect.bottom = rect.top + pDoc->GetSize().cy;
// Center lines
CPen penDash;
penDash.CreatePen(PS_DASH, 1, m_gridColor);
CPen* pOldPen = pDC->SelectObject(&penDash);
pDC->MoveTo(0, rect.top);
pDC->LineTo(0, rect.bottom);
pDC->MoveTo(rect.left, 0);
pDC->LineTo(rect.right, 0);
// Major unit lines
CPen penDot;
penDot.CreatePen(PS_DOT, 1, m_gridColor);
pDC->SelectObject(&penDot);
for (int x = rect.left / 100 * 100; x < rect.right; x += 100)
{
if (x != 0)
{
pDC->MoveTo(x, rect.top);
pDC->LineTo(x, rect.bottom);
}
}
for (int y = rect.top / 100 * 100; y < rect.bottom; y += 100)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -