본문으로 바로가기

[MFC] NI CWGraph 사용 잘 하는 법

category 개발언어/c++ 2016. 8. 2. 13:16

image

NI CWGraph는 Graph를 그리기 좋은 매우 유용한 툴 입니다.
Graph를 표현하는데 이만한 툴이 있을까 생각이 듭니다.
줌인, 줌아웃, 드래그,커서,Log 등 아주 많은 기능을 가지고 있습니다.

그런데 MFC에서 사용하려면 초심자 입장에서는 다루기가 쉽지가 않습니다.

VB에서는 다소 쉽게 다룰 수 있습니다.엄밀히 따지면 쉽게 다 룰 수 있다기 보다. 쉽게 느껴 집니다

그 이유는 VB의 변수는 Variant로 처리 되어 자료 타입에 대해 신경을 쓰지 않아도 됩니다.
하지만 MFC에 익숙하고 Variant의 사용에 익숙하지 않은 초심자의 경우 당황스러운데요.
NI CWGraph는 ActiveX Control이므로 ATL,OCX를 잘 모르면 상당히 어렵게 보입니다.
 
VB사용자의 경우 CWGraph를 그대로 활용하는데 집중하지, 좀더 분석하여 응용하는 데는 크게 신경 쓰지 않습니다.
어차피 깊이 파고 들어 봐야 VB가 접근 할 수 부분은 한계가 있어서 깊이까지 고민 자체가 무의미 합니다.
예를 들어 화면에 Graph가 1~30사이에서 필요한 경우에 따라 보여줄 수 가 달라 져야 한다고 가정 했을 때
VB개발 자는 30개 컨트롤을 모두 만들어 놓고 필요한 만큼만 보여주는 방법을 많이 선택 합니다.
반면 C++개발자는 모듈화 Class화 시키려고 신경을 좀 더 써는 경향이 있습니다.

제 경험 상으로 CWGraph그대로 사용 했을 때는 코드의 재사용성 이 떨어 지고, 소스 관리가 잘 되지 않는 부분을 개선하기 위해
조금 다른 방법을 사용합니다.
즉 CWGraph를 상속 받아서 Graph라는 Class를 따로 만들어 사용 합니다.
간혹 다루게 되는 이 컨트롤에 대한 사용법을 주석도 달고, 동료 들과 공유하면 보다 효과적으로 사용 할 수 있습니다.

이렇게 구성해 놓고 필요한 기능을 추가 해 주면 활용도 가 아주 높아 지고 개발 시간을 절약 할 수 있습니다.

코드 예

헤더


// Graph.h: interface for the CGraph class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_GRAPH_H__A7266096_E26E_47EF_B687_E7DEF1FAAB2B__INCLUDED_)
#define AFX_GRAPH_H__A7266096_E26E_47EF_B687_E7DEF1FAAB2B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "NiGraph.h"
#include "NiIncludes.h"
#define GGraph      CGraph//CNiGraph
#define GCursor     CNiCursor
#define GPlot       CNiPlot
#define CAnnotation CNiAnnotation
#define CAnnotations CNiAnnotations
#define GTrackModes CNiGraph::GraphTrackModes
class CGraph : public CNiGraph   
{
public:
    void SetColor(COLORREF color);
    GPlot m_PLOT;
    CAnnotation m_anotxt;
    CMap <CString,LPCSTR,GPlot*,GPlot*> m_PlotMap;
    CMap <CString,LPCSTR,CAnnotation*,CAnnotation*> m_AnnotationMap;
    void SetGraphPlot(LPCSTR szName,COLORREF color);
    //CAnnotation m_anotxt;
    CGraph();
    virtual ~CGraph();
    BOOL Create_DIRECT(CWnd* pParentWnd, UINT nID);
};

#endif // !defined(AFX_GRAPH_H__A7266096_E26E_47EF_B687_E7DEF1FAAB2B__INCLUDED_)

 

CPP


// Graph.cpp: implementation of the CGraph class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Graph.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CGraph::CGraph()
{

}

CGraph::~CGraph()
{

}

BOOL CGraph::Create_DIRECT(CWnd* pParentWnd, UINT nID)
{//동적으로 CWGraph를 생성 시킵니다. 필요 할 때 마다 컨트롤을 추가 합니다.
    UINT sz=0;
    CString fmt;
    DWORD dw_Style=WS_CHILD|WS_VISIBLE;       
    const RECT m_rect={0,0,0,0};
    _bstr_t bLic="ocgbldjknfmmkgmepoihbcengpbiacekipdhgacfankalkbinbec";//동적으로 컨트롤을 생성하기 위한 CWGraph License입니다,
    return  CNiGraph::CreateControl(NULL,NULL, dw_Style, m_rect,pParentWnd,nID, NULL, FALSE, bLic);
}//이 부분이 없으면 UI상에 디자인 모들에서 CWGraph를 올려 놓고 사용해야 합니다.그래프 수가 늘어 나면 상당히 짜증 입니다.

void CGraph::SetGraphPlot(LPCSTR szName, COLORREF color)
{ //Graph에 출력 되는 Line및 Text의 속성 및 색상을 변경합니다.  
    int index=1;
    m_PLOT=CNiGraph::Plots.Add();
    m_PLOT.LineWidth=1;
    m_PLOT.LineColor = color;
    m_PLOT.Visible =TRUE;//(pn->b_Visible?TRUE:FALSE);
    m_anotxt=CNiGraph::Annotations.Add();
    m_anotxt.Plot = m_PLOT;
    m_anotxt.CoordinateType=CNiAnnotation::PlotAreaCoordinates;
    m_anotxt.Shape.PointStyle= CNiShape::PointNone ;
    m_anotxt.Arrow.Visible=false;
    m_anotxt.SnapMode =CNiAnnotation::SnapFixed  ;
    m_anotxt.Shape.Type = CNiShape::None  ;
    m_anotxt.Shape.LineStyle= CNiShape::LineNone;
    m_anotxt.Caption.Text = szName;       
    m_anotxt.Caption.SetCoordinates(16,index*18);
    m_anotxt.Caption.Color=color;
}

void CGraph::SetColor(COLORREF color)
{
    m_PLOT.LineColor = color;
    m_anotxt.Caption.Color=color;
}