C# WPF RichTextBox: Wie komm ich an den formatierten Text?

UID0

Lt. Commander
Registriert
Juli 2010
Beiträge
1.049
Hallo,
ich habe ein Program, dass Text, Bilder und andere Dateien verschlüsselt. Dazu gehört auch eine richTextBox, in der Text geschrieben und formatiert werden kann:

Code:
public string GetText(System.Windows.Documents.FlowDocument document)
            {
                return new TextRange(document.ContentStart, document.ContentEnd).Text;
            }

            public void SetText(System.Windows.Documents.FlowDocument document, string text)
            {
                new TextRange(document.ContentStart, document.ContentEnd).Text = text;
            }
        public void Encrypt(string Key, string path)
        {
            byte[] dt;
            richTextBox1.SelectAll();
            dt = Encoding.UTF8.GetBytes(GetText(richTextBox1.Document));

            Rijndael ri = Rijndael.Create();
            byte[] tb2 = Encoding.UTF8.GetBytes(Key);
            ri.IV = *******;
            ri.Key = *******;

            File.Delete(path);
            FileStream mem = new FileStream(path, FileMode.CreateNew);

            CryptoStream stream = new CryptoStream(mem, ri.CreateEncryptor(ri.Key, ri.IV), CryptoStreamMode.Write);
            StreamWriter SW = new StreamWriter(stream);
            SW.Write(Encoding.UTF8.GetString(dt));
            SW.Close();
            SW.Dispose();
            mem.Close();

        }
        public void Decrypt(string path, string Key)
        {
            byte[] dt;
            dt = File.ReadAllBytes(path);

            Rijndael ri = Rijndael.Create();
            byte[] tb2 = Encoding.UTF8.GetBytes(Key);
            ri.IV = *******;
            ri.Key = *******;

            MemoryStream mem = new MemoryStream(dt, true);

            CryptoStream stream = new CryptoStream(mem, ri.CreateDecryptor(ri.Key, ri.IV), CryptoStreamMode.Read);
            StreamReader SR = new StreamReader(stream);

            richTextBox1.SelectAll();
            SetText(richTextBox1.Document,SR.ReadToEnd());

            SR.Close();
            stream.Flush();
            mem.Close();
        }
Alles läuft in WPF. Mittlerweile habe ich schon das extendedWPF Toolkit benutzt, jedoch finde ich dort auch nichts, mit dem ich den Text (bevorzugt im richText Format), formatiert speichern kann.
Ich hoffe mir kann jemand helfen.:) Alle Google Anleitungen haben entweder nicht funktioniert, oder sie waren zu kompliziert. :(

PS: In Windows Forms hats ganz einfach mit dem .rtf funktioniert. Warum ist das in WPF so kompliziert?!?:(
Ergänzung ()

Keiner eine Idee?:(
 
Wie bekomme ich dann das was ausgegeben wurde ohne das es dazwischen irgendwo gespeichert wurde (Aufgrund der Sicherheit) zu einem String, welchen ich wieder verschlüsseln kann. Und wie bekomme ich nachdem dieser String wieder entschlüsselt wurde, ihn in ein Flowdocument?
 
Kannst du der TextRange.Save() Methode nicht den Crypot-Stream übergeben? Und das gleiche auch mit Load?
 
Dann habe ich doch aber nur den Text ohne Formatierungen. Nur Text habe ich schon hinbekommen. Ich brauche aber auch noch die Formatierungen. Und da komme ich nicht weiter. Dort fehlt mir das .rtf der Forms RTB.
 
Wenn du DataFormats.Rtf als zweites Argument angibst, bekommst du doch auch die Formatierungen, siehe meinen geposteten Link.
 
Ich versuchs mal, aber ich könnte meinen, ich hab das auch shconmal versucht. naja ich versuchs mal. :)
 
Ich hab jetzt folgendes:
Code:
public void Encrypt(string Key, string path)
        {
            SHA256 sha = SHA256.Create();
            Rijndael ri = Rijndael.Create();
            ri.BlockSize = 256;

            ri.IV = sha.ComputeHash(ivhash(Key));
            ri.Key = sha.ComputeHash(UTF8Encoding.UTF8.GetBytes(UTF8Encoding.UTF8.GetString(keyhash(UTF8Encoding.UTF8.GetString(ivhash(Key))))));

            File.Delete(path);
            FileStream mem = new FileStream(path, FileMode.CreateNew);
            CryptoStream stream = new CryptoStream(mem, ri.CreateEncryptor(ri.Key, ri.IV), CryptoStreamMode.Write);

            TextRange range = new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd);

            range.Save(stream, DataFormats.Rtf);

            stream.Flush();
            mem.Close();
        }
        public void Decrypt(string path, string Key)
        {
            FileStream fil = new FileStream(path, FileMode.Open, FileAccess.Read);
            byte[] dt = new byte[fil.Length];
            fil.Read(dt, 0, Convert.ToInt32(fil.Length));
            SHA256 sha = SHA256.Create();
            Rijndael ri = Rijndael.Create();
            ri.BlockSize = 256;

            ri.IV = sha.ComputeHash(ivhash(Key));
            ri.Key = sha.ComputeHash(UTF8Encoding.UTF8.GetBytes(UTF8Encoding.UTF8.GetString(keyhash(UTF8Encoding.UTF8.GetString(ivhash(Key))))));


            MemoryStream mem2 = new MemoryStream();
            MemoryStream mem3 = new MemoryStream();
            CryptoStream stream = new CryptoStream(mem3, ri.CreateDecryptor(ri.Key, ri.IV), CryptoStreamMode.Write);

            stream.Write(dt, 0, dt.Length);

            StreamReader SR = new StreamReader(mem3);
            TextRange range = new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd);
            mem3.Write(UTF8Encoding.UTF8.GetBytes(SR.ReadToEnd()), 0, UTF8Encoding.UTF8.GetBytes(SR.ReadToEnd()).Length);
            range.Load(mem3, DataFormats.Rtf);
            SR.Close();
        }

