WidgView.h
// WidgView.h : interface of the CWidgetView class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_WIDGVIEW_H__877329C1_C22E_11D0_B2D8_444553540000__INCLUDED_)
#define AFX_WIDGVIEW_H__877329C1_C22E_11D0_B2D8_444553540000__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
typedef struct tagWIDGETDATA {
int nType; // Widget type (0=Circle, 1=Triangle, 2=Square)
RECT rcItem; // Widget rectangle (logical coordinates)
POINT ptDrag; // Drag point (logical coordinates)
} WIDGETDATA;
class CWidgetView : public CScrollView
{
protected: // create from serialization only
CWidgetView();
DECLARE_DYNCREATE(CWidgetView)
// Attributes
public:
CWidgetDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWidgetView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState,
CPoint point);
virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState,
CPoint point);
virtual void OnDragLeave();
virtual BOOL OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect,
CPoint point);
protected:
virtual void OnInitialUpdate(); // called first time after construct
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CWidgetView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
int m_nWidget;
COleDropTarget m_oleDropTarget;
CPoint m_ptPrevPos;
CPoint m_ptOldImage;
CSize m_sizeDelta;
CWidget* m_pWidget;
//{{AFX_MSG(CWidgetView)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in WidgView.cpp
inline CWidgetDoc* CWidgetView::GetDocument()
{ return (CWidgetDoc*)m_pDocument; }
#endif
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations
immediately before the previous line.
#endif // !defined(AFX_WIDGVIEW_H__877329C1_C22E_11D0_B2D8_444553540000__INCLUDED_)
WidgView.cpp
// WidgView.cpp : implementation of the CWidgetView class
//
#include "stdafx.h"
#include "Widget.h"
#include "WidgBase.h"
#include "Circle.h"
#include "Triangle.h"
#include "Square.h"
#include "WidgDoc.h"
#include "WidgView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CWidgetView
IMPLEMENT_DYNCREATE(CWidgetView, CScrollView)
BEGIN_MESSAGE_MAP(CWidgetView, CScrollView)
//{{AFX_MSG_MAP(CWidgetView)
ON_WM_LBUTTONDOWN()
ON_WM_CREATE()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWidgetView construction/destruction
CWidgetView::CWidgetView()
{
}
CWidgetView::~CWidgetView()
{
}
BOOL CWidgetView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CScrollView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CWidgetView drawing
void CWidgetView::OnDraw(CDC* pDC)
{
CWidgetDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
int nCount = pDoc->GetWidgetCount ();
if (nCount) {
for (int i=0; i<nCount; i++)
pDoc->GetWidget (i)->Draw (pDC);
}
}
void CWidgetView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
sizeTotal.cx = sizeTotal.cy = 1024;
SetScrollSizes(MM_TEXT, sizeTotal);
m_nWidget = -1; // Index of the widget that's being dragged
m_pWidget = NULL; // Pointer to temporary widget used in drag imaging
}
/////////////////////////////////////////////////////////////////////////////
// CWidgetView printing
BOOL CWidgetView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CWidgetView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CWidgetView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CWidgetView diagnostics
#ifdef _DEBUG
void CWidgetView::AssertValid() const
{
CScrollView::AssertValid();
}
void CWidgetView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}
CWidgetDoc* CWidgetView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWidgetDoc)));
return (CWidgetDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CWidgetView message handlers
void CWidgetView::OnLButtonDown(UINT nFlags, CPoint point)
{
CWidgetDoc* pDoc = GetDocument ();
int nCount = pDoc->GetWidgetCount ();
if (nCount) {
//
// Convert the click point to logical coordinates.
//
CClientDC dc (this);
OnPrepareDC (&dc);
dc.DPtoLP (&point);
//
// Find out whether a widget was clicked.
//
int i;
BOOL bHit = FALSE;
for (i=nCount - 1; i>=0 && !bHit; i--) {
CWidget* pWidget = pDoc->GetWidget (i);
if (pWidget->PtInWidget (point)) {
bHit = TRUE;
}
}
//
// If a widget was clicked, initiate a drag-drop operation.
//
if (bHit) {
m_nWidget = ++i;
HANDLE hData =
::GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE, sizeof (WIDGETDATA));
WIDGETDATA* pWidgetData = (WIDGETDATA*) ::GlobalLock (hData);
CWidget* pWidget = pDoc->GetWidget (m_nWidget);
pWidgetData->nType = pWidget->GetType ();
pWidget->GetItemRect (&pWidgetData->rcItem);
pWidgetData->ptDrag = point;
::GlobalUnlock (hData);
COleDataSource ods;
UINT nFormat = ((CWidgetApp*) AfxGetApp ())->m_nFormat;
ods.CacheGlobalData (nFormat, hData);
DROPEFFECT de = ods.DoDragDrop (DROPEFFECT_COPY | DROPEFFECT_MOVE);
if (de == DROPEFFECT_MOVE) {
pDoc->RemoveWidget (m_nWidget);
pDoc->UpdateAllViews (NULL);
}
m_nWidget = -1;
}
}
CScrollView::OnLButtonDown(nFlags, point);
}
DROPEFFECT CWidgetView::OnDragEnter(COleDataObject* pDataObject,
DWORD dwKeyState, CPoint point)
{
CScrollView::OnDragEnter(pDataObject, dwKeyState, point);
//
// Return now if the object being dragged is not a widget.
//
UINT nFormat = ((CWidgetApp*) AfxGetApp ())->m_nFormat;
if (!pDataObject->IsDataAvailable (nFormat))
return DROPEFFECT_NONE;
//
// Create a temporary widget for drag imaging.
//
HGLOBAL hData = pDataObject->GetGlobalData (nFormat);
WIDGETDATA* pWidgetData = (WIDGETDATA*) ::GlobalLock (hData);
int nType = pWidgetData->nType;
CRect rect = pWidgetData->rcItem;
CPoint pt = pWidgetData->ptDrag;
::GlobalUnlock (hData);
switch (nType) {
case 0: // Circle
m_pWidget = new CCircle (rect);
break;
case 1: // Triangle
m_pWidget = new CTriangle (rect);
break;
case 2: // Square
m_pWidget = new CSquare (rect);
break;
default: // Just in case
return DROPEFFECT_NONE;
}
//
// Begin dragging.
//
CClientDC dc (this);
OnPrepareDC (&dc);
dc.DPtoLP (&point);
m_sizeDelta.cx = pt.x - rect.left;
m_sizeDelta.cy = pt.y - rect.top;
CPoint ptDrag (point.x - m_sizeDelta.cx, point.y - m_sizeDelta.cy);
m_ptOldImage.x = m_ptOldImage.y = -32000;
m_ptPrevPos = point;
return (dwKeyState & MK_CONTROL) ? DROPEFFECT_COPY : DROPEFFECT_MOVE;
}
DROPEFFECT CWidgetView::OnDragOver(COleDataObject* pDataObject,
DWORD dwKeyState, CPoint point)
{
CScrollView::OnDragOver(pDataObject, dwKeyState, point);
//
// Return now if the object being dragged is not a widget.
//
if (m_pWidget == NULL)
return DROPEFFECT_NONE;
//
// Erase the old drag image and draw a new one if the cursor has moved.
//
CClientDC dc (this);
OnPrepareDC (&dc);
dc.DPtoLP (&point);
if (point != m_ptPrevPos) {
m_pWidget->DrawDragImage (&dc, m_ptOldImage);
CPoint ptDrag (point.x - m_sizeDelta.cx, point.y - m_sizeDelta.cy);
m_pWidget->DrawDragImage (&dc, ptDrag);
m_ptOldImage = ptDrag;
m_ptPrevPos = point;
}
return (dwKeyState & MK_CONTROL) ? DROPEFFECT_COPY : DROPEFFECT_MOVE;
}
void CWidgetView::OnDragLeave()
{
CScrollView::OnDragLeave();
//
// Erase the old drag image and delete the temporary widget.
//
if (m_pWidget != NULL) {
CClientDC dc (this);
OnPrepareDC (&dc);
m_pWidget->DrawDragImage (&dc, m_ptOldImage);
delete m_pWidget;
m_pWidget = NULL;
}
}
BOOL CWidgetView::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect,
CPoint point)
{
CScrollView::OnDrop(pDataObject, dropEffect, point);
//
// Convert point to logical coordinates.
//
CClientDC dc (this);
OnPrepareDC (&dc);
dc.DPtoLP (&point);
//
// Erase the old drag image and delete the temporary widget.
//
if (m_pWidget != NULL) {
m_pWidget->DrawDragImage (&dc, m_ptOldImage);
delete m_pWidget;
m_pWidget = NULL;
}
//
// Retrieve the HGLOBAL from the data object.
//
UINT nFormat = ((CWidgetApp*) AfxGetApp ())->m_nFormat;
HGLOBAL hData = pDataObject->GetGlobalData (nFormat);
if (hData == NULL)
return FALSE;
//
// Create a widget from the data in the HGLOBAL.
//
WIDGETDATA* pWidgetData = (WIDGETDATA*) ::GlobalLock (hData);
int nType = pWidgetData->nType;
CRect rect = pWidgetData->rcItem;
::GlobalUnlock (hData);
CRect rcItem;
rcItem.left = point.x - m_sizeDelta.cx;
rcItem.top = point.y - m_sizeDelta.cy;
rcItem.right = rcItem.left + rect.Width ();
rcItem.bottom = rcItem.top + rect.Height ();
CWidgetDoc* pDoc = GetDocument ();
pDoc->AddWidget (nType, &rcItem);
pDoc->UpdateAllViews (NULL);
return TRUE;
}
int CWidgetView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CScrollView::OnCreate(lpCreateStruct) == -1)
return -1;
m_oleDropTarget.Register (this);
return 0;
}
WidgDoc.h
// WidgDoc.h : interface of the CWidgetDoc class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_WIDGDOC_H__877329BF_C22E_11D0_B2D8_444553540000__INCLUDED_)
#define AFX_WIDGDOC_H__877329BF_C22E_11D0_B2D8_444553540000__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CWidgetDoc : public CDocument
{
protected: // create from serialization only
CWidgetDoc();
DECLARE_DYNCREATE(CWidgetDoc)
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWidgetDoc)
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
virtual void DeleteContents();
//}}AFX_VIRTUAL
// Implementation
public:
BOOL RemoveWidget (int nIndex);
int AddWidget (int nType, LPCRECT pRect);
CWidget* GetWidget (int nIndex);
int GetWidgetCount ();
virtual ~CWidgetDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
CObArray m_aWidgets;
//{{AFX_MSG(CWidgetDoc)
afx_msg void OnInsertTriangle();
afx_msg void OnInsertCircle();
afx_msg void OnInsertSquare();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately
// before the previous line.
#endif // !defined(AFX_WIDGDOC_H__877329BF_C22E_11D0_B2D8_444553540000__INCLUDED_)
WidgDoc.cpp
// WidgDoc.cpp : implementation of the CWidgetDoc class
//
#include "stdafx.h"
#include "Widget.h"
#include "WidgBase.h"
#include "Circle.h"
#include "Triangle.h"
#include "Square.h"
#include "WidgDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CWidgetDoc
IMPLEMENT_DYNCREATE(CWidgetDoc, CDocument)
BEGIN_MESSAGE_MAP(CWidgetDoc, CDocument)
//{{AFX_MSG_MAP(CWidgetDoc)
ON_COMMAND(ID_INSERT_TRIANGLE, OnInsertTriangle)
ON_COMMAND(ID_INSERT_CIRCLE, OnInsertCircle)
ON_COMMAND(ID_INSERT_SQUARE, OnInsertSquare)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWidgetDoc construction/destruction
CWidgetDoc::CWidgetDoc()
{
// TODO: add one-time construction code here
}
CWidgetDoc::~CWidgetDoc()
{
}
BOOL CWidgetDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
m_aWidgets.SetSize (0, 16);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CWidgetDoc serialization
void CWidgetDoc::Serialize(CArchive& ar)
{
m_aWidgets.Serialize (ar);
}
/////////////////////////////////////////////////////////////////////////////
// CWidgetDoc diagnostics
#ifdef _DEBUG
void CWidgetDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CWidgetDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CWidgetDoc commands
void CWidgetDoc::OnInsertCircle()
{
AddWidget (0, CRect (10, 10, 100, 100));
UpdateAllViews (NULL);
}
void CWidgetDoc::OnInsertTriangle()
{
AddWidget (1, CRect (10, 10, 100, 100));
UpdateAllViews (NULL);
}
void CWidgetDoc::OnInsertSquare()
{
AddWidget (2, CRect (10, 10, 100, 100));
UpdateAllViews (NULL);
}
void CWidgetDoc::DeleteContents()
{
int nCount = m_aWidgets.GetSize ();
while (nCount--)
delete m_aWidgets[nCount];
m_aWidgets.RemoveAll ();
CDocument::DeleteContents();
}
int CWidgetDoc::GetWidgetCount()
{
return m_aWidgets.GetSize ();
}
CWidget* CWidgetDoc::GetWidget(int nIndex)
{
if (nIndex > (m_aWidgets.GetSize () - 1))
return NULL;
return (CWidget*) m_aWidgets[nIndex];
}
int CWidgetDoc::AddWidget(int nType, LPCRECT pRect)
{
int nIndex;
CWidget* pWidget;
try {
switch (nType) {
case 0: // Circle widget
pWidget = new CCircle (pRect);
break;
case 1: // Triangle widget
pWidget = new CTriangle (pRect);
break;
case 2: // Square widget
pWidget = new CSquare (pRect);
break;
}
nIndex = m_aWidgets.Add (pWidget);
}
catch (CMemoryException* e) {
AfxMessageBox ("Out of memory");
if (pWidget != NULL)
delete pWidget;
e->Delete ();
return -1;
}
SetModifiedFlag ();
return nIndex;
}
BOOL CWidgetDoc::RemoveWidget(int nIndex)
{
if (nIndex >= m_aWidgets.GetSize ())
return FALSE;
delete m_aWidgets[nIndex];
m_aWidgets.RemoveAt (nIndex);
return TRUE;
}
Circle.h
#if !defined(AFX_CIRCLE_H__877329CB_C22E_11D0_B2D8_444553540001__INCLUDED_)
#define AFX_CIRCLE_H__877329CB_C22E_11D0_B2D8_444553540001__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// Circle.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CCircle
class CCircle : public CWidget
{
DECLARE_SERIAL(CCircle)
CCircle(); // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
virtual ~CCircle();
virtual int GetType ();
CCircle (LPCRECT pRect);
CCircle (int left, int top, int right, int bottom);
virtual BOOL PtInWidget (POINT point);
virtual void DrawDragImage (CDC* pDC, POINT point);
virtual void Draw (CDC* pDC);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCircle)
//}}AFX_VIRTUAL
virtual void Serialize (CArchive& ar);
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CCircle)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately
// before the previous line.
#endif // !defined(AFX_CIRCLE_H__877329CB_C22E_11D0_B2D8_444553540001__INCLUDED_)
Circle.cpp
// Circle.cpp : implementation file
//
#include "stdafx.h"
#include "Widget.h"
#include "WidgBase.h"
#include "Circle.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCircle
IMPLEMENT_SERIAL(CCircle, CWidget, 1)
CCircle::CCircle()
{
}
CCircle::CCircle (LPCRECT pRect)
{
m_rect = *pRect;
}
CCircle::CCircle (int left, int top, int right, int bottom)
{
m_rect.SetRect (left, top, right, bottom);
}
CCircle::~CCircle()
{
}
BEGIN_MESSAGE_MAP(CCircle, CWidget)
//{{AFX_MSG_MAP(CCircle)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCircle message handlers
void CCircle::Draw(CDC * pDC)
{
CBrush brush (RGB (255, 255, 0)); // Yellow
CBrush* pOldBrush = pDC->SelectObject (&brush);
pDC->Ellipse (m_rect);
pDC->SelectObject (pOldBrush);
}
void CCircle::DrawDragImage(CDC * pDC, POINT point)
{
int nOldMode = pDC->SetROP2 (R2_NOT);
CBrush* pOldBrush = (CBrush*) pDC->SelectStockObject (NULL_BRUSH);
pDC->Ellipse (point.x, point.y,
point.x + m_rect.Width (),
point.y + m_rect.Height ());
pDC->SelectObject (pOldBrush);
pDC->SetROP2 (nOldMode);
}
BOOL CCircle::PtInWidget(POINT point)
{
if (!m_rect.PtInRect (point))
return FALSE;
CPoint ptCenter;
ptCenter.x = m_rect.left + (m_rect.Width () / 2);
ptCenter.y = m_rect.top + (m_rect.Height () / 2);
int cx = point.x - ptCenter.x;
int cy = point.y - ptCenter.y;
if ((cx * cx) + (cy * cy) <
(m_rect.Width () / 2) * (m_rect.Width () / 2))
return TRUE;
return FALSE;
}
int CCircle::GetType()
{
return 0; // Circle
}
void CCircle::Serialize (CArchive& ar)
{
CWidget::Serialize (ar);
if (ar.IsStoring ())
ar << m_rect;
else
ar >> m_rect;
}
Triangle.h
#if !defined(AFX_TRIANGLE_H__877329CB_C22E_11D0_B2D8_444553540000__INCLUDED_)
#define AFX_TRIANGLE_H__877329CB_C22E_11D0_B2D8_444553540000__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// Triangle.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CTriangle
class CTriangle : public CWidget
{
DECLARE_SERIAL(CTriangle)
CTriangle(); // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
virtual ~CTriangle();
virtual int GetType ();
CTriangle (LPCRECT pRect);
CTriangle (int left, int top, int right, int bottom);
virtual BOOL PtInWidget (POINT point);
virtual void DrawDragImage (CDC* pDC, POINT point);
virtual void Draw (CDC* pDC);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTriangle)
//}}AFX_VIRTUAL
virtual void Serialize (CArchive& ar);
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CTriangle)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately
// before the previous line.
#endif // !defined(AFX_TRIANGLE_H__877329CB_C22E_11D0_B2D8_444553540000__INCLUDED_)
Triangle.cpp
// Triangle.cpp : implementation file
//
#include "stdafx.h"
#include "Widget.h"
#include "WidgBase.h"
#include "Triangle.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTriangle
IMPLEMENT_SERIAL(CTriangle, CWidget, 1)
CTriangle::CTriangle()
{
}
CTriangle::CTriangle (LPCRECT pRect)
{
m_rect = *pRect;
}
CTriangle::CTriangle (int left, int top, int right, int bottom)
{
m_rect.SetRect (left, top, right, bottom);
}
CTriangle::~CTriangle()
{
}
BEGIN_MESSAGE_MAP(CTriangle, CWidget)
//{{AFX_MSG_MAP(CTriangle)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTriangle message handlers
void CTriangle::Draw(CDC * pDC)
{
CBrush brush (RGB (0, 0, 255)); // Blue
CBrush* pOldBrush = pDC->SelectObject (&brush);
CPoint points[3];
points[0].x = m_rect.left;
points[0].y = m_rect.bottom;
points[1].x = m_rect.left + ((m_rect.right - m_rect.left) / 2);
points[1].y = m_rect.top;
points[2].x = m_rect.right;
points[2].y = m_rect.bottom;
pDC->Polygon (points, 3);
pDC->SelectObject (pOldBrush);
}
void CTriangle::DrawDragImage(CDC * pDC, POINT point)
{
int nOldMode = pDC->SetROP2 (R2_NOT);
CBrush* pOldBrush = (CBrush*) pDC->SelectStockObject (NULL_BRUSH);
CPoint points[3];
points[0].x = point.x;
points[0].y = point.y + m_rect.Height ();
points[1].x = point.x + (m_rect.Width () / 2);
points[1].y = point.y;
points[2].x = point.x + m_rect.Width ();
points[2].y = point.y + m_rect.Height ();
pDC->Polygon (points, 3);
pDC->SelectObject (pOldBrush);
pDC->SetROP2 (nOldMode);
}
BOOL CTriangle::PtInWidget(POINT point)
{
if (!m_rect.PtInRect (point))
return FALSE;
int cx = min (point.x - m_rect.left, m_rect.right - point.x);
return ((m_rect.bottom - point.y) <= (2 * cx));
}
int CTriangle::GetType()
{
return 1; // Triangle
}
void CTriangle::Serialize (CArchive& ar)
{
CWidget::Serialize (ar);
if (ar.IsStoring ())
ar << m_rect;
else
ar >> m_rect;
}
Square.h
#if !defined(AFX_SQUARE_H__877329CB_C22E_11D0_B2D8_444553540002__INCLUDED_)
#define AFX_SQUARE_H__877329CB_C22E_11D0_B2D8_444553540002__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// Square.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CSquare
class CSquare : public CWidget
{
DECLARE_SERIAL(CSquare)
CSquare(); // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
virtual ~CSquare();
virtual int GetType ();
CSquare (LPCRECT pRect);
CSquare (int left, int top, int right, int bottom);
virtual BOOL PtInWidget (POINT point);
virtual void DrawDragImage (CDC* pDC, POINT point);
virtual void Draw (CDC* pDC);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSquare)
//}}AFX_VIRTUAL
virtual void Serialize (CArchive& ar);
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CSquare)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately
// before the previous line.
#endif // !defined(AFX_SQUARE_H__877329CB_C22E_11D0_B2D8_444553540002__INCLUDED_)
Square.cpp
// Square.cpp : implementation file
//
#include "stdafx.h"
#include "Widget.h"
#include "WidgBase.h"
#include "Square.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSquare
IMPLEMENT_SERIAL(CSquare, CWidget, 1)
CSquare::CSquare()
{
}
CSquare::CSquare (LPCRECT pRect)
{
m_rect = *pRect;
}
CSquare::CSquare (int left, int top, int right, int bottom)
{
m_rect.SetRect (left, top, right, bottom);
}
CSquare::~CSquare()
{
}
BEGIN_MESSAGE_MAP(CSquare, CWidget)
//{{AFX_MSG_MAP(CSquare)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSquare message handlers
void CSquare::Draw(CDC * pDC)
{
CBrush brush (RGB (255, 0, 0)); // Red
CBrush* pOldBrush = pDC->SelectObject (&brush);
pDC->Rectangle (m_rect);
pDC->SelectObject (pOldBrush);
}
void CSquare::DrawDragImage(CDC * pDC, POINT point)
{
int nOldMode = pDC->SetROP2 (R2_NOT);
CBrush* pOldBrush = (CBrush*) pDC->SelectStockObject (NULL_BRUSH);
pDC->Rectangle (point.x, point.y,
point.x + m_rect.Width (),
point.y + m_rect.Height ());
pDC->SelectObject (pOldBrush);
pDC->SetROP2 (nOldMode);
}
BOOL CSquare::PtInWidget(POINT point)
{
return m_rect.PtInRect (point);
}
int CSquare::GetType()
{
return 2; // Square
}
void CSquare::Serialize (CArchive& ar)
{
CWidget::Serialize (ar);
if (ar.IsStoring ())
ar << m_rect;
else
ar >> m_rect;
}
WidgBase.h
#if !defined(AFX_WIDGBASE_H__877329CA_C22E_11D0_B2D8_444553540000__INCLUDED_)
#define AFX_WIDGBASE_H__877329CA_C22E_11D0_B2D8_444553540000__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// WidgBase.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CWidget command target
class CWidget : public CCmdTarget
{
DECLARE_DYNCREATE(CWidget)
CWidget(); // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
virtual void GetItemRect (LPRECT pRect);
virtual ~CWidget();
virtual int GetType ();
virtual BOOL PtInWidget (POINT point);
virtual void DrawDragImage (CDC* pDC, POINT point);
virtual void Draw (CDC* pDC);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWidget)
//}}AFX_VIRTUAL
// Implementation
protected:
CRect m_rect;
// Generated message map functions
//{{AFX_MSG(CWidget)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately
// before the previous line.
#endif // !defined(AFX_WIDGBASE_H__877329CA_C22E_11D0_B2D8_444553540000__INCLUDED_)
WidgBase.cpp
// WidgBase.cpp : implementation file
//
#include "stdafx.h"
#include "Widget.h"
#include "WidgBase.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CWidget
IMPLEMENT_DYNCREATE(CWidget, CCmdTarget)
CWidget::CWidget()
{
}
CWidget::~CWidget()
{
}
BEGIN_MESSAGE_MAP(CWidget, CCmdTarget)
//{{AFX_MSG_MAP(CWidget)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWidget message handlers
void CWidget::Draw(CDC * pDC)
{
ASSERT (FALSE); // Override this function in a derived class
}
void CWidget::DrawDragImage(CDC * pDC, POINT point)
{
ASSERT (FALSE); // Override this function in a derived class
}
BOOL CWidget::PtInWidget(POINT point)
{
ASSERT (FALSE); // Override this function in a derived class
return FALSE;
}
int CWidget::GetType()
{
ASSERT (FALSE); // Override this function in a derived class
return -1;
}
void CWidget::GetItemRect(LPRECT pRect)
{
*pRect = m_rect;
}
Figure 4 Saving a Widget's Address
HGLOBAL hData = pDataObject->GetGlobalData (nFormat);
WIDGETDATA* pWidgetData = (WIDGETDATA*) ::GlobalLock (hData);
int nType = pWidgetData->nType;
CRect rect = pWidgetData->rcItem;
CPoint pt = pWidgetData->ptDrag;
::GlobalUnlock (hData);
switch (nType) {
case 0: // Circle
m_pWidget = new CCircle (rect);
break;
case 1: // Triangle
m_pWidget = new CTriangle (rect);
break;
case 2: // Square
m_pWidget = new CSquare (rect);
break;
default: // Just in case
return DROPEFFECT_NONE;
}