C# Controls übereinander legen

Fou-Lu

Lt. Junior Grade
Registriert
Aug. 2006
Beiträge
290
Hallo Leute,
tut mir leid, wenn ich euch mit so ner (mehr oder weniger) Noob-Frage störe, aber irgendwie komm ich da nicht ganz dahinter. :(

Also folgende Situation: Ich habe eine Form (Hauptformular), in dieser Form befindet sich eine Picturebox (Dock: Fill - also die ist immer auf die ganze Größe des Formulars ausgebreitet). Außerdem hab ich ein Benutzerdefiniertes Panel mit einem Transparenten hintergrund. Als Background-Image wird ein PNG Bild hergenohmen.

Nun will ich dass das benutzerdefinierte Control ÜBER der Picturebox angezeigt wird, aber irgendwie happert es an dieser Stelle. Zwar wird im Designer das Control oben angezeigt, aber wenn ich es ausführe das ganze, dann überblendet die Picturebox mein Panel.

Ich habe auch bereits versucht das Panel der Picturebox als Childcontrol zuzuweisen. In diesem Fall wirds auch richtig angezeigt, aber da die Picturebox mehrmals in der Sekunde refreshed wird, zeichnet sich auch das Panel neu. Solls aber nicht außerdem wirkt sich das ja negativ auf die Performance aus.


Die Frage also: Wie kann ich es so anstellen, dass das benutzerdefinierte Panel über der Picturebox angezeigt wird, aber die Form als Parentelement hat?

PS: Mir ist auch aufgefallen, dass wenn ich das Fenster kurz außerhalb des WorkingArea schiebe und zurück, dann wird das Panel kurz eingeblendet und dann wieder überblendet von der Picturebox.
 
Hmmm... also in der Dokumentgliederung wirds eigentlich richtig angezeigt:

PHP:
-> Form
  -> myControl
  -> picturebox
Ergänzung ()

Hmm... jetzt ist mir grad auch aufgefallen, dass wenn ich mit der Maus über den Bereich des Panels bewege, dann wirds auch kurz ein- und wieder ausgeblendet.

EDIT: bzw. nicht direkt beim Bereich des Panels sondern wenn ich über den Bereich des Buttons IM PANEL bewege. Dann tritt der Effekt auf.
 
Zuletzt bearbeitet:
Kann es sein, dass du einfach nur wegen dem transparenten Hintergrund wieder auf dein Bild schaust?

Reagierst du auf irgendwelche Events die das Verhalten auslösen?
 
Nein bis jetzt noch nicht. Events sind zwar geplant, aber so weit bin ich noch nicht gekommen.

Naja wenn es am Transparenten hintergrund liegen würde, dann müsste ich ja wenigstens den Button sehen können der sich im Panel befindet. Aber der verschwindet genauso wie das Hintergrundbild bzw. das ganze Panel.

Wenn ich die Form jedoch dazubringe das Panel neuzuzeichnen (die Form außerhalb des Bildschirms schieben und wieder zurück), dann sieht man es kurz.
 
Screenshots ist schlecht (vom laufenden Programm) da ich das ganze im richtigen Moment erwischen müsste und der ist nur paar Millisekunden lang :D

Kann aber vom Designer mal paar Screens reinstellen.

So wie im Designer solls auch während der Laufzeit aussehen, aber es wird einfach von der PB überblendet und nur dann kurz angezeigt wenn ich mit der Maus über den Button fahre. In diesem Fall wird aber auch das Hintergrundbild vom Panel nicht angezeigt sondern nur der Button danach verschwindet der wieder.
Ergänzung ()

BringToFront() bringt leider auch nichts.
Ergänzung ()

Hier wäre noch der Quellcode von dem Control:

PHP:
using System;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace TEST {
	public abstract class DrawingArea : Panel {
		protected Graphics graphics;

		abstract protected void OnDraw();

		protected void DrawText(string text, Point position) {
			DrawingArea.DrawText(this.graphics, text, "Microsoft Sans Serif", 8.25f, 
				FontStyle.Regular, Brushes.Black, position);
		}

		static public void DrawText(Graphics graphics, string text, string fontFamily, 
			float fontSize, FontStyle style, Brush color, Point position) {
			Font font = new Font(fontFamily, fontSize, style);

			SizeF textSizeF = graphics.MeasureString(text, font);
			int width = (int)Math.Ceiling(textSizeF.Width);
			int height = (int)Math.Ceiling(textSizeF.Height);
			Size textSize = new Size(width, height);
			Rectangle rectangle = new Rectangle(position, textSize);

			graphics.DrawString(text, font, color, rectangle);
		}

		protected override CreateParams CreateParams {
			get {
				CreateParams cp = base.CreateParams;
				cp.ExStyle |= 0x00000020;

				return cp;
			}
		}

		protected override void OnPaintBackground(PaintEventArgs e) {
		}

		protected override void OnPaint(PaintEventArgs e) {
			this.graphics = e.Graphics;

			this.graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
			this.graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
			this.graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
			this.graphics.SmoothingMode = SmoothingMode.HighQuality;

			OnDraw();
		}
	}
}

Das war jetzt der Quellcode von dem Control das vom Panel erbt und für einen Transparenten Hintergrund sorgt.

Das hier ist der Quellcode von dem Control das in den Designer eingefügt wird und vom oberen Control erbt:

PHP:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TEST {
	public partial class MenuControl : DrawingArea {
		public MenuControl() {
			InitializeComponent();
		}

		protected override void OnDraw() {
			Image img = global::Viewer.Properties.Resources.test;

			Rectangle rect = new Rectangle(0, 0, img.Width, img.Height);

			this.graphics.DrawImage(img, rect);
		}
	}
}
Ergänzung ()

Das Ganze habe ich übrigens aus diesem Tutorial (http://www.codeproject.com/KB/dotnet/transparent_controls_net.aspx) , aber beim Vergleich fällt mir echt nichts auf. Ist eigentlich alles genauso gemacht wie dort beschrieben.
Ergänzung ()

Also langsam glaube ich, dass es irgendwie an der DrawingArea Klasse liegt die direkt vom Panel erbt. Irgendwas scheint bei Ihr nicht zu stimmen.

Leider hab ich aber immernoch keine Lösung.
 

Anhänge

  • screenshot.jpg
    screenshot.jpg
    50 KB · Aufrufe: 416
Zuletzt bearbeitet:
was genau bezweckst du damit? Willst du einen Eigenen Layout für das Fenster haben?
 
@MarcBomber: gute Idee. Werd ich gleich mal ausprobieren

@roker002: Ich will einen komplett Transparenten Hintergrund haben bei meinem benutzerdefinierten Panel. Wenn du einfach nur Backgroundcolor: Transparent stellst, dann ist es trotzdem keine echte Transparenz. Wenn du nämlich das Control über ein anderes legst, dann sieht man durchaus die Umrisse und den Background von deinem "quasi-transparenten" Control.

Das benutzerdefinierte Control das vom Panel erbt, beugt aber genau dem vor. Es ist zu 100 % Transparent.

Ein eigenes Layout für das ganze Fenster zu nennen ist evtl. bisschen übertrieben. Es ist so, dass der Inhalt der PB sich stets ändert. Was anderes anzeigt und ich eben eine kleine "Menüleiste" mit einigen Buttons haben will die sich aus- und einblendet wenn man drüber fährt (da dort Funktionen für die PB versteckt sein sollen). Diese Menüleiste soll natürlich eine eigene Form besitzen. Nicht irgendwie ein plumpes Rechteck sein sondern etwas ausgefalleneres (dafür müsste aber der Hintergrund des Panels - der Menüleiste - transparent sein und transparente PNGs unterstützen) :)
Ergänzung ()

@MarcBomber: Also ich habs ausprobiert und dabei ist mir gekommen, dass es bei der ganzen Sache einen kleinen Denkfehler gibt. Wenn ich die PB und mein Control jeweils in Panels packe, dann steh ich wieder genau dort wo ich angefangen habe. Und zwar, dass der Hintergrund vom Panel mit meinem Control NICHT "transparent" ist!!

Dabei ist die Transparenz überhaupt erst der Grund wieso ich ein benutzerdefiniertes Control erstelle :D

Nun den... dann muss ich wohl weiterhin nach der Ursache suchen wieso es stets überblendet wird. Falls jemandem was einfällt, dann würde ich mich über eine Lösung freuen. Falls ich doch selber eine finden sollte, dann werd ichs hier posten.
Ergänzung ()

Also langsam gehts echt auf den Nerv :mad:

Ich verstehe einfach nicht, wieso ich das Steuerelement jedes mal aufs neue Zeichnen muss, damit es eingeblendet wird, wenn sich der Inhalt der PB ändert.

Das Problem ist, dass sich der Inhalt der PB in einer Schleife zig mal in der Sekunde ändert. Sprich jedes mal wenn ich PB.refresh aufrufe müsste ich auch CONTROL.refresh aufrufen. Das kostet aber Performance außerdem flackert es ständig.

Hat wirklich niemand mehr nen Tipp/Lösung?? Wäre sehr dankbar für.
Ergänzung ()

Ok... ich komme zwar der Rätselslösung näher, aber wie ich das ganze lösen soll, dass mir der Transparente Hintergrund bleibt weiß ich dennoch nicht. Trotzdem kann ich nun mit 100 %iger Sicherheit sagen, dass es an der "CreateParams" Methode in der DrawingArea-Klasse liegt.

Werd hier mal bisschen weiterhin experimentieren und vielleicht wirds ja noch was (was ich jedoch nicht denke :D ).
 
Zuletzt bearbeitet:
Falls du es hin bekommst, gib Bescheid wie.
Wenn jemand mit der Suchfunktion den Thread findet, ist die Person bestimmt dankbar :)
 
