www.pudn.com > Exclent_image_learn.rar > DibView.cpp


// DibView.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "ImageBoard.h" 
#include "DibView.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CDibView 
 
IMPLEMENT_DYNCREATE(CDibView, CScrollView) 
 
CDibView::CDibView() 
{ 
	m_pDib = NULL; 
	m_pFloatWnd = NULL; 
	m_bDrawingRubber = FALSE; 
	m_bDrawFreeline = FALSE; 
	m_nDrawCurveStep = -1; 
	m_bDrawCurve = FALSE; 
	m_nDrawType = DT_SELECT; 
	m_nPenStyle = PS_SOLID; 
	m_nPenWidth = 1; 
	m_crPenColor = RGB(0,0,0); 
	m_crFillColor = RGB(0,0,0); 
	m_nTextAlign = DT_LEFT; 
 
	m_hCursorGeneralDraw = NULL; 
	m_hCursorFreeline = NULL; 
	m_hCursorFill = NULL; 
	m_hCursorCurve = NULL; 
} 
 
CDibView::~CDibView() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CDibView, CScrollView) 
	//{{AFX_MSG_MAP(CDibView) 
	ON_WM_LBUTTONUP() 
	ON_WM_DESTROY() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_MOUSEMOVE() 
	ON_WM_CTLCOLOR() 
	ON_WM_CREATE() 
	ON_WM_SETCURSOR() 
	//}}AFX_MSG_MAP 
	ON_MESSAGE(WM_REALIZEPAL, OnRealizePal) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CDibView drawing 
 
BOOL CDibView::PreCreateWindow(CREATESTRUCT& cs)  
{ 
	m_hCursorGeneralDraw = AfxGetApp()->LoadCursor(IDC_CURSORGENERALDRAW); 
	cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS, 
					m_hCursorGeneralDraw,  
					(HBRUSH)(COLOR_WINDOW-1), 
					AfxGetApp()->LoadIcon(IDR_IMAGEBTYPE)); 
	 
	return CScrollView::PreCreateWindow(cs); 
} 
 
void CDibView::Initialize(CDib* pDib) 
{ 
	m_pDib = pDib; 
} 
 
void CDibView::OnInitialUpdate() 
{ 
	CScrollView::OnInitialUpdate(); 
 
	CSize sizeTotal; 
	// TODO: calculate the total size of this view 
	sizeTotal.cx = sizeTotal.cy = 100; 
	SetScrollSizes(MM_TEXT, sizeTotal); 
} 
 