Jedoch bekomme ich, wenn ich meine richTextBox reinschreibe:

das zurück:
Chriss 000 <- die Null(letztes Zeichen) wird nicht formatiert.

Das heißt, es wird immer das letzte Zeichen nicht formatiert. Woran liegt es?:)
 
Du kannst das FlowDocument mit einem XamlWriter in einen string schreiben, verschlüsseln und dann speichern. Laden kannst du es dann via XamlReader.

Code:
string toEncrypt = XamlWriter.Save( richTextBox1.Document );
...
FlowDocument doc = XamlReader.Load( fromDecryptedStream ) as FlowDocument;
if ( doc == null ) { ... }
richTextBox1.Document = doc;
 
oder so:
----------

public static string CreateFormatedString(FlowDocument flowDoc, string dataFormats, Encoding byteEncoding)
{
StringBuilder resultBuilder = new StringBuilder();
TextRange range = new TextRange(flowDoc.ContentStart, flowDoc.ContentEnd);
MemoryStream memory = new MemoryStream();
try
{
range.Save(memory, dataFormats);
memory.Seek(0, SeekOrigin.Begin);
byte[] buffer = new byte[8192];
int length = memory.Read(buffer, 0, buffer.Length);
while (length > 0)
{
resultBuilder.Append(byteEncoding.GetString(buffer, 0, length));
length = memory.Read(buffer, 0, buffer.Length);
}
}
catch (Exception exception)
{
throw new Exception("HIER DEINE EIGENE FEHLERMELDUNG EINTRAGEN",exception);
}
finally
{
memory.Close();
}
return resultBuilder.ToString();
}
 
@awez:
Deine Methode finde ich etwas kompliziert. :rolleyes: Ich nehme lieber die von holy.;)

Das ist der momentane Decrypt - Teil:
Code:
public void Decrypt(string path, string Key)
        {
            FileStream fil = new FileStream(path, FileMode.Open, FileAccess.Read);
            byte[] dt = new byte[fil.Length];
            fil.Read(dt, 0, Convert.ToInt32(fil.Length));
            SHA256 sha = SHA256.Create();
            Rijndael ri = Rijndael.Create();
            ri.BlockSize = 256;

            ri.IV = sha.ComputeHash(ivhash(Key));
            ri.Key = sha.ComputeHash(UTF8Encoding.UTF8.GetBytes(UTF8Encoding.UTF8.GetString(keyhash(UTF8Encoding.UTF8.GetString(ivhash(Key))))));


            MemoryStream mem2 = new MemoryStream();
            MemoryStream mem3 = new MemoryStream();
            CryptoStream stream = new CryptoStream(mem3, ri.CreateDecryptor(ri.Key, ri.IV), CryptoStreamMode.Write);

            stream.Write(dt, 0, dt.Length);

            FlowDocument doc = XamlReader.Load(mem3) as FlowDocument;
            richTextBox1.Document = doc;
        }