kannst du dein projekt mal hochladen und nen download link bereitstellen?
 
Könnte ja mal den Teil mit dem Panel auslagern und Uppen. Das ganze Projekt wird nämlich nichts nützen, da es in mehrere Teile aufgeteilt ist und die Images, die in der PB angezeigt werden, übers Netzwerk erhält. Man könnte sich das als eine Art Streaming vorstellen =)

Dauert paar min bis ichs geuppt hab ;-)


EDIT: Ok im Anhang ist das ausgelagerte Projekt mit den Controls und fast dem exakten Aufbau wie bei mir im Projekt. Das einzige was fehlt ist nur eine Schleife (oder ähnliches) das in einem anderen Thread über Delagates die Bilder in der Picturebox auswechselt.

Wie gesagt werden bei mir die Bilder übers Netzwerk empfangen (in einem separaten Thread) und dann einfach nur per "pbImage.Image = img;" ersetzt. Man könnte aber auch genauso gut zum testen nen lokalen Ordner mit mehreren Bildern nehmen und die Bilder in einer Endlosschleife stets der PB zuweisen =)
 

Anhänge

Zuletzt bearbeitet:
Ok werds mir danach bei gelegenheit mal anschaun und debuggen
vllt find ich ja den fehler ;P
 
Ach ja... ich bin immerhin soweit, dass ich sicher sagen kann, dass dieses ständige überblenden/ausblenden des Panels an der "cp.ExStyle = 0x00000020" Eigenschaft (in der DrawingArea-Klasse in der CreateParams-Methode) liegt. Kommentiere ich diese Zeile aus wirds ganz normal gezeichnet, aber dafür auch ohne Transparenten Hintergrund :(
 
Gibts einen Grund warum du Windows Forms verwendest und nicht WPF? (mal so am Rande)
Hab jetzt nicht alle gelesen, aber Gerade wenns um transparenz o.ä. geht will ich nicht auf WPF verzichten wollen.
 
Zuletzt bearbeitet:
Ja weil die Anwendung unter WinXP hauptsächlich laufen soll ohne irgendwelche zusätzlichen Frameworks oder so nach zu installieren. Meines Wissens aber muss man WPF unter WinXP nachinstallieren. Bei Vista und Seven ists ja von Haus aus dabei.

(Bitte korrigieren wenn ich mich irre :) )
 