void CDibView::OnDraw(CDC* pDC) 
{ 
	if (::IsWindow(m_EditText.m_hWnd)) 
	{ 
		CRect rc; 
		m_EditText.GetWindowRect(&rc); 
		ScreenToClient(&rc); 
		rc.InflateRect(2,2); 
 
		CPen pen(PS_DASH,1,RGB(0,0,255)); 
		CPen *pOldPen = pDC->SelectObject(&pen); 
		CBrush *pOldBrush = pDC->SelectObject(CBrush::FromHandle((HBRUSH)::GetStockObject(NULL_BRUSH))); 
		pDC->Rectangle(&rc); 
		pDC->SelectObject(pOldBrush); 
		pDC->SelectObject(pOldPen); 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CDibView diagnostics 
 
#ifdef _DEBUG 
void CDibView::AssertValid() const 
{ 
	CScrollView::AssertValid(); 
} 
 
void CDibView::Dump(CDumpContext& dc) const 
{ 
	CScrollView::Dump(dc); 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CDibView message handlers 
 
void CDibView::OnDestroy()  
{ 
	CScrollView::OnDestroy(); 
	 
	DeleteFloatWnd(); 
	delete m_pFont; 
} 
 
void CDibView::CreateFloatWnd(HDIB hDib, CPoint ptTopLeft) 
{ 
	MergeFloatDib(); 
 
	// get DIB width and height 
    LPBYTE lpDIB = (LPBYTE)GlobalLock(hDib);  
	if (! lpDIB) 
	{ 
		GlobalUnlock(hDib); 
		return; 
	} 
	int nWidth  = (int)DIBWidth(lpDIB); 
	int nHeight = (int)DIBHeight(lpDIB); 
	GlobalUnlock(hDib); 
 
	// create float window 
	CRect rc(ptTopLeft.x, ptTopLeft.y, ptTopLeft.x+nWidth, ptTopLeft.y+nHeight); 
	m_pFloatWnd	= new CFloatDibWnd(hDib, rc, this); 
} 
 
void CDibView::DeleteFloatWnd() 
{ 
	if (m_pFloatWnd) 
	{ 
		delete m_pFloatWnd; 
		m_pFloatWnd = NULL; 
	} 
} 
 
void CDibView::ClientToDib(CPoint& point) 
{ 
	point.x += GetScrollPos(SB_HORZ); 
	point.y += GetScrollPos(SB_VERT); 
} 
 
void CDibView::ClientToDib(CRect& rect) 
{ 
	rect.left += GetScrollPos(SB_HORZ); 
	rect.top += GetScrollPos(SB_VERT); 
	rect.right += GetScrollPos(SB_HORZ); 
	rect.bottom += GetScrollPos(SB_VERT); 
} 
 
void CDibView::DibToClient(CPoint& point) 
{ 
	point.x -= GetScrollPos(SB_HORZ); 
	point.y -= GetScrollPos(SB_VERT); 
} 
 
void CDibView::DibToClient(CRect& rect) 
{ 
	rect.left -= GetScrollPos(SB_HORZ); 
	rect.top -= GetScrollPos(SB_VERT); 
	rect.right -= GetScrollPos(SB_HORZ); 
	rect.bottom -= GetScrollPos(SB_VERT); 
} 
 
BOOL CDibView::AdjustPointinDib(CPoint& point) 
{ 
	int nWidth = m_pDib->GetWidth(); 
	int nHeight = m_pDib->GetHeight(); 
	BOOL bOut = FALSE; 
 
	ClientToDib(point); 
	if (point.x < 0) 
	{ 
		point.x = 0; 
		bOut = TRUE; 
	} 
	else if (point.x >= nWidth) 
	{ 
		point.x = nWidth; 
		bOut = TRUE; 
	} 
	if (point.y < 0) 
	{ 
		point.y = 0; 
		bOut = TRUE; 
	} 
	else if (point.y >= nHeight) 
	{ 
		point.y = nHeight; 
		bOut = TRUE; 
	} 
	DibToClient(point); 
 
	return bOut; 
} 
 
void CDibView::DoDrawRubber(CDC *pDC, CRect rc) 
{ 
	if (rc.IsRectEmpty()) 
		return; 
 
	// draw  
	switch(m_nDrawType) 
	{ 
	case DT_SELECT: 
	case DT_TEXT: 
		pDC->Rectangle(&rc); 
		break; 
	case DT_LINE: 
		{ 
			// use client coordinates 
			CPoint ptStart(m_ptStart); 
			DibToClient(ptStart); 
			if (ptStart == rc.TopLeft() ||  
				ptStart == rc.BottomRight()) 
			{ 
				pDC->MoveTo(rc.TopLeft()); 
				pDC->LineTo(rc.BottomRight()); 
			} 
			else 
			{ 
				pDC->MoveTo(rc.right, rc.top); 
				pDC->LineTo(rc.left, rc.bottom); 
			} 
		} 
		break; 
	case DT_CURVE: 
		{ 
			if (m_nDrawCurveStep == 0) 
			{ 
				// use client coordinates 
				CPoint ptStart(m_ptStart); 
				DibToClient(ptStart); 
				if (ptStart == rc.TopLeft() ||  
					ptStart == rc.BottomRight()) 
				{ 
					pDC->MoveTo(rc.TopLeft()); 
					pDC->LineTo(rc.BottomRight()); 
				} 
				else 
				{ 
					pDC->MoveTo(rc.right, rc.top); 
					pDC->LineTo(rc.left, rc.bottom); 
				} 
			} 
		} 
		break; 
	case DT_RECT_H: 
	case DT_RECT_F: 
		pDC->Rectangle(&rc); 
		break; 
	case DT_ROUNDRECT_H: 
	case DT_ROUNDRECT_F: 
		pDC->RoundRect(&rc, CPoint((int)(rc.Width()/3), (int)(rc.Height()/3))); 
		break; 
	case DT_ELLIP_H: 
	case DT_ELLIP_F: 
		pDC->Ellipse(&rc); 
		break; 
	} 
} 
 
void CDibView::StartDrawRubber(CPoint point) 
{ 
	// save current mouse position 
	ClientToDib(point); 
	m_ptStart = point; 
 
	// empty current rectangle 
	m_rcClip.SetRectEmpty(); 
	m_rcRubber.SetRectEmpty(); 
 
	// capture mouse 
	SetCapture(); 
} 
 
void CDibView::DrawRubber(CPoint point) 
{ 
	// get DC and set its ROP 
	CClientDC dc(this); 
 
	// define used pen 
	int nPenStyle; 
	int nPenWidth; 
	COLORREF color; 
	int nOldRop = dc.SetROP2(R2_NOTXORPEN); 
	if (m_nDrawType == DT_SELECT || m_nDrawType == DT_TEXT) 
	{ 
		nPenStyle = PS_DOT; 
		nPenWidth = 1; 
		color = RGB(0,0,0); 
	} 
	else 
	{ 
		nPenStyle = m_nPenStyle; 
		nPenWidth = m_nPenWidth; 
		color = m_crPenColor; 
	} 
	CPen pen(nPenStyle, nPenWidth, color); 
	CPen* pOldPen = dc.SelectObject(&pen); 
 
	// if there is rectangle drawn, clear it 
	DoDrawRubber(&dc, m_rcRubber); 
 
	// Adjust cooridnates for select 
	if (m_nDrawType == DT_SELECT) 
	{ 
		// get current scroll pos 
		int nScrollX = GetScrollPos(SB_HORZ); 
		int nScrollY = GetScrollPos(SB_VERT); 
		// calculate new scroll pos, and set it 
		CRect rcClient; 
		GetClientRect(&rcClient); 
		int nMinX, nMaxX, nMinY, nMaxY; 
		GetScrollRange(SB_HORZ, &nMinX, &nMaxX); 
		GetScrollRange(SB_VERT, &nMinY, &nMaxY); 
		BOOL bNeedRedraw = FALSE; 
		if ((rcClient.Width() < m_pDib->GetWidth()) && 
			(point.x < 0 || point.x > rcClient.right)) 
		{ 
			nScrollX += point.x; 
			nScrollX = BOUND(nScrollX, nMinX, nMaxX); 
			SetScrollPos(SB_HORZ, nScrollX); 
			bNeedRedraw = TRUE; 
		} 
		if ((rcClient.Height() < m_pDib->GetHeight()) && 
			(point.y < 0 || point.y > rcClient.bottom)) 
		{ 
			nScrollY += point.y; 
			nScrollY = BOUND(nScrollY, nMinY, nMaxY); 
			SetScrollPos(SB_VERT, nScrollY); 
			bNeedRedraw = TRUE; 
		} 
		if (bNeedRedraw) 
		{ 
			// redraw 
			Invalidate(FALSE); 
			UpdateWindow(); 
		} 
		// normalize point coordinate 
		if (AdjustPointinDib(point)) 
		{ 
			ClientToScreen(&point); 
			SetCursorPos(point.x, point.y); 
			ScreenToClient(&point); 
		} 
	} 
 
	// use client coordinates 
	CPoint ptStart(m_ptStart); 
	DibToClient(ptStart); 
	// set new rectangle 
	if (point.x < ptStart.x) 
	{ 
		m_rcRubber.left = point.x; 
		m_rcRubber.right = ptStart.x; 
	}	 
	else 
	{ 
		m_rcRubber.left = ptStart.x; 
		m_rcRubber.right = point.x; 
	} 
	if (point.y < ptStart.y) 
	{ 
		m_rcRubber.top = point.y; 
		m_rcRubber.bottom = ptStart.y; 
	} 
	else 
	{ 
		m_rcRubber.top = ptStart.y; 
		m_rcRubber.bottom = point.y; 
	} 
	m_rcRubber.NormalizeRect(); 
 
	// draw new rectangle 
	DoDrawRubber(&dc, m_rcRubber); 
 
	// restore 
	dc.SelectObject(pOldPen); 
	dc.SetROP2(nOldRop); 
} 
 
void CDibView::StopDrawRubber() 
{ 
	if (m_nDrawType == DT_SELECT || m_nDrawType == DT_TEXT) 
	{ 
		m_rcClip = m_rcRubber; 
 
		// if there is rectangle drawn, clear it 
		if (! m_rcClip.IsRectEmpty()) 
		{ 
			// get DC and set its ROP 
			CClientDC dc(this); 
			int OldRop = dc.SetROP2(R2_NOTXORPEN); 
			// define used pen 
			CPen pen(PS_DOT, 1, RGB(0,0,0)); 
			CPen* pOldPen = dc.SelectObject(&pen); 
			 
			// draw to clear 
			DoDrawRubber(&dc, m_rcClip); 
		 
			// restore 
			dc.SetROP2(OldRop); 
			dc.SelectObject(pOldPen); 
		} 
		 
		if (m_nDrawType == DT_TEXT) 
		{ 
			// empty clip area  
			m_rcClip.SetRectEmpty(); 
 
			CRect rc = m_rcRubber; 
 
			CClientDC dc(this); 
			CFont *pOldFont = dc.SelectObject(m_pFont); 
			CRect rcLetter(0,0,1,1); 
			int nHeight = dc.DrawText(_T("жа"),&rcLetter, DT_CALCRECT); 
			int nWidth = 4*rcLetter.Width(); 
			dc.SelectObject(pOldFont); 
 
			if (rc.Height() < nHeight) 
				rc.bottom = rc.top + nHeight; 
			if (rc.Width() < nWidth) 
				rc.right = rc.left + nWidth; 
			ClientToDib(rc); 
			if (rc.bottom > m_pDib->GetHeight()) 
				rc.bottom = m_pDib->GetHeight(); 
			if (rc.right > m_pDib->GetWidth()) 
				rc.right = m_pDib->GetWidth(); 
			DibToClient(rc); 
 
			DWORD style = ES_LEFT; 
			if (m_nTextAlign == DT_LEFT) 
				style = ES_LEFT; 
			else if (m_nTextAlign == DT_CENTER) 
				style = ES_CENTER; 
			else if (m_nTextAlign == DT_RIGHT) 
				style = ES_RIGHT; 
			m_EditText.Create(style|WS_VISIBLE|WS_CHILD|ES_MULTILINE,  
						  rc,  
						  this,  
						  IDC_EDIT); 
			rc.InflateRect(2,2); 
			InvalidateRect(&rc); 
			m_EditText.SetFont(m_pFont); 
			m_EditText.SetFocus(); 
		} 
	} 
	else 
	{ 
		// if there is rectangle drawn, clear it 
		CClientDC dc(this); 
		CPen pen(m_nPenStyle, m_nPenWidth, m_crPenColor); 
		int nOldRop = dc.SetROP2(R2_NOTXORPEN); 
		CPen* pOldPen = dc.SelectObject(&pen); 
		DoDrawRubber(&dc, m_rcRubber); 
		dc.SetROP2(nOldRop); 
		dc.SelectObject(pOldPen); 
		 
		// draw on dib		 
		CRect rc = m_rcRubber; 
		ClientToDib(rc); 
		CBrush brush(m_crFillColor); 
		CBrush* pOldBrush; 
		CDC * pDibDC = m_pDib->BeginPaint(&dc); 
		pOldPen = pDibDC->SelectObject(&pen); 
		if (m_nDrawType == DT_RECT_F ||  
			m_nDrawType == DT_ROUNDRECT_F ||  
			m_nDrawType == DT_ELLIP_F) 
		{ 
			pOldBrush = pDibDC->SelectObject(&brush); 
		} 
		else 
			pOldBrush = dc.SelectObject(CBrush::FromHandle((HBRUSH)GetStockObject(HOLLOW_BRUSH))); 
 
		switch(m_nDrawType) 
		{ 
		case DT_LINE: 
			{ 
				if (m_ptStart == rc.TopLeft() ||  
					m_ptStart == rc.BottomRight()) 
				{ 
					pDibDC->MoveTo(rc.TopLeft()); 
					pDibDC->LineTo(rc.BottomRight()); 
				} 
				else 
				{ 
					pDibDC->MoveTo(rc.right, rc.top); 
					pDibDC->LineTo(rc.left, rc.bottom); 
				} 
			} 
			break; 
		case DT_RECT_H: 
		case DT_RECT_F: 
			pDibDC->Rectangle(&rc); 
			break; 
		case DT_ROUNDRECT_H: 
		case DT_ROUNDRECT_F: 
			pDibDC->RoundRect(&rc, CPoint((int)(rc.Width()/3), (int)(rc.Height()/3))); 
			break; 
		case DT_ELLIP_H: 
		case DT_ELLIP_F: 
			pDibDC->Ellipse(&rc); 
			break; 
		} 
 
		pDibDC->SelectObject(pOldPen); 
		pDibDC->SelectObject(pOldBrush); 
 
		m_pDib->EndPaint(); 
 
		Invalidate(FALSE); 
	} 
 
	// release capture mouse 
	ReleaseCapture(); 
} 
 
BOOL CDibView::PointInDib(CPoint point) 
{ 
	if (m_pDib->IsEmpty()) 
		return FALSE; 
 
	ClientToDib(point); 
	CRect rcDib(0, 0, m_pDib->GetWidth(), m_pDib->GetWidth()); 
	return rcDib.PtInRect(point); 
} 
 
BOOL CDibView::MergeText() 
{ 
	if (! ::IsWindow(m_EditText.m_hWnd)) 
		return FALSE; 
 
	CString s; 
	m_EditText.GetWindowText(s); 
 
	CRect rc; 
	m_EditText.GetWindowRect(&rc); 
	ScreenToClient(&rc); 
	CRect rcClear = rc; 
	rcClear.InflateRect(3,3); 
	m_EditText.DestroyWindow(); 
	InvalidateRect(&rcClear); 
 
	// Merge Text into DIB 
	if (! s.IsEmpty()) 
	{ 
		CClientDC dc(this); 
 
		CDC * pDibDC = m_pDib->BeginPaint(&dc); 
		int nOldBkMode = pDibDC->SetBkMode(TRANSPARENT); 
		COLORREF crOldTextColor = pDibDC->SetTextColor(m_crPenColor); 
		CFont *pOldFont = pDibDC->SelectObject(m_pFont); 
 
		// needed rectangle 
		ClientToDib(rc); 
		if (rc.bottom > m_pDib->GetHeight()) 
			rc.bottom = m_pDib->GetHeight(); 
		if (rc.right > m_pDib->GetWidth()) 
			rc.right = m_pDib->GetWidth(); 
 
		pDibDC->DrawText(s, &rc, m_nTextAlign); 
		pDibDC->SetBkMode(nOldBkMode); 
		pDibDC->SetTextColor(crOldTextColor); 
		pDibDC->SelectObject(pOldFont); 
		m_pDib->EndPaint(); 
	} 
 
	return TRUE; 
} 
 
void CDibView::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	if (PointInDib(point)) 
	{ 
		// Merge and delete old float DIB (if exist) 
		MergeFloatDib(); 
 
		// if ther is text, just merge it into DIB 
		if (! MergeText())	// else, do paint 
		{ 
			if (m_nDrawType == DT_FREELINE) 
			{ 
				m_bDrawFreeline = TRUE; 
				m_ptFreelineStart = point; 
				SetCapture(); 
 
				// set a pixel anyway 
				CClientDC dc(this); 
				dc.SetPixel(point, m_crPenColor); 
 
				ClientToDib(point); 
				CDC * pDibDC = m_pDib->BeginPaint(&dc); 
				pDibDC->SetPixel(point, m_crPenColor); 
				m_pDib->EndPaint(); 
			} 
			else if (m_nDrawType == DT_FILL) 
			{ 
				CBrush brush(m_crFillColor); 
 
				CClientDC dc(this); 
				COLORREF crColor = dc.GetPixel(point); 
 
				CBrush* pOldBrush = dc.SelectObject(&brush); 
				dc.ExtFloodFill(point.x,			// x-coordinate where filling begins 
								point.y,			// y-coordinate where filling begins 
								crColor,			// fill color   
								FLOODFILLSURFACE);	// fill type 
				dc.SelectObject(pOldBrush); 
 
				ClientToDib(point); 
				CDC * pDibDC = m_pDib->BeginPaint(&dc); 
				pOldBrush = pDibDC->SelectObject(&brush); 
				pDibDC->ExtFloodFill(point.x,				// x-coordinate where filling begins 
									 point.y,				// y-coordinate where filling begins 
									 crColor,				// fill color   
									 FLOODFILLSURFACE);		// fill type 
				pDibDC->SelectObject(pOldBrush); 
				m_pDib->EndPaint(); 
			} 
			else if (m_nDrawType == DT_CURVE) 
			{ 
				if (! m_bDrawCurve) 
				{ 
					m_bDrawCurve = TRUE; 
					m_nDrawCurveStep = 1; 
					m_ptCurve[0] = point; 
					m_ptCurve[1] = point; 
					m_ptCurve[2] = point; 
					m_ptCurve[3] = point; 
					// capture mouse 
					::SetCursor(m_hCursorCurve); 
					SetCapture(); 
				} 
				else 
				{ 
					CRect rc; 
					GetClientRect(&rc); 
					if (! rc.PtInRect(point)) 
					{ 
						DrawTmpCurve(); 
						m_bDrawCurve = FALSE; 
						ReleaseCapture(); 
						::SetCursor(m_hCursorGeneralDraw); 
					} 
					else 
					{ 
						DrawTmpCurve(); 
						if (m_nDrawCurveStep == 2) 
							m_ptCurve[2] = point; 
						else if (m_nDrawCurveStep == 3) 
							m_ptCurve[1] = point; 
						DrawTmpCurve(); 
					} 
				} 
			} 
			else 
			{ 
				if (m_nDrawType == DT_LINE) 
				{ 
					// set a pixel anyway 
					CClientDC dc(this); 
					dc.SetPixel(point, m_crPenColor); 
 
					ClientToDib(point); 
					CDC * pDibDC = m_pDib->BeginPaint(&dc); 
					pDibDC->SetPixel(point, m_crPenColor); 
					m_pDib->EndPaint(); 
				} 
				// start draw rectangle 
				StartDrawRubber(point); 
				m_bDrawingRubber = TRUE; 
			} 
		} 
	} 
 
	CScrollView::OnLButtonDown(nFlags, point); 
} 
 
void CDibView::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	// change rectangle 
	if (m_bDrawingRubber) 
		DrawRubber(point); 
 
	if (m_bDrawCurve && nFlags == MK_LBUTTON) 
	{ 
		DrawTmpCurve(); 
		if (m_nDrawCurveStep == 1) 
			m_ptCurve[3] = point; 
		else if (m_nDrawCurveStep == 2) 
			m_ptCurve[2] = point; 
		else if (m_nDrawCurveStep == 3) 
			m_ptCurve[1] = point; 
		DrawTmpCurve(); 
	} 
 
	// draw FREELINE 
	if (m_bDrawFreeline) //m_nDrawType == DT_FREELINE && nFlags == MK_LBUTTON) 
	{ 
		CPen pen(m_nPenStyle, m_nPenWidth, m_crPenColor); 
 
		CClientDC dc(this); 
		CPen* pOldPen = dc.SelectObject(&pen); 
		dc.MoveTo(m_ptFreelineStart); 
		dc.LineTo(point); 
		dc.SelectObject(pOldPen); 
 
		CPoint pt = point; 
 
		ClientToDib(m_ptFreelineStart); 
		ClientToDib(pt); 
		CDC * pDibDC = m_pDib->BeginPaint(&dc); 
		pOldPen = pDibDC->SelectObject(&pen); 
		pDibDC->MoveTo(m_ptFreelineStart); 
		pDibDC->LineTo(pt); 
		pDibDC->SelectObject(pOldPen); 
		m_pDib->EndPaint(); 
 
		// new start point 
		m_ptFreelineStart = point; 
	} 
 
	CScrollView::OnMouseMove(nFlags, point); 
} 
 
void CDibView::OnLButtonUp(UINT nFlags, CPoint point)  
{ 
	if (m_bDrawFreeline) 
	{ 
		m_bDrawFreeline = FALSE; 
		ReleaseCapture(); 
	} 
	else if (m_bDrawCurve) 
	{ 
		m_nDrawCurveStep++; 
		// finish draw curve 
		if (m_nDrawCurveStep > 3) 
		{ 
			ReleaseCapture(); 
			::SetCursor(m_hCursorGeneralDraw); 
			m_bDrawCurve = FALSE; 
			DrawCurve(); 
		} 
	} 
	else if (m_bDrawingRubber) 
	{ 
		StopDrawRubber(); 
		m_bDrawingRubber = FALSE; 
 
		if (! m_rcClip.IsRectEmpty()) 
		{ 
			// adjust position with scroll position 
			CRect rcInDib(m_rcClip); 
			ClientToDib(rcInDib); 
 
			// create float DIB 
			HDIB hDib = m_pDib->CopyRect(rcInDib); 
 
			// create new float DIB window 
			CreateFloatWnd(hDib, m_rcClip.TopLeft()); 
		} 
	} 
 
	CScrollView::OnLButtonUp(nFlags, point); 
} 
 
void CDibView::DrawTmpCurve() 
{ 
	CPen penCurve(PS_SOLID, m_nPenWidth, m_crPenColor); 
 
	CClientDC dc(this); 
	CPen* pOldPen = dc.SelectObject(&penCurve); 
	int nOldRop = dc.SetROP2(R2_NOTXORPEN); 
	dc.PolyBezier(m_ptCurve, 4); 
	dc.SelectObject(pOldPen); 
	dc.SetROP2(nOldRop); 
} 
 
void CDibView::DrawCurve() 
{ 
	DrawTmpCurve(); 
 
	CPen penCurve(PS_SOLID, m_nPenWidth, m_crPenColor); 
 
	CClientDC dc(this); 
	CDC * pDibDC = m_pDib->BeginPaint(&dc); 
 
	CPen* pOldPen = pDibDC->SelectObject(&penCurve); 
	pDibDC->PolyBezier(m_ptCurve, 4); 
	pDibDC->SelectObject(pOldPen); 
	m_pDib->EndPaint(); 
 
	Invalidate(FALSE); 
} 
 
void CDibView::CutSelectedRect() 
{ 
	if (! m_rcClip.IsRectEmpty()) 
	{ 
		// adjust position with scroll position 
		CRect rcInDib(m_rcClip); 
		ClientToDib(rcInDib); 
 
		// cut select rectangle in m_pDib 
		m_pDib->CutRect(rcInDib); 
 
		// empty current rectangle 
		m_rcClip.SetRectEmpty(); 
 
		// document changed 
		CDocument* pDoc = GetDocument(); 
		pDoc->SetModifiedFlag(TRUE); 
	} 
} 
 
void CDibView::MergeFloatDib() 
{ 
	if (m_pFloatWnd) 
	{ 
		CRect rc; 
		m_pFloatWnd->GetWindowRect(&rc); 
		CPoint point = rc.TopLeft(); 
		ScreenToClient(&point); 
		ClientToDib(point); 
		m_pDib->MergeDib(m_pFloatWnd->m_hDibFloat, point); 
	 
		// document changed 
		CDocument* pDoc = GetDocument(); 
		pDoc->SetModifiedFlag(TRUE); 
	} 
	DeleteFloatWnd(); 
} 
 
void CDibView::DeleteFloatDib() 
{ 
	// if selected rect is exist, cut it 
	CutSelectedRect(); 
	// if float DIB window exist, delete it 
	DeleteFloatWnd(); 
} 
 
void CDibView::CutFloatDib() 
{ 
	// copy to clipboard first 
	CopyToClipboard(); 
	// then delete 
	DeleteFloatDib(); 
} 
 
void CDibView::CopyToClipboard() 
{ 
	// Clean clipboard of contents, and copy the DIB/DDB/PAL. 
	// Actual copy will occured in WM_RENDERALLFORMATS/WM_RENDERFORMAT 
	if (OpenClipboard()) 
	{ 
		EmptyClipboard(); 
 
		HDIB hDib; 
		HBITMAP hBitmap; 
		HPALETTE hPalette; 
		// if there is float dib, copy it 
		if (m_pFloatWnd) 
		{ 
			hDib = CopyHandle(m_pFloatWnd->m_hDibFloat); 
			hBitmap = DIBToBitmap(m_pFloatWnd->m_hDibFloat, (HPALETTE)m_pDib->m_pPalette->GetSafeHandle()); 
			hPalette = CopyPalette((HPALETTE)m_pDib->m_pPalette->GetSafeHandle()); 
		} 
		else	// otherwise, copy the entire DIB 
		{ 
			hDib = CopyHandle(m_pDib->m_hDib); 
			hBitmap = DIBToBitmap(m_pDib->m_hDib, (HPALETTE)m_pDib->m_pPalette->GetSafeHandle ()); 
			hPalette = CopyPalette((HPALETTE)m_pDib->m_pPalette->GetSafeHandle()); 
		} 
 
		// set them to clipboard 
		SetClipboardData(CF_DIB, hDib); 
		SetClipboardData(CF_BITMAP, hBitmap); 
		SetClipboardData(CF_PALETTE, hPalette); 
 
		CloseClipboard(); 
	} 
} 
 
void CDibView::Cut() 
{ 
	// copy to clipboard first 
	CopyToClipboard(); 
	// then delete 
	Delete(); 
} 
 
void CDibView::Delete() 
{ 
	if (m_pFloatWnd) // clip area 
		DeleteFloatDib(); 
	else			// entire DIB 
	{ 
		m_pDib->Destroy(); 
		// modify document flags 
		CSize sizeTotal(0, 0); 
		SetScrollSizes(MM_TEXT, sizeTotal); 
		CDocument* pDoc = GetDocument(); 
		pDoc->UpdateAllViews(NULL); 
		pDoc->SetModifiedFlag(TRUE); 
	} 
} 
 
BOOL CDibView::PasteDibFromClipboard() 
{ 
	// get DIB handle from clipboard 
	HDIB hNewDIB = NULL; 
	if (OpenClipboard()) 
	{ 
		if (IsClipboardFormatAvailable(CF_DIB)) 
			hNewDIB = CopyHandle(GetClipboardData(CF_DIB)); 
 
		CloseClipboard(); 
	} 
	if (hNewDIB == NULL) 
		return FALSE; 
 
	// if current DIB is empty, use the pasted one as current 
	if (m_pDib->IsEmpty()) 
	{ 
		// create current DIB 
		LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDIB); 
		m_pDib->Create(lpDIB); 
		GlobalUnlock(hNewDIB); 
		GlobalFree(hNewDIB); 
 
		// modify document flags 
		CSize sizeTotal(m_pDib->GetWidth(), m_pDib->GetHeight()); 
		SetScrollSizes(MM_TEXT, sizeTotal); 
		CDocument* pDoc = GetDocument(); 
		OnRealizePal((WPARAM)m_hWnd,0);  // realize the new palette 
		pDoc->UpdateAllViews(NULL); 
		pDoc->SetModifiedFlag(TRUE); 
	} 
	else // put it in float DIB window 
	{ 
		// empty current rectangle 
		m_rcClip.SetRectEmpty(); 
		CreateFloatWnd(hNewDIB, CPoint(0, 0)); 
	} 
 
	return TRUE; 
} 
 
