www.gusucode.com > VC++增强版画图板源码源码程序 > VC++增强版画图板源码源码程序\code\HDraw\HDrawView.cpp

    // HDrawView.cpp : implementation of the CHDrawView class
// Download by http://www.NewXing.com

#include "stdafx.h"
#include "HDraw.h"

#include "HDrawDoc.h"
#include "HDrawView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CHDrawView

BEGIN_MESSAGE_MAP(CHDrawView, CView)
	//{{AFX_MSG_MAP(CHDrawView)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_COMMAND(ID_BMP_SAVE, OnBmpSave)
	ON_WM_RBUTTONDOWN()
	ON_COMMAND(ID_PIC_COLOR_BLUE, OnPicColorBlue)
	ON_COMMAND(ID_PIC_COLOR_GREEN, OnPicColorGreen)
	ON_COMMAND(ID_PIC_COLOR_OTHER, OnPicColorOther)
	ON_COMMAND(ID_PIC_COLOR_RED, OnPicColorRed)
	ON_COMMAND(ID_PIC_DASH, OnPicDash)
	ON_COMMAND(ID_PIC_SOLID, OnPicSolid)
	ON_COMMAND(ID_PIC_W1, OnPicW1)
	ON_COMMAND(ID_PIC_W2, OnPicW2)
	ON_COMMAND(ID_PIC_W3, OnPicW3)
	ON_COMMAND(ID_PIC_DELETE, OnPicDelete)
	ON_WM_SETCURSOR()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHDrawView construction/destruction
CHDrawView::CHDrawView()
{
	// TODO: add construction code here
	m_pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
}

CHDrawView::~CHDrawView()
{
	m_pDocument = pOldDoc;
}

BOOL CHDrawView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CHDrawView drawing

void CHDrawView::OnDraw(CDC* pDC)
{
	CHDrawDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	OnPrepareDC(pDC);

	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
		pDoc->m_strokeList.GetAt(i)->DrawStroke(pDC);
	}
}



/////////////////////////////////////////////////////////////////////////////
// CHDrawView diagnostics

#ifdef _DEBUG
void CHDrawView::AssertValid() const
{
	CView::AssertValid();
}

void CHDrawView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}


CHDrawDoc* CHDrawView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CHDrawDoc)));
	return (CHDrawDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CHDrawView message handlers
/************************************************************************
很复杂的条件判断
条件1:鼠标是否点中图形:是/否
条件2:是否按下Ctrl:是/否
条件3:选中多少个:一/多/零

非Ctrl+Track:
点中+Ctrl:			选中或取消选中
点中+非Ctrl:		选中点中,取消所有非点中

************************************************************************/
void CHDrawView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CDC* pDC = GetDC();
	OnPrepareDC(pDC);
	pDC->DPtoLP(&point);

	CHDrawDoc* pDoc = GetDocument();
	BOOL refresh = FALSE, bTrack = false, ctrlPressed = nFlags & MK_CONTROL;
	int i;
	//没有Ctrl, Track
	if(!ctrlPressed){
		for(i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
			if(pDoc->m_strokeList.GetAt(i)->m_bSelected){
				int hit = pDoc->m_strokeList.GetAt(i)->m_tracker.HitTest(point);
				if(hit >= 0 &&
					pDoc->m_strokeList.GetAt(i)->m_tracker.Track(this,point)){
					//step1. cavas reset
					pDoc->m_strokeList.GetAt(i)->ReSize(
						pDoc->m_strokeList.GetAt(i)->m_tracker.m_rect);
					Invalidate();
					GetDocument()->BackUp();//备份
					bTrack = true;
					break;
				}
			}
		}
	}
	for(i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
		if(pDoc->m_strokeList.GetAt(i)->IsPointIn(point)){
			//情况1. 点中,Ctrl按下,选中或取消选中
			if(ctrlPressed){
				//select/deselect
				pDoc->m_strokeList.GetAt(i)->m_bSelected = 
					!pDoc->m_strokeList.GetAt(i)->m_bSelected;
			}
			//情况2. 点中,没有Ctrl,选中
			else{
				//select
				pDoc->m_strokeList.GetAt(i)->m_bSelected = true;
			}
			refresh = true;
		}
		//情况3. 没有点中,没有Ctrl,取消选中
		else if(!ctrlPressed)
			pDoc->m_strokeList.GetAt(i)->m_bSelected = false;
	}
	if(refresh){
		Invalidate();
	}
	else{
		//画图
		if(!bTrack && !ctrlPressed){
			//Step1. 设置捕获
			SetCapture();
			//Step2. 加入新图形
			m_stroke = pDoc->NewStroke();
			//Step3. 设置起点
			m_stroke->SetCurrentPoint(point);
			//Step4. 设置文件已经修改状态
			pDoc->SetModifiedFlag();
		}
	}
	
	ReleaseDC(pDC);

	CView::OnLButtonDown(nFlags, point);
}

