2025-11-27 16:46:48 +09:00

350 lines
9.0 KiB
C++

// scribvw.cpp : implementation of the CScribView class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and Microsoft
// QuickHelp and/or WinHelp documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include "scribble.h"
#include "scribdoc.h"
#include "scribvw.h"
#include "UTBStrOp.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CScribView
IMPLEMENT_DYNCREATE(CScribView, COXZoomView)
BEGIN_MESSAGE_MAP(CScribView, COXZoomView)
//{{AFX_MSG_MAP(CScribView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_ZOOM_100, OnZoom100)
ON_UPDATE_COMMAND_UI(ID_ZOOM_100, OnUpdateZoom100)
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_ZOOM_TOWINDOW, OnZoomToWindow)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_ZOOM, OnUpdateZoom)
ON_COMMAND(ID_ZOOM_UP, OnZoomUp)
ON_UPDATE_COMMAND_UI(ID_ZOOM_UP, OnUpdateZoomUp)
ON_COMMAND(ID_ZOOM_DOWN, OnZoomDown)
ON_UPDATE_COMMAND_UI(ID_ZOOM_DOWN, OnUpdateZoomDown)
ON_COMMAND(ID_WINDOW_DUPLICATE, OnWindowDuplicate)
//}}AFX_MSG_MAP
// Standard printing commands
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CScribView construction/destruction
CScribView::CScribView()
{
// TODO: add construction code here
action = IDLE;
}
CScribView::~CScribView()
{
}
/////////////////////////////////////////////////////////////////////////////
void CScribView::OnUpdate(CView*, LPARAM, CObject* pHint)
{
// The document has informed this view that some data has changed.
if (pHint != NULL)
{
if (pHint->IsKindOf(RUNTIME_CLASS(CStroke)))
{
// The hint is that a stroke as been added (or changed).
// So, invalidate its rectangle.
CStroke* pStroke = (CStroke*)pHint;
CClientDC dc(this);
OnPrepareDC(&dc);
CRect rectInvalid = pStroke->GetBoundingRect();
dc.LPtoDP(&rectInvalid);
InvalidateRect(&rectInvalid);
return;
}
}
// We can't interpret the hint, so assume that anything might
// have been updated.
Invalidate(TRUE);
return;
}
/////////////////////////////////////////////////////////////////////////////
// A view's OnInitialUpdate() overrideable function is called immediately
// after the frame window is created, and the view within the frame
// window is attached to its document. This provides the scroll view the
// opportunity to set its size (m_totalSize) based on the document size.
void CScribView::OnInitialUpdate()
{
SetDeviceScrollSizesRelative(MM_LOENGLISH, GetDocument()->GetDocRect());
//SetDeviceScrollSizesRelative(CSize(600,400), GetDocument()->GetDocRect());
SetAlignToBottom( TRUE );
SetZoomAlign( ZV_CENTER );
}
/////////////////////////////////////////////////////////////////////////////
// CScribView drawing
void CScribView::OnDraw(CDC* pDC)
{
CScribDoc* pDoc = GetDocument();
// Get the invalidated rectangle of the view, or in the case
// of printing, the clipping region of the printer dc.
CRect rectClip;
CRect rectStroke;
pDC->GetClipBox(&rectClip);
pDC->LPtoDP(&rectClip);
if( !pDC->IsPrinting() )
rectClip.InflateRect(1,1);
// Note: COXZoomView::OnPaint() will have already adjusted the
// viewport origin before calling OnDraw(), to reflect the
// currently scrolled position.
// The view delegates the drawing of individual strokes to
// CStroke::DrawStroke().
for (POSITION pos = pDoc->GetFirstStrokePos(); pos != NULL; )
{
CStroke* pStroke = pDoc->GetNextStroke(pos);
rectStroke = pStroke->GetBoundingRect();
pDC->LPtoDP(&rectStroke);
if (!rectStroke.IntersectRect(&rectStroke, &rectClip))
continue;
pStroke->DrawStroke(pDC);
}
}
/////////////////////////////////////////////////////////////////////////////
// CScribView diagnostics
#ifdef _DEBUG
void CScribView::AssertValid() const
{
COXZoomView::AssertValid();
}
void CScribView::Dump(CDumpContext& dc) const
{
COXZoomView::Dump(dc);
}
CScribDoc* CScribView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CScribDoc)));
return (CScribDoc*) m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CScribView message handlers
void CScribView::OnLButtonDown(UINT, CPoint point)
{ // When the user presses the mouse button, she may be
// starting a new stroke, or selecting or de-selecting a stroke.
// COXZoomView changes the viewport origin and mapping mode.
// It's necessary to convert the point from device coordinates
// to logical coordinates, such as are stored in the document.
if( action != IDLE ) return;
CClientDC dc(this);
OnPrepareDC(&dc);
CRect rcClip, rcClient;
rcClip = GetDocument()->GetDocRect();
dc.LPtoDP( rcClip );
GetClientRect( rcClient );
rcClip.IntersectRect( rcClip, rcClient );
CRect rcPen( 0, 0, GetDocument()->m_nPenWidth, 0 );
dc.LPtoDP( rcPen );
int i = rcPen.Width();
i++;
i/=2;
rcClip.InflateRect( -i, -i );
if( !rcClip.PtInRect( point ) )
return;
ClientToScreen( rcClip );
::ClipCursor( rcClip );
action = DRAWING;
dc.DPtoLP(&point);
m_pStrokeCur = GetDocument()->NewStroke();
m_pStrokeCur->AddPoint(point); // add first point to the new stroke
SetCapture(); // Capture the mouse until button up.
m_ptPrev = point; // Serves as the MoveTo() anchor point for the
// LineTo() the next point, as the user drags the
// mouse.
return;
}
/////////////////////////////////////////////////////////////////////////////
void CScribView::OnLButtonUp(UINT, CPoint point)
{
// Mouse button up is interesting in the Scribble application
// only if the user is currently drawing a new stroke by dragging
// the captured mouse.
if( action != DRAWING ) return;
action = IDLE;
::ClipCursor( NULL );
CScribDoc* pDoc = GetDocument();
CClientDC dc(this);
// COXZoomView changes the viewport origin and mapping mode.
// It's necessary to convert the point from device coordinates
// to logical coordinates, such as are stored in the document.
OnPrepareDC(&dc); // set up mapping mode and viewport origin
dc.DPtoLP(&point);
CPen* pOldPen = dc.SelectObject(pDoc->GetCurrentPen());
dc.MoveTo(m_ptPrev);
dc.LineTo(point);
dc.SelectObject(pOldPen);
m_pStrokeCur->AddPoint(point);
// Tell the stroke item that we're done adding points to it.
// This is so it can finish computing its bounding rectangle.
m_pStrokeCur->FinishStroke();
// Tell the other views that this stroke has been added
// so that they can invalidate this stroke's area in their
// client area.
pDoc->UpdateAllViews(this, 0L, m_pStrokeCur);
ReleaseCapture(); // Release the mouse capture established at
// the beginning of the mouse drag.
return;
}
void CScribView::OnRButtonDown(UINT , CPoint point)
{
if( action != IDLE ) return;
action = ZOOMING;
CRect rectZoom;
CZoomRect zoom;
if( zoom.TrackTheMouse( WM_RBUTTONUP, this, rectZoom, point ) )
ZoomToRectangle( rectZoom );
action = IDLE;
return;
}
/////////////////////////////////////////////////////////////////////////////
void CScribView::OnMouseMove(UINT, CPoint point)
{
// Mouse movement is interesting in the Scribble application
// only if the user is currently drawing a new stroke by dragging
// the captured mouse.
switch( action )
{
case DRAWING:
{
CClientDC dc(this);
// COXZoomView changes the viewport origin and mapping mode.
// It's necessary to convert the point from device coordinates
// to logical coordinates, such as are stored in the document.
OnPrepareDC(&dc);
dc.DPtoLP(&point);
m_pStrokeCur->AddPoint(point);
// Draw a line from the previous detected point in the mouse
// drag to the current point.
CPen* pOldPen = dc.SelectObject(GetDocument()->GetCurrentPen());
dc.MoveTo(m_ptPrev);
dc.LineTo(point);
dc.SelectObject(pOldPen);
m_ptPrev = point;
}
break;
}
return;
}
void CScribView::OnZoom100()
{
SetZoomLevel( 100 );
}
void CScribView::OnUpdateZoom100(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck( 100 == GetZoomLevel() ? 1 : 0 );
}
void CScribView::OnZoomToWindow()
{
ZoomToWindow();
}
void CScribView::OnUpdateZoom(CCmdUI* pCmdUI)
{
TCHAR szBuf[10];
UTBStr::stprintf(szBuf, 10, _T("%4i%%"), GetZoomLevel() );
pCmdUI->Enable( TRUE );
pCmdUI->SetText( szBuf );
}
void CScribView::OnZoomUp()
{
int i = GetZoomLevel();
i = MulDiv( 1000,i,707);
SetZoomLevel( i );
}
void CScribView::OnUpdateZoomUp(CCmdUI* pCmdUI)
{
pCmdUI->Enable( 1000 > GetZoomLevel() );
}
void CScribView::OnZoomDown()
{
int i = GetZoomLevel();
i = MulDiv( 707,i,1000);
SetZoomLevel( i );
}
void CScribView::OnUpdateZoomDown(CCmdUI* pCmdUI)
{
pCmdUI->Enable( 10 < GetZoomLevel() );
}
void CScribView::OnWindowDuplicate()
{
CDocTemplate* pTempl = GetDocument()->GetDocTemplate();
CFrameWnd* pFrame = pTempl->CreateNewFrame( GetDocument(), GetParentFrame() );
pTempl->InitialUpdateFrame( pFrame, GetDocument() );
}