BOOL CDibView::PasteBitmapFromClipboard() 
{ 
	// get DIB handle from clipboard 
	HBITMAP hNewDDB = NULL; 
	HPALETTE hPal = NULL; 
	if (OpenClipboard()) 
	{ 
		if (IsClipboardFormatAvailable(CF_BITMAP)) 
			hNewDDB = (HBITMAP)GetClipboardData(CF_BITMAP); 
		if (IsClipboardFormatAvailable(CF_PALETTE)) 
			hPal = (HPALETTE)GetClipboardData(CF_PALETTE); 
 
		CloseClipboard(); 
	} 
	if (hNewDDB == NULL) 
		return FALSE; 
 
	// if current DIB is empty, use the pasted one as current 
	if (m_pDib->IsEmpty()) 
	{ 
		// create current DIB 
		m_pDib->Create(hNewDDB, hPal); 
 
		// modify document flags 
		CSize sizeTotal(m_pDib->GetWidth(), m_pDib->GetHeight()); 
		SetScrollSizes(MM_TEXT, sizeTotal); 
		CDocument* pDoc = GetDocument(); 
		OnRealizePal((WPARAM)m_hWnd,0);  // realize the new palette 
		pDoc->UpdateAllViews(NULL); 
		pDoc->SetModifiedFlag(TRUE); 
	} 
	else // put it in float DIB window 
	{ 
		// empty current rectangle 
		m_rcClip.SetRectEmpty(); 
		HDIB hDib = BitmapToDIB(hNewDDB, (HPALETTE)m_pDib->m_pPalette->GetSafeHandle()); 
		HDIB hNewDib = ConvertDIBFormat(hDib, m_pDib->GetBitCount(), (HPALETTE)m_pDib->m_pPalette->GetSafeHandle()); 
		DestroyDIB(hDib); 
		CreateFloatWnd(hNewDib, CPoint(0, 0)); 
	} 
 
	return TRUE; 
} 
 