void CHDrawView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if(GetCapture() == this){
		CHDrawDoc *pDoc = GetDocument();

 		CDC *pDC = GetDC();
 		OnPrepareDC(pDC);
 		pDC->DPtoLP(&point);

		//Step0.1 点下松开,没有画
		if(m_stroke->m_points.GetSize() == 1){
			delete m_stroke;
		}
		//Step0.2 选择框
		else if(PIC_select == m_stroke->m_picType){
			bool refresh = false;
			CRect rect(m_stroke->m_points[0], m_stroke->m_points[1]);
			rect.NormalizeRect();//防止从右下往左上选
			for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
				if(rect.PtInRect(pDoc->m_strokeList.GetAt(i)->m_points.GetAt(0)) &&
					rect.PtInRect(pDoc->m_strokeList.GetAt(i)->m_points.GetAt(1))){
					pDoc->m_strokeList.GetAt(i)->m_bSelected = true;
					refresh = true;
				}
			}
			if(refresh)
				Invalidate();
			delete m_stroke;
		}
		//Step0.3 画
		else{
			//Step1. 加入新点
			m_stroke->SetCurrentPoint(point);
			pDoc->m_strokeList.Add(m_stroke);
			pDoc->BackUp();//备份
		}
		//Step2. 释放捕获
		ReleaseCapture();
		m_stroke = NULL;
		
 		ReleaseDC(pDC);

		//Step3. 全部重画
		Invalidate();
	}	
	CView::OnLButtonUp(nFlags, point);
}

void CHDrawView::OnMouseMove(UINT nFlags, CPoint point) 
{
	CString curPos;
	curPos.Format("(%d,%d)", point.x, point.y);
	GetParentFrame()->SetMessageText(curPos);

	
	CDC *pDC = GetDC();
	OnPrepareDC(pDC);
	pDC->DPtoLP(&point);

	//state1: 处于捕获状态,画图
	if(GetCapture() == this){
		m_stroke->ReDrawStroke(pDC, point);
	}
	//state2: 非捕获状态,高亮
	else{	
		bool refresh = false;
		for(int i = 0; i < GetDocument()->m_strokeList.GetSize(); i ++)
		{
			if(GetDocument()->m_strokeList.GetAt(i)->IsPointIn(point)){
				//修改鼠标
				//SetCursor(LoadCursor(NULL, IDC_ARROW));
				//if state changed from NOT selected to selected
				if(!GetDocument()->m_strokeList.GetAt(i)->IsHightLight())
					refresh = true;
				GetDocument()->m_strokeList.GetAt(i)->SetHighLight(TRUE);
			}
			else{
				//if state changed from selected to NOT selected
				if(GetDocument()->m_strokeList.GetAt(i)->IsHightLight())
					refresh = true;
				GetDocument()->m_strokeList.GetAt(i)->SetHighLight(FALSE);
			}
		}
		if(refresh)
			Invalidate();
	}
	ReleaseDC(pDC);
	CView::OnMouseMove(nFlags, point);
}

void CHDrawView::SetDocument(CHDrawDoc *pDoc)
{
	pOldDoc = m_pDocument;
	m_pDocument = pDoc;
}


