Main Window flackert


CopWorker

Mitglied
Hallo,

meine Anwendung hat den Zweck ein Bild (bmp) als Startbild darzustellen.
Der Einfachheit halber übergebe ich meiner Klasse "WpcStartupView"
C#:
public partial class WpcStarupView : Form
nur eine Bitmap als BackgroundImage.
Erst mache ich die Anweisung über Größe und Style des Fensters:
Auf ganzem Bildschirm und ohne Titelzeile anzeigen.
Dann erzeuge ich ein Image aus einer Bitmap-Datei.
Anschließend weise ich dieses Image dem Background zu mit Angabe der Breite und Höhe.

C#:
//Window an Bildschirm anpassen; Maximiert und ohne Titelzeile
this.WindowState = FormWindowState.Maximized;
this.FormBorderStyle = FormBorderStyle.FixedDialog;
                
//Image von Bitmap Datei erzuegen und Image vom Bitmap auf BackgroundImage skalieren
Image imOldFile = Image.FromFile(strBitmapFilePath);
this.BackgroundImage = new Bitmap(imOldFile, this.Width, this.Height);
Application.DoEvents();
Danach möchte ich noch den Benutzer einige Infos zukommen lassen.
Diese Infos zeige ich mit dem Tool "ErrorProvider" incl. ToolTip oben links neben einem unsichtbaren Steuerelement "Textbox" an.
C#:
epInfo.Icon = Properties.Resources.Check_Good;
epInfo.SetError(lbInfo, "The suitable image was successfully loaded");
Das Unschöne dabei ist, dass die Anzeige in diesem Moment anfängt zu flackern.
Ich nehme an, dass hierbei das Fenster mehrmals hintereinander neu aufgebaut wird.

Ist es möglich diese Flackern zu umgehen.


Vielen Dank für eure Hilfe.

Grüße von CopWorker
 

Spyke

Premium-User
Application.DoEvents nur in wirklich wirklich wirklich wirklich wirklich Ausnahmefällen verwenden.
Mit DoEvents sagst du ja jetzt soll Windows erstmal die ausstehenden Nachrichten verarbeiten.
Dies kann zu häßlichen Fehler führen. Lass das Windows über die normale Nachrichtenschleife steuern.
Wenn du mehrere DoEvents hast könnte dies, ev, eine Ursache für das Flackern sein.

Dann erzeugst du 2 Bitmaps einmal lädst du das Bild aus der Datei und mit diesem Image erzeugst du direkt nochmal ein neues Bitmap für das BackgroudnImage. Warum nicht direkt mit dem ersten Image den Background setzen.
Diese 2 Bitmaps sollten zwar kein flackern verursachen aber könnten bei größeren Bildern ev. auf den Speicher gehen.

Und zu guter letzt, wo setzt du die ganzen Sachen, direkt im Konstruktor deines Forms oder woanders (vermute mal woanders)?
 

CopWorker

Mitglied
Hallo Spyke,

ohne Application.DoEvents();
flackert das Bild gefühlt 20 mal.
mit Application.DoEvents();
flackert das Bild gefühlt 5 mal.

Des Weiteren:

Warum nicht direkt mit dem ersten Image den Background setzen.
Beim ersten Erzeugen eines Image kann ich die Größe vom Window Fensters noch nicht einstellen.
C#:
Image imOldFile = Image.FromFile(strBitmapFilePath);
Wie soll ich sonst da Image auf die richtige Größe bringen?

MfG.
CopWorker
 

Spyke

Premium-User
zur Größe des Bildes:
die Größenänderung hatte ich übersehen, aber hast du schonmal
BackgroundImageLayout = ImageLayout.Stretch
probiert?

zum flackern:
wo führst du den ganzen Code aus?
was du noch probieren könntest vor deinem ganzen Code folgendes aufrufen:
SuspendLayout()
und am Ende deines Codes
ResumeLayout()
Control.SuspendLayout Method (System.Windows.Forms)
 

CopWorker

Mitglied
Hallo Spyke,
den Code führe im "Load" - Event aus.

Zu folgendem muss ich dir leider mitteilen....
die Größenänderung hatte ich übersehen, aber hast du schonmal
BackgroundImageLayout = ImageLayout.Stretch
....es flackert noch viel heftiger.

Nachfolgende Tipps probier ich dann bei Gelegenheit aus, aber heute noch.
Vielen Dank für die Hilfe.
Grüße von CopWorker
 

Spyke

Premium-User
Weiß zwar nicht obs was bringt aber probiers mal ganz blöd anstatt im Load im Shown.
Sprich wenns dann wirklich zur Anzeige kommt.
 

Spyke

Premium-User
Im übrigen zum DoEvents, hatte gestern ein Problem da ruft eine dritte Componente DoEvents auf was meine standard Nachrichten schleife komplett zerhaut und ich ne Exception bekam.
Als Workaround musste ich nen kleinen Delay einbauen beim anstoßen der dritt Componente damit meine Standardabläufe erstmal normal abgearbeitet werden können.
(Muss aber sagen war ein WinForms Control welches ich aus WPF heraus anstoßen musste)

Deshalb nach Möglichkeit DoEvents immer vermeiden ;-)
 

CopWorker

Mitglied
Hallo Spyke,

perfekt, man sieht nur noch wie das Hintergrundbild einmal aufgebaut wird.
Das darf so sein, es ist eine mega große Bitmap die ich verwenden muss.

Es hat anscheinend ausgereicht, das "ErrorProvider" Steuerelement in das
"Show" Event zu verschieben.
C#:
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void WpcStarupView_Shown(object sender, EventArgs e)
{
    if (_BLoadImage)
    {
        if (mySettings.Get("ShowErrorInfoGood"))
        {
            epInfo.Icon = Properties.Resources.Check_Good;
            epInfo.SetError(lbInfo, "The suitable image was successfully loaded".ToString());
        }
    }
    else
    {
        if (mySettings.Get("ShowErrorInfoBad"))
        {
            if (string.IsNullOrEmpty(_strMsg)) _strMsg = "Error: Message is missing!".ToString();
            epInfo.Icon = Properties.Resources.Check_Bad;
            epInfo.SetError(lbInfo, _strMsg);
        }
    }
}
Vielen Dank dafür.
Wenn nur alles so einfach lösbar wäre.

Grüße von CopWorker
 

Spyke

Premium-User
Kleine Anmekrung:
Das ToString bei
"The suitable image was successfully loaded"
und
"Error: Message is missing!"
brauchst du nicht, es sind ja schon strings.
 

CopWorker

Mitglied
Hallo Spyke,

das weiß ich wohl, darin steckt auch noch ein Problem.
Bei diesem String handelt es sich um den Text, welcher im ErrorProvider im ToolTip ausgegeben wird.
Ohne ".ToString()" sieht der Inhalt des ToolTip wie folgt aus:
C#:
epInfo.SetError(lbInfo, "Error: Message is missing!");
Ausgabe--> !Error: Message is missing

Des letzte Zeichen vom String wird immer am Anfang ausgegeben.
Warum ist mir ein Rätsel.
Ich habe den hart codierten String auch über eine Variable vom Typ "string" übergeben.
Mit ".ToString()" erfolgt die Ausgabe korrekt.

Kapute Welt irgendwie.

Der Rest läuft wunderbar.
Wenn du noch ein Tipp für mich hast, gerne jederzeit.

Grüße von CopWorker
 

Spyke

Premium-User
Ich würde vermuten in deinem ersten Test hast du das Ausrufezeichen einfach vorne gehabt.
Auch wenn du dir die ToString Methode von String anschaust, da passiert nixs, er gibt sich selbst zurück.
C#:
public override string ToString()
{
    return this;
}
Es gibt so paar special sachen wie string gelesen werden sollen aber die finden sich eher in der C++ Welt.

Habs auch mal schnell nachgestellt, das verhalten hab ich auch nicht das Ausrufezeichen plötzlich vorne ist.
Ich vermute mal war ein kleiner Tippfehler.
 

Spyke

Premium-User
Dein Code machst du ja direkt in deinem WpcStarupView Form oder?
Dann musst du das Ereignis Load oder Shown nicht abonnieren.
Bei Microsoft gibt es eigentlich standardmäßig zu jedem Ereignis eine entsprechende On Methode.
In deinem Beispiel OnLoad und OnShown, von dennen könntest du direkt ableiten und dein Code rein packen.

z.B.:
C#:
protected override void OnShown(EventArgs e)
{
    if (_BLoadImage)
    {
        if (mySettings.Get("ShowErrorInfoGood"))
        {
            epInfo.Icon = Properties.Resources.Check_Good;
            epInfo.SetError(lbInfo, "The suitable image was successfully loaded".ToString());
        }
    }
    else
    {
        if (mySettings.Get("ShowErrorInfoBad"))
        {
            if (string.IsNullOrEmpty(_strMsg)) _strMsg = "Error: Message is missing!".ToString();
            epInfo.Icon = Properties.Resources.Check_Bad;
            epInfo.SetError(lbInfo, _strMsg);
        }
    }
    
    
    base.OnShown(e); //<--- wichtig weiterlaufen lassen damit andere, die das Form außerhalb verwenden, das Ereignis abonnieren/abfragen können
}
 

CopWorker

Mitglied
Hallo Spyke,

das habe ich jetzt so in meinen Code implementiert.
Verhält sich aber leider gleich, was den korrupten String anbetrifft.

Die Message stelle ich so zusammen:
C#:
_strMsg = string.Format("Current language \"{0}\" is faulty or not in list of \"*.ini\"", strCurrentLang);
Im ToolTip vom "ErrorPovider" erscheint die Message so:
"Current language "FRE" is faulty or not in list of "*.ini"

Ich vermute die Methode "Format" der String-Klasse kommt mit der
Escape-Sequenz am Ende des Strings nicht klar.
Füge ich noch mind. 1 Zeichen hinten an, dann funktioniert alles richtig
C#:
_strMsg = string.Format("Current language \"{0}\" is faulty or not in list of \"*.ini\" file", strCurrentLang);
Im ToolTip vom "ErrorPovider" erscheint die Message so:
Current language "FRE" is faulty or not in list of "*.ini" file

So mach ich das.
Trotzdem noch vielen Dank.

Ach übrigens, kennst du dich mit "BackgroundWorker" aus?
Der scheint bei mit überhaupt keine Wirkung zu zeigen.

Grüße von CopWorker