BOOL CDibView::PastePalFromClipboard() 
{ 
	// egt DIB handle from clipboard 
	HPALETTE hPal = NULL; 
	if (OpenClipboard()) 
	{ 
		if (IsClipboardFormatAvailable(CF_PALETTE)) 
			hPal = (HPALETTE)GetClipboardData(CF_PALETTE); 
 
		CloseClipboard(); 
	} 
	if (hPal == NULL) 
		return FALSE; 
 
	// if current DIB is empty, do nothing 
	if (m_pDib->IsEmpty()) 
		return FALSE; 
 
	// get color bits 
	int nEntries; 
	WORD wBpp; 
	GetObject(hPal, sizeof(int), &nEntries); 
	if (nEntries > 16) 
		wBpp = 8; 
	else if (nEntries > 2) 
		wBpp = 4; 
	else 
		wBpp = 1; 
 
	// convert to new DIB 
	HDIB hNewDib = ConvertDIBFormat(m_pDib->m_hDib, wBpp, hPal); 
	if (! hNewDib) 
		return FALSE; 
 
	m_pDib->Destroy(); 
	// create current DIB 
	LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib); 
	m_pDib->Create(lpDIB); 
	GlobalUnlock(hNewDib); 
	GlobalFree(hNewDib); 
	// modify document flags 
	CDocument* pDoc = GetDocument(); 
	OnRealizePal((WPARAM)m_hWnd,0);  // realize the new palette 
	pDoc->UpdateAllViews(NULL); 
	pDoc->SetModifiedFlag(TRUE); 
 
	return TRUE; 
} 
 
