My requirement is to plot the Sine wave graph in my MFC desktop
application.
How to achive this?
Is there any ready made APIs present in MFC?
Or we need to third party code?
I searched that some of the people used GCL.
If windows doesn't have any readymade API, then any body knows any
free open source code available to draw or plot the graph.
Thanks in advance.
Most languages have the trig functions available.
Then all you need is a loop and the MFC drawing classes.
--
Dean Earley (dean....@icode.co.uk)
i-Catcher Development Team
iCode Systems
Yes, you can use the Win32 MSChart control.
(VtChChartType enum for the type of graph)
> Yes, you can use the Win32 MSChart control.
> (VtChChartType enum for the type of graph)
Hi Christian,
When you say Win32, do you mean it can be accessed via the Platform SDK (if
so what is the control's Window Class Name) or is this an ActiveX/Com
control.
Also, it is not clear to me what provides the actual control - my initial
searches indicate Microsoft Office, but hopefully you will tell me its now
part of Windows since XP or some other good news (I am hoping).
Thanks
Leslie.
> When you say Win32, do you mean it can be accessed via the Platform SDK (if
> so what is the control's Window Class Name) or is this an ActiveX/Com
> control.
>
> Also, it is not clear to me what provides the actual control - my initial
> searches indicate Microsoft Office, but hopefully you will tell me its now
> part of Windows since XP or some other good news (I am hoping).
It's an old MS control (first versions of mschrt20.ocx are from 1998),
but I don't remember if it was furnished with NT...
I use it in C / Win32 SDK with the ProgId "MSChart20Lib.MSChart.
2" (with ATL (KB192560) or native "OCHost" window class for ActiveX
hosting)
Use Windows GDI, or MFC's wrapper around it. Set up a pen with a
brush, MoveTo the left side of your client area, and use DrawTo in a
loop to draw a line from your current position to your next position.
In this case, a charting widget is massive overkill.
Or you can populate an array of X,Y values and
draw the whole graph all at once with PolyLine.
Best regards,
Bob Masta
DAQARTA v4.51
Data AcQuisition And Real-Time Analysis
www.daqarta.com
Scope, Spectrum, Spectrogram, Sound Level Meter
FREE Signal Generator
Science with your sound card!
Is there an example for this? Is it possible to use it with plain
win32?
More importantly, is there a window class for this?
> > Is there an example for this? Is it possible to use it with plain
> > win32?
>
> More importantly, is there a window class for this?
I can post a sample but there is nothing special to do.
You just have to use the #import directive (msdatsrc.tlb,
mschrt20.ocx) to get COM interfaces and ::put_ChartData() to set the
data
An example would be very kind; I am not working with C/C++ but in a
Smalltalk world (which uses COM /API wrappers), so I have to basically
translate at least once.
> An example would be very kind; I am not working with C/C++ but in a
> Smalltalk world (which uses COM /API wrappers), so I have to basically
> translate at least once.
A basic Win32 sample (with ATL) , which gives
http://nsa05.casimages.com/img/2009/02/13/090213064957607572.jpg
Details on properties/methods are in mschrt20.tlh; there is also a
small mschart.hlp in KB275649...
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <tchar.h>
//#import "C:\Winnt\system32\msdatsrc.tlb" named_guids
//#import "C:\Winnt\system32\mschrt20.ocx" named_guids
#include "msdatsrc.tlh"
#include "mschrt20.tlh"
#include <atlbase.h>
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
using namespace MSChart20Lib;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
hInst = hInstance;
WNDCLASSEX wcex =
{
sizeof(WNDCLASSEX), 0, WndProc, 0, 0, hInst, LoadIcon(NULL,
IDI_APPLICATION),
LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL,
L"MSChart", NULL,
};
if(!RegisterClassEx(&wcex))
return MessageBox(NULL, L"Cannot register class !", L"Error",
MB_ICONERROR | MB_OK);
HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, L"Test MSChart",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
NULL, hInst, NULL);
if(!hWnd)
return MessageBox(NULL, L"Cannot create window !", L"Error",
MB_ICONERROR | MB_OK);
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
UpdateWindow(hWnd);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
static HWND hWndActiveX ;
static _DMSChart * pMSChart = NULL;
switch (message)
{
case WM_CREATE:
{
HINSTANCE hDLL = LoadLibrary(TEXT("atl71.dll"));
typedef BOOL (__stdcall *PAAWI)(void);
PAAWI pAtlAxWinInit = (PAAWI)GetProcAddress(hDLL, "AtlAxWinInit");
if (pAtlAxWinInit)
pAtlAxWinInit();
typedef HRESULT (__stdcall *PAAGC) (HWND hWnd, IUnknown**
pUnknown);
PAAGC pAAGC = (PAAGC) GetProcAddress(hDLL, "AtlAxGetControl");
HRESULT hr;
wchar_t wszCLSID[129];
OLECHAR progid[] = L"MSChart20Lib.MSChart.2";
CLSID clsid;
hr = CLSIDFromProgID(progid, &clsid);
StringFromGUID2(clsid, wszCLSID, 128);
CoInitialize(NULL);
hWndActiveX = CreateWindow(TEXT("AtlAxWin71"), wszCLSID,
WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hWnd, 0, hInst, 0);
IUnknown* pUnk = NULL;
hr = pAAGC(hWndActiveX, (IUnknown**)&pUnk);
hr = pUnk->QueryInterface(IID__DMSChart, (LPVOID *) &pMSChart);
if (hr == 0)
{
VARIANT varData, var;
SAFEARRAY *psa;
SAFEARRAYBOUND sabound[2];
long nElement[2];
char sChar[256];
int nValue;
sabound[0].lLbound = 0;
sabound[0].cElements = 10;
sabound[1].lLbound = 0;
sabound[1].cElements = 10;
psa = SafeArrayCreate(VT_VARIANT, 2, sabound);
for(nValue = 0; nValue < 10; nValue++)
{
sprintf(sChar, "Value %d", nValue);
V_BSTR(&var) = SysAllocString(_bstr_t(sChar));
V_VT(&var) = VT_BSTR;
nElement[0] = 0;
nElement[1] = nValue;
hr = SafeArrayPutElement(psa, nElement, &var);
SysFreeString (var.bstrVal);
VariantClear(&var);
V_I4(&var) = nValue + 5;
V_VT(&var) = VT_I4;
nElement[0] = 1;
nElement[1] = nValue;
hr = SafeArrayPutElement(psa, nElement, &var);
VariantClear(&var);
}
varData.vt = VT_ARRAY | VT_VARIANT;
varData.parray = psa;
hr = pMSChart->put_ChartData(varData);
hr = pMSChart->put_ColumnCount(10);
hr = pMSChart->put_RowCount(1);
hr = pMSChart->put_RowLabel(L"Foo");
IVcPlot* pPlot;
hr = pMSChart->get_Plot(&pPlot);
IVcSeriesCollection* pSeriesCollection;
hr = pPlot->get_SeriesCollection(&pSeriesCollection);
long nCount;
pSeriesCollection->raw_Count(&nCount);
for (int nIndex = 1; nIndex <= nCount; nIndex ++)
{
IVcSeries* pSeries;
hr = pSeriesCollection->get_Item(nIndex, &pSeries);
IVcDataPoints* pDataPoints;
hr = pSeries->get_DataPoints(&pDataPoints);
IVcDataPoint* pDataPoint;
hr = pDataPoints->get_Item (-1, &pDataPoint);
IVcDataPointLabel* pDataPointLabel;
hr = pDataPoint->get_DataPointLabel(&pDataPointLabel);
pDataPointLabel->put_PercentFormat(L"0%");
pDataPointLabel->put_LocationType(VtChLabelLocationTypeInside);
pDataPointLabel->put_Component(VtChLabelComponentPercent);
IVcFont* pFont;
hr = pDataPointLabel->get_VtFont(&pFont);
pFont->put_Size(13);
pFont->put_Style(VtFontStyleItalic);
}
IVcLegend* pLegend;
hr = pMSChart->get_Legend(&pLegend);
IVcLocation * pLocationLegend;
hr = pLegend->get_Location (&pLocationLegend);
pLocationLegend->put_LocationType(VtChLocationTypeBottom);
IVcTitle *pTitle ;
hr = pMSChart->get_Title(&pTitle);
IVcFont* pFont;
hr = pTitle->get_VtFont(&pFont);
pFont->put_Size(13);
pFont->put_Style(VtFontStyleBold);
IVcBackdrop* pBackdropTitle;
hr = pTitle->get_Backdrop(&pBackdropTitle);
IVcFill* pFillTitle;
hr = pBackdropTitle->get_Fill(&pFillTitle);
pFillTitle->put_Style(VtFillStyleBrush);
IVcBrush* pBrushTitle;
hr = pFillTitle->get_Brush(&pBrushTitle);
pBrushTitle->put_Style(VtBrushStyleSolid);
IVcColor* pColorTitle;
hr = pBrushTitle->get_FillColor(&pColorTitle);
pColorTitle->raw_Set(255,255,30);
IVcFrame* pFrameTitle;
hr = pBackdropTitle->get_Frame(&pFrameTitle);
pFrameTitle->put_Style(VtFrameStyleThickOuter);
IVcBackdrop* pBackdrop;
hr = pPlot->get_Backdrop(&pBackdrop);
IVcFill* pFill;
hr = pBackdrop->get_Fill(&pFill);
hr = pFill->put_Style(VtFillStyleBrush);
IVcBrush* pBrush;
hr = pFill->get_Brush(&pBrush);
pBrush->put_Style(VtBrushStylePattern);
pBrush->put_Index(VtBrushPatternTrellis);
IVcColor* pPatternColor;
hr = pBrush->get_PatternColor(&pPatternColor);
pPatternColor->raw_Set(255,204,102);
IVcShadow* pShadow;
hr = pBackdrop->get_Shadow(&pShadow);
pShadow->put_Style(VtShadowStyleDrop);
hr = pMSChart->put_chartType(VtChChartType2dPie);
pMSChart->put_ShowLegend(VARIANT_TRUE);
pMSChart->put_TitleText(L"Title of Chart");
}
}
break;
case WM_SIZE:
MoveWindow(hWndActiveX, 0, 0, LOWORD(lParam), HIWORD(lParam),
TRUE);
break;
case WM_DESTROY:
{
if (pMSChart)
pMSChart->Release();
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
[ ... ]
> > Is there an example for this? Is it possible to use it with plain
> > win32?
>
> More importantly, is there a window class for this?
In this case, the MS Chart control seems (at least to me) a lot more
trouble than it's worth, unless you have something to automate almost
all of using an OCX. The code Christian posted is reasonable as an
example of using the control, but is (IMO) an extremely roundabout way
of displaying a sine wave in a window.
The OP mentioned using MFC, so I'll assume that's in use. Starting from
a reasonably typical MFC app (e.g. a default-generated MFC application)
you'd have YourView::OnDraw look something lik this:
pDC->MoveTo(0, 100);
for (double i=0; i<6.28; i+=0.01)
pDC->LineTo(100*i, 100-(int)(100.0*sin(i)));
At the moment this doesn't attept to do any scaling or anything like
that, but the basic idea is there -- generate X values and the Y values
that go with them. If you're going to do this a lot, Bob Masta's idea
should be added -- pre-compute the values, put them into an array, then
draw them all at once using PolyLine. For something like he does
(working with the sound card in real time) that kind of optimization is
probably just about a necessity -- but depending on what you're doing,
it may be overkill (though it's only a tiny bit of extra work...)
Another place you might want to look would be:
http://www.codeproject.com/KB/miscctrl/xgraph.aspx
Again, if you're only interested in displaying a sine wave, it's
probably overkill -- but unless my memory is pretty lousy, it's better
suited to the kinds of things you seem to want to do, and a whole lot
easier to use under MFC as well.
--
Later,
Jerry.
The universe is a figment of its own imagination.