Beispiel 5 — Zahnrad

Erstellt: 2026-05-27 · Aktualisiert: 2026-05-27

Advanced Snippet Editor

Das komplexeste Beispiel: Ein Zahnrad wird durch drei aufeinanderfolgende Boolean-Operationen auf einem Stern und Kreisen erzeugt. Zeigt, wie man Ergebnis-Formen weiterverwendet und alle verfügbaren Zahnanzahlen unterstützt.


Ergebnis


Verfügbare Zahnanzahlen

PowerPoint stellt nur bestimmte Stern-Formen bereit — nicht alle Zahnzahlen sind möglich:

Zähne MsoAutoShapeType
4 msoShape4pointStar
5 msoShape5pointStar
6 msoShape6pointStar
7 msoShape7pointStar
8 msoShape8pointStar
10 msoShape10pointStar
12 msoShape12pointStar (Standard)
16 msoShape16pointStar
24 msoShape24pointStar
32 msoShape32pointStar

Warum keine 20 Zähne?

PowerPoint stellt keinen 20-Zacken-Stern bereit — es gibt keinen entsprechenden MsoAutoShapeType-Wert.
20, 28 usw. sind daher nicht möglich.
Vollständige Liste aller Formen: MsoAutoShapeType auf learn.microsoft.com


Code

/* PARAMS */
string tooths    = "12";   // 4|5|6|7|8|10|12|16|24|32
float  left      = 100f;
float  top       = 80f;
float  size      = 200f;
var    fillColor = System.Drawing.Color.FromArgb(52, 73, 94);
var    lineColor = System.Drawing.Color.FromArgb(30, 45, 60);
/* END PARAMS */

int fillRgb = System.Drawing.ColorTranslator.ToOle(fillColor);
int lineRgb = System.Drawing.ColorTranslator.ToOle(lineColor);

float cx        = left + size / 2f;
float cy        = top  + size / 2f;
float sizeSmall = size * 0.5713f;
float sizeBig   = size * 0.7143f;
float sizeHole  = size * 0.3136f;

void ApplyStyle(dynamic sh)
{
    sh.Fill.ForeColor.RGB = fillRgb;
    sh.Fill.Transparency  = 0f;
    sh.Line.Weight        = 1.5f;
    sh.Line.ForeColor.RGB = lineRgb;
    sh.Line.Transparency  = 0f;
    sh.Line.DashStyle     = MsoLineDashStyle.msoLineSolid;
    sh.Line.Style         = MsoLineStyle.msoLineSingle;
}

MsoAutoShapeType starType;
float adj;
switch (tooths)
{
    case  "4": starType = MsoAutoShapeType.msoShape4pointStar;  adj = 0.25f;    break;
    case  "5": starType = MsoAutoShapeType.msoShape5pointStar;  adj = 0.25f;    break;
    case  "6": starType = MsoAutoShapeType.msoShape6pointStar;  adj = 0.25f;    break;
    case  "7": starType = MsoAutoShapeType.msoShape7pointStar;  adj = 0.25f;    break;
    case  "8": starType = MsoAutoShapeType.msoShape8pointStar;  adj = 0.22781f; break;
    case "10": starType = MsoAutoShapeType.msoShape10pointStar; adj = 0.23f;    break;
    case "12": starType = MsoAutoShapeType.msoShape12pointStar; adj = 0.21753f; break;
    case "16": starType = MsoAutoShapeType.msoShape16pointStar; adj = 0.22f;    break;
    case "24": starType = MsoAutoShapeType.msoShape24pointStar; adj = 0.21f;    break;
    case "32": starType = MsoAutoShapeType.msoShape32pointStar; adj = 0.20f;    break;
    default:   starType = MsoAutoShapeType.msoShape12pointStar; adj = 0.21753f; break;
}

// 1. Stern erstellen
var oStar = ppptools.AddShape(starType, cx - size/2f, cy - size/2f, size, size);
oStar.Adjustments[1] = adj;
ApplyStyle(oStar);

// 2. Kleiner Kreis + Union → Zahnspitzen abrunden
var oSmall = ppptools.AddOval(cx - sizeSmall/2f, cy - sizeSmall/2f, sizeSmall, sizeSmall);
ApplyStyle(oSmall);
oStar.Select(MsoTriState.msoTrue);
oSmall.Select(MsoTriState.msoFalse);
ppptools.Union();
dynamic oUnion = ppptools.GetSelected();

// 3. Grosser Kreis + Intersect → Aussenkontur begrenzen
var oBig = ppptools.AddOval(cx - sizeBig/2f, cy - sizeBig/2f, sizeBig, sizeBig);
ApplyStyle(oBig);
oUnion.Select(MsoTriState.msoTrue);
oBig.Select(MsoTriState.msoFalse);
ppptools.Intersect();
dynamic oIntersect = ppptools.GetSelected();

// 4. Loch-Kreis + Combine → Mitte ausstanzen
var oHole = ppptools.AddOval(cx - sizeHole/2f, cy - sizeHole/2f, sizeHole, sizeHole);
ApplyStyle(oHole);
oIntersect.Select(MsoTriState.msoTrue);
oHole.Select(MsoTriState.msoFalse);
ppptools.Combine();

foreach (dynamic sh in ppptools.GetSelectedRange())
{
    sh.Name = "GearWheel_" + tooths;
    ApplyStyle(sh);
}

Schritt-für-Schritt-Erklärung

1. Hilfsfunktion ApplyStyle

void ApplyStyle(dynamic sh)
{
    sh.Fill.ForeColor.RGB = fillRgb;
    ...
}

Statt den Stil für jede der vier Formen zu wiederholen, wird er in einer lokalen Funktion gekapselt. Das spart Code und stellt sicher, dass alle Zwischenergebnisse konsistent formatiert sind — was für die Boolean-Operationen wichtig ist (nicht stilisierte Formen können unerwartete Ergebnisse liefern).

Warum void ApplyStyle(dynamic sh) statt Action<dynamic> applyStyle?
Action<> ist im System-Namespace, der in Roslyn nicht automatisch importiert wird. Lokale Funktionen funktionieren problemlos. Siehe Scripting-Regeln.

2. Zahnzahl-Auswahl: switch (tooths) mit adj

MsoAutoShapeType starType;
float adj;
switch (tooths)
{
    case "12": starType = MsoAutoShapeType.msoShape12pointStar; adj = 0.21753f; break;
    ...
}

Jede Stern-Form hat eine andere optimale Innenradius-Ratio (adj). Dieser Wert steuert, wie weit die Täler zwischen den Zacken nach innen reichen. Der Adjustment-Wert wird im nächsten Schritt gesetzt:

oStar.Adjustments[1] = adj;

Adjustments ist ein Index-basiertes Array (1-basiert) für form-spezifische Parameter. Bei Sternen steuert [1] das Verhältnis Innenradius/Aussenradius.

3. Operation 1: Union — Zahnspitzen abrunden

// Kleiner Kreis (57,13 % der Grösse) + Union mit Stern
var oSmall = ppptools.AddOval(cx - sizeSmall/2f, cy - sizeSmall/2f, sizeSmall, sizeSmall);
oStar.Select(MsoTriState.msoTrue);
oSmall.Select(MsoTriState.msoFalse);
ppptools.Union();
dynamic oUnion = ppptools.GetSelected();

Ein Kreis, der etwas kleiner als der Stern-Aussenkreis ist (sizeSmall = size * 0.5713f), wird mit dem Stern vereinigt. Dadurch werden die Täler zwischen den Zacken nach aussen aufgefüllt — die Zahnspitzen bleiben, die Einbuchtungen werden runder.

Wichtig: Das Ergebnis wird sofort in dynamic oUnion gespeichert, da die Originale (oStar, oSmall) nach der Operation nicht mehr existieren.

4. Operation 2: Intersect — Aussenkontur begrenzen

// Grosser Kreis (71,43 % der Grösse) + Intersect
var oBig = ppptools.AddOval(cx - sizeBig/2f, cy - sizeBig/2f, sizeBig, sizeBig);
oUnion.Select(MsoTriState.msoTrue);
oBig.Select(MsoTriState.msoFalse);
ppptools.Intersect();
dynamic oIntersect = ppptools.GetSelected();

Ein grosser Kreis (sizeBig = size * 0.7143f) wird mit dem Ergebnis der Union verschnitten: Nur der Bereich, der in beiden Formen liegt, bleibt übrig. Dadurch werden die spitzen Zahnenden abgerundet — das Zahnrad bekommt seine charakteristischen gerundeten Zahnköpfe.

5. Operation 3: Combine — Mittelloch ausstanzen

// Loch-Kreis (31,36 % der Grösse) + Combine
var oHole = ppptools.AddOval(cx - sizeHole/2f, cy - sizeHole/2f, sizeHole, sizeHole);
oIntersect.Select(MsoTriState.msoTrue);
oHole.Select(MsoTriState.msoFalse);
ppptools.Combine();

Zum Abschluss wird das Mittelloch erzeugt: Ein kleiner Kreis (sizeHole = size * 0.3136f) wird mit Combine aus dem Zahnrad ausgestanzt.

Die drei Grössenproportionen

Variable Formel Bedeutung
sizeSmall size * 0.5713 Füllt Täler auf → rundet Zähne ein
sizeBig size * 0.7143 Begrenzt Zahnköpfe → rundet Zähne ab
sizeHole size * 0.3136 Mittelloch-Durchmesser

Diese Proportionen wurden empirisch ermittelt und ergeben für alle Zahnzahlen ein optisch ausgewogenes Zahnrad.


Besonderheiten dieses Beispiels

  • Drei aufeinanderfolgende Boolean-Ops — jede nimmt das Ergebnis der vorherigen als Input. Zwischenergebnisse werden in dynamic-Variablen gespeichert.
  • dynamic oUnion = ppptools.GetSelected() — nach jeder Boolean-Op wird das Ergebnis sofort abgegriffen, bevor die nächste Selektion es überschreibt.
  • Adjustments[1] — form-spezifischer Parameter, der die Innenradius-Ratio des Sterns steuert. Unterschiedliche Werte pro Zahnzahl ergeben gleichmässig aussehende Zähne.
  • Warum kein 20-Zahn-Zahnrad? — PowerPoint hat keinen msoShape20pointStar. Auch nicht 9, 11, 13 usw.
  • ApplyStyle auch auf Zwischenformen — damit die Boolean-Ops die Formatierungseigenschaften der Eingabe-Formen konsistent übernehmen.

Zurück: Beispiel 4 — Loch (Combine) · Advanced Snippet Editor Übersicht