Laden...

GradientBrush als Ring

Erstellt von Lector vor 15 Jahren Letzter Beitrag vor 15 Jahren 3.649 Views
L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 15 Jahren
GradientBrush als Ring

Hallo,

Ich versuche so etwas mit WPF Brushes zu realisieren:

[siehe unten]

Jedoch gibt es nur 2 GradientBrushes im .NET 3.5. Ich habe es weder mit Linear noch mit Radial geschafft. Es handelt sich ja weder um eine Linie noch um einen Kreis.
Es ist eher ein Ring den ich als GradientBrush darstellen möchte.

Ich habe auch schon versucht direkt von GradientBrush abzuleiten bin daran jedoch leider gescheitert.
Laut .NET Reflector wird der eigendliche Zeichenalgorythmus in LinearGradientBrush in einer internal Methode angetriggert auf die ich gar nicht zugreifen kann.

Meine Frage ist nun:
Kann ich solche Farbverläufe mit Standardbrushes darstellen (mal abgesehen von Image/Visual-Brush).
Und falls nein: Wie kann ich selbst ein GradientBrush schreiben. Ich kann zwar von GradientBrush ableiten aber mir fehlt irgendwie der rote Faden wo ich überhaupt anfangen soll und wie ich dort den Farbverlauf zeichne (in welcher Methode, und wann...)

V
327 Beiträge seit 2005
vor 15 Jahren

Hallo,

ich würde nicht in richtung gradient denken sondern das teil einfach über schleifen und das zeichnen von geraden selber zeichnen...

rot = 255.0.0 = 0°
orange 255.255.0 = 60°
gelb = 0.255.0 = 120°
grün = 0.255.255 = 180°
blau = 0.0.255 = 240°
violett = 255.0.255 = 300°

entsprechen R, G oder B hoch und runterzählen lassen und immer wieder zeichnen, oder so ähnlich.

MFG Veasel

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 15 Jahren

d.h. ich müsste SEHR viele Linien malen wenn ich dich richtig verstehe.
Wäre das nicht sehr langsam?
Ausserdem was passiert wenn der Kreis größer wird? Dann würde die Linienmenge irgendwann ausfransen.

V
327 Beiträge seit 2005
vor 15 Jahren

Guten morgen,

ja, da hast du wohl recht. war auch erstmal nur so eine idee. hab noch nicht mit der erstellung eines gradient beschäftigt.

könnte man nicht nen lineargradient zeichnen auf ein rect vielleicht und dieses recht dann per trasfomation "verbiegen"?

MFG Veasel

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 15 Jahren

So weit ich weis gibt es 4 TransformationsTypen in WPF:
1.Verschieben (was hier vollkommen Nutzlos ist) 1.Rotieren (ja vielleicht hätte ich einen ähnlichen Effekt wenn ich SEHR schnell rotieren würde^^) 1.Skalieren (größer und kleiner machen nützt hier relativ wenig) 1.Kippen (bringt auch nichts)

Also ist eine Transformation wohl auch nicht die Lösung...

V
327 Beiträge seit 2005
vor 15 Jahren

hey...du hast gefragt und ich mach nur ein bißchen brainstorming...

tja, sonst hab ich auch erstmal keine lösung...aber interessant ist es trotzdem.

schreibt aber auch kein anderer was dazu... ist dann wohl doch nicht so trivial.

MFG Veasel

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 15 Jahren

Ich denke ich muss wohl doch ein eigenes Gradient erstellen. Ich poste mal ausschnitte aus LinearGradientBrush laut .NET Reflector:

Dies ist die einzige Methode die das eigendliche Zeichnen antriggert:


[SecurityCritical, SecurityTreatAsSafe]
internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck)
{
    this.ManualUpdateResource(channel, skipOnChannelCheck);//<-eigendlicher Zeichenvorgang
    base.UpdateResource(channel, skipOnChannelCheck);
}

Wenn das jetzt nicht internal wäre könnte ich UpdateResource ja auch überschreiben und dort ein Gradient malen. Diese Methode ist für mich jedoch leider nicht sichtbar....

Hier das eigendilche Zeichnen:


[SecurityTreatAsSafe, SecurityCritical]
private unsafe void ManualUpdateResource(DUCE.Channel channel, bool skipOnChannelCheck)
{
    if (skipOnChannelCheck || this._duceResource.IsOnChannel(channel))
    {
        DUCE.ResourceHandle handle;
        DUCE.ResourceHandle @null;
        DUCE.MILCMD_LINEARGRADIENTBRUSH milcmd_lineargradientbrush;
        Transform objA = base.Transform;
        Transform relativeTransform = base.RelativeTransform;
        GradientStopCollection gradientStops = base.GradientStops;
        if ((objA == null) || object.ReferenceEquals(objA, Transform.Identity))
        {
            @null = DUCE.ResourceHandle.Null;
        }
        else
        {
            @null = ((DUCE.IResource) objA).GetHandle(channel);
        }
        if ((relativeTransform == null) || object.ReferenceEquals(relativeTransform, Transform.Identity))
        {
            handle = DUCE.ResourceHandle.Null;
        }
        else
        {
            handle = ((DUCE.IResource) relativeTransform).GetHandle(channel);
        }
        DUCE.ResourceHandle animationResourceHandle = base.GetAnimationResourceHandle(Brush.OpacityProperty, channel);
        DUCE.ResourceHandle handle4 = base.GetAnimationResourceHandle(StartPointProperty, channel);
        DUCE.ResourceHandle handle3 = base.GetAnimationResourceHandle(EndPointProperty, channel);
        milcmd_lineargradientbrush.Type = MILCMD.MilCmdLinearGradientBrush;
        milcmd_lineargradientbrush.Handle = this._duceResource.GetHandle(channel);
        double opacity = base.Opacity;
        DUCE.CopyBytes((byte*) &milcmd_lineargradientbrush.Opacity, (byte*) &opacity, 8);
        milcmd_lineargradientbrush.hOpacityAnimations = animationResourceHandle;
        milcmd_lineargradientbrush.hTransform = @null;
        milcmd_lineargradientbrush.hRelativeTransform = handle;
        milcmd_lineargradientbrush.ColorInterpolationMode = base.ColorInterpolationMode;
        milcmd_lineargradientbrush.MappingMode = base.MappingMode;
        milcmd_lineargradientbrush.SpreadMethod = base.SpreadMethod;
        Point startPoint = this.StartPoint;
        DUCE.CopyBytes((byte*) &milcmd_lineargradientbrush.StartPoint, (byte*) &startPoint, 0x10);
        milcmd_lineargradientbrush.hStartPointAnimations = handle4;
        Point endPoint = this.EndPoint;
        DUCE.CopyBytes((byte*) &milcmd_lineargradientbrush.EndPoint, (byte*) &endPoint, 0x10);
        milcmd_lineargradientbrush.hEndPointAnimations = handle3;
        int num2 = (gradientStops == null) ? 0 : gradientStops.Count;
        milcmd_lineargradientbrush.GradientStopsSize = (uint) (sizeof(DUCE.MIL_GRADIENTSTOP) * num2);
        channel.BeginCommand((byte*) &milcmd_lineargradientbrush, sizeof(DUCE.MILCMD_LINEARGRADIENTBRUSH), sizeof(DUCE.MIL_GRADIENTSTOP) * num2);
//Hier werden wohl die Gradientstops durchlaufen
        for (int i = 0; i < num2; i++)
        {
            DUCE.MIL_GRADIENTSTOP mil_gradientstop;
            GradientStop stop = gradientStops.Internal_GetItem(i);
            double offset = stop.Offset;
            DUCE.CopyBytes((byte*) &mil_gradientstop.Position, (byte*) &offset, 8);
            mil_gradientstop.Color = CompositionResourceManager.ColorToMilColorF(stop.Color);
            channel.AppendCommandData((byte*) &mil_gradientstop, sizeof(DUCE.MIL_GRADIENTSTOP));
        }
        channel.EndCommand();
    }
}

K
593 Beiträge seit 2007
vor 15 Jahren

Hallo,

ich denke nicht das du alles selbst machen musst. WPF gibt eigentlich viele möglichkeiten. Vielleicht hilft dir dieser Artikel .

Gruß Daniel

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 15 Jahren

Also wenn es eine Möglichkeit mit Standard-WPF Controls gibt würde ich diese natürlich vorziehen.
Bis jetzt habe ich allerdings immer noch keinen Lösungsansatz gefunden...

P
67 Beiträge seit 2008
vor 15 Jahren

Vielleicht bringt dir die PathGradientBrush-Klasse eher was.

Religionskriege sind Konflikte zwischen erwachsenen Menschen, bei denen es darum geht, wer den cooleren, imaginaeren Freund hat

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 15 Jahren

Nach dem was ich hier sehe ist das genau das was ich brauche.
Nur kann ich in meiner WPF-Anwendung leider nicht darauf zugreifen weil es eine WinForms-Klasse ist...

Gibt es davon irgendeine WPF-Version?

K
593 Beiträge seit 2007
vor 15 Jahren

Ach so....

Jetzt sehe ich was du willst ^^ ja natürlich gibts das auch so... Man man 😛
Hier viel spass damit! 😄

Gruß Daniel

946 Beiträge seit 2008
vor 15 Jahren

Ein anderer Ansatz wäre in einem Kegel, den man von oben sieht mit dem LinearGradientBrusch die Oberfläche zeichnen (Kegel gibt es z.Bsp. da).

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 15 Jahren

Jetzt sehe ich was du willst ^^ ja natürlich gibts das auch so... Man man 😛

>
viel spass damit! 😄

Ein netter Artikel aber irgendwie finde ich da auch nur Linear- und RadialGradientBrush.

Hab ich was übersehen???

Kegel wäre auch ein Ansatz aber ist 3D für einen einfachen Farbkreis nicht ein Overkill?