⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textdiagramctrl.cpp

📁 TabBars的开源源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		break;

	case SB_BOTTOM:
		m_ptScrollOffset.y = (rDiagram.bottom - rClient.bottom);
		break;

	case SB_THUMBPOSITION:
		m_ptScrollOffset.y = (nPos / CHARSIZE_Y) * CHARSIZE_Y;
		break;

	case SB_THUMBTRACK:
		m_ptScrollOffset.y = (nPos / CHARSIZE_Y) * CHARSIZE_Y;
		break;
	}

	if (m_ptScrollOffset != ptOffset)
	{
		Invalidate();
		UpdateScrollbars();
	}
	
	CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CTextDiagramCtrl::OnSize(UINT nType, int cx, int cy) 
{
	CWnd::OnSize(nType, cx, cy);
	
	UpdateScrollbars();
}

BOOL CTextDiagramCtrl::RebuildConnections()
{
	if (!CTextDiagram::RebuildConnections())
	{
//		GetParent()->PostMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), TDN_INTERNALERROR), (LPARAM)GetSafeHwnd());
		return FALSE;
	}

	return TRUE;
}

void CTextDiagramCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (m_bMoving || m_nSizing != HTNOWHERE)
	{
		ASSERT (GetCapture() == this);

		// get the original rect
		CTDRect rect;
		GetRect(m_nSelRect, rect);

		CRect rNew(rect);

		BOOL bStart = (m_ptDragPrev == m_ptDragStart);

		CPoint ptPrev(m_ptDragPrev); // cache
		CPoint ptOrg(point); // cache

		ClientToLogical(ptPrev);
		ClientToLogical(point);
		
		// get new pos
		if (m_bMoving)
		{
			rect.OffsetRect(ptPrev);
			rNew.OffsetRect(point);

			// prevent the rects preceding the origin
			rect.OffsetRect(max(0, 1 - rect.left), max(0, 1 - rect.top));
			rNew.OffsetRect(max(0, 1 - rNew.left), max(0, 1 - rNew.top));
		}
		else
		{
			switch (m_nSizing)
			{
			case HTLEFT:
				rect.left += ptPrev.x;
				rNew.left += point.x;

				rect.left = max(1, min(rect.left, rect.right - 2));
				rNew.left = max(1, min(rNew.left, rNew.right - 2));
				break;

			case HTRIGHT:
				rect.right += ptPrev.x;
				rNew.right += point.x;

				rect.right = max(rect.right, rect.left + 2);
				rNew.right = max(rNew.right, rNew.left + 2);
				break;

			case HTTOP:
				rect.top += ptPrev.y;
				rNew.top += point.y;

				rect.top = max(1, min(rect.top, rect.bottom - 2));
				rNew.top = max(1, min(rNew.top, rNew.bottom - 2));
				break;

			case HTBOTTOM:
				rect.bottom += ptPrev.y;
				rNew.bottom += point.y;

				rect.bottom = max(rect.bottom, rect.top + 2);
				rNew.bottom = max(rNew.bottom, rNew.top + 2);
				break;
			}
		}

		if (rNew != rect)
		{
			// set the cursor
			rNew.InflateRect(1, 1);

			if (IntersectRect(rNew, m_nSelRect) || rNew.left < 0 || rNew.top < 0)
				SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO));
			else
			{
				if (m_bMoving)
					SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
				else
				{
					switch (m_nSizing)
					{
					case HTLEFT:
					case HTRIGHT:
						SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
						break;

					case HTTOP:
					case HTBOTTOM:
						SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
						break;
					}
				}
			}

			// draw rect tracker
			rNew.DeflateRect(1, 1);

			LogicalToClient(rect);
			LogicalToClient(rNew);

			CDC* pDC = GetDC();
			pDC->DrawDragRect(rNew, CSize(2, 2), bStart ? NULL : &rect, CSize(2, 2));
			ReleaseDC(pDC);

			m_ptDragPrev = ptOrg;
		}
	}
	
	CWnd::OnMouseMove(nFlags, point);
}

void CTextDiagramCtrl::SnapToGrid(CRect& rect)
{
	rect.left = (rect.left / CHARSIZE_X) * CHARSIZE_X + CHARSIZE_X / 2;
	rect.right = (rect.right / CHARSIZE_X) * CHARSIZE_X + CHARSIZE_X / 2;
	rect.top = (rect.top / CHARSIZE_Y) * CHARSIZE_Y + CHARSIZE_Y / 2;
	rect.bottom = (rect.bottom / CHARSIZE_Y) * CHARSIZE_Y + CHARSIZE_Y / 2;
}

