home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
msdn_vcb
/
samples
/
vc98
/
mfc
/
ole
/
drawcli
/
drawtool.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-03-26
|
11KB
|
468 lines
// drawtool.cpp - implementation for drawing tools
//
// 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 "drawcli.h"
#include "drawdoc.h"
#include "drawvw.h"
#include "drawobj.h"
#include "drawtool.h"
/////////////////////////////////////////////////////////////////////////////
// CDrawTool implementation
CPtrList CDrawTool::c_tools;
static CSelectTool selectTool;
static CRectTool lineTool(line);
static CRectTool rectTool(rect);
static CRectTool roundRectTool(roundRect);
static CRectTool ellipseTool(ellipse);
static CPolyTool polyTool;
CPoint CDrawTool::c_down;
UINT CDrawTool::c_nDownFlags;
CPoint CDrawTool::c_last;
DrawShape CDrawTool::c_drawShape = selection;
CDrawTool::CDrawTool(DrawShape drawShape)
{
m_drawShape = drawShape;
c_tools.AddTail(this);
}
CDrawTool* CDrawTool::FindTool(DrawShape drawShape)
{
POSITION pos = c_tools.GetHeadPosition();
while (pos != NULL)
{
CDrawTool* pTool = (CDrawTool*)c_tools.GetNext(pos);
if (pTool->m_drawShape == drawShape)
return pTool;
}
return NULL;
}
void CDrawTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
{
// deactivate any in-place active item on this view!
COleClientItem* pActiveItem = pView->GetDocument()->GetInPlaceActiveItem(pView);
if (pActiveItem != NULL)
{
pActiveItem->Close();
ASSERT(pView->GetDocument()->GetInPlaceActiveItem(pView) == NULL);
}
pView->SetCapture();
c_nDownFlags = nFlags;
c_down = point;
c_last = point;
}
void CDrawTool::OnLButtonDblClk(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& /*point*/)
{
}
void CDrawTool::OnLButtonUp(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& point)
{
ReleaseCapture();
if (point == c_down)
c_drawShape = selection;
}
void CDrawTool::OnMouseMove(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& point)
{
c_last = point;
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
}
void CDrawTool::OnEditProperties(CDrawView* /*pView*/)
{
}
void CDrawTool::OnCancel()
{
c_drawShape = selection;
}
////////////////////////////////////////////////////////////////////////////
// CResizeTool
enum SelectMode
{
none,
netSelect,
move,
size
};
SelectMode selectMode = none;
int nDragHandle;
CPoint lastPoint;
CSelectTool::CSelectTool()
: CDrawTool(selection)
{
}
void CSelectTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
{
CPoint local = point;
pView->ClientToDoc(local);
CDrawObj* pObj;
selectMode = none;
// Check for resizing (only allowed on single selections)
if (pView->m_selection.GetCount() == 1)
{
pObj = pView->m_selection.GetHead();
nDragHandle = pObj->HitTest(local, pView, TRUE);
if (nDragHandle != 0)
selectMode = size;
}
// See if the click was on an object, select and start move if so
if (selectMode == none)
{
pObj = pView->GetDocument()->ObjectAt(local);
if (pObj != NULL)
{
selectMode = move;
if (!pView->IsSelected(pObj))
pView->Select(pObj, (nFlags & MK_SHIFT) != 0);
// Ctrl+Click clones the selection...
if ((nFlags & MK_CONTROL) != 0)
pView->CloneSelection();
}
}
// Click on background, start a net-selection
if (selectMode == none)
{
if ((nFlags & MK_SHIFT) == 0)
pView->Select(NULL);
selectMode = netSelect;
CClientDC dc(pView);
CRect rect(point.x, point.y, point.x, point.y);
rect.NormalizeRect();
dc.DrawFocusRect(rect);
}
lastPoint = local;
CDrawTool::OnLButtonDown(pView, nFlags, point);
}
void CSelectTool::OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point)
{
if ((nFlags & MK_SHIFT) != 0)
{
// Shift+DblClk deselects object...
CPoint local = point;
pView->ClientToDoc(local);
CDrawObj* pObj = pView->GetDocument()->ObjectAt(local);
if (pObj != NULL)
pView->Deselect(pObj);
}
else
{
// "Normal" DblClk opens properties, or OLE server...
if (pView->m_selection.GetCount() == 1)
pView->m_selection.GetHead()->OnOpen(pView);
}
CDrawTool::OnLButtonDblClk(pView, nFlags, point);
}
void CSelectTool::OnEditProperties(CDrawView* pView)
{
if (pView->m_selection.GetCount() == 1)
pView->m_selection.GetHead()->OnEditProperties();
}
void CSelectTool::OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point)
{
if (pView->GetCapture() == pView)
{
if (selectMode == netSelect)
{
CClientDC dc(pView);
CRect rect(c_down.x, c_down.y, c_last.x, c_last.y);
rect.NormalizeRect();
dc.DrawFocusRect(rect);
pView->SelectWithinRect(rect, TRUE);
}
else if (selectMode != none)
{
pView->GetDocument()->UpdateAllViews(pView);
}
}
CDrawTool::OnLButtonUp(pView, nFlags, point);
}
void CSelectTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
{
if (pView->GetCapture() != pView)
{
if (c_drawShape == selection && pView->m_selection.GetCount() == 1)
{
CDrawObj* pObj = pView->m_selection.GetHead();
CPoint local = point;
pView->ClientToDoc(local);
int nHandle = pObj->HitTest(local, pView, TRUE);
if (nHandle != 0)
{
SetCursor(pObj->GetHandleCursor(nHandle));
return; // bypass CDrawTool
}
}
if (c_drawShape == selection)
CDrawTool::OnMouseMove(pView, nFlags, point);
return;
}
if (selectMode == netSelect)
{
CClientDC dc(pView);
CRect rect(c_down.x, c_down.y, c_last.x, c_last.y);
rect.NormalizeRect();
dc.DrawFocusRect(rect);
rect.SetRect(c_down.x, c_down.y, point.x, point.y);
rect.NormalizeRect();
dc.DrawFocusRect(rect);
CDrawTool::OnMouseMove(pView, nFlags, point);
return;
}
CPoint local = point;
pView->ClientToDoc(local);
CPoint delta = (CPoint)(local - lastPoint);
POSITION pos = pView->m_selection.GetHeadPosition();
while (pos != NULL)
{
CDrawObj* pObj = pView->m_selection.GetNext(pos);
CRect position = pObj->m_position;
if (selectMode == move)
{
position += delta;
pObj->MoveTo(position, pView);
}
else if (nDragHandle != 0)
{
pObj->MoveHandleTo(nDragHandle, local, pView);
}
}
lastPoint = local;
if (selectMode == size && c_drawShape == selection)
{
c_last = point;
SetCursor(pView->m_selection.GetHead()->GetHandleCursor(nDragHandle));
return; // bypass CDrawTool
}
c_last = point;
if (c_drawShape == selection)
CDrawTool::OnMouseMove(pView, nFlags, point);
}
////////////////////////////////////////////////////////////////////////////
// CRectTool (does rectangles, round-rectangles, and ellipses)
CRectTool::CRectTool(DrawShape drawShape)
: CDrawTool(drawShape)
{
}
void CRectTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
{
CDrawTool::OnLButtonDown(pView, nFlags, point);
CPoint local = point;
pView->ClientToDoc(local);
CDrawRect* pObj = new CDrawRect(CRect(local, CSize(0, 0)));
switch (m_drawShape)
{
default:
ASSERT(FALSE); // unsuported shape!
case rect:
pObj->m_nShape = CDrawRect::rectangle;
break;
case roundRect:
pObj->m_nShape = CDrawRect::roundRectangle;
break;
case ellipse:
pObj->m_nShape = CDrawRect::ellipse;
break;
case line:
pObj->m_nShape = CDrawRect::line;
break;
}
pView->GetDocument()->Add(pObj);
pView->Select(pObj);
selectMode = size;
nDragHandle = 1;
lastPoint = local;
}
void CRectTool::OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point)
{
CDrawTool::OnLButtonDblClk(pView, nFlags, point);
}
void CRectTool::OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point)
{
if (point == c_down)
{
// Don't create empty objects...
CDrawObj *pObj = pView->m_selection.GetTail();
pView->GetDocument()->Remove(pObj);
pObj->Remove();
selectTool.OnLButtonDown(pView, nFlags, point); // try a select!
}
selectTool.OnLButtonUp(pView, nFlags, point);
}
void CRectTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
selectTool.OnMouseMove(pView, nFlags, point);
}
////////////////////////////////////////////////////////////////////////////
// CPolyTool
CPolyTool::CPolyTool()
: CDrawTool(poly)
{
m_pDrawObj = NULL;
}
void CPolyTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
{
CDrawTool::OnLButtonDown(pView, nFlags, point);
CPoint local = point;
pView->ClientToDoc(local);
if (m_pDrawObj == NULL)
{
pView->SetCapture();
m_pDrawObj = new CDrawPoly(CRect(local, CSize(0, 0)));
pView->GetDocument()->Add(m_pDrawObj);
pView->Select(m_pDrawObj);
m_pDrawObj->AddPoint(local, pView);
}
else if (local == m_pDrawObj->m_points[0])
{
// Stop when the first point is repeated...
ReleaseCapture();
m_pDrawObj->m_nPoints -= 1;
if (m_pDrawObj->m_nPoints < 2)
{
m_pDrawObj->Remove();
}
else
{
pView->InvalObj(m_pDrawObj);
}
m_pDrawObj = NULL;
c_drawShape = selection;
return;
}
local.x += 1; // adjacent points can't be the same!
m_pDrawObj->AddPoint(local, pView);
selectMode = size;
nDragHandle = m_pDrawObj->GetHandleCount();
lastPoint = local;
}
void CPolyTool::OnLButtonUp(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& /*point*/)
{
// Don't release capture yet!
}
void CPolyTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
{
if (m_pDrawObj != NULL && (nFlags & MK_LBUTTON) != 0)
{
CPoint local = point;
pView->ClientToDoc(local);
m_pDrawObj->AddPoint(local);
nDragHandle = m_pDrawObj->GetHandleCount();
lastPoint = local;
c_last = point;
SetCursor(AfxGetApp()->LoadCursor(IDC_PENCIL));
}
else
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
selectTool.OnMouseMove(pView, nFlags, point);
}
}
void CPolyTool::OnLButtonDblClk(CDrawView* pView, UINT , const CPoint& )
{
ReleaseCapture();
int nPoints = m_pDrawObj->m_nPoints;
if (nPoints > 2 &&
(m_pDrawObj->m_points[nPoints - 1] == m_pDrawObj->m_points[nPoints - 2] ||
m_pDrawObj->m_points[nPoints - 1].x - 1 == m_pDrawObj->m_points[nPoints - 2].x &&
m_pDrawObj->m_points[nPoints - 1].y == m_pDrawObj->m_points[nPoints - 2].y))
{
// Nuke the last point if it's the same as the next to last...
m_pDrawObj->m_nPoints -= 1;
pView->InvalObj(m_pDrawObj);
}
m_pDrawObj = NULL;
c_drawShape = selection;
}
void CPolyTool::OnCancel()
{
CDrawTool::OnCancel();
m_pDrawObj = NULL;
}
/////////////////////////////////////////////////////////////////////////////