The MS_CHART control is not allowed to control its display effect according to the data automatically (at least I have not found) when displaying the linear map, so I wrote a class specifically used to value the linear map. From 9CBS and other VC related to other VC Many things, so I will ask the master criticism to refer to the guidelines. Use the method: Use M_Chart.Subclassdlgitem (IDC_MYCHART, THIS) in the user_define control; otherwise not Say it. Below is the implementation code of the class:
// lyhlinechart.cpp: Implementation File
// Written by Yuhai Liu (Group35@tom.com) // [usage] // 1.init window by ClyhlineChart.Subclassdlgitem (ID (DLGITEM), PARENTWND); // 2.Use addlinetochart () To Add a serial data DELARE // 3.Use deleteLine () to delete a serial data. and after this, take care of // the index changes //4.Use Adddata (x, y, nindex) To Add a point to special line // copyright (c) 2003.//// This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing That this notice and the authors name is incruded. IF // The source code in this file is buy in any Commercial Application // THEN A Simple Email Would Be Nice./// This File Is Provided "As IS" with no expressed or implied warranty.// The author accepts no liability if it causes any damage whatsoever.// It's free - so you get what you pay for.//#include "stdafx.h" #include "mychart.h" #include "lyhlinechart.h"
#ifdef _debug # define new debug_new # undef this_filestatic char this_file [] = __file __; # ENDIF
/// ClyhlineChart
Clyhlinechart :: Clyhlinechart () {Clyhlinechart :: RegisterWndClass (AfxGetInstanceHandle ()); // addlinetochart ();}
Clyhlinechart :: ~ ClyhlineChart () {int ncount = m_items.getsize (); for (int i = 0; i BEGIN_MESSAGE_MAP (CLyhLineChart, CWnd) file: // {{AFX_MSG_MAP (CLyhLineChart) ON_WM_PAINT () ON_WM_SIZE () file: //}} AFX_MSG_MAPEND_MESSAGE_MAP () /// CLyhLineChart message handlers BOOL CLyhLineChart :: RegisterWndClass (HINSTANCE hInstance) {WNDCLASS wc; wc.lpszClassName = "LYH_LINE_CHART"; // matches class name in client wc.hInstance = hInstance; wc.lpfnWndProc = :: DefWindowProc; wc.hCursor = :: LoadCursor ( NULL, IDC_ARROW); wc.hIcon = 0; wc.lpszMenuName = NULL; wc.hbrBackground = (HBRUSH) :: GetStockObject (LTGRAY_BRUSH); // default windows color wc.style = CS_GLOBALCLASS; // to be modified wc. Cbclsextra = 0; wc.cbWndextra = 0; Return (:: registerclass (& wc)! = 0); BOOL CLyhLineChart :: {CLineChartItem * pItem = new CLineChartItem AddLineToChart (COLORREF color); COLORREF linecolor; linecolor = color; if (color == DEFAULTCOLOR) {int nCount = m_items.GetSize (); switch (nCount) {case 0: linecolor = RGB (55, 0, 255); Break; Case 1: LineColor = RGB (0,255,55); Break; Case 2: LineColor = RGB (255, 0, 55); Break; Case 3: LineColor = RGB (255, 255, 255); Break; default: linecolor = rgb (0, 0); Break;} Pitem-> m_colorline = linecolor;} else pitem-> m_colorline = color; pitem-> m_legenD.format ("line% d", m_items.getsize () 1); try {m_items.add (pitem); CClientDC DC (this); CRECT RCCLIENT; GetClientRect (rcclient); if (m_memdc.getsafehdc () == null) {m_memdc.createcompatibledc (& DC); m_Bitmap.CreateCompatibleBitmap (& dc, rcClient.Width (), rcClient.Height ()); m_Bitmap.SetBitmapDimension (rcClient.Width (), rcClient.Height ()); m_MemDC.SelectObject (m_Bitmap); m_Bitmap.DeleteObject (); CFont font; font.CreateFont (m_set.fontsize, 0, 0,0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, m_set.fontname); m_MemDC.SelectObject (& font); font.DeleteObject (); CBrush bkBrush (m_set.bkColor); if (m_set.bBorder) {CPen mpen (PS_SOLID, m_set.BorderWidth, m_set.BorderColor); CBrush * oldbrush = m_MemDC.SelectObject (& bkBrush); m_MemDC.Rectangle (rcClient); m_MemDC.SelectObject (oldbrush); mpen.DeleteObject ();} else m_MemDC.FillRect (rcClient, & bkBrush); bkBrush.DeleteObject ();} InvalidateRect (rcClient, FALSE); return TRUE;} catch (CMemoryException * e) {if (Pitem! = null) delete pitem; e-> delete (); return false;}} Bool Clyhlinechart :: setAutoRange (Bool Bauto, Double Minx, Double Maxx, Double Miny, Double Maxy) {m_set.xmax = maxx; m_set .ymax = maxy; m_set.ymin = miny; m_set.autorange = bauto; return bauto;} Void Clyhlinechart :: Refresh () {create; getClientRect (Rect); if (m_set.autorating) CALRANGE (); DrawPic (); invalidateERECT (RECT, M_SET.BSTRETCH);} Void Clyhlinechart :: onpaint () {CPAINTDC DC (this); // Device Context for Painting CRECT RCCLIENT; GetClientRect (RcClient); // Draw Scale IF (M_Memdc.getsafeHDC ()! = null) DC.Bitblt (0, 0 , rcclient.width (), rcclient.height (), & m_memdc, 0, 0, srcopy; } Void Clyhlinechart :: DrawPic () { CRect rcClient, rect; GetClientRect (rcClient); rect = rcClient; UINT i; if (! M_MemDC.GetSafeHdc () = NULL) {CClientDC dc (this); CFont font; CString fontname, CurStr; BOOL xVer = false; // Whether the X coordinate int xdec = 0; // x coordinate displayed decix INT YDEC = 0; // Y coordinate displayed decimal point number cpoint Point; csize size, size1; double dx, dy, temp; m_bitmap. CreateCompatibleBitmap (& dc, rcClient.Width (), rcClient.Height ()); m_Bitmap.SetBitmapDimension (rcClient.Width (), rcClient.Height ()); m_MemDC.SelectObject (m_Bitmap); m_Bitmap.DeleteObject (); size1 = m_MemDC .Gettextextent ((lpctstr) "a", 1); // get the window for the height of the font size size = size1; m_memdc.gettextface (fontname); file: // Reserved title, coordinate display blank rcclient.right = Rect.right -m_set.rightspace; // While blank is the length of the short line on the coordinate axis rcclient.Light = Rect.LcClient.RightSpace; rcclient.bottom = Rect.bottom-m_set.rightspace; if (! m_set.ytitle.isempty )) rcclient.left = rcclient.Left size.cy * 3/2 m_set.charspace; if (! m_set.title.isempty ()) RcClient.top = Rect.top size.cy * 2; Else RcClient. TOP = Rect.top m_set.rightspace; if (! m_set.xtitle.isempty ()) rcclient.bottom = rcclient.bottom-size.cy * 3/2 m_set.charspace; if (! m_set.footnote.isempty ()) rcclient.bottom = rcclient.bottom-size.cy * 3/2; if (m_set.blegend) rcclient.bottom = rcclient.bottom-size.cy * 3/2; File: / / Make sure the interval of the coordinates is above 10, avoiding the value of the value of the coordinate display as YDEC = CalDecnum (m_set. Ymin, m_set.ymax, curstr); size = m_memdc.gettextextent (CURST); rcclient.LEFT = RcClient.Charspace; // size.cy/2; xdec = caldecnum (m_set.xmin , m_set.xmax, curStr); size = m_memdc.gettextextent (curStr); if (size.cx> (int) (rcclient.width () / m_set.hlinenum)) xver = true; if (xver) {RcClient.bottom = Rcx-m_set.charspace; rcclient.right- = size.cy / 2;} else {rcclient.bottom = rcclient.bottom-m_set.charspace-size.cy * 3/2; rcclient.right- = size.cx / 2;} file: // Eliminate the window width cannot be tied to the resulting error int = m_set.hlinenum * (int) (RcClient.width () / m_set.hlinenum); int height = m_set.vlinenum * (INT) (rcclient.height () / m_set.vlinenum); rcclient.Left = rcclient.right-iWidth; rcclient.top = rcclient.bottom-iHeight; File: // Clear window content CBRUSH BKBRUSH (m_set.bkcolor); file: // border if (m_set.bBorder) {CPen mpen (PS_SOLID, m_set.BorderWidth, m_set.BorderColor); CBrush * oldbrush = m_MemDC.SelectObject (& bkBrush); m_MemDC.Rectangle (rect); m_MemDC.SelectObject (oldbrush) ; mpen.DeleteObject ();} else m_MemDC.FillRect (rcClient, & bkBrush); bkBrush.DeleteObject (); int bkmode = m_MemDC.SetBkMode (TRANSPARENT); file: // title character string output COLORREF crOldColor = m_MemDC.SetTextColor (m_set .Tilecolor; font.createfont (size1.cy, 0, 0, 0, fw_bold, 0, 0, 0, default_precis, ut_default_precis, default_quality, default AULT_PITCH, FONTNAME); M_MEMDC.SELECTOBJECT (& font); // <- font.deleteObject (); // -> Size = m_memdc.gettextextent (m_set.title); Point.x = Rect.Left Rect.Width () / 2-size.cx/2;/ / 位 中 中 中国 = Rect.top Size.cy / 2; m_memdc.textout (Point.x, point.y, m_set.title); if (rcclient.bottom CPEN * OLDPEN = M_MEMDC.SelectObject (& Pen); iWidth = (int) (rcclient.hlinenum); iHEIGHT = (int) (RcClient.Height () / m_set.vlinenum); dx = (m_set. XMAX-m_set.xmin) / (double) m_set.hlinenum; DY = (m_set.ymax-m_set.ymin) / (double) m_set.vlinenum; int dotpos; if (xver) {font.createfont (size1.cy, 0 , -900,900, FW_NORMAL, 0,0,0,1, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, fontname); // "Times New Roman"); m_MemDC.SelectObject (& font); // <- font.DeleteObject () ; // ->} for (i = 0; i <= m_set.hlinenum; i ) {temp = m_set.xmin (double) i * dx; curStr.format ("% f", temp); dotpos = Curstr. Find ('.'); If (xDec> 0) Curstr = Curstr.Left (Dotpos XDEC 1); Else Curstr = Curstr.left (dotpos); size = m_memdc.gettextExtent (Curstr); if (xver) { Point.x = rcclient.x = * iWidth size.cy / 2; point.y = rcclient.bottom m_set.rightspace m_set.charspace;} else {Point.x = rcclient.LEFT i * iWidth-Size .cx / 2; point.y = rcclient.bottom m_set.right.com (} m_memdc.textout (Point.x, Point.y, Curstr) ; // Output coordinate data m_memdc.moveto (rcclient.bottom); m_memdc.lineto (rcclient.plineto (rcclient.bottom m_set.rightspace); if (m_set.bxinborder) {M_MEMDC.Moveto (RcClient.LINTOP); M_Memdc.Lineto (RcClient.Lineto);}}}}}}}}} {font.createfont (size1.cy, 0,0,0, FW_NORMAL, 0,0,0,1, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, fontname); // "Times New Roman"); m_MemDC.SelectObject (& font); // <- font.DeleteObject (); // ->} for (i = 0; i <= m_set.vlinenum; i ) {temp = m_set.ymax- (double) i * Dy; curStr.format ("% f", temp); dotpos = curStr.Find ('); if (YDEC> 0) Curstr = CURSTR.LEFT (DotPos YDEC 1); Else Curstr = Curstr.LSE CURSTR = Curstr.Left (dotpos); size = m_memdc.gettextextent (Curstr); Point.x = rcclient.LEFT-M_SET.RightSpace-m_set.charspace-size.cx Point.y = rcclient.top i * Iheight-size.cy / 2; m_memdc.textout (Point.x, Point.y, Curstr); m_memdc.moveto (rcclient.moveto (rcclient.left-m_set.rightspace, rcclient.top i * Iheight); m_memdc.lineto (rcclient.LinT, rcclient.top i * ife); if (m_set.byinborder) {m_memdc.moveto (rcclient.moveto (rcclient.moveto); m_memdc.lineto ( rcClient.right, rcClient.top i * iHeight);}} pen.DeleteObject (); m_MemDC.SelectObject (oldPen); file: // output pattern int nCount = m_items.GetSize (); CLineChartItem * pItem; CPoint ptOld, Ptnew; DataStru Curdata; Bool Bsplit = false; file: // Output legend size = m_memdc.gettextextent (m_set.xtit); // The font and X axis of the legend are temporarily set to uniform Point.x = rcclient.left; point.y = Rect.Bottom-size.cy; / / The height of the line (! m_set.footnote.ise Mpty ()) Point.y = point.y-size.cy * 3/2; if (m_set.blegend) {for (i = 0; i <(unsigned) ncount; i ) {pItem = m_items.getat (i ); Pen.createpen (Pitem-> iStyle, Pitem-> iWidth, Pitem-> m_colorline); cpen * oldpen = m_memdc.selectobject (& pen); m_memdc.moveto (point); Point.x = 3 * m_set.rightspace; // The wire is set to 3 times the spacing, Maybe Caculate from Rectangle's Width? M_memdc.lineto (Point); m_memdc.selectObject (OldPen); pen.deleteObject (); point.x = size.cy / 2; // all Space for Half of Font Height Point.Y = Point.y-size.cy / 2; M_Memdc.SetTextColor (Pitem-> LegendColor); m_memdc.textout (Point.x, Point.y, Pitem-> M_Legend); size = m_memdc.gettextextent (pitem-> m_legend); point.x = size.cx size.cy; // legendary distance is The height of the font .Y = size.cy / 2;}} m_memdc.setbkmode (bkmode); m_memdc.settextColor (croldcolor); file: // zuotu for (i = 0; i <(unsigned) ncount; i ) { Pitem = m_items.getat (i); position pos = pitem-> m_data.getHeadPosition (); if (pOS! = null) {CPEN Linepen (Pitem-> iStyle, Pitem-> iWidth, Pitem-> m_colorline); CPEN * Oldpen = m_memdc.selectObject (& linepen); file: // Picture Curdata = pitem-> m_data.getHead (); dx = (curdata.x-m_set.xmin) / (m_set.xmax-m_set.xmin); DY = (Curdata.y-m_set.ymin) / (m_set.ymax-m_set.ymin); ptold.x = rcclient.LID (DX * (Double) rcclient.width ()); ptold.y = rcclient.bottom - (int) (DY * (Double) rcclient.Height ()); while (pOS! = null) {curdata = pitem-> m_data.getnext (POS); if (Curdata.x! = nodata) {dx = Curdata.x-m_set.xmin) / (m_set.xmax-m_set.xmin); DY = (Curdata.y-m_set.ymin) / (m_set.ymax-m_set.ymin); Ptnew.x = rcclient .lef (int) (DX * (Double) RcCClient.width ()); Ptnew.y = rcclient.bottom- (int) (DY * (Double) rcclient.Height ()); if (bsplit) {ptold = ptnew BSPLIT = false;} m_memdc.moveto (ptold); ptold = ptnew; m_memdc.lineto (ptnew);} else bsplit = true;} m_memdc.selectObject (}); linepen.deleteObject ();}}}} Void Clyhlinechart :: CalRange () {Double DX, DY, PX, PY; File: // Make zero Calculation DX = m_set.xmax-m_set.xmin; DY = m_set.ymax-m_set.ymin; px = dx / Double) m_set.hlinenum; py = DY / (Double) m_set.vlinenum; file: // If the interval is greater than the minimum, it is zero if (m_set.xmin> = 0.0 && m_set.xmin INT Clyhlinechart :: Caldecnum (Double Minnum, Double Maxnum, CString & Data) {DOUBLE DY; INT DECNUM = 0; DY = MaxNum-minnum; // The interval cannot be less than a certain value, set to 9.9 While (DY <9.9) { DY = DY * 10.0; DECNUM ;} // Calculate the number of bits after the decimal point DY = MaxNum; file: // find one IF (DY <0.0) {if (-d <0.0) {if (-d <0.0) {if (-dy <-minnum) DY = MinNum } Else if (DY <= - minnum) DY = minnum; data.format ("% f", dy); int dotpos = data.find ('); if (Decnum> 0) Data = data.left (Dotpos Decnum 1); Else Data = DATA.LEFT (DOTPOS); Return Decnum;} int ClyHlineChart :: AddData (Double X, Double Y, INT lineIndex) {Int ncount = m_items.getsize (); if (LineIndex > ncount || LineIndex <1) Return 0; CLINECHARTITEM * PITEM = m_items.get (lineIndex-1); DataStru curdata; if (! m_set.autorance) {if (x> m_set.xmax) x = m_set.xmax; if (x INT ClyhlineChart :: Batchadddata (Double * x, double * y, int ncount, int nindex) {int nNum = m_items.getsize (); if (nindex> nnum || NINDEX <1) Return 0; if (ncount <= 0 Return 0; CLINECHARTITEM * PITEM = m_items.getat (nindex-1); if (pitem-> m_data.getcount () <= 0) {m_set.xmax = x [0]; m_set.xmin = x [0]; m_set.ymax = y [0]; m_set.ymin = y [0];} for (INT i = 0; I void CLyhLineChart :: SetLineStyle (int nStyle, int nWidth, COLORREF crColor, int nIndex) {if (nIndex> m_items.GetSize () || nIndex <1) return; CLineChartItem * pItem = m_items.GetAt (nIndex-1); pItem -> iStyle = nstyle; pitem-> iWidth = nwidth; pitem-> m_colorline = crcolor; Void Clyhlinechart :: SetTitle (CString Cstitle, ColorRef crcolor) {if (crcolor! = defaultcolor) m_set.tilecolor = crcolor; m_set.title = cstitle; ColorRef Clyhlinechart :: GetTitle (CString & Cstitle) {cstitle = m_set.title; return m_set.tilecolor;} CString CLyhLineChart :: SetXTitle (CString csXTitle, COLORREF crColor) {CString str; str = m_set.XTitle; m_set.XTitle = csXTitle; if (crColor = DEFAULTCOLOR!) M_set.XTileColor = crColor; return str;} CString CLyhLineChart :: SetYTitle (CString Csytitle) {CString Str; Str = m_set.ytitle; m_set.ytitle = csytitle; if (crcolor! = Defaultcolor) m_set.ytilecolor = crcolor; Return Str; CString CLyhLineChart :: SetFootNote (CString csFootNote, COLORREF crColor) {CString str; str = m_set.FootNote; m_set.FootNote = csFootNote; if (crColor = DEFAULTCOLOR!) M_set.FootColor = crColor; return str;} Bool Clyhlinechart :: Showlegeng (Bool Bshow) {bool il; old; m_set.blegend = bshow; returno} void CLyhLineChart :: SetLegend (CString csLegend, int nIndex, COLORREF crColor) {if (nIndex> m_items.GetSize () || nIndex <1) return; CLineChartItem * pItem = m_items.GetAt (nIndex-1); if (crColor! = DefaultColor) Pitem-> legendcolor = crcolor; pitem-> m_legend = CSLGEND; Void Clyhlinechart :: DeleteLine (INT NINDEX) {IF (Nindex> M_Items.getsize () || NINDEX <1) Return; CLINECHARTITEM * PITEM = m_items.getat (nindex-1); delete pitem; m_items.removeat (NINDEX-1);} INT ClyhlineChart :: getindex (cstring cslegend) {clinechartitem * pitem; for (int i = 0; i INT Clyhlinechart :: getLinenum () {Return M_Items.getsize (); INT ClyhlineChart :: setxdivision (int NDIV) {INT I; IF (NDIV <1) ndiv = 1; i = m_set.hlinenum; m_set.hlinenum = ndiv; returni} INT ClyhlineChart :: setdivision {INT i; if (NDIV <1) ndiv = 1; i = m_set.vlinenum; m_set.vlinenum = ndiv; returni} void Clyhlinechart :: ShowxGrid (bool bsign) {m_set .bxinborder = bsign;} Void Clyhlinechart :: ShowyGrid (Bool Bsign) {m_set.byinborder = bsign;} ColorRef ClyhlineChart :: setBkcolor (ColorRef crcolor) {colorref color; color = m_set.bkcolor; m_set.bkcolor = crcolor; return color;} Void Clyhlinechart :: setPicFont (int FontSize, CString FontName) {m_set.fontname = fontname; m_set.fontsize = fontsize;} Void Clyhlinechart :: setAxiedColor (colorRef crcolor) {m_set.axiednumcolor = crcolor; Void ClyhlineChart :: Onsize (uint ntype, int cx, int CY) {CWnd :: Onse (NTYPE, CX, CY); // Todo: add Your message handler code here drawpic (); invalidate }