void CTextDiagramCtrl::ClientToLogical(CPoint& point)
{
	point.Offset(m_ptScrollOffset);
	
	if (m_bMoving || m_nSizing != HTNOWHERE)
		point.Offset(-m_ptDragStart);

	// convert to logical coords
	point.x = point.x / CHARSIZE_X;
	point.y = point.y / CHARSIZE_Y;
}

void CTextDiagramCtrl::LogicalToClient(CRect& rect)
{
	rect.left *= CHARSIZE_X;
	rect.right *= CHARSIZE_X;
	rect.top *= CHARSIZE_Y;
	rect.bottom *= CHARSIZE_Y;

	rect.OffsetRect(CHARSIZE_X / 2, CHARSIZE_Y / 2);

	rect.right++;
	rect.bottom++;

	rect.OffsetRect(-m_ptScrollOffset);
}

void CTextDiagramCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
{
	CWnd::OnLButtonUp(nFlags, point);

	if (m_bMoving || m_nSizing != HTNOWHERE)
	{
		ClientToLogical(point);

		CTDRect rect;
		GetRect(m_nSelRect, rect);

		CRect rNew(rect);

		// get new pos
		if (m_bMoving)
		{
			rNew.OffsetRect(point);

			// prevent the rect preceding the origin
			rNew.OffsetRect(max(0, 1 - rNew.left), max(0, 1 - rNew.top));
		}
		else
		{
			switch (m_nSizing)
			{
			case HTLEFT:
				rNew.left += point.x;
				rNew.left = max(1, min(rNew.left, rNew.right - 2));
				break;

			case HTRIGHT:
				rNew.right += point.x;
				rNew.right = max(rNew.right, rNew.left + 2);
				break;

			case HTTOP:
				rNew.top += point.y;
				rNew.top = max(1, min(rNew.top, rNew.bottom - 2));
				break;

			case HTBOTTOM:
				rNew.bottom += point.y;
				rNew.bottom = max(rNew.bottom, rNew.top + 2);
				break;
			}
		}

		// test the new pos
		if (rNew != rect)
		{
			rect.CopyRect(rNew);

			if (SetRect(m_nSelRect, rect))
				SendNotification(TDN_SELRECTMOVE);
		}
		
		m_bMoving = FALSE;
		m_nSizing = HTNOWHERE;

		ReleaseCapture();
		Invalidate();
	}
	else if (m_bDblClick)
	{
		if (m_nSelRect != -1)
			EditSelectedText();
		else
			SendNotification(TDN_DBLCLK, point);
	}
}

void CTextDiagramCtrl::EditSelectedText()
{
	ASSERT (m_nSelRect != -1);

	if (m_nSelRect != -1)
	{
		CTDRect rect;
		
		if (GetRect(m_nSelRect, rect))
		{
			CRect rPos(rect);
			LogicalToClient(rPos);
			
			if (!m_editText.GetSafeHwnd())
			{
				m_editText.Create(WS_VISIBLE | WS_CHILD | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL, rPos, this, IDC_EDITTEXT);
				m_editText.SetFont(CFont::FromHandle((HFONT)GetStockObject(ANSI_FIXED_FONT)));
			}
			else
			{
				m_editText.ShowWindow(SW_SHOW);
				m_editText.MoveWindow(rPos);
			}
			
			rPos.OffsetRect(-rPos.TopLeft());
			rPos.left += CHARSIZE_X / 2 - 2;
			rPos.top += CHARSIZE_Y / 2 - 2;
			
			m_editText.SetRect(rPos);
			m_editText.SetWindowText(rect.GetText());
			m_editText.SetFocus();
		}
	}
}

void CTextDiagramCtrl::OnCaptureChanged(CWnd *pWnd) 
{
	if (m_bMoving && pWnd == this)
	{
		// just cancel
		m_bMoving = FALSE;
		Invalidate();
	}
	
	CWnd::OnCaptureChanged(pWnd);
}


UINT CTextDiagramCtrl::OnNcHitTest(CPoint point) 
{
	
	return CWnd::OnNcHitTest(point);
}

