본문 바로가기
Software/C++&MFC

MFC그래프 라이브러리, ChartCtrl 마우스 휠 기능 추가

by lovey25 2019. 10. 7.
반응형

C++/MFC에서 다양한 그래프를 손쉽게 그릴수 있도록 해주는 오픈소스 라이브러리인 ChartCtrl 관련 포스팅입니다. 해당 라이브러리에 대한 소개와 간단 사용법은 관련 포스팅에서 확인해 주세요.

 

'ChartCtrl' 태그의 글 목록

블로그 EveryX 입니다. C++, Python, Arduino등 학습노트로 시작했고, 신기하고 재미있는 제품 리뷰와 맛집/여행에 대한 추억도 남기고 있습니다.

kwonkyo.tistory.com

 

이 라이브러리는 정말 잘 만들어진 라이브러리라서 다양한 기능들이 구현이 되어 있어 사용하기에 편리합니다. 그런데 사용을 하다보면 아쉬는 기능이 하나둘 보이기마련이죠. 이럴때 이런 오픈소스 라이브러리의 잠재력이 드러납니다.

오래 된 코드이긴 하지만 프로그래밍을 배우고 있는 입장에게는 도움이 많이 되고 있는데요. 필요에 따라서 기능을 개선하거나 추가하는것도 가능하기 때문이죠.

그래서 지난 라이브러리 소개글에서 잠깐 언급했던 내용이었는데 마우스 휠을 사용해서 그리프를 조작하는 기능이 있었으면 좋겠다 라는 생각을 했었는데 생각보다 간단하게 구현할 수 있어서 그내용 남겨둡니다.

 

ChartCtrl은  다양한 그래프를 그릴 수도 있고 그려진 그래프를 마우스로 영역을 지정해서 확대가서나 축소 그리고 마우스 우크릭으로 그래프 영역을 이동하는 기능이 가능한데요. 아쉽게도 마우스 휠을 이용한 움직임은 구현이 되어 있지않았습니다.

나중에 그래프를 그리는 프로그램을 만들게 되면 마우스 휠을 돌려서 스크롤을 한다던가 줌을 한다던가 하는 기능이 필요할 것 같아서 ChartCtrl라이브러리의 액션부분에 마우스 휠을 활용하는 기능을 추가하였습니다.

 

마우스휠로 그래프 좌우로 스크롤하기

먼저 그래프 스크롤입니다. 마우스휠을 돌려서 가로축 스크롤을 움직이도록 하는 기능입니다.

라이브러리의 매인 코드인 "ChartCtrl.cpp" 파일에 아래 코드를 추가만 해 주면 끝입니다. 

마우스 휠을 위로 올리면 오른쪽으로 스크롤되고 아래로 돌리면 왼쪽으로 스크롤되며 그래프가 좌우로 스크롤 되면서 세로축 방향의 표현되는 데이터의 범위가 변함에 따라 세로축 범위도 자동으로 조절되도록 하였습니다.

// Make a sliding according to the movement of mouse wheel
// Wheel up : slide right /  Wheel down : slide left
BOOL CChartCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

	ScreenToClient(&pt);
	double MinVal = 0;
	double MaxVal = 0;

	double rate = 0.1;
	double scrollgap = 0;

	if (zDelta > 0)
	{
		rate = rate * 1;
	}
	else
	{
		rate = rate * -1;
	}

	if (m_pAxes[BottomAxis])
	{
		m_pAxes[BottomAxis]->GetMinMax(MinVal, MaxVal);
		scrollgap = (MaxVal - MinVal) * rate;
		MinVal = MinVal + scrollgap;
		MaxVal = MaxVal + scrollgap;
		m_pAxes[BottomAxis]->SetZoomMinMax(MinVal, MaxVal);
	}

	if (m_pAxes[TopAxis])
	{
		m_pAxes[TopAxis]->GetMinMax(MinVal, MaxVal);
		scrollgap = (MaxVal - MinVal) * rate;
		MinVal = MinVal + scrollgap;
		MaxVal = MaxVal + scrollgap;
		m_pAxes[TopAxis]->SetZoomMinMax(MinVal, MaxVal);
	}

	if (m_pAxes[LeftAxis])
	{
		m_pAxes[LeftAxis]->GetSeriesScreenMinMax(MinVal, MaxVal);
		m_pAxes[LeftAxis]->SetZoomMinMax(MinVal, MaxVal);
	}

	if (m_pAxes[RightAxis])
	{
		m_pAxes[RightAxis]->GetSeriesScreenMinMax(MinVal, MaxVal);
		m_pAxes[RightAxis]->SetZoomMinMax(MinVal, MaxVal);
	}

	RefreshCtrl();

	if (m_PlottingRect.PtInRect(pt))
	{
		TCursorMap::iterator iter = m_mapCursors.begin();
		for (iter; iter != m_mapCursors.end(); iter++)
			iter->second->OnMouseButtonUp(pt);

		Invalidate();
	}

	return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}

 

마우스휠로 그래프 확대/축소

이번에는 마우스 휠을 올리고 내리는 동일한 동작을 그래프를 확대하고 축소하는 줌으로 사용할 수 있도록 하는 코드 입니다. 동일하게 "ChartCtrl.cpp"파일에 추가하면 됩니다. 

// Make a zoom according to the movement of mouse wheel
// Wheel up : Zoom in /  Wheel down : Zoom out
BOOL CChartCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

	ScreenToClient(&pt);
	double MinVal = 0;
	double MaxVal = 0;

	double rate = 0.1;

	if (m_bZoomEnabled)
	{
		if (zDelta > 0)
		{
			rate = rate * 1;
		}
		else
		{
			rate = rate * -1;
		}

		double ZoomCenter = 0;

		if (m_pAxes[BottomAxis])
		{
			m_pAxes[BottomAxis]->GetMinMax(MinVal, MaxVal);
			ZoomCenter = m_pAxes[BottomAxis]->ScreenToValue(pt.x);
			MinVal = MinVal + (ZoomCenter - MinVal) * rate;
			MaxVal = MaxVal - (MaxVal - ZoomCenter) * rate;
			m_pAxes[BottomAxis]->SetZoomMinMax(MinVal, MaxVal);
		}

		if (m_pAxes[LeftAxis])
		{
			m_pAxes[LeftAxis]->GetMinMax(MinVal, MaxVal);
			ZoomCenter = m_pAxes[LeftAxis]->ScreenToValue(pt.y);
			MinVal = MinVal + (ZoomCenter - MinVal) * rate;
			MaxVal = MaxVal - (MaxVal - ZoomCenter) * rate;
			m_pAxes[LeftAxis]->SetZoomMinMax(MinVal, MaxVal);
		}

		if (m_pAxes[TopAxis])
		{
			m_pAxes[TopAxis]->GetMinMax(MinVal, MaxVal);
			ZoomCenter = m_pAxes[TopAxis]->ScreenToValue(pt.x);
			MinVal = MinVal + (ZoomCenter - MinVal) * rate;
			MaxVal = MaxVal - (MaxVal - ZoomCenter) * rate;
			m_pAxes[TopAxis]->SetZoomMinMax(MinVal, MaxVal);
		}

		if (m_pAxes[RightAxis])
		{
			m_pAxes[RightAxis]->GetMinMax(MinVal, MaxVal);
			ZoomCenter = m_pAxes[RightAxis]->ScreenToValue(pt.y);
			MinVal = MinVal + (ZoomCenter - MinVal) * rate;
			MaxVal = MaxVal - (MaxVal - ZoomCenter) * rate;
			m_pAxes[RightAxis]->SetZoomMinMax(MinVal, MaxVal);
		}

		RefreshCtrl();

		if (m_PlottingRect.PtInRect(pt))
		{
			TCursorMap::iterator iter = m_mapCursors.begin();
			for (iter; iter != m_mapCursors.end(); iter++)
				iter->second->OnMouseButtonUp(pt);

			Invalidate();
		}

	}

	return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}

 

마무리

라이브러리에 대한 이해가 좀더 깊어지게 되면 다른 기능들도 더 넣어보고 싶네요. 마우스 커서가 그래프를 트랙한다던가 마우스 커서가 위치한 데이터의 상세값을 오버레이 해 준다던가 하는 그런기능도 구현할 수 있으면 좋을것 같습니다.

 

 

끝!

반응형

댓글