void CDibView::SelectPaste(int nCF) 
{ 
	switch(nCF) 
	{ 
	case CF_DIB: 
		PasteDibFromClipboard(); 
		return; 
	case CF_BITMAP: 
		PasteBitmapFromClipboard(); 
		return; 
	case CF_PALETTE: 
		PastePalFromClipboard(); 
		return; 
	} 
} 
 
void CDibView::Paste() 
{ 
	if (! PasteDibFromClipboard()) 
		if (! PasteBitmapFromClipboard()) 
			PastePalFromClipboard(); 
} 
 
void CDibView::OnRealizePal(WPARAM wParam, LPARAM lParam) 
{ 
	ASSERT(wParam != NULL); 
 
	if (m_pDib->IsEmpty()) 
		return;  // must be a new document 
 
	CPalette* pPal = m_pDib->GetPalette(); 
	if (pPal != NULL) 
	{ 
		CWnd* pAppFrame = AfxGetApp()->m_pMainWnd; 
 
		CClientDC appDC(pAppFrame); 
		// All views but one should be a background palette. 
		// wParam contains a handle to the active view, so the SelectPalette 
		// bForceBackground flag is FALSE only if wParam == m_hWnd (this view) 
		CPalette* oldPalette = appDC.SelectPalette(pPal, ((HWND)wParam) != m_hWnd); 
 
		if (oldPalette != NULL) 
		{ 
			UINT nColorsChanged = appDC.RealizePalette(); 
			if (nColorsChanged > 0) 
				GetDocument()->UpdateAllViews(NULL); 
			appDC.SelectPalette(oldPalette, TRUE); 
		} 
		else 
		{ 
			TRACE0("\tSelectPalette failed in CDibView::OnPaletteChanged\n"); 
		} 
	} 
} 
 