Naja "WPF nachinstallieren" ist vllt. der falsche Ausdruck. Man brauch halt die aktuelle Version des .NET Frameworks. Sonst nichts.
 
Zuletzt bearbeitet:
Ach so... nagut dass ist wieder was anderes :) Framework 4.0 wird man nämlich so oder so installieren müssen. Aber ich hab irgendwo gelesen, dass man neben dem Framework 4.0 irgendwie noch das Framework für WPF nebenbei installieren muss.

In diesem Fall sieht die Sache wieder ganz anders aus, aber ich muss mal prüfen wie Groß der Aufwand ist wenn ich jetzt alles auf WPF umstelle. Ich hab nämlich insgesamt ein doch etwas größeres Projekt und in WPF müsste ich mich erst einarbeiten.

PS: Im Anhang ist jetzt mal die Version meines ausgelagerten Projekts bei der die Schleife und der Thread für den Bildwechsel bereits drin sind. Man muss nur den Ordner mit den Bildern angeben sonst nichts. Auch hier tritt der Effekt wieder auf, dass das benutzerdefinierte Panel überblendet wird von den Pics.
Ergänzung ()

Ich würde es aber in jedem Fall trotzdem gerne diese Variante mit WinForms zum laufen bringen.
 

Anhänge

Zurück
Oben