Laden...

Transparenz in CustomControl (.NET-Bug?)

Erstellt von mustang-1969 vor 17 Jahren Letzter Beitrag vor 17 Jahren 2.447 Views
M
mustang-1969 Themenstarter:in
27 Beiträge seit 2007
vor 17 Jahren
Transparenz in CustomControl (.NET-Bug?)

Hallo erstmal!

Ich habe ein UserControl mit transparentem Hintergrund und darauf ein in der OnPaint-Methode erstellter Pfeil. Dieses Usercontrol wird zur Laufzeit dynamisch mehrmals in ein Panel geladen.
Die Anzeige ist grundsätzlich korrekt: der Hintergrund ist Transparent und der Pfeil sichtbar.
ABER: Wenn sich zwei dieser UserControls überschneiden ist zwar immernoch der Hintergrund des Panels sichtbar, aber ein Control verdeckt den Pfeil des zweiten darunterliegenden Controls. D.h. die Transparenz bezieht sich darauf, dass der PanelHintergrund immer sichtbar ist, aber nicht ein zweites unter einem Control liegendes Control. Dieses (also die Pfeilreste) sieht man erst außerhalb des darüberliegenden Controls (bzw. des imaginären Randes).

Hab' schon alles im Netz abgesucht, aber nichts dazu gefunden. Rumgespielt mit Opacity - nix.

Folgender Code ist auch eingebaut:


this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

Hilft aber alles nichts!

Hat irgendjemand eine Idee oder geht das grundsätzlich mit UserControls nicht?

Anbei noch ein Screenshot. Ich habe ihn etwas modifiziert:
Das Raster ist der Panelhintergrund.
Der durchgehende Pfeil in der Mitte ist das betreffende obenliegende transparente UserControl. Den roten Rand habe ich jetzt nachträglich eingezeichnet und stellt dessen 'offiziellen' Rand dar.
Darunter liegt ein zweiter UserControl-Pfeil mit gleichem Anfangspunkt. Der gestrichelte Teil fehlt in echt, sollte aber (nach Logik der Transparenz) ebenfalls sichtbar sein.

Grüsse Ralf

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo mustang-1969,

Wenn sich zwei dieser UserControls überschneiden ist zwar immernoch der Hintergrund des Panels sichtbar, aber ein Control verdeckt den Pfeil des zweiten darunterliegenden Controls. D.h. die Transparenz bezieht sich darauf, dass der PanelHintergrund immer sichtbar ist, aber nicht ein zweites unter einem Control liegendes Control.

ja, genau so ist das. Works as designed.

herbivore

M
mustang-1969 Themenstarter:in
27 Beiträge seit 2007
vor 17 Jahren

Hallo herbivore,

ja, genau so ist das. Works as designed.

🙁 Gibt es da einen Workaround?
Einfach so ins Panel zeichnen kann ich nicht. Es müssen Controls sein, da die Pfeile auswählbar sein müssen.

Gruß Ralf

830 Beiträge seit 2005
vor 17 Jahren

Hallo mustang-1969,

schau dir mal die folgenden Eibträge an:

Überlappende Controls & Transparenz

und

Keine echte Transparenz

Gruss
Friedel

Ohne Ziel ist auch der Weg egal.

4.506 Beiträge seit 2004
vor 17 Jahren

Hallo mustang-1969,

Es müssen Controls sein, da die Pfeile auswählbar sein müssen.

Das ist noch kein Kriterium dafür, dass es Controls sein müssen. Ich weiß nicht wie viele Pfeile dargestellt werden müssen, aber das kann schon sehr träge werden, besonders dann, wenn Scrollen hinzukommen sollte.

Es besteht auch die Möglichkeit hier direkt zu zeichnen, und sich jeweils die Positionen der Pfeile zu merken. Bei einem Klick muss man lediglich die Positionen überprüfen und dementsprechend reagieren, um dann neu zeichnen zu lassen.

Dabei kann eine eigene "Pfeil-Klasse" (die nicht von Control abgeleitet ist) auch einen Zustand wie "ausgewählt" besitzen.

Andere Frage: Wenn Du 2 Controls hast, die so wie Du gezeichnet hast sich überlappen, und der Benutzer klickt auf den Überlappenden Bereich, welcher Pfeil wird dann ausgewählt?

Gruß
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

M
mustang-1969 Themenstarter:in
27 Beiträge seit 2007
vor 17 Jahren

@Friedel:

Einen riesen Dank an dich erst mal!!! Es funzt. =)

Folgender Code in OnPaint ergänzt


SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
BackColor = Color.FromArgb(0, 0, 0, 0);

und es geht.

Aber nun habe ich gleich die nächsten Probleme:
1.
Wenn ich meine grüne Balken verschiebe (ebenfalls CustomControls) bleibt der Panel-Hintergrund an der alten Balkenposition solange grau, wie das OnMouseMove-Event wirkt. Erst bei kurzen Pausen wird der Hintergrund neu gezeichnet. Dies hat natürlich sehr häßliche Effekte (siehe Bild).
Wie kann dies vermieden werden?

2.
Auch die Pfeil-Controls, deren OnPaint-Methode durch das Balkenschieben getriggert werden verhalten sich nicht korrekt:


protected override void OnPaintBackground(PaintEventArgs pevent)
{}

verhindert das Neuzeichnen des Backgounds, wodurch teilweise 'alte' Pfeile einfach in der Landschaft stehen bleiben. Mit


protected override void OnPaintBackground(PaintEventArgs pevent)
{
   base.OnPaintBackground(pevent);
}

bleiben keine Pfeile fälschlichweise stehen, aber wie bei (1) bleibt der Background bei OnMove grau bis der Pfeil 'stehen bleibt'.
Wenn ich in die Pfeil-Controls die Clear-Funktion einbaue


public void Clear()
{
   if (Parent == null)
      return;

   Rectangle rc = new Rectangle(this.Location, this.Size);
   Parent.Invalidate(rc, true);
}   

und von außerhalb bei Balken-OnMouseMoves, wo das Neuzeichnen der betreffenden Pfeile mit Pfeil.Invalidate() getriggert wird mit aufrufe, dann flackert der betreffende Bereich.
Lösungsvorschlag?

3.
Das gesamte Raster im zugrunde liegenden Panel wird bei jedem neuzeichnen (Panel_OnPaint()) neu berechnet. Dies ist natürlich performance-mäßig ziemlich schlecht.
Ich denke es wäre eine gute Idee, dass beim ersten Zeichnen des Rasters dieses in ein Image geschoben wird und dann ab dem 2. Neuzeichnen nur mehr das Image neu hinterlegt wird.
Ist dies eine gute Idee und wenn ja wie könnte dies Code-technisch realisiert werden?

@norman_timo
Ich habe deshalb Controls verwendet, da in diesen die Referenzen der benachbarten Balken-Controls mit hinterlegt sind und sich somit der Pfeil beim Triggern des Neuzeichnens alle benötigten Koordinaten 'in sich trägt'. Da ist mir halt im ersten Versuch nix besseres eingefallen.

Aber ich denke, Du hast da ganz recht, dass Controls hier etwas unperformant sind. Das Ganze kann auch in einer Klasse realisiert weredn. Ich habe da was Brauchbares zum Thema RubberBand gefunden und mach mich mal daran, dies auf die Pfeile umzumünzen und die Pfeile direkt ins Panel zu zeichnen. Das größte Problem wird wohl im Merken der Pfeil-Positionen liegen.

Im überlappenden Bereich wird natürlich der 'obere' Pfeil gewählt. Aber egal, welche Technik man verwendet, dieses Problem kommt wohl immer hoch.

Also nochmals Danke an euch beide!

Gruß Ralf