BOOL CTextDiagramCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	if (pWnd == this && nHitTest == HTCLIENT && m_nSelRect != -1)
	{
		CPoint point;

		GetCursorPos(&point);
		ScreenToClient(&point);
		point.Offset(m_ptScrollOffset);

		int nRect = IntersectRect(point.x / CHARSIZE_X, point.y / CHARSIZE_Y);

		if (nRect == m_nSelRect)
		{
			// see if we're on the rect border
			CTDRect rect;
			GetRect(m_nSelRect, rect);

			CRect rDraw(rect);
			LogicalToClient(rDraw);

			rDraw.OffsetRect(m_ptScrollOffset);

			// deflate this and then check we're still inside
			rDraw.DeflateRect(2, 2);

			if (!rDraw.PtInRect(point))
			{
				if (point.x < rDraw.left || point.x > rDraw.right)
					return (BOOL)SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
				else
					return (BOOL)SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
			}
		}
	}
	
	return CWnd::OnSetCursor(pWnd, nHitTest, message);
}

int CTextDiagramCtrl::HitTestConn(CPoint point)
{
	// convert to logical coords
	ClientToLogical(point);

	int nConn = IntersectConn(point, TRUE);

	if (nConn == -1)
		nConn = IntersectConn(point, FALSE);
	
	return nConn;
}

int CTextDiagramCtrl::HitTestRect(CPoint point)
{
	// convert to logical coords
	ClientToLogical(point);

	return IntersectRect(point);
}

void CTextDiagramCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	CWnd::OnLButtonDblClk(nFlags, point);
	
	m_bDblClick = TRUE;
}

UINT CTextDiagramCtrl::OnGetDlgCode() 
{
	if (m_nSelRect != -1)
		return DLGC_WANTARROWS;
	
	return CWnd::OnGetDlgCode();
}

void CTextDiagramCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if (m_nSelRect != -1)
	{
		CTDRect rect;
		GetRect(m_nSelRect, rect);

		switch (nChar)
		{
		case VK_DELETE:
			if (DeleteRect(m_nSelRect))
			{
				UpdateWindow();

				m_nSelRect = -1;
				SendNotification(TDN_SELRECTDELETE);
			}
			break;
			
		case VK_LEFT: 
			{
				rect.OffsetRect(-1, 0);

				if (SetRect(m_nSelRect, rect))
				{
					UpdateWindow();
					SendNotification(TDN_SELRECTMOVE);
				}
			}
			break; 
			
		case VK_RIGHT: 
			{
				rect.OffsetRect(1, 0);

				if (SetRect(m_nSelRect, rect))
				{
					UpdateWindow();
					SendNotification(TDN_SELRECTMOVE);
				}
			}
			break; 
			
		case VK_UP: 
			{
				rect.OffsetRect(0, -1);

				if (SetRect(m_nSelRect, rect))
				{
					UpdateWindow();
					SendNotification(TDN_SELRECTMOVE);
				}
			}
			break; 
			
		case VK_DOWN: 
			{
				rect.OffsetRect(0, 1);

				if (SetRect(m_nSelRect, rect))
				{
					UpdateWindow();
					SendNotification(TDN_SELRECTMOVE);
				}
			}
			break;

		case VK_F2:
			EditSelectedText();
			break;
		}
	}
	
	CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CTextDiagramCtrl::OnEndTextEdit()
{
	if (EditingText())
	{
		if (m_nSelRect != -1 && m_editText.IsWindowVisible())
		{
			CString sItemText;

			if (GetText(m_nSelRect, sItemText))
			{
				CString sText;
				m_editText.GetWindowText(sText);

				if (sText != sItemText)
				{
					SetText(m_nSelRect, sText);
					SendNotification(TDN_SELRECTTEXTCHANGE);
				}
			}
		}
			
		m_editText.ShowWindow(SW_HIDE);
	}
}


BOOL CTextDiagramCtrl::PreTranslateMessage(MSG* pMsg) 
{
	if (pMsg->message == WM_KEYDOWN && pMsg->hwnd == m_editText)
	{
		switch (pMsg->wParam)
		{
		case VK_ESCAPE:
			m_editText.ShowWindow(SW_HIDE);
			SetFocus(); // hiding the window first casues the text changes to be ignored
			return TRUE;

		case VK_RETURN:
			if (!(GetAsyncKeyState(VK_CONTROL) & 0x8000))
			{
				SetFocus(); // this automatically causes an end edit
				return TRUE;
			}
			break;
		}
	}
	
	return CWnd::PreTranslateMessage(pMsg);
}

void CTextDiagramCtrl::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	// always make sure existing edit is finished
	OnEndTextEdit();

	CMenu menu;

	if (!menu.CreatePopupMenu())
		return;

	// what have we hit
	ScreenToClient(&point);
	m_ptContextMenu = point; // cache for command handlers

	int nRect = HitTestRect(point);

	if (nRect != -1)
	{
		// remove selection
		if (m_nSelRect != nRect)
		{
			m_nSelRect = nRect;
			Invalidate();

			SendNotification(TDN_SELCHANGE);
		}
		
		// build menu
		menu.AppendMenu(MF_STRING, ID_RECT_EDITTEXT, "Edit Box Text");
		menu.AppendMenu(MF_STRING, ID_RECT_DELETE, "Delete Box");
		menu.AppendMenu(MF_SEPARATOR);
		menu.AppendMenu(MF_STRING, ID_CONN_NEW, "New Connection To...");
		menu.AppendMenu(MF_SEPARATOR);
		menu.AppendMenu(MF_STRING, IDCANCEL, "Cancel\tEsc");
	}
	else
	{
		// remove selection
		if (m_nSelRect != -1)
		{
			m_nSelRect = -1;
			Invalidate();

			SendNotification(TDN_SELCHANGE);
		}
		
		int nConn = HitTestConn(point);

		if (nConn != -1)
		{
			// build menu
			menu.AppendMenu(MF_STRING, ID_CONN_MODIFY, "Modify Connection...");
			menu.AppendMenu(MF_STRING, ID_CONN_DELETE, "Delete Connection");
			menu.AppendMenu(MF_SEPARATOR);
			menu.AppendMenu(MF_STRING, IDCANCEL, "Cancel\tEsc");
		}
		else
		{
			menu.AppendMenu(MF_STRING, ID_RECT_NEW, "New Box");
			menu.AppendMenu(MF_SEPARATOR);
			menu.AppendMenu(MF_STRING, ID_RESET, "Reset Diagram");
			menu.AppendMenu(MF_SEPARATOR);
			menu.AppendMenu(MF_STRING, IDCANCEL, "Cancel\tEsc");

			// determine whether 'new box' is enabled or not
			CPoint ptTopLeft(point);
			ClientToLogical(ptTopLeft);

			CRect rNew(ptTopLeft, CSize(5, 3));
			rNew.InflateRect(1, 1);

			menu.EnableMenuItem(ID_RECT_NEW, IntersectRect(rNew) ? MF_GRAYED : MF_ENABLED);
		}
	}

	ClientToScreen(&point);

	menu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
}

void CTextDiagramCtrl::OnRectNew()
{
	if (HitTestRect(m_ptContextMenu) == -1 && HitTestConn(m_ptContextMenu) == -1)
	{
		CPoint ptTopLeft(m_ptContextMenu);
		ClientToLogical(ptTopLeft);

		if (AddRect(CRect(ptTopLeft, CSize(5, 3))) != -1)
		{
			EditSelectedText();
		}
	}
}

void CTextDiagramCtrl::OnRectDelete()
{
	ASSERT (m_nSelRect == HitTestRect(m_ptContextMenu));
	
	if (m_nSelRect != -1)
		DeleteRect(m_nSelRect);
}

void CTextDiagramCtrl::OnRectEditText()
{
	ASSERT (m_nSelRect == HitTestRect(m_ptContextMenu));
	
	if (m_nSelRect != -1)
		EditSelectedText();
}

void CTextDiagramCtrl::OnConnNew()
{
	ASSERT (m_nSelRect == HitTestRect(m_ptContextMenu));
	
	if (m_nSelRect != -1)
	{
		// short term fudge sends a notification to the parent to provide this functionality
		SendNotification(TDN_IMPLCONNNEW, m_ptContextMenu);
	}
}

void CTextDiagramCtrl::OnConnModify()
{
	int nConn = HitTestConn(m_ptContextMenu);
	
	if (nConn != -1)
	{
		// short term fudge sends a notification to the parent to provide this functionality
		SendNotification(TDN_DBLCLK, m_ptContextMenu);
	}
}

void CTextDiagramCtrl::OnConnDelete()
{
	int nConn = HitTestConn(m_ptContextMenu);
	
	if (nConn != -1)
		DeleteConnection(nConn);
}

void CTextDiagramCtrl::OnReset()
{
	if (MessageBox("Are you sure you want to reset the diagram", "Code Plotter", MB_YESNO) == IDYES)
		ResetDiagram();
}

void CTextDiagramCtrl::SendNotification(UINT nCode, CPoint point)
{
	TDNHDR tdn = { { *this, GetDlgCtrlID(), nCode }, { point.x, point.y } };

	GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&tdn);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -