Frage von Appgalaxy, 53

Wie kann man in C# verändern das wenn ich die Form verschiebe sich die Opacity auf 50% stellt?

Antwort
von CrystalixXx, 38

Ich vermute mal, du willst es nur während des Verschiebens auf 50% haben und sonst auf 100%?

Man würde zwar vermuten, das Move-Ereignis wäre geeignet, aber dafür müsstest du noch einiges an Code drum herum packen, um festzustellen, ob die Bewegung beendet wurde. Am einfachsten wären daher die beiden Events ResizeBegin und ResizeEnd.

private void Form1_ResizeBegin(object sender, EventArgs e)
{
this.Opacity = 0.5F;
}

private void Form1_ResizeEnd(object sender, EventArgs e)
{
this.Opacity = 1.0F;
}
Kommentar von KnorxyThieus ,

Hm, das sieht aber für Nutzer blöd aus, die aktiviert haben, beim Verschieben den Fensterinhalt anzuzeigen ... es soll sich doch eigentlich während der Bewegung ändern, oder?

Kommentar von CrystalixXx ,

Mit der Einstellung "Fensterinhalt beim Ziehen anzeigen" ist genau das der Fall.

ResizeBegin-Ereignis wird ausgelöst, sobald mit der Maus auf die Titelleiste geklickt und gehalten wird. Während des Verschiebens ist also die Opacity auf 50% festgelegt. Lässt man die Maus wieder los, wird das ResizeEnd-Ereignis ausgelöst und die Opacity wieder auf 100% festgelegt. (Ich finde ein solches Verhalten sogar sehr schön. Danke an den Fragesteller für die Idee!)

Wenn die Einstellung aber deaktiviert ist und beim Ziehen nur das Auswahlrechteck zu sehen ist, dann sieht es tatsächlich etwas blöd aus. Da könnte man in der Registry nachschauen, ob die Option aktiviert ist und entsprechend die Opacity festlegen - oder eben auch nicht.

Kommentar von CrystalixXx ,

Ich bin gerade zufällig über die Option in SystemInformation gestolpert. Damit entfiele ein Zugriff auf die Registry und eine Fallunterscheidung ist simpel:

private void Form1_ResizeBegin(object sender, EventArgs e)
{
if (SystemInformation.DragFullWindows)
this.Opacity = 0.5F;
}

private void Form1_ResizeEnd(object sender, EventArgs e)
{
this.Opacity = 1.0F;
}
Kommentar von KnorxyThieus ,

Guter Rat!

(Ich liebe C# :). ♥)

Aber ich glaube, die CPU-Belastung wäre doch noch geringer, wenn man gleich beim Ladevorgang im Konstruktor das Event  ResizeBegin += Form1_ResizeBegin an diese Bedingung knüpft bzw. das Event dann gar nicht erst um diese Methode erweitert.

Oder wäre das nicht mehr richtlinienkonform, da der Benutzer ja innerhalb einer Sitzung diese Einstellungen ändern könnte? :-)

MfG

Kommentar von CrystalixXx ,

Von Belastung kann man beim Abrufen der Eigenschaft gar nicht sprechen. Ich habe mal die Zeit gemessen, wie lange es dauert, wenn man die Eigenschaft 100.000 mal abruft.

bool flag;
Stopwatch sw = new Stopwatch();
sw.Start();

for (int i = 0; i < 100000; i++)
flag = SystemInformation.DragFullWindows;

sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds);

Bei mir werden 68 ms ausgegeben. Das fällt beim einmaligen Abrufen überhaupt nicht mehr ins Gewicht. Dann lieber in dem Ereignis stehen lassen, dann macht sich die Änderung der Grafikoption sofort bemerkbar. Aus den Zeiten mit dem "Neustarten, um die Änderungen zu übernehmen" sind wir doch schon lange raus. ; )

Kommentar von KnorxyThieus ,

Stimmt ... :-)

Aber ich frage mich generell, wie sich bei ähnlichen Problemen (schon bedeutender wäre: Wechsel des Visual Styles) der Konflikt zwischen Richtlinien und Geschwindigkeit auflösen lässt. Oder gibt es so eine Art VisualStyleChanged-Event? :)

Kommentar von CrystalixXx ,

Nun ja, ich bin im Bereich der Desktop-Anwendungen tätig und halte mich an die typischen durch das Betriebssystem festgelegten Stile, d.h. also keine Custom-Forms mit eigen definierten Grafiken oder Freiformflächen. Und diese Fensterstile (Verlauf, Breite, Farbe, Transparenz, Blur- und Schatteneffekte etc.) werden vom Betriebssystem vorgegeben, weshalb die Fenster meine Anwendung natürlich auch automatisch durch das OS angepasst werden, wenn solche Einstellungen geändert werden.

Will man aber basierend auf solchen Einstellungen eigene anwendungsweite Stile festlegen, dann sollte man auf die Änderung solcher Einstellungen möglichst schnell reagieren - spätestens aber nach einem Anwendungsneustart. Ich weiß nicht, ob es dafür Richtlinien gibt (aber auch die wären keine Gesetze, sondern eben nur Richtlinien).

Im privaten Bereich ist es vielleicht nicht so relevant, aber in irgendwelchen Betrieben, wo häufig gespart werden muss, kann es schon anstrengend sein, wenn das System auf niedrigen Grafik-Einstellungen läuft, um die Leistung zu optimieren, aber dann eine Anwendung diese Einstellungen ignoriert und immernoch im fetzigen Vista-Design erstrahlt. So zum Beispiel an meinem Arbeitsrechner, der nicht sonderlich leistungsfähig ist und die wenigen Resourcen, die ich woanders gut gebrauchen kann, in die Oberfläche gesteckt werden.

Kommentar von KnorxyThieus ,

Nun ja ... ich meinte eher andersherum ... dass eine Anwendung zu schlechtes Design verwendet.

Wenn ich zum Beispiel irgendeiner Steuerelement per Hand baue oder ein Bild farblich an den Visual Style anpasse (oder gar ein ganzen Iconset), dann kann das Neurendern schon mal ein Weilchen dauern ...

Kommentar von CrystalixXx ,

Ich denke das muss man abwägen. Bei eigenen Steuerelementen kann man schon einiges an Performance rausholen, wenn man die Stile im Konstruktur richtig setzt (z.B. DoubleBuffer für solche, die oft/viel gezeichnet werden). Wenn du außerdem selbst zeichnest, dann hängt auch viel mit deinem Programmcode zusammen.

Ich habe erst vor wenigen Wochen ein Steuerelement erstellt, bei dem ein Bild angegeben und mit verschiedenen Farbeffekten belegt werden kann. Würde man mit GetPixel und SetPixel der Bitmap-Klasse arbeiten, wäre der Aufwand enorm (schon aus Sicht des Programmieraufwands). Die ColorMatrix-Klasse ist dafür geeigneter.

Ansonsten würde ich solche grundlegenden Render-Arbeiten in Renderer-Klassen auslagern und diese über die Programmoptionen für den Benutzer zur Verfügung stellen. Dann darf er auch ruhig mal warten, bis alles neu gerendert ist - wie es eben auch bei Windows ist, wenn ich z.B. das Schema von Aero auf Klassisch stelle.

PS: Zur Not einfach auf eine andere Grafik-Engine umsteigen, anstatt die GDI+ Methoden der Graphics-Klasse zu nutzen. Die TextRenderer-Klasse hingegen nutzt GDI.

Antwort
von KnorxyThieus, 53

Pseudocode:

Im Konstruktor:

WindowMove += (args, ...) => {Opacity = 0.5);

Weiß gerade nicht, die das Event für Fensterbewegung heißt - das kannst du ja googeln, oder du blätterst in VS einfach mal alle Vorschläge unter this. durch. Die Parameter müsstest du dann auch selbst ergänzen.

Keine passende Antwort gefunden?

Fragen Sie die Community