void CDibView::Rotate(int nAngle) 
{ 
	if (m_pFloatWnd) 
	{ 
		LPBYTE lpDIB = (LPBYTE)GlobalLock(m_pFloatWnd->m_hDibFloat); 
		CDib dib; 
		if (! dib.Create(lpDIB)) 
			return; 
		GlobalUnlock(m_pFloatWnd->m_hDibFloat); 
		switch (nAngle) 
		{ 
		case 90: 
			dib.Rotate90(); 
			break; 
		case 180: 
			dib.Rotate180(); 
			break; 
		case 270: 
			dib.Rotate270(); 
			break; 
		} 
 
		// get float window position 
		CRect rcFloat; 
		m_pFloatWnd->GetWindowRect(&rcFloat); 
		CPoint ptTopLeft = rcFloat.TopLeft(); 
		ScreenToClient(&ptTopLeft); 
 
		// delete old float window 
		DeleteFloatWnd(); 
		CutSelectedRect(); 
 
		// create float window 
			// get DIB width and height 
		int nWidth  = (int)dib.GetWidth(); 
		int nHeight = (int)dib.GetHeight(); 
		CRect rc(ptTopLeft.x, ptTopLeft.y, ptTopLeft.x+nWidth, ptTopLeft.y+nHeight); 
			// create it 
		HDIB hDib = CopyHandle(dib.GetHandle()); 
		m_pFloatWnd	= new CFloatDibWnd(hDib, rc, this); 
	} 
	else	// otherwise, copy the entire DIB 
	{ 
		switch (nAngle) 
		{ 
		case 90: 
			m_pDib->Rotate90(); 
			break; 
		case 180: 
			m_pDib->Rotate180(); 
			break; 
		case 270: 
			m_pDib->Rotate270(); 
			break; 
		} 
	} 
} 
 