void CHDrawView::OnBmpSave() 
{
	// TODO: Add your command handler code here
	CFileDialog dlg(FALSE, "bmp","hjz.bmp");
	if(dlg.DoModal() != IDOK){
		return ;
	}
	CString filePath = dlg.GetPathName();
	// TODO: Add your command handler code here
	CClientDC client(this);//用于本控件的,楼主可以不用此句
	CDC cdc;
	CBitmap bitmap;
	RECT rect;CRect r;
	GetClientRect(&rect);
	int cx = rect.right - rect.left;
	int cy = rect.bottom - rect.top;
	bitmap.CreateCompatibleBitmap(&client, cx, cy);
	cdc.CreateCompatibleDC(NULL);
	CBitmap * oldbitmap = (CBitmap* ) cdc.SelectObject(&bitmap);
	cdc.FillRect(&rect, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
	for(int i = 0; i < GetDocument()->m_strokeList.GetSize(); i ++){
		GetDocument()->m_strokeList.GetAt(i)->DrawStroke(&cdc);
	}
	cdc.SelectObject(oldbitmap);
	::OpenClipboard(this->m_hWnd);
	::EmptyClipboard();
	::SetClipboardData(CF_BITMAP, bitmap);
	::CloseClipboard();
	
	
	HBITMAP hBitmap = (HBITMAP)bitmap;
	HDC hDC;
	int iBits;
	WORD wBitCount;
	DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
	BITMAP Bitmap; 
	BITMAPFILEHEADER bmfHdr; 
	BITMAPINFOHEADER bi; 
	LPBITMAPINFOHEADER lpbi; 
	HANDLE fh, hDib, hPal,hOldPal=NULL;
	
	hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
	iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
	DeleteDC(hDC);
	if (iBits <= 1)  wBitCount = 1;
	else if (iBits <= 4)  wBitCount = 4;
	else if (iBits <= 8)  wBitCount = 8;
	else      wBitCount = 24;
	
	GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
	bi.biSize   = sizeof(BITMAPINFOHEADER);
	bi.biWidth   = Bitmap.bmWidth;
	bi.biHeight   = Bitmap.bmHeight;
	bi.biPlanes   = 1;
	bi.biBitCount  = wBitCount;
	bi.biCompression = BI_RGB;
	bi.biSizeImage  = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrImportant = 0;
	bi.biClrUsed  = 0;
	
	dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
	
	hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
	*lpbi = bi;
	
	hPal = GetStockObject(DEFAULT_PALETTE);
	if (hPal)
	{
		hDC = ::GetDC(NULL);
		hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
		RealizePalette(hDC);
	}
	
	GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
		+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
	
	if (hOldPal)
	{
		::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
		RealizePalette(hDC);
		::ReleaseDC(NULL, hDC);
	}
	
	fh = CreateFile(filePath, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
	
	if (fh == INVALID_HANDLE_VALUE)  
		return 		;
	
	bmfHdr.bfType = 0x4D42; // "BM"
	dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; 
	bmfHdr.bfSize = dwDIBSize;
	bmfHdr.bfReserved1 = 0;
	bmfHdr.bfReserved2 = 0;
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
	
	WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
	WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
	
	GlobalUnlock(hDib);
	GlobalFree(hDib);
	CloseHandle(fh); 
}


void CHDrawView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	//context menu
	CMenu rmenu;
	rmenu.LoadMenu(IDR_MENU_SET);
	ClientToScreen(&point);
	rmenu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
	rmenu.Detach();
	CView::OnRButtonDown(nFlags, point);
}

void CHDrawView::OnPicColorBlue() 
{
	CHDrawDoc *pDoc = GetDocument();
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++)
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight)
			pDoc->m_strokeList.GetAt(i)->m_penColor = RGB(0,0,255);
	GetDocument()->BackUp();//备份
	Invalidate();
}

void CHDrawView::OnPicColorRed() 
{
	// TODO: Add your command handler code here
	CHDrawDoc *pDoc = GetDocument();
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++)
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight)
			pDoc->m_strokeList.GetAt(i)->m_penColor = RGB(255,0,0);
	GetDocument()->BackUp();//备份
	Invalidate();
}

void CHDrawView::OnPicColorGreen() 
{
	// TODO: Add your command handler code here
	CHDrawDoc *pDoc = GetDocument();
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++)
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight)
			pDoc->m_strokeList.GetAt(i)->m_penColor = RGB(0,255,0);
	GetDocument()->BackUp();//备份
	Invalidate();
}

void CHDrawView::OnPicColorOther() 
{
	// TODO: Add your command handler code here
	CColorDialog dlg;
	if(dlg.DoModal() == IDOK){
		CHDrawDoc *pDoc = GetDocument();
		for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
			if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
				pDoc->m_strokeList.GetAt(i)->m_bHighLight){
				pDoc->m_strokeList.GetAt(i)->m_penColor = dlg.GetColor();
			}
		}
		GetDocument()->BackUp();//备份
		Invalidate();
	}
}

void CHDrawView::OnPicSolid() 
{
	// TODO: Add your command handler code here
	CHDrawDoc *pDoc = GetDocument();
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++)
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight)
			pDoc->m_strokeList.GetAt(i)->m_penStyle = PS_SOLID;
	Invalidate();
}
void CHDrawView::OnPicDash() 
{
	// TODO: Add your command handler code here
	CHDrawDoc *pDoc = GetDocument();
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++)
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight)
			pDoc->m_strokeList.GetAt(i)->m_penStyle = PS_DASH;
	GetDocument()->BackUp();//备份
	Invalidate();
}



