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

MFC 그래프 라이브러리, Chart Control 기본 사용법 - 보통그래프 및 봉차트 그리기

by lovey25 2019. 10. 5.

이전 포스팅에서 소개했던 그래프를 그려주는 MFC 라이브러리, Chart Control의 기본 사용법입니다. CodeProject에도 기본 사용법이 잘 나와있지만 저같은 초보는 맘먹고 정독해야 겨우 이해할 수 있기 때문에 그 겨우 이해한 내용을 기록으로 남깁니다.

라이브러리 소스는 아래 포스팅 참고하시면 됩니다.

 

[라이브러리] MFC 그래프 라이브러리 - High-speed Charting Control

MFC용 그래프 그리는 라이브러리를 소개합니다. Codeproject사이트에 등록된 소스인데 X-Y 기본 그래프 뿐만아니라 캔들스틱, 바차트 등 다양한 기능을 지원하는 라이브러리 입니다. 원본 출처: https://www.cod..

kwonkyo.tistory.com

Chart Control 라이브러리를 이용해서 기본 그래프와 캔들차트를 그리는 예제 프로젝트를 만들어 봤고 그 과정으로 Step by step으로 남기겠습니다.

MFC 기본 프로젝트 생성

먼저 Visual Studio 2019를 시작하고 새 프로젝트 만들기를 눌러서 새로운 프로젝트를 시작합니다. 저는 Community 2019버전을 사용했습니다. VS개발환경에 대한 내용은 생략하도록 하겠습니다.

프로젝트 생성마법사에서 "MFC"로 검색을 하고 MFC앱을 선탠하고 다음을 눌러줍니다.

프로젝트 이름과 프로젝트의 위치를 지정해서 한번더 다음을 눌러줍니다.

MFC 앱 설정창에서는 종류를 "대화 상자 기반"으로 바꿔주고 마침을 눌러줍니다. 대화 상자 기반을 이용하는 특별한 이유는 없습니다. 그냥... 전 이것만 사용해봐서 이렇게 해요. ;;

프로젝트가 생성이 되면, F5 한번 눌러서 기본 앱이 잘 실행되는지 확인을 하고 다음으로 넘어가겠습니다.

프로젝트에 라이브러리 추가하기

본문의 앞쪽에서 언급된 Chart Control의 소개 포스팅에서 라이브러리의 소스파일을 다운받고 만들어준 프로젝트 폴더에 저장해 줍니다.

저는 아래 그림처럼 프로젝트 소스코드 폴더에 같이 저장해 주었습니다.

Visual Studio로 돌아가서 솔루션 탐색기에서 다운받아온 라이브러리 소스들을 추가해 줍니다. 저는 편의를 위해서 다음과 같이 "ChartCtrl"이라는 필터를 하나 만들어 주고 그 안에 소스를 추가하였습니다.

추가 하는 방법은 새로 만든 ChartCtrl필터를 우클릭해서 "추가 > 기존 항목" 을 차례대로 선택하고 

아까 다운받았던 소스파일들을 몽땅 선택해서 확인을 눌러줍니다.

다이얼로그 구성

리소스 뷰 창에서 메인 다이얼로그를 더블클릭해서 다이얼로그 디자인 페이지를 열어줍니다.

그리고 도구창에서 "Custom Control"을 찾아서 다이얼로그 창으로 끌고와서 적당한 크기로 배치를 해 줍니다.

"Custom Control"의 속성을 다음 그림에 표시된 부분과 같이 수정을 해 줍니다. 마지막 부분의  'Style'은 대화상자의 갱신이 일어날때마다 번쩍거리는 현상을 피하기 위해서 설정해 주는 부분이라고 합니다. 스타일의 상세내용은 MS의 다음 문서의 설명을 참고하면 됩니다.

https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles

이제 마우스 오른쪽 클릭을 해서 '클래스 마법사'를 열어줍니다. 단축키가 'Ctrl + Shift + X'네요. 알아두면 유용합니다.

클래스 마법사 창에서 '멤버 변수'탭으로 이동한 다음 위에서 만들었던 Custom Control에 변수를 등록해 주기 위해서 컨트롤의 아이디를 선택하고 '변수추가' 버튼을 눌러줍니다.

변수 추가창에서 아래와 같이 변수의 이름과 타입을 지정하고 '마침'을 눌러줍니다.

