VC++ MSChart (Kreisdiagramm);

Dieses Thema VC++ MSChart (Kreisdiagramm); im Forum "Webentwicklung, Hosting & Programmierung" wurde erstellt von Don_Pazo, 14. Apr. 2006.

Thema: VC++ MSChart (Kreisdiagramm); Hallo, ich habe ein Programmchen mit Visual C++ 6.0 erstellt, indem einen MSChart Element (Kreisdiagramm) gibt. Das...

  1. Hallo,
    ich habe ein Programmchen mit Visual C++ 6.0 erstellt, indem einen MSChart Element (Kreisdiagramm) gibt. Das ist eine Kreisdiagramm. Sie zeigt für eine bestimmte Person seine (geplante, laufende und fertige) Projekte. (Beispiel http://www.fh-augsburg.de/~nenov/images/forum/EM.gif)

    Ich will, dass noch der Anzahl bzw. Prozentualanteil auf der Diagramm erscheinen (wie z.B. im http://www.fh-augsburg.de/~nenov/images/forum/EM_2.gif). Weist jemand, wie ich das implementieren kann?
     
  2. [​IMG]

    Verwendest Du VC7 oder höher? Hast Du die Wrapper generieren lassen (wenn >=VC7: Rechtsklick auf Projekt im Solution-Explorer, Klasse hinzufügen, MFC-Klasse aus Typbibliothek, Microsoft Chart Control ... und dann alle IVc*-Klassen wählen).
    Anschließend kannst Du die Header wieder aus dem Projekt entfernen, außer

    CVcplot.h
    CVcseriescollection.h
    CVcdatapoint.h
    CVcdatapoints.h
    CVcSeries.h
    CVcDataPointLabel.h
    CVcFont.h
    CVcLegend.h
    CVcColor.h
    CVcBrush.h

    Du kannst Dir dann eine kleine Helferklasse schreiben, die das Ganze kapselt, z.B. so (ich habe als Beispiel noch ein paar andere Funktionen eingefügt):

    Code:
    #include mschart.h // Name kann variieren
    #include CVcplot.h
    #include CVcseriescollection.h
    #include CVcdatapoint.h
    #include CVcdatapoints.h
    #include CVcSeries.h
    #include CVcDataPointLabel.h
    #include CVcFont.h
    #include CVcLegend.h
    #include CVcColor.h
    #include CVcBrush.h
    
    class PieChartHelper {
    private:
      CMschart& chart;
      CVcPlot plot;
      CVcSeriesCollection serCol;
    
      void getDPsp(int idx, CVcDataPoint& dp) {
        CVcSeries ser = serCol.get_Item(idx);
        CVcDataPoints dps = ser.get_DataPoints();
        dp = dps.get_Item(-1);
      }
    
    public:
      PieChartHelper(CMschart& _chart) : chart(_chart) {
        plot = chart.get_Plot();
        serCol = plot.get_SeriesCollection();    
        SetDefaults();
      }  
    
      void SetData(int a, int b, int c) {
    
        COleSafeArray sarr;
        DWORD numElements[] = {1, 3};
        sarr.Create(VT_I4, 2, numElements);
    
        long index[2];
        index[0] = 0;
        index[1] = 0;
        sarr.PutElement(index, (void*)&a);
    
        index[1] = 1;
        sarr.PutElement(index, (void*)&b);
    
        index[1] = 2;
        sarr.PutElement(index, (void*)&c);
    
        chart.put_ChartData(sarr.Detach());
        chart.Refresh();
      }
    
      void SetData(int values[], int len) {
        
        COleSafeArray sarr;
        DWORD numElements[] = {1, len};
        sarr.Create(VT_I4, 2, numElements);
    
        long index[2];
        index[0] = 0;
        for(int idx = 0; idx < len; ++idx) {
          index[1] = idx;
          sarr.PutElement(index, (void*)&values[idx]);
        }
    
        chart.put_ChartData(sarr.Detach());
        chart.Refresh();
      }
    
      void SetLabels(const CString& l1, const CString& l2, const CString& l3) {
        
        ASSERT(serCol.Count() == 3);
        
        CVcSeries ser = serCol.get_Item(1);
        ser.put_LegendText(l1);
        ser = serCol.get_Item(2);
        ser.put_LegendText(l2);
        ser = serCol.get_Item(3);
        ser.put_LegendText(l3);    
      }
    
      void SetLabels(const CStringArray& sl) {
        
        ASSERT(serCol.Count() == sl.GetCount());
    
        CVcSeries ser;
        for(int idx = 1; idx <= sl.GetCount(); ++idx) {
          ser = serCol.get_Item(idx);
          ser.put_LegendText(sl[idx-1]);
        }    
      }
    
      void SetColors(COLORREF colors[], int len) {
    
        ASSERT(serCol.Count() == len);
    
        for(int dpointIdx = 1; dpointIdx <= serCol.Count(); ++dpointIdx) {
          CVcDataPoint dp;
          getDPsp(dpointIdx, dp);
          CVcBrush brush = dp.get_Brush();
          CVcColor cfill = brush.get_FillColor();
          cfill.Set(GetRValue(colors[dpointIdx-1]), GetGValue(colors[dpointIdx-1]),
            GetBValue(colors[dpointIdx-1]));
        }
      }
      
      // Danach hast Du gefragt.
      // Wenn->percent' false ist, werden die Werte selbst angezeigt
      // CMschart::VtChLabelLocationTypeInside = Im Kreis 
    
      void SetDataPointLabels(bool percent, float fntSize = 10.0f) {
    
        for(int dpointIdx = 1; dpointIdx <= serCol.Count(); ++dpointIdx) {
    
          CVcDataPoint dp;
          getDPsp(dpointIdx, dp);
    
          CVcDataPointLabel dpl = dp.get_DataPointLabel();
    
          if(percent) {
            dpl.put_PercentFormat(0%);
            dpl.put_LocationType(CMschart::VtChLabelLocationTypeInside);
            dpl.put_Component(CMschart::VtChLabelComponentPercent);
          } else {
            dpl.put_LocationType(CMschart::VtChLabelLocationTypeInside);
            dpl.put_Component(CMschart::VtChLabelComponentValue);
          }
    
          CVcFont dFnt(dpl.get_VtFont());
          dFnt.put_Size(fntSize); 
    
        }
      }
    
      void SetDefaultValues() {
        SetData(0, 0, 0);
      }
    
      void SetDefaultColors() {
        COLORREF colors[] = {RGB(0, 250, 0), RGB(250, 250, 0), RGB(250, 0, 0)};
        SetColors(colors, 3);
      }
    
      void SetDefaultLabels() {
        SetLabels(Fertige Projekte, Laufende Projekte, Geplante Projekte);
      }
    
      void SetDefaultDataPointLabels() {
        SetDataPointLabels(true);
      }
    
      void SetName(const CString& name) {
        chart.put_RowLabel(name);
      }
    
      void SetDefaults() {
        chart.put_chartType(CMschart::VtChChartType2dPie);
        chart.put_ShowLegend(TRUE);
        chart.put_RowCount(1);
        chart.put_ColumnCount(3);
        chart.put_AllowDynamicRotation(FALSE);
        chart.put_AllowSelections(FALSE);
        chart.put_AllowSeriesSelection(FALSE);
        
        SetDefaultValues();
        SetDefaultColors();
        SetDefaultLabels();
        SetDefaultDataPointLabels();
      }
    };
    
    In Deiner Dialog/PropertyPage/... -Klasse kannst Du dann eine entsprechende Variable deklarieren:

    PieChartHelper* m_p3ch;

    In OnInitDialog:

    m_p3ch = new PieChartHelper(m_chart);

    m_chart ist die Control-Variable, die Du sicher schon vom Class/Variable-Wizard hast erzeugen lassen.
    CMschart oben ist die entsprechende Klasse; beides kann bei Dir natürlich anders heißen.

    Dann

    m_p3ch->SetData(10, 5, 7);
    m_p3ch->SetName(Egbert Brendle);

    etc.

    Solltest Du VC6 verwenden, funktioniert der Code oben so nicht, da die Namen der Funktionen teilweise anders lauten ...
    z.B. GetPlot statt get_Plot, SetRowLabel statt put_RowLabel usw.; alles mehr oder weniger nach diesem Muster.
     
  3. Danke,
    ich benutze leider genau Visual C++ 6.0 ( das sollte ich eigentlich erwehnen). Ich habe versucht von deinen Code selbst die passende Funktionen abzuleiten, es ist mir nicht gelungen.
    Ich zeige dir  wie wiet ich bin:

    Code:
    // Diagramm Variablen
    double dGrunNiko	= 0;
    double dGelbNiko	= 0;
    double dRotNiko	= 0;
    
    long index[2];	// [0][]Benutzer, [1][]Farben
    
    COleSafeArray saDiagram;		// Diagram Objekt
    DWORD numElements[] = {1, 3};	// Diagram Elemente 1(Benutzer) x 3(Farben)
    
    
    //... hier werden die Werte für dGrunNiko, dGelbNiko und dRotNiko erstellt
    
    
    /*========= Diagram erstellen ===============*/
    
    // Diagram Create, 2-Dimensional, mit 1x3 Elemente
    saDiagram.Create(VT_R8, 2, numElements);
    
    for(index[0]=0; index[0]<1; index[0]++) {	// Benutzer
        for(index[1]=0; index[1]<3; index[1]++) {	// Wariable
    			
    	if(index[0] == 0){			// Niko
    		if(index[1] == 0){		// Grün
    			saDiagram.PutElement(index, &dGrunNiko);
    		}
    		else if(index[1] == 1){	// Gelb
    			saDiagram.PutElement(index, &dGelbNiko);
    		}
    		else if(index[1] == 2){	// Rot
    			saDiagram.PutElement(index, &dRotNiko);
    		}
    	}
       }
    }
    
    // Diagramm Werte einfügen
    m_cDiagram.SetChartData(saDiagram.Detach());
    	
    // Farbenbedeutung setzen
    m_cDiagram.SetColumn(1);
    m_cDiagram.SetColumnLabel(fertige Projekte);
    
    m_cDiagram.SetColumn(2);
    m_cDiagram.SetColumnLabel(laufende Projekte);
    	
    m_cDiagram.SetColumn(3);
    m_cDiagram.SetColumnLabel(geplante Projekte);
    	
    // Benutzer setzen
    m_cDiagram.SetRow(1);
    m_cDiagram.SetRowLabel(Nikolay Nenov);
    
    /*===============================*/
    //    Hier gleube ich sollte es möglich sein die
    //    Prozentun in dem Kreisdiagram einzufügen (nun wie ???)
    /*===============================*/
    	
    m_cDiagram.Refresh();
    Weisst du zufällig wie das beim Visual C++ 6.0 geht?
     
  4. Bei VC6 werden mehr oder weniger automatisch die Wrapper (als Header- und Source-Dateien) generiert. Wenn man bei VC7 wie beschrieben vorgeht, erhält man nur eine Pseudo-Sourcedatei; der eigentliche Code steht in den ganzen Header-Dateien (alles inline).

    [Wenn Du diese Dateien nicht hast:
    Als Du den Klassenassistenten aufgerufen hast, um die Variable m_cDiagram erzeugen zu lassen, müsste eine solche Meldung angezeigt worden sein:
    Das ActiveX-Steuerelement Microsoft Chart Control ... wurde nicht in Ihr Projekt eingefügt. Developer Studio wird dies jetzt vornehmen und eine C++-Wrapper-Klasse dafür erstellen.
    Danach kannst Du Häkchen bei den Klassen setzen, die generiert werden sollen. Zuerst steht da die Klasse, welche auf jeden Fall benötigt wird: CMSChart. Darunter dann eine ganze Menge Klassen, die mit CVc beginnen. Diese (bzw. einige davon) benötigst Du hier auch, nicht nur CMSChart.
    Wenn Du auf OK klickst, werden cpp- und h-Dateien erzeugt und in Dein Projekt eingefügt. Wenn unten alles klappt, kannst sie sicher teilweise auch wieder aus dem Projekt nehmen bzw. von Hand in einen eigenen Unterordner verschieben, damit es übersichtlicher ist.]

    Ansonsten gleiche Vorgehensweise wie bei VC7, nur die Funktionen heißen anders (wie gesagt): Statt put_ Set als Prefix und statt get_ dann Get. Kleiner Schönheitsfehler bei VC6: Es sind keine enums für die Konstanten vorhanden.

    So sollte es mit VC6 klappen (ist aber relativ unflexibel; Du kannst Dich ja an dem Code oben orientieren, wenn es erst mal funktioniert):

    Code:
    
    // ...
    
    #include mschart.h // bzw. der gewählte Dateiname
    #include vcplot.h
    #include vcseriescollection.h
    #include vcseries.h
    #include vcdatapoints.h
    #include vcdatapoint.h
    #include vcdatapointlabel.h
    #include vcfont.h
    
    // ...
    
    enum
    {
      VtChLabelLocationTypeNone = 0,
      VtChLabelLocationTypeAbovePoint = 1,
      VtChLabelLocationTypeBelowPoint = 2,
      VtChLabelLocationTypeCenter = 3,
      VtChLabelLocationTypeBase = 4,
      VtChLabelLocationTypeInside = 5,
      VtChLabelLocationTypeOutside = 6,
      VtChLabelLocationTypeLeft = 7,
      VtChLabelLocationTypeRight = 8
    } VtChLabelLocationType;
    
    enum
    {
        VtChLabelComponentValue = 1,
        VtChLabelComponentPercent = 2,
        VtChLabelComponentSeriesName = 4,
        VtChLabelComponentPointName = 8
    } VtChLabelComponent;
    
    // ...
    
    void CDeinIrgendwas::SetChart(const CString& name, bool dispPercent, float componentFntSize, int gruen, int gelb, int rot) {
    
      COleSafeArray saDiagram;	                // Hilfsobjekt zum Füllen des Diagramms
      DWORD numElements[] = {1, 3};	// 1(Kreisdiagramm) x 3(Kreisabschnitte)
      long index[2];
    
      saDiagram.Create(VT_I4, 2, numElements);
      
      // index[0] = row index = 0
      // In diesem Fall haben wir immer nur ein Diagramm gleichzeitig, also ist der row index immer gleich 0.
      index[0]=0;
    
      // index[1] (column) bestimmt, um welchen Kreisabschnitt es geht; also hier 0 bis 2  index[0]=0;
      index[1]=0;
      saDiagram.PutElement(index, &gruen);
      index[1]=1;
      saDiagram.PutElement(index, &gelb);
      index[1]=2;
      saDiagram.PutElement(index, &rot);
    
      // Diagramm mit Werten belegen
      m_cDiagram.SetChartData(saDiagram.Detach());
    	
      m_cDiagram.SetRowLabel(name);
    	
      // Legende setzen  
      m_cDiagram.SetColumn(1);
      m_cDiagram.SetColumnLabel(fertige Projekte);
      m_cDiagram.SetColumn(2);
      m_cDiagram.SetColumnLabel(laufende Projekte);	
      m_cDiagram.SetColumn(3);
      m_cDiagram.SetColumnLabel(geplante Projekte);
      
      // Dem Chart-Control mitteilen, ob bzw. wie es Prozente/Werte der Kreisabschnitte anzeigen soll
      CVcPlot plot(m_cDiagram.GetPlot());
      CVcSeriesCollection serCol = plot.GetSeriesCollection();
      CVcSeries ser;
      CVcDataPoints dps;
      CVcDataPoint dp;
      CVcDataPointLabel dpl;
      for(int idx = 1; idx <= 3; ++idx) {
        ser = serCol.GetItem(idx);
        dps = ser.GetDataPoints();
        dp = dps.GetItem(-1);
        dpl = dp.GetDataPointLabel();
    
        if(dispPercent) {
            // Prozente anzeigen
            dpl.SetPercentFormat(0%);
            dpl.SetLocationType(VtChLabelLocationTypeInside);
            dpl.SetComponent(VtChLabelComponentPercent);
        } else {
            // Werte selbst anzeigen
            dpl.SetLocationType(VtChLabelLocationTypeInside);
            dpl.SetComponent(VtChLabelComponentValue);
        }
        // Größe der Prozent- bzw. Wertedarstellung setzen (ist sonst wahrscheinlich etwas zu klein)
        CVcFont dFnt(dpl.GetVtFont());
        dFnt.SetSize(componentFntSize);
      }
      
      m_cDiagram.Refresh();  
    }
    
    
    // Mit Anzeige der Prozente (hier 25%, 33%, 42%)
    SetChart(Nikolay Nenov, true, 10.0f, 3, 4, 5);

    // Mit Anzeige der Werte (hier 3, 4, 5)
    SetChart(Nikolay Nenov, true, 10.0f, 3, 4, 5);

    Die Farben des Diagramms musst Du natürlich noch auf grün, gelb und rot ändern. Standard ist rot, grün, blau. Auch die Möglichkeit des Selektierens etc. würde ich ausschalten (in den Eigenschaften/Properties).
     
  5. Vielen Dank für die Hilfe. Es klapt prima !!!
     
Die Seite wird geladen...

VC++ MSChart (Kreisdiagramm); - Ähnliche Themen

Forum Datum
Vista startet nicht nach VC++ install Windows Vista Forum 30. Apr. 2010
[VC++] TabControl SizeMode Webentwicklung, Hosting & Programmierung 24. Juli 2006
VC++ Forms dynamisch erstellen Webentwicklung, Hosting & Programmierung 19. Juli 2006
Zeitberechnungen unter VC++ Windows XP Forum 23. Aug. 2005
Systeminfos mit VC++ Windows XP Forum 20. Aug. 2005