void CHDrawView::OnPicW1() 
{
	// TODO: Add your command handler code here
	CHDrawDoc *pDoc = GetDocument();
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight)
			pDoc->m_strokeList.GetAt(i)->m_penWidth = 1;
	}
	GetDocument()->BackUp();//备份
	Invalidate();
}

void CHDrawView::OnPicW2() 
{
	// TODO: Add your command handler code here
	CHDrawDoc *pDoc = GetDocument();
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight)
			pDoc->m_strokeList.GetAt(i)->m_penWidth = 2;
	}
	GetDocument()->BackUp();//备份
	Invalidate();
}

void CHDrawView::OnPicW3() 
{
	// TODO: Add your command handler code here
	CHDrawDoc *pDoc = GetDocument();
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight)
			pDoc->m_strokeList.GetAt(i)->m_penWidth = 3;
	}
	GetDocument()->BackUp();//备份
	Invalidate();
}


void CHDrawView::OnPicDelete() 
{
	// TODO: Add your command handler code here
	CHDrawDoc *pDoc = GetDocument();
	//remove all strokes
	bool refresh = false;
	for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
		if(pDoc->m_strokeList.GetAt(i)->m_bSelected ||
			pDoc->m_strokeList.GetAt(i)->m_bHighLight){
			delete pDoc->m_strokeList.GetAt(i);
			pDoc->m_strokeList.RemoveAt(i);
			i--;
			refresh = true;
		}
	}
	//refresh if needed
	if(refresh){
		GetDocument()->BackUp();//备份
		Invalidate();
	}
}



BOOL CHDrawView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	if(pWnd == this){
		CPoint point;
		//Step1. get cursor position
		GetCursorPos(&point);
		//Step2. convert point from screen to client
		ScreenToClient(&point);
		
		CDC* pDC = GetDC();//获得DC
		OnPrepareDC(pDC);//设置DC的滚动属性,与ScollView的滚动有关
		pDC->DPtoLP(&point);//转换当前点为逻辑位置坐标
		CHDrawDoc *pDoc = GetDocument();
		//Track判断
		for(int i = 0; i < pDoc->m_strokeList.GetSize(); i ++){
			if(pDoc->m_strokeList.GetAt(i)->m_bSelected && 
				pDoc->m_strokeList.GetAt(i)->m_tracker.HitTest(point) >= 0){
				pDoc->m_strokeList.GetAt(i)->m_tracker.SetCursor(pWnd, nHitTest);
				ReleaseDC(pDC);
				return TRUE;
			}
		}		
		ReleaseDC(pDC);
	}
	
	return CView::OnSetCursor(pWnd, nHitTest, message);
}

BOOL CHDrawView::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	CHDrawDoc *pDoc = GetDocument();
	BOOL deleted = FALSE;
	int i, x, y;
	if   (pMsg->message   ==   WM_KEYDOWN)  
	{  
		switch (pMsg->wParam){
		case VK_DELETE:
			for(i = 0; i <pDoc->m_strokeList.GetSize(); i ++){
				if(pDoc->m_strokeList.GetAt(i)->m_bSelected){
					pDoc->m_strokeList.RemoveAt(i--);
					deleted = TRUE;
				}
			}
			if(deleted)
				Invalidate();
			break;
		case 'A':
		case 'a':
			if(::GetKeyState(VK_CONTROL) < 0){	
				for(int i = 0; i <pDoc->m_strokeList.GetSize(); i ++){
					pDoc->m_strokeList.GetAt(i)->m_bSelected = TRUE;
				}
				Invalidate();
			}
			break;
		case VK_UP:
		case VK_DOWN:
		case VK_LEFT:
		case VK_RIGHT:
			x = (pMsg->wParam==VK_RIGHT) - (pMsg->wParam==VK_LEFT);
			y = (pMsg->wParam==VK_DOWN) - (pMsg->wParam==VK_UP);
			if(::GetKeyState(VK_SHIFT) < 0){
				x *= 8;
				y *= 8;
			}
			for(int i = 0; i <pDoc->m_strokeList.GetSize(); i ++){
				if(pDoc->m_strokeList.GetAt(i)->m_bSelected){
					pDoc->m_strokeList.GetAt(i)->Move(x,y);
				}
			}
			Invalidate();
			break;
		}
	}
	return CView::PreTranslateMessage(pMsg);
}