Nun gibt er mir bei
FlowDocument doc = XamlReader.Load(mem3) as FlowDocument;
diese Fehlermeldung aus: "Das Stammelement ist nicht vorhanden."
Was ist falsch? Wüsste nicht, woran es liegt.:)
 
Hm, anscheinend mag er den MemoryStream nicht :)

Code:
byte[] data = mem3.GetBuffer();
string xaml = Encoding.UTF8.GetString( data );
FlowDocument doc = XamlReader.Parse( xaml ) as FlowDocument;
// error handling...
richTextBox1.Document = doc;

Naja, debuggen und MSDN lesen lernst du sicher noch.
Und wenn wir schon beim belehren sind, gewöhn dir bitte an, deine Streams gescheit zu schließen und vor Allem try-catch-finally drum rum zu bauen ;)

Edit/Ergänzung.
Der XamlReader kann auch eine Exception werfen, wenn der string kein gültiges Xaml ist. Der Safe-Cast verhindert das nicht.
 
Zuletzt bearbeitet: (Ergänzung...)
MSDN lesen versuche ich schon, nur meistens ist es dort etwas kompliziert erklärt. ;)
Try - Catch hätte ich auch noch drumherum gebaut, nur wollte ich ja sehen, was nicht funktioniert. :)
Ich versuche mal das mit dem bytearray.

EDIT: Er zeigt mir nun immer diesen Fehler an:
'.', hexidezimaler Wert 0x00, ist ein ungültiges Zeichen. Zeile 1, Position 193.

Er ließt nur den Xaml String aus. Er sieht so aus:
<FlowDocument PagePadding="5,0,5,0" AllowDrop="True" NumberSubstitution.CultureSource="User" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Paragraph><Run xml:lang="de-de">
Ich glaube, da fehlen im String die "/>" und der Text.
 
Zuletzt bearbeitet:
Mein Fehler, sorry.
Als ich den Code getestet habe, habe ich ein anderes Encoding als du verwendet.
Du musst von UTF8 auf Unicode (UTF16) wechseln.

Frag mich bitte nicht warum, wahrscheinlich weil MS es als Standard benutzt, musst du es auch :p
 
Ok, ich versuchs gleich. :)
 
Zuletzt bearbeitet:
Habs grad nochmal im MSDN nachgelesen.
Wenn du den String parst, wird intern ein StreamReader erzeugt und dann XamlReader.Load aufgerufen. Der StreamReader verwendet aber per default UTF16. Vermute da liegt der Fehler.

Falls du weiterhin UTF8 verwenden möchtest, reicht es wahrscheinlich einfach selber nen UTF8 StreamReader zu erzeugen und dann XamlReader.Load anstelle von Parse zu verwenden.
 
Von UTF8 zu UTF16 gibt es aber so gut wie keine Einbußen oder?
 
Laut MS ist UTF8 schneller, kann aber im worst case 3 byte belegen (UTF16 2 byte).
Von der Darstellung bekommst du keine Probleme.
 
Habe es nun in Unicode umgeändert:
Code:
......
            byte[] data = mem3.GetBuffer();
            string xaml = Encoding.Unicode.GetString(data);
            FlowDocument doc = XamlReader.Parse(xaml) as FlowDocument;
            richTextBox1.Document = doc;
        }

Nun erhalte ich beim lesen folgenden Fehler:
Unerwartetes Ende der Datei bei der Syntaxanalyse von Name. Zeile 1, Position 209.

Warum wurde das so kompliziert gemacht? In Forms war das so einfach. Ich hätte ich weiterhin Forms genommen, jedoch finde ich WPF schöner und besser gestaltbar (dient ja auch dazu ;)).
 
Im Grunde ist es nicht sonderlich kompliziert :D

Du musst alles auf Unicode umstellen, nicht nur die eine Zeile :p
 
Zurück
Oben