void CDibView::Flip(int nDirection) 
{ 
	if (m_pFloatWnd) 
	{ 
		LPBYTE lpDIB = (LPBYTE)GlobalLock(m_pFloatWnd->m_hDibFloat); 
		CDib dib; 
		if (! dib.Create(lpDIB)) 
			return; 
		GlobalUnlock(m_pFloatWnd->m_hDibFloat); 
		switch (nDirection) 
		{ 
		case MD_HORZ: 
			dib.FlipHorz(); 
			break; 
		case MD_VERT: 
			dib.FlipVert(); 
			break; 
		} 
 
		// get float window position 
		CRect rcFloat; 
		m_pFloatWnd->GetWindowRect(&rcFloat); 
		CPoint ptTopLeft = rcFloat.TopLeft(); 
		ScreenToClient(&ptTopLeft); 
 
		// delete old float window 
		DeleteFloatWnd(); 
		CutSelectedRect(); 
 
		// create float window 
			// get DIB width and height 
		int nWidth  = (int)dib.GetWidth(); 
		int nHeight = (int)dib.GetHeight(); 
		CRect rc(ptTopLeft.x, ptTopLeft.y, ptTopLeft.x+nWidth, ptTopLeft.y+nHeight); 
			// create it 
		HDIB hDib = CopyHandle(dib.GetHandle()); 
		m_pFloatWnd	= new CFloatDibWnd(hDib, rc, this); 
	} 
	else	// otherwise, copy the entire DIB 
	{ 
		switch (nDirection) 
		{ 
		case MD_HORZ: 
			m_pDib->FlipHorz(); 
			break; 
		case MD_VERT: 
			m_pDib->FlipVert(); 
			break; 
		} 
	} 
} 
 
void CDibView::Zoom(double fRatioX, double fRatioY) 
{ 
	if (m_pFloatWnd) 
	{ 
		LPBYTE lpDIB = (LPBYTE)GlobalLock(m_pFloatWnd->m_hDibFloat); 
		CDib dib; 
		if (! dib.Create(lpDIB)) 
			return; 
		GlobalUnlock(m_pFloatWnd->m_hDibFloat); 
		dib.Zoom(fRatioX, fRatioY); 
 
		// get float window position 
		CRect rcFloat; 
		m_pFloatWnd->GetWindowRect(&rcFloat); 
		CPoint ptTopLeft = rcFloat.TopLeft(); 
		ScreenToClient(&ptTopLeft); 
 
		// delete old float window 
		DeleteFloatWnd(); 
		CutSelectedRect(); 
 
		// create float window 
			// get DIB width and height 
		int nWidth  = (int)dib.GetWidth(); 
		int nHeight = (int)dib.GetHeight(); 
		CRect rc(ptTopLeft.x, ptTopLeft.y, ptTopLeft.x+nWidth, ptTopLeft.y+nHeight); 
			// create it 
		HDIB hDib = CopyHandle(dib.GetHandle()); 
		m_pFloatWnd	= new CFloatDibWnd(hDib, rc, this); 
	} 
	else	// otherwise, copy the entire DIB 
	{ 
		m_pDib->Zoom(fRatioX, fRatioY); 
	} 
} 
 
void CDibView::ChangeImageSize(int nWidth, int nHeight) 
{ 
	if (m_pFloatWnd) 
	{ 
		LPBYTE lpDIB = (LPBYTE)GlobalLock(m_pFloatWnd->m_hDibFloat); 
		CDib dib; 
		if (! dib.Create(lpDIB)) 
			return; 
		GlobalUnlock(m_pFloatWnd->m_hDibFloat); 
		dib.ChangeImageSize(nWidth, nHeight); 
 
		// get float window position 
		CRect rcFloat; 
		m_pFloatWnd->GetWindowRect(&rcFloat); 
		CPoint ptTopLeft = rcFloat.TopLeft(); 
		ScreenToClient(&ptTopLeft); 
 
		// delete old float window 
		DeleteFloatWnd(); 
		CutSelectedRect(); 
 
		// create float window 
			// get DIB width and height 
		int nWidth  = (int)dib.GetWidth(); 
		int nHeight = (int)dib.GetHeight(); 
		CRect rc(ptTopLeft.x, ptTopLeft.y, ptTopLeft.x+nWidth, ptTopLeft.y+nHeight); 
			// create it 
		HDIB hDib = CopyHandle(dib.GetHandle()); 
		m_pFloatWnd	= new CFloatDibWnd(hDib, rc, this); 
	} 
	else	// otherwise, copy the entire DIB 
	{ 
		m_pDib->ChangeImageSize(nWidth, nHeight); 
	} 
} 
 
void CDibView::ChangeCanvasSize(int nWidth, int nHeight, int nPosition) 
{ 
	if (m_pFloatWnd) 
	{ 
		LPBYTE lpDIB = (LPBYTE)GlobalLock(m_pFloatWnd->m_hDibFloat); 
		CDib dib; 
		if (! dib.Create(lpDIB)) 
			return; 
		GlobalUnlock(m_pFloatWnd->m_hDibFloat); 
		dib.ChangeCanvasSize(nWidth, nHeight, nPosition); 
 
		// get float window position 
		CRect rcFloat; 
		m_pFloatWnd->GetWindowRect(&rcFloat); 
		CPoint ptTopLeft = rcFloat.TopLeft(); 
		ScreenToClient(&ptTopLeft); 
 
		// delete old float window 
		DeleteFloatWnd(); 
		CutSelectedRect(); 
 
		// create float window 
			// get DIB width and height 
		int nWidth  = (int)dib.GetWidth(); 
		int nHeight = (int)dib.GetHeight(); 
		CRect rc(ptTopLeft.x, ptTopLeft.y, ptTopLeft.x+nWidth, ptTopLeft.y+nHeight); 
			// create it 
		HDIB hDib = CopyHandle(dib.GetHandle()); 
		m_pFloatWnd	= new CFloatDibWnd(hDib, rc, this); 
	} 
	else	// otherwise, copy the entire DIB 
	{ 
		m_pDib->ChangeCanvasSize(nWidth, nHeight, nPosition); 
	} 
} 
 
void CDibView::Crop() 
{ 
	if (! m_rcClip.IsRectEmpty()) 
	{ 
		m_pDib->Crop(m_rcClip); 
		DeleteFloatWnd(); 
		m_rcClip.SetRectEmpty(); 
	} 
} 
 
 
HBRUSH CDibView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
{ 
	HBRUSH hbr = CScrollView::OnCtlColor(pDC, pWnd, nCtlColor); 
	 
	if (pWnd->m_hWnd == m_EditText.m_hWnd) 
		pDC->SetTextColor(m_crPenColor); 
	 
	// TODO: Return a different brush if the default is not desired 
	return hbr; 
} 
 
int CDibView::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CScrollView::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	m_hCursorFreeline = AfxGetApp()->LoadCursor(IDC_CURSORFREELINE); 
	m_hCursorFill = AfxGetApp()->LoadCursor(IDC_CURSORFILL); 
	m_hCursorCurve = AfxGetApp()->LoadCursor(IDC_CURSORCURVE); 
	 
	LOGFONT lf; 
	HFONT hFont = (HFONT)GetStockObject(SYSTEM_FONT); 
	GetObject(hFont, sizeof(LOGFONT), &lf); 
	m_pFont = new CFont; 
	m_pFont->CreateFontIndirect(&lf); 
	 
	return 0; 
} 
 
BOOL CDibView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)  
{ 
	if (m_nDrawType == DT_FREELINE) 
	{ 
		::SetCursor(m_hCursorFreeline); 
		return TRUE; 
	} 
	else if (m_nDrawType == DT_FILL) 
	{ 
		::SetCursor(m_hCursorFill); 
		return TRUE; 
	} 
 
	return CScrollView::OnSetCursor(pWnd, nHitTest, message); 
}