이렇게 하면 메인 다이얼로그 헤더파일인 "ChartCtrlDlg.h"에 "CChartCtrl" 클래스 선언이 추가됩니다.

그리고 cpp파일에는 자동으로 DDX_Control이 추가됩니다.

그런데 아직 이 프로젝트에 ChartCtrl 클래스 라이브러리를 연결해 주지 않았기 때문에 CChartCtrl이 어떤 형식인지 모르기 때문에 인텔리센스가 빨간줄로 표시하고 있습니다. 

라이브러리 추가

준비의 마지막 단계인 ChartCtrl 라이브러리를 연결시켜 줍니다.

다이얼로그 헤더에 다음과 같이 "ChartCtrl.h" 헤더를 include 해주면 되는데 폴더안에 있어서인지 폴더경로까지 넣어주어야 인식을 하네요.

이제 모든 준비가 완료 되었습니다. 여기서 한번더 "F5"키를 눌러서 에러가 없는지 확인해 봅니다. 빠뜨린 내용없이 잘 따라왔다면 문제없이 컴파일이 되고 빈창이 실행됩니다. 

이제 여기에 차트를 그려보도록 하겠습니다.

 

차트 그리기

처음 예제로 f(x, y) 형식의 2차원 데이터를 X-Y평면상에 그려주는 가장 기본적인 그래프와 주식거래 데이터를 표현하는 봉차트를 그려보겠습니다.

차트타입에 맞는 헤더파일 추가

먼저 필요한 헤더파일을 추가해 줍니다. 일반적인 라인을 직교좌표에 그리는 "ChartLineSerie.h"헤더와 봉차트를 그리는 "ChartCandlestickSerie.h"를 추가해 줍니다. 위치는 메인 다이얼로그의 헤더파일입니다.

멤버변수 추가

이제 화면에 그려질 데이터가 저장될 변수를 선언해 줍니다.

'CChartLineSerie'와 'CChartCandlestickSerie'는 각각 라인차트와 봉차트를 그리는데 필요한 데이터가 저장될 구조체입니다.

그리고 아래 그림에 42번 라인에 있는 "ReadData()"함수는 봉차트를 그리기 위해서 필요한 데이터를 외부파일에서 읽어오기 위한 함수입니다. 일단 같이 선언해 줍니다.

봉차트 데이터를 불러올 ReadData()함수 정의

그리고 아래코드는 ReadData() 함수의 정의입니다.

23번째 줄에 보시는 것처럼 저는 일단 봉차트를 그릴 데이터를 수집해서 '날짜, 시가, 종가, 고가, 저가, 거래량' 순으로 쉼표로 구분하여 저장해 두었습니다.

void CChartTrainingDlg::ReadData(SChartCandlestickPoint (&pCandlePoint)[600])
{
	UpdateData(TRUE);
	
	//@ 파일에서 데이터 불러오기
	// 파일열기
	CStringA strCSVfileName = (CStringA)theApp.m_sAppPath + L"\\data\\testdata.csv";
	char* BufOfFileName = strCSVfileName.GetBuffer(strCSVfileName.GetLength());
	FILE* f = nullptr;
	errno_t err;

	err = fopen_s(&f, BufOfFileName, "rt");	//읽기모드
	if (err || f == NULL)
	{
		AfxMessageBox(L"파일열기 실패");
		return;
	}

	double temp;
	int year, month, day;
	for (int i = 0; i < 600; i++)
	{
		fscanf_s(f, "%4d%2d%2d,%lf,%lf,%lf,%lf,%lf\n",	//  날짜, 시가, 종가, 고가, 저가, 거래량
			&year, &month, &day,
			&pCandlePoint[i].Open,
			&pCandlePoint[i].Close,
			&pCandlePoint[i].High,
			&pCandlePoint[i].Low,
			&temp);

		COleDateTime date(year, month, day, 0, 0, 0);
		pCandlePoint[i].XVal = CChartCtrl::DateToValue(date);
	}
	fclose(f);				//파일 닫기
}

위 코드에서 7번째 줄에 파일을 읽어오기위해서 파일이 저장된 경로를 지정하기 위해서 "m_sAppPath"라는 변수를 사용하였습니다. 이 변수는 지금 만들고 있는 프로그램이 실행이 되면 그 실행 경로를 저장하기 위한 변수입니다. 다음과 같이 'Ctrl + Shift + X'를 눌러서 클래스 마법사를 열어서 변수를 추가해 줍니다.

※확인사항

여기서 한가지 확인할 사항이 있습니다. 변수 m_sAppPath는 Public으로 생성을 하였는데 제컴퓨터의 경우 컴파일을 하면 변수에 접근을 할 수 없다고 에러가 났습니다. 그래서 클래스 마법사에서 생성한 변수가 선언된 코드를 찾아가서 다음과 같이 수정을 해야지만 문제가 해결되었습니다.

그리고 아래 코드를 프로그램 메인 cpp파일의 초기화 루틴에 추가해 줍니다. 현재 프로젝트 기준으로 "MFC_ChartCtrl.cpp"파일에 "BOOL CMFCChartCtrlApp::InitInstance()" 함수입니다. 적당한 위치에 추가를 해 줍니다.

이코드의 역할은 프로그램이 실행되는 경로를 확인하고 그 위치에 "data"라는 폴더의 유무를 확인하고 없으면 만들어줍니다.

//////////////////////////////////////////////////////////////////
/// 실행파일의 경로를 저장
///--------------------------------------------------------------
wchar_t szPath[MAX_PATH];
GetModuleFileName(AfxGetInstanceHandle(), szPath, MAX_PATH);
*wcsrchr(szPath, '\\') = '\0';
m_sAppPath = szPath;
/// data를 저장할 폴더를 만들어주기
///--------------------------------------------------------------
CString strFileName = m_sAppPath + "/data";
if (!::PathIsDirectory(strFileName))		// 폴더가 없다면
{
	::CreateDirectory(strFileName, NULL);
}
////////////////////////////////////////////////////////////////////

본격적으로 그래프를 그리기

이제는 정말 모든 준비가 끝났네요. 프로그램에 ChartCtrl 이식도 끝났고 필요한 변수들도 선언이 되었고 필요한 데이터도 준비가 되었습니다. 라인차트를 그릴 데이터는 복잡한 데이터가 필요한게 아니기 때문에 간단하게 사인함수를 이용하도록 하겠습니다. 

아래 코드는 프로그램이 시작되면 바로 그래프를 그려주도록 메인 다이얼로그 cpp 파일(MFC_ChartCtrlDlg.cpp)의 "BOOL CMFCChartCtrlDlg::OnInitDialog()" 함수에 "//TODO: 주석"과 "return" 명령어 사이에 추가를 해 줍니다.

	// TODO: 여기에 추가 초기화 작업을 추가합니다.

	/// 초기화
	CChartDateTimeAxis* pBottomAxis = m_ChartCtrl.CreateDateTimeAxis(CChartCtrl::BottomAxis);
	CChartStandardAxis* pLeftAxis = m_ChartCtrl.CreateStandardAxis(CChartCtrl::LeftAxis);
	pLeftAxis->SetAutomaticMode(CChartAxis::FullAutomatic);
	pBottomAxis->SetAutomaticMode(CChartAxis::FullAutomatic);

	pBottomAxis->SetDiscrete(false);
	m_ChartCtrl.ShowMouseCursor(false);
	CChartCrossHairCursor* pCrossHair = m_ChartCtrl.CreateCrossHairCursor();

	/// 라인차트 파트
	CChartXYSerie* pSeries = nullptr;
	pSeries = m_ChartCtrl.CreateLineSerie();

	double XVal[50];
	double YVal[50];
	for (int i = 0; i < 50; i++)
	{
		COleDateTime date(2017, 6, 1, 0, 0, 0);
		XVal[i] = CChartCtrl::DateToValue(date) + i * 16;
		YVal[i] = sin(i) * 5000 + 47000;
	}
	pSeries->SetPoints(XVal, YVal, 50);
	pSeries->SetColor(RGB(255, 0, 0));
	pSeries->CreateBalloonLabel(5, _T("This is a sin curve"));

	/// 봉차트 파트
	CChartCandlestickSerie* pCandle = nullptr;
	pCandle = m_ChartCtrl.CreateCandlestickSerie();
	SChartCandlestickPoint pCandlePoint[600];

	ReadData(pCandlePoint);

	pCandle->SetPoints(pCandlePoint, 600);
	pCandle->SetColor(RGB(0, 255, 0));
	pCandle->CreateBalloonLabel(5, _T("This is a candle"));

	return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.

워낙 잘 만들어진 코드라 어렵고 복잡하진 않지만 ChartCtrl 라이브러리를 사용하는데 가장 중요한 부분이 여기이기 때문에 사용된 기본적인 내용 한줄씩 정리해 보겠습니다.

 

4~7행: 그래프를 그리기 위해서 먼저 어떤 축을 사용할지 정해야 하는데요. ChartCtrl은 그래프가 그려지는 창 기준으로 상하좌우에 각각 1개씩 총 4개의 축을 설정할 수 있습니다. 여기서는 좌측(LeftAxis)과 하단(BottomAxis) 축을 사용하겠다는 것이다. 좌측은 일반축(StandardAxis) 하단은 날짜와시간축(DateTimeAxis)으로 시정하고 있습니다.

※여기서는 축을 자동(FullAutomatic)으로 설정하였는데 경우에 따라 임의로 지정할 필요도 있을텐데요. 그때는 다음과 같이 축의 최소값, 최대값, 눈금간격, 라벨형식 등을 지정해 줄 수 있습니다.

COleDateTime minValue(2019, 1, 1, 0, 0, 0);
COleDateTime maxValue(2019, 9, 30, 0, 0, 0);
pBottomAxis->SetMinMax(CChartCtrl::DateToValue(minValue), CChartCtrl::DateToValue(maxValue));
pBottomAxis->SetTickIncrement(false, CChartDateTimeAxis::tiMonth, 1);
pBottomAxis->SetTickLabelFormat(false, _T("%b %Y"));

 

9행: 연속적이지 않은 데이터를 라인으로 연결할때 그 연결선이 각지지 않고 부드러운 곡선으로 이어지도록 하는 옵션입니다. 데이터의 산포정도에 따라 다르겠지만 엑셀에서처럼 그런 부드러운 곡선까지는 안되는것 같습니다.

 

10행: 그려진 그래프 위로 마우스를 움직일때 마우스 커서를 숨겨주는 옵션입니다.

 

11행: 10행에서 마우스 커서를 숨기는 대신에 마우스 포인터 위치에서 상하좌우로 그래프 범위 끝까지 연결선을 표시해주는 옵션입니다.

 

14~15행: 라인차트의 데이터를 저장하기 위한 공간을 설정하는 부분입니다. pSeries 포인터를 저장변수로 설정했습니다.

 

17~24행: XVal 변수와 YVal변수를 각각 만들어서 각각에 임의의 데이터를 넣어주는 부분입니다.  X값은 2017년6월1일 부터의 날짜를 나타내는 더블형 값 넣어주고 Y에도 역시 사인함수를 따라서 증감을 하는 임의의 더블형 값을 넣어서 배열로 만들었습니다. (수식에 사용된 함수는 나중에 그릴 봉차트와 스케일을 맞추기 위해서 임의로 넣은 값입니다.)

25행에 "SetPoints"라는 함수를 사용해서 15행에서 지정한 포인터에 위에서 만든 데이터 값을 넣어줍니다.

 

26~27행: 그래프의 색상과 표시할 라벨을 설정합니다.

 

30~32행: 이번에는 봉차트의 데이터를 저장할 변수입니다. pCandlePoint이라는 배열을 저장변수로 설정했습니다.

 

34행: 앞에서 추가했던 파일에서 데이터를 읽어오는 루틴을 호출합니다. 함수가 실행되고 나면 pCandlePoint에 파일에 있던 데이터가 로딩됩니다.

 

36행: 파일에서 로딩한 데이터를 그래프를 그릴 구조체에 넣어줍니다. 역시 SetPoints라는 함수를 사용합니다.

 

37~38행: 그래프 색상과 라벨을 설정합니다.

 

이제 모든 준비가 끝났습니다. 빌드(F7)를 해서 실행파일이 잘 만들어 지는지 확인합니다.

문제없이 빌드가 완료되었다면 실행파일이 만들어진 위치를 찾아가서 "data"라는 폴더를 만들어주고 다음 파일을 다운받아서 저장합니다.

이 파일은 2017년 4월6일부터 2019년9월20일까지 삼성전자의 일봉데이터입니다.

testdata.csv
0.02MB

결과

문제없이 잘 따라왔다면 다음과 같은 그래프를 보실 수 있습니다.

이 그래프는 기본적으로 마우스 좌측 드래그로 그래프 줌이 가능하고 오른쪽 드래그로는 그래프 이동이 가능합니다.

그래프 시인성을 높이기 위해서 몇가지만 더 손을 본다면 정말 유용하게 활용할 수 있는 라이브러리인것 같습니다.

아쉬운건 마우스 휠로 그래프 줌이나 그래프 이동이 된다면 좋을것 같은데 그 기능이 없어서 아쉽네요. 시간이 된다면 추가해 봐야 겠어요. 틀이 탄탄하게 잘 만들어진 라이브러리라서 깊이있는 지식없는 저도 도전해볼만한것 같습니다.

 

끝!

728x90

댓글28

  • 유나아빠 2020.05.25 08:36

    많은 도움이 되었습니다. 감사합니다.
    답글

  • BAIK 2020.06.04 17:56

    소스코드추가를 했는데 빌드에러가 나네요;; ㅠㅠ
    답글

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.06.04 19:10 신고

      빌드조건은 워낙 다양하기때문에 뭐라 말씀을 드리기 어렵지만 왠만한 오류는 구글링으로 해결가능하니 포기하지마세요

  • 제제 2020.06.11 04:15

    좋은 글 감사합니다.
    덕분에 한참 시도하다가 성공했네요.
    혹시나 저처럼 실수하는 사람이 있을까봐 답글 남기면
    BOOL CMFCChartCtrlApp::InitInstance() 함수 내에 파일 경로 생성해주는 코드 넣을 때,
    함수 괄호 내에서 뒷 부분에다 코드를 붙여넣으면 오류가 나네요.
    맨 앞으로 옮겨 붙이니 해결되었어요.
    이 문제 때문에 한참 머리썼는데 붙여넣은 위치가 문제였네요.
    답글

  • 질문 2020.08.10 10:30

    ChartAxis.cppp 에서 #include pch.h 을 열수없다는데 라이브러리 빌드 되는거 맞나요?
    답글

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.08.10 10:35 신고

      네 저는 잘 사용하고있어요 pch.h는 라이브러리와 관계없는 파일이에요 미리 컴파일된 헤더 사용과 관련된 내용 검색해 보세요

  • 질문 2020.08.10 11:06

    빠른답변 감사합니다. 그런데 ChartCtrl.cpp 에선 E0147 선언이 적합하지 않는 문제가 발생하고, ChartAxis.cpp와 ChartTitle.cpp에서는 자료형으로 인한 data 손실 경우가 발생하네요. 이런 경우에 라이브러리 직접 수정해줘야하는 건가요?
    답글

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.08.10 11:09 신고

      네 라이브러리가 워낙 오래된거라 직접고쳐쓸수밖에 없어요 대체할만한 마땅한것도 못찾겠네요

  • 질문 2020.08.10 11:30

    확인해보니 size_t 관련하여 선언이 잘못되어있었네요. 답변 감사합니다
    답글

  • 하이헬로 2020.08.18 11:22

    외부종속성에 필터 추가하는 방법 알려주실 수 있나요?ㅜㅜ
    답글

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.08.18 13:29 신고

      방문 감사합니다 댓글로 알려드리긴 힘들거같은데 말씀하신내용은 별도주제로 다루는걸 고려해보겠습니다 도움이 못되어 죄송합니다

  • 도움이되어요 2020.09.16 20:40

    먼저 보여주신 데이터로 너무 감사합니다. 그런데 현재는 데이터를 예를 들어 100개를 받아오면 한번에 그림을 그리는데 1포인트씩 100개씩 그리고 싶은데, 그럴려면 기본적으로 void CChartCtrl::OnPaint() 를 호출할수있어야 될어같은데 MFC_ChartCtrlDlg.cpp에서 호출 할수 없을까요?ㅠ 제 실력으로는 호출이 불가능해서 여쭤봅니다. ㅠ
    답글

    • BlogIcon 도움이되어요 2020.09.17 07:50

      제가 현재 pPoint를 여러개 만들어서 한 화면에 하나씩 그리면 되지 않을까해서 시도를 했는데, 실시간이 아니라 한번에 데이터를 보여주네요.ㅜ 예를들어 pPoint1 , pPoint2를 해서 라인을 만들어주면, 저는 pPoint1이 그려지는것이 보이고 pPoint2가 그려지는 모습을 보여주고 싶은데 너무 막막하여 조심스럽게 도움을 요청합니다 ㅠ
      저는 addPoint가 있길래 SetPoint 말고 사용하면 가능하다고 생각해서 했는데 ㅠ어떻게 방법없을까요? 해당 라이브러리로 뭔가 하신 한국인분은 처음찾아서 염치불구하고 여쭤봅니다 ㅠ

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.09.17 10:54 신고

      저도 잘 알지 못해서 헛소리를 할 수 있으니 감안하시고 참고해주세요 ^^
      포인트가 하나씩 생겨나는 그래프를 그리고 싶으신것 같은데 포인트가 증가되는 트리거가 뭔지 모르겠지만 ChartControl 라이브러리는 포인트 시리즈에 등록된 데이터는 무조건 그리게끔 되어 있으니까 트리거에 맞게 포인트 시리즈에 데이터를 하나씩 추가하도록만 하면 되지 않을까요? pPoint를 여러개 만드는게 아니라 pPoint를 업데이트 하는거죠.
      말씀하신대로 addPoint 함수가 그런용도가 아닐까 싶은데 그건 확인해보지 못했습니다.

  • 도움이되어요 2020.09.17 13:26

    댓글 너무나 감사드립니다. 그런데 제가 질문을 조금 자세하게 하겠습니다.ㅠㅠ
    addpoint라는 것을 하면 pPoint를 업데이트를 하는것은 맞습니다. 그런데 저는 1개씩 그리게 하고싶은데,
    위의 예제에서는 아무리 해봐도 addpoint에 1개씩 넣던 100개씩 넣던 그래픽 창을 업데이트를 제가 하는 방법을 모르다 보니 ㅠㅠ너무 답답한 마음에 말씀을 드렸습니다 ㅠㅠ그래픽 show 같은것을 불러와서 하고 싶은데ㅜ 해당부분을...도저히 어디인지 불러오지를 못하겠습니다 ㅠ
    즉 위의 예제에서 사인파형을 그려진것이 보여지고, 다른 버튼이나 시간이 지나면 캔들이 그려지는것을
    구현하고 싶은것인데, 위의 파일예제에서도 사인파와 캔들이 함께 그려져서요 ㅠ위의 예시만으로도 엄청난 도움이 되었는데, 딱하나 마치 실시간처럼 처리하는 모양을 보이고 싶은데, 그래픽을 보여주는 부분을 몇날 몇일째해도 모르겠어서..정말 염치불구하고 여쭤봅니다 ㅠ
    답글

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.09.17 13:31 신고

      아~ 그렇죠. 한번에 그려지게끔 되어 있죠. 제가 이해하는 라이브러리 컨셉상 따로 그려지게 하려면 데이터 업데이트를 따로 해야합니다. 그러니까 첨에 사인파 데이터를 등록하고 다음 이벤트에서 캔들을 등록하는거죠. 그래프는 등록된 데이터를 모두 보여주니까요. 도움이 되실까 모르겠네요.

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.09.17 13:32 신고

      아~ 그렇죠. 한번에 그려지게끔 되어 있죠. 제가 이해하는 라이브러리 컨셉상 따로 그려지게 하려면 데이터 업데이트를 따로 해야합니다. 그러니까 첨에 사인파 데이터를 등록하고 다음 이벤트에서 캔들을 등록하는거죠. 그래프는 등록된 데이터를 모두 보여주니까요. 도움이 되실까 모르겠네요.

  • 도움이되어요 2020.09.17 13:35

    네. 지금은 사인파 데이터 정보 완료 + 캔들 정보완료 -> 그래픽 보여줌
    이것을 사인파 정보 입력 -> 그래픽 보여줌 -> 캔들 정보입력 -> 그래픽 보여줌 이렇게 갈순없을까요?ㅠㅠ
    답글

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.09.17 14:21 신고

      가능하죠 이글에서 그래프 데이터를 입력하는 부분이 OnInitDialog함수에 있잖아요?! 여기서 라인차트부분과 봉차트부분을 필요한 다른 이벤트함수를 만들어서 옮기시면 됩니다

  • 도움이되어요 2020.09.17 15:08

    몇날 몇일 밤새면서...하지도 못하는 MFC로 하고 있는데, 계속 여쭤봐서 죄송합니다. 알려주신 OnInitDialog 의 내부를 2개로 분리해서 즉, 버튼을 2개 만들어서 1번 버튼에 사인파 그리기
    버튼2번에 봉차트 그리기 하면 1번을 누르면 사인파만 나오고 2번을 누르면 봉차트만 나옵니다...
    1번이 먼저 그려지고 2번이 위에 덧붙여 그려지는 형태가 아니라서요 어디서 그림에 대한 그래픽 정보를 가져와서 거기에 붙이는 형태로 갈 수가없는건지요..ㅠㅠ
    답글

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.09.17 15:14 신고

      아! 리프래쉬 된다는건 생각못했네요. 그래픽 정보를 다루는건 저도 잘 모르는 부분이라 뭐라 드릴말씀이 없네요.

    • Favicon of https://kwonkyo.tistory.com BlogIcon lovey25 2020.09.17 15:59 신고

      제가 테스트를 해보지 못해서 맞는 솔루션인지 모르겠는데 두번째 그래프를 그리실때 m_ChartCtrl.EnableRefresh(false); 옵션을 줘서 리프래쉬를 잠시 비활성화 시켜보면 어떨까요?
      그래프를 다 그리고 나면 다시 활성화 시켜줘야겠죠.
      저와 유사한 관심사가 있으신 분이라서 최대한 도와드리고 싶은데 저도 능력이 비루해서 마음만 앞서네요.

  • 섬바디 2021.05.07 15:21

    안녕하세요 설명해 주신 글 보고 잘 활용하고 있습니다. 감사합니다.
    질문이 하나 있어 글 남깁니다.

    위 내용 중 라인차트, 봉차트를 oninitdialog 함수에서 진행 했는데
    저는 특정 이벤트에서 진행 했습니다.

    윈도우 어플 켜 지고 첫 시도는 잘 되어 그래프가 잘 생성 되나 그 상태에서 다시 한번 시도했을 경우
    ChartAxis.cpp의 ValueToScreen함수에서 Access Violation 에러가 발생합니다.

    혹시 이런 에러가 생겼을 경우 어떻게 해야하는지 질문 드립니다. 감사합니다.
    답글

  • ElmeBH 2021.05.20 14:26

    글 보고 잘 활용했습니다. 좋은 글 감사드립니다.

    저는 라인차트만 사용했고, 특정 데이터를 지속해서 받으면서 차트에 그 데이터값을 갱신해주는 걸 했습니다.
    데이터를 계속해서 불러와줄 필요가 있기때문에 별도의 함수를 정의해서 호출하면서 동작시켰고, 시행착오를 많이 겪었습니다.
    StandardAxis로 Bottom Axis, Left Axis 생성은 젤 처음에만 생성되게끔 Oninitdialog에서 작업했고
    CChartXYSerie* 포인터변수 생성은 별도 정의 함수에서 생성하여 돌렸구요

    라이브러리 상세설명 자료에는 SetPoints 함수가 이전의 데이터를 지우고 Set한다는 식으로 적혀있었는데, 계속해서 SetPoints 함수로 데이터를 그릴 경우 차트에 누적되고 누적되어서 엄청나게 쌓여버렸습니다.. 이걸 RemoveAllSeries 함수 호출로 계속해서 지워줬구요.

    그런데 지우고 새 데이터를 갱신할때마다 자꾸 Assertion Failed 에러창이 떳습니다. afxwin1.ini의 632Line으로 떳는데 검색해봐도 안나오더라구요..

    제가 해결한 방법은, 삽질한 과정은 생략하고... ChartSerie.cpp의 SetColor 함수와, ChartCtrl.cpp의 RemoveAllSeries 함수에서 RefreshCtrl() 함수를 지워서 해결했습니다.
    사실 해결하고나서도 완전히 해결된건지, 이게 왜 해결된건지는 전혀 모르겠습니다만은.. 현재 30분넘게 돌려봐도 한번도 에러창이 안나왔어요.
    완벽한 해결책은 아니더라도 참고가 될까싶어 공유합니당..
    답글