Laden...

Forenbeiträge von SirSydom Ingesamt 141 Beiträge

08.05.2012 - 10:26 Uhr

Hallo zusammen,

im voraus mein Setup:

  • Applikation für eine ganze Reihe von User, MSI-Setup mit WIX erstellt
  • Verteilung über Webseite mit Downloadmöglichkeit
  • AutoUpdate über Funktion in Programm, dass eine XML-Seite auf der Webseite lädt und dann ggf. sich selbst beendet und eine MSI-Datei lädt uns ausführt

Problem:
Beim Laden und Installieren von der Webseite wird die MSI in den Temporary Internet Files abgelegt.
Beim Update (hier wird ja erst die alte Version deinstalliert) oder Deinstallation kommt es nun manchmal dazu, dass die MSI nicht mehr in den Temporary Internet Files liegt. Der Installer fordert dann erst auf den Pfad zur "alten" MSI nochmal anzuegeben.

Wie kann ich dass denn verhindern? Das gefällt mir überhaupt nicht.

23.01.2012 - 15:08 Uhr

Hallo Leute,

um aus meiner .Net 2.0 Anwendung PDF-Reports (Tabellen mit Text, Kopf- und Fußzeilen) zu erstellen, nutze ich derzeit PDFSharp und MigraDoc.

Leider stoße ich dabei an zwei Stellen auf unlösbare Probleme:
Zum Einen unterstützt PDFSharp keine chinesischen Zeichen zum Anderen werden Tabellen-Zeilen am Seitenende nicht umgebrochen.

Welche Library, die gerne auch kommerziell sein darf, könnt ihr mir empfehlen die meinen Anforderungen genügt?

Gruß
SirSydom

02.08.2011 - 10:14 Uhr

schon mal was von subqueries gehört?

02.08.2011 - 09:58 Uhr

verwendetes Datenbanksystem: <MS Jet (Access 2000)>

Hi,

ich benutzte eine C# WinForms GUI um auf eine MS JET DB zuzugreifen.
Die GUI soll um eine Funktion erweitert werden, die die Erstellung beliebiger, benutzerspezifischen Abfragen (und anschließend den Export in Excel) ermöglicht.

Es soll aber nur ein lesender, kein schreibender Zugriff möglich sein.

Bisher benutze ich OleDBDataAdapter und fülle damit eine DataTable.

Wie kann ich sicher und möglichst einfach der eingegebenen SQL-String überprüfen, ob dieser tatsächlich nur lesend zugreift?

16.09.2010 - 12:13 Uhr

Hallo,

ich habe eine C# .Net Applikation mit der ich über OLEDB eine bestehende Excel-Tabelle (mit Excel 2003 erstellt) befülle.
Insert, Update über OLEDBCommand - das funktinoniert soweit gut. Das Ganze läuft in einem Backgroundworker ab.

Jetzt kommt es bei großen Datenmengen vor, dass nachdem der Backgroundworker zurückkommt und die OLEDBConnection auch sauber geschlossen wurde, dass ich die Datei mit Exel nicht öffnen kann. Fehlermeldung: "Zugriff auf Datei.xls verweigert". Erst nachdem ich die gesamte Applikation geschlossen habe, kann ich die Datei mit Excel öffnen. Nebenbei fällt mir dabei auf, dass die Dateigröße der XLS-Datei sich erst beim schließen der C# Applikation verändert.

Sind es 10-20 Zeilen, kommt das nicht vor. Bei >100 praktisch immer, es gibt aber keine exakte Grenze..

Was kann denn das sein?

16.08.2010 - 16:32 Uhr

Hallo zusammen,

Grob zusammengefasst: In einer C# .Net 2.0 Applikation (DB-Frontend für eine Access-DB) habe ich eine Export in ein Word-Format realisiert.

Ich weiß, das klingt gruslig, aber es gibt halt Rahmenbedingungen (heterogene Toollandschaft).

Ich habe auf jeden Fall Probleme mit dem Word.Interop (ich benutzte Office 2003 / Office 11).


if (oWord == null)
   oWord = new Word.Application();
oWord.Visible = false;
oWord.DisplayAlerts = Microsoft.Office.Interop.Word.WdAlertLevel.wdAlertsNone;

Problem 1:
nach einiger Zeit bekomme ich eine Exception, "Durch den Messagefilter wurde angezeigt, dass die Anwendung ausgelastet ist. (Ausnahme von HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))"

Gleichzeitig, wenn das Dokument sichtbar ist, eine Messagebox mit der Meldung, dass zuviele Rechtschreib- und Grammatikfehler gefunden wurde und ich eine Überprüfung über Menü Extras usw durchführen kann.
Ein Deaktivieren der Rechtschreib- und Grammatikprüfung im Ausgangsdokument bringt keine Änderung, die Prüfung ist zwar tatsächlich abgeschaltet, die Meldung kommt trotzdem. Und damit auch die Exception.
Auch das Abschalten der Alerts (siehe Code) bringt keinen Erfolg, die Box kommt trotzdem!

Problem 2:
Trotz setzen der Sichtbarkeit auf false (siehe Code) kommt es manchmal (!) vor, dass das Fenster trotzdem sichtbar ist. Und das obwohl in jedem Aufruf zur Manipulation des Dokuments ein die Visible Eigenschaft geprüft und ggf. auf false gesetzt wird.

Ich bin soweit mit meinem Latein am Ende - Google hat auch nicht mehr ausgespuckt als das, was ich schon probiert habe (DisplayAlerts, Abschalten Prüfung..)

Bin für jede Hilfe dankbar.

Gruß
SirSydom

30.09.2009 - 10:14 Uhr

Ich präzisiere nochmal, ich hab mich zu schwammig ausgedrückt.

Also das Programm wird vorerst in Deutsch und Englisch erstellt.
Eine Lokalisierung ins Franzöische ist aber in der Zukunft denkbar.

Das Programm soll in der Regel die Culture des Rechners erkennen und automatisch die Sprache auswählen.
Da es aber Menschen mit Rechnern gibt, die ein englisches Windows benutzen aber trotzdem die App in deutsch haben wollen, möchte ich noch eine manuelle Umschaltung einbauen in der Form:

  • OS default
  • deutsch
  • englisch
    ...

Wenn das OS-default aber nun spanisch ist wird ja der als "Standard" eingetragene Text verwendet. Den zusätzlich pflegen will ich aber nicht.
In dem Fall soll Englisch verwendet werden.

Hier sehe ich 2 Möglichkeiten:
a) ich kopiere im VS irgendwie von Englisch nach Standard vor jedem Build
b) ich ignoriere Standard und frage progammatisch ab welche Culture aktuell ist und wenn ich diese nicht darstellen kann wähle ich "en" aus.
Da ich zur Loaklisierung aber NeutralCultures verwende, kann ich da nicht einfach auf Gleichheit prüfen...
Ich werde da über die Parents gehen müssen denke ich..

30.09.2009 - 09:18 Uhr

Hallo,

für meine Applikation verwende ich um das Programm zu loaklisieren das Language-Property. Im Designer (VS Exp C# 2008) stelle ich das Property auf die entsprechende Sprache um und ändere die entsprechenden Texte.

Beim Programmstart - direkt in der Main() - schalte ich mit

System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en");
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CreateSpecificCulture("en"); 

die Sprache um.
Nun ist es so dass bisher das Programm in deutsch designed wurde. Das Language-Property stand dabei auf "Standard". Wenn ich jetzt für Englisch die Text ändere um umschalte funktioniert es prima.
Aber wie sclate ich zurück auf "Standard" ?
Wie genau verhält sich das mit dem "Standard"?

Danke.

21.07.2009 - 12:05 Uhr

So, nochmal angerufen.
VB 6 ist in allen MSDN Abos bis auf Operating Systems drin - passt.

Es läuft bei uns anscheinend so, dass die einzelnen MSDN Abos einzelnen Mitarbeitern zugeordnet und bei Bedarf nachbestellt oder so - die werden das schon machen.

Übringens: Die MSDN-Hotline von MS ist 0800-1815190 - ích hab sie lange gesucht.

Gruß,
SirSydom

21.07.2009 - 09:27 Uhr

Man - gerade hab ich mit MS mit der MSDN Hotline telefoniert, da wurde mir gesagt Visual Studio 6 wäre in MSDN nicht enthalten.

Jetzt fällt mir aber ein das ich nicht nach Visual Basic 6.0 gefragt habe..
So ein Mist.

21.07.2009 - 08:35 Uhr

Ebay ist bei uns aus dem Intranet gesperrt 😉 Außerdem wird es schwierig dem Einkauf dazu zu bringen was bei Ebay zu kaufen. Ich hab über Google-Suche und Google Cache bei Ebay eins für 399 gefunden, das wäre okay, aber wie gesagt.. Einkauf..

Wenn das in der MSDN Subscription drin ist, wäre das super.
Ich finde hier (http://msdn.microsoft.com/de-de/subscriptions/subscriptionschart.aspx) jedoch keine Infos dazu.

In welchem MSDN Abo ist es ddenn drin deiner Meinung nach?

21.07.2009 - 08:13 Uhr

Guten Morgen,

für die Pflege eines (Ur-)Altprojektes brauche ich dringend die Entwicklungsumgebung Visual Basic 6.0.

Das ganze muss 100% legal laufen, da der Konzern für den ich arbeite in letzter Zeit genau drauf schaut. Meiner persönlichen Einstellung nach sowieso.

Problem ist, unsere IT-Fuzzis sagen mir die Software gibts nimmer zu kaufen, keine Chance.

Welche Möglichkeit außer irgendwo eine gebrauchte Lizenz zu erwerben gibts denn sonst noch?

Danke & Gruß

SirSydom

02.12.2008 - 17:03 Uhr

stimmt, gute Idee!

Ich habs jetzt so gelöst und allen Klassen, die ich so überschreiben muss, eine

void CopyInfoFrom(MyClass NewObjekt)
{
     this.Foo = NewObject.Foo;
...
}

Methode hinzugefügt, die einfach alle Member kopiert.

02.12.2008 - 16:22 Uhr

Ich parse ein XML-Dokument, in dem Element vorkommen, die auf andere Element verweisen.
Es kann vorkommen, dass zuerst das verweisende, dann das Zielelement im XML-Datenstrom vorkommt.

In meinen (C#-)Objekten sind solche Verweise nicht über ID sondern direkt über eine Referenz abgebildet, das Objekt welches andere hält hat eine List<>.

Nun kann ich aber das Objekt dieser List<> nicht hinzufüen, da es noch nicht existiert.
Daher lege ich dieses Objekt "leer", also mir mit ID an.
Es wird dann dem oder den Vaterobjekte(n) zugewiesen
Später, wenn ich dann das eigentlich Objekte parse, spuckt meine Parse-Funktion ein NEUES Objekt aus. Und nun soll das leere, alte Objekt durch das neue so ersetzt werden, dass die Referenzen in der Vaterelementen gültig bleiben.

02.12.2008 - 13:46 Uhr

Hallo,

Ich habe zwei Objekte A und B.

object A; ist ja im Endeffekt nicht weiter als eine Referenz (Pointer) auf eine tatschliche Instanz der Klasse object.

Nun kann ich mit X = A, Y = A, List.Add(A) diese Referenz woanders benutzen. Sie verweisen alle auf die eine tatsächliche Instanz.

Nun möchte ich diese Instanz durch eine andere ersetzen (Refernenz auf diese neue Instanz in B), aber nicht so das ich den "Pointer" in A auf die neue Instanz zeigen lasse, sondern ich möchte den Inhalt von B an die Stelle A kopieren, so dass auch X, Y und die Liste nun die neue Instanz referenzieren.

Ist sowas in C# möglich, und wie?

30.11.2008 - 10:45 Uhr

Ich lege jetzt nochmal mein komplettes Problem dar, zum einen als Rekapitulation für mich selbst, als auch für den interessierten Leser.

Ich schreibe an einem Programm, das verschiedene Geomatrische Figuren auf einer Oberfläche darstellt. Man soll diese Objekte auswählen und bearbeiten können.
Es gibt Punkte, Wege, und Polygone (geschlossene Wege mit bestimmten Eigenschaften)

Ich gehe folgendermaßen vor:

Im Hintergrund eine Datenstruktur (R*-Baum) Die alle Punkte und Wege (Sammlung von Punkten) enthält und nach X/Y Koordinaten indexiert sind.

Für einen bestimmten zu zeichnenden Bildausschnitt kann ich also direkt die entsprechende Elemente aus dem Baum abrufen. Dabei bekomme ich alle Elemente, deren BoundingBox (minimal umgebendens, achsparellels Rechteck) sich mit der BoundingBox der Anzeige überscheidet.

Aus diesen Elemente werden dann GraphicsObjekete (ähnliche wie in den div. Tutorials hier) erstellt und gezeichnet.

Selektieren (Klick):

Wird mit der Maus auf ein bestimmtes Pixel geklickt, wird für eine Quadrat um das Pixel eine BoundingBox aus dem Baum angerufen, die GraphicsObjekte erstellt und auf Hit (Node oder Weg) oder Contain (Polygon) überprüft.

Das umgebende Rechteck aus dem Grund weil ein Node mit einem Symbol viel größer gezeichnet werden kann. wenn sich also neben einem Weg ein Punkt befindet, der aber so groß gezeichnet ist das er den Weg überdeckt, soll trotzdem der Punkt und nicht der Weg selektiert werden.

Selektieren (aufgespanntes Rechteck):

ähnlich wie oben, nur sollen diesmal alle Objekte ausgewählt werden, die mit mind. 1 Pixel innerhalb des Rechtecks sind.

Daraus ergeben sich einige Probleme:

  1. Zeichnen

Wege oder Polygon haben recht große umgebende Rechtecke. Daher kommt es dazu, dass teilweise gar keine oder nur kleine Teile tatsächlich im Bildauschnitt zu sehen sind, obwohl die BB sich überlappen. Das führt dazu, dass das Zeichnen wesentlich länger dauert als nötig.

  1. Klick-Hit-Test

Die Abfrage ob ein Punkt in einem Polygon liegt (Contains) dauert ewig. Das liegt einfach daran, das dies ein Problem ist, das grundsätzlich nur mit quadratischem Aufwand gelöst werden kann.
Die Idee, die Polygone einfach mit der sichtbaren Fläche zu clippen fuktioniert. Der Hit-Test ist dann wesentlich schneller (da der Polygon dann oft aus <10 Punkten besteht anstatt von > 500).
Nur das Clippen dauert auch ewig..

  1. Contains-Test
    das im ersten Post beschriebene Problem. Nicht trivial lösbar.

Lösungen:

  1. Das Problem besteht darin, das Wege bei denen gar kein oder sehr wenige Segemente (Linie zw. 2 Punkten) tatsächlich gzeichnet werden müssen oft noch >100 andere Segmente haben. Bisher wurden diese einfach gezeichnet (außerhalb des sichtbaren Bereichs) Das ist i.d.R. sehr schnell. Außer man verwendet DashStyles, dann wirds langsam.
    Diese Problem habe ich gelöst, in dem jedes Segement (dessen BB) geprüft wird, ob es in der Anzeige-BB liegt. Funktioniert gut!

  2. Keine Lösung in Sicht. Evtl werde ich mich darauf beschränken, dass man Polygone nur selektieren kann, indem man auf den sie immer umgebenden Weg klickt.

  3. Auch keine gute Lösung in Sicht. Evtl. werde ich nur noch solche Objekte auswählen, die komplett in der Auswahl liegen. Dann ist der Test leicht (anhand der BBs)

29.11.2008 - 12:08 Uhr

Bist du dir sicher dass das so funktioniert?

Außer den dürftigen Informationen aus dem MSDN finde ich nicht viel zu Intersect und IsEmpty, aber ich verstehe das so:

Intersect bildet eine neue Region, die nur aus der Schnittmenge von this und der übergebenen Region/Rectangle besteht, richtig?

IsEmpty überprüft, ob eine Region auf einer Zeichenoberfläche leer ist (also ob in diesem Bereich schon mal gezeichnet wurde).

Ich sehe folgende Probleme:

Eine Region, die ich aus einer dimensionlosem Objekt wie einer nicht geschlossenen Abfolge von Linien bilde, ist keine Region. Vielmehr wird beim erstellen der Region der Path geschlossen, es entseht also eine Fläche (was nicht Sinn der Sache ist).

Wenn IsEmpty sich auf die Fläche der Region beziehen würde, könnte ich es ja noch nachvollziehen- aber so? Irgendwie haut das so nicht hin.

Korrigiere mich bitte wenn ich dich falsch verstanden habe oder falsche Annahmen gemacht habe..

28.11.2008 - 20:33 Uhr

nicht vollständig, das habe ich vergessen zu erwähnen. Es reicht wenn nur ein Pixel des gezeichneten Paths in dem Rechteck ist.

Ansonsten wäre es wirklich einfach, und - wäre auch selbst drauf gekommen 😉

28.11.2008 - 20:17 Uhr

Hallo,

ich suche schon länger eine vernünftige Lösung für folgendes Problem:

Ich will feststellen, ob ein GraphicPath (gezeichnet mit einem bestimmten Pen) in einem bestimmten Rectangle sichtbar ist.

Ähnlich wie GraphicPath.IsVisible bzw IsOutlineVisible, nur nicht mit Punkten sondern mit Rectangles.

Hintergrund ist eine Select-Funktipon bei der man mit der Maus ein Rechteck aufspannt und so alle Objekte darin selektiert. Die "Rohdaten" der Objekte kann ich dafür nicht wirklich verwenden um das geometrisch zu berechnen, denn die werden alle mit unterschiedlichen widths oder Dash-Styles gezeichnet.

24.11.2008 - 19:24 Uhr

Hallo,

ich möchte für meine Anwendung ermitteln, ob gewisse Tasten gedrückt sind.

Bisher bin ich so vorgegangen, die KeyUp und Down Ereignisse zu behandeln und mir zu merken welche Tasten gedrückt sind.

Das funktioniert soweit, wenn jedoch das Programm den Fokus verliert kommt alles durcheinander.

z.B. wenn man Ctrl gedrückt hält und dann ein anderes Prog dazwischen funkt (z.B. Avira AntiVir Update-Meldung grml) lässt man idR die Ctrl Taste los, klicktz das weg und geht zurück ins Programm und arbeitet weiter. Wenn man nicht sofort wieder die Ctrl-Taste drückt, ist im Programm immer noch (falsch) hinterlegt, das Ctrl gedrückz ist.
Das führt zu unerwünschten Verhalten. Wie kann ich das abstellen?

Gibt es evtl. ein systemweite Keyboard-Zustands-Info? Oder die Möglichkeit Events auch zu erhalten wenn man nicht den Fokus hat?

Gruß,

SirSydom

20.11.2008 - 22:50 Uhr

Ja ne - is klar.

Mir gehts darum wie ich aus einer Collection und einer Reihe von Indizes eine neue Collection erstellen kann, ohne die Daten erneut in irgendwelche Listen reinzustopfen.

Ich möchte das halt sauber kapseln, von außen soll man nicht sehen das da ListBox.SelectIndizes usw dahinterstehen - und da suche ich noch einen sauberen Weg.

20.11.2008 - 17:55 Uhr

Folgende Situation:

Ich habe eine Collection (die von CollectionBase erbt) und eine Reihe von Elementen hält.
Dann ist da eine Listbox, die alle Elemente dieser Collection darstellt.
Nun möchte ich 2te, neue Collection haben (um sie mit foreach zu durchlaufen, per Count die Größe festzustellen und per [] zu indexieren) die die Elemente abbildet, die in der ListBox Selektiert sind.

IMO ist es ja unnötig da eine weitere Collection zu erstellen, die Basisdaten sind ja da, man müsste nur den Index umbiegen usw..

Wie könnte man sowas elegant lösen?

19.11.2008 - 11:09 Uhr

Selbst kompiliert?
Welcher Compiler / Entwicklungsumgebung / Framework?

18.11.2008 - 20:44 Uhr

Ha!

Nach ewigem Probieren und Erstellen von Forms bin ich drauf gekommen:

Ich füge die Rows hinzu, während das DataGridView Disabled wurde (Enabled=false).
Wenn es danach wieder enabled wird, hat der Scrollbalken diese Fehlfunktion.

Ich hab mal ein Beispielprojekt im VS2005 mit .Net 2.0 gemacht, wer mag kann sichs ansehen.

IMO ist das ein Fehlverhalten..

18.11.2008 - 19:21 Uhr

Hallo,

ich habe ein Problem mit einem DataGridView.

Dieses befindet sich als einziges Element in einem Form und hat die Eigenschaft Dock=Fill.

Wenn ich nun das DataGridView befülle, und es mehr Rows werden als angeziegt werden können, erscheint zwar ein Scrollbalken, mit diesem kann ich jedoch nur 1-2 Reihen nach unten scrollen, obwohl da noch weitere Rows sind.

Scroll ich herunter, indem ich mit den Cursortasten die Elemente selektiere, bekomme ich nach ein paar Reihen eine OutOfRange Exception in der SetScrollBar Methode.. urgs

was läuft da denn falsch? Ist das ein .Net Bug?

PS: wenn ich das Form Resize, dann stellt sich die Scrollbar auf den richtigen Zustand ein.

16.11.2008 - 19:22 Uhr

Mittlerweile haut es hin - aber nur so halb.

Warum, kann ich auch nicht genau sagen.

Bei einem neuem Wert, welcher nicht in der DataSource vorhanden ist, füge ich diese Wert neu hinzu, und setze mit cell.Value auf diesen Wert.
Das funktioniert auch, cell.Value hat danach diesen neuen Wert.

Genau jedes zweite mal passiert es jedoch, dass zwischen CellValidating und der normalen Programmschleife der cell.Value Wert wieder verändert wird - auf den vormals Ausgewählten. Auch im CellValidated ist dieser Wert schon wieder verändert.

Wer oder was ändert mir hier den Wert und warum?!?

16.11.2008 - 12:32 Uhr

Hallo,

ich habe eine DataGridViewComboBoxCell, die über DataSource eine Reihe von Werten hat.
Trotzdem setze ich den DropDownStyle auf DropDown, so können neue Werte hinzugefügt werden.

dabei überprüfe ich, ob der Wert bereits vorhanden ist, und falls nicht füge ich der entsprechenden DataTable eine neue DataRow hinzu. Klappt.

Jetzt gibt es aber noch den Spezialfall, dass zwar der eingegebene Wert nicht exakt dem Display Wert entspricht, ich aber trotzdem diesen Wert setzen will.

z.B. gibt es die Werte "ABC (2)", "EFG (7)" oder "Hugo (0)". Wenn nun e.formatedvalue "Hugo (0)" ist, passt alles. Gibt der Nutzer aber "Hugo" ein, soll der Wert auf "Hugo (0)" springen.

Das versuche ich mittels cell.Value, den ich auf das entsprechende Objekt setze. Doch dann bekomme ich im DataError-Event eine Exception "kann nicht in System.String konvertieren".

Setze ich außerhalb des CellValidating-Events denn cell.Value auf das selbe Objekt, gibt keine Probleme!

Wie kann ich das Problem lösen?

15.11.2008 - 15:28 Uhr

Hallo,

ich nutze ein DataGridView und darin unter anderem ComboBoxCell.
Diese fülle ich entweder selbst über Items.Add mit einer bestimmten Klasse (MyColumnData) die dann per ToString() das richtige anzeigt oder auch per DataTable. Beides funktioniert.

Nun möchte ich jedoch, das gewisse Items kursiv oder anderweitig hervorgehoben werden. Wie kann ich denn sowas realisieren??

mit

cell2.Style.Font = new Font(dataGridView1.DefaultCellStyle.Font, FontStyle.Italic);

kann ich zwar alle kursiv machen, möchte es aber nur bei bestimmten elementen. Besonders toll wäre wenn man dies in der Klasse MyColumnData realisieren könnte..

12.11.2008 - 18:40 Uhr

Joa.. so hab ichs auch gemacht.
Finde die Lösung aber irgendwie "unelegant"..

12.11.2008 - 18:10 Uhr

das ändert auch nichts daran, das bei jedem Aufruf dann das Event ausgelöst wird..
Das will ich verhindern.

12.11.2008 - 17:31 Uhr

Hallo,

in meinem ListBox Control will ich - programmatisch - mehrere bzw alle Einträge auswählen.

Da es sowas wie AddRange, AddItems für SeletedItems bzw SelectedIndices gibt, lauf ich halt über ne foreach drüber und rufe Add(). Das führt aber dazu, dass das SelectedIndexChanged Event immer ausführt, trotz Beginn- und EndUpdate().

Mir fällt kein guter Weg ein dieses Problem zu lösen? Euch?

Achja, .Net 2.0, gibt also kein ListBox.SelectAll() (ab 3.5)

Gruß,

SirSydom

23.10.2008 - 13:39 Uhr

wäre es nciht sinnvoller die daten auf das sichtbare und den zoom aufzuarbeiten und dann der gui zu sagen mach damit was du willst? und die gui nimmt das und zeichnet nur noch die daten runter?

Logisch getrennt ist es. Fakt ist, dass das holen der Daten aus dem Baum und aufbereiten nur einen geringen Teil der Zeit benötigt. Richtig aufwändig ist die tatsächliche DrawX - Methode.

wenn du nämlich im hintergrund bereits viele bitmaps renderst, kannst du evtl speicherprobleme bekommen.

wenn du aber sagst das das rendern der aktuell anzuzeigenden daten sehr viel zeit in anspruch nimmt, dann kannst du die gui dazu bringen das aktuell sichtbare auf eine einzige bitmap zu zeichnen und dann hast du keine probleme mehr mit invalidate & co.

Zur Zeit habe ich ein Bitmap in der Größe der Anzeige, das bei Bedarf (und nur dann) gezeichnet wird. Kommen Invalidates wegen eines überblendeten Menüs, wird nur das bereits gerenderte Bitmap gezeichnet, was sehr schnell und problemlos geht.
Ich cache also nur den gerade angezeigten Inhalt, das sind max ein paar MB.

Nur das erstellen des Bitmaps dauert lange, und zwar vorallem das tatsächliche zeichnen. Daher der Ansatz, das Bitmap (z.B.) in 4 Teile aufzuteilen und jeden Kern eines davon rendern (zeichnen) zu lassen. Sind alle fertig, kommt das ganze aufs Display.

Ob ich nun in ein Bitmap mit 16001200 oder in 4 mit 800600 zeichne, ist vom Speicher her egal.

Wenn ich nun zoome oder in ein komplett neues Gebiet springe, muss ich neu rendern. Und das dauert und das will ich beschleunigen.

23.10.2008 - 13:23 Uhr

Das wäre doch Blödsinn. Ich erstelle Bitmaps, die dann später auf die Anzeige gebracht werden. Warum sollte ich das zeichnen der Bitmaps nicht parallelisieren? Gerade da liegt ja ein Großteil des Rechenaufwandes!
Im Hauptthread, also der der GUI, greife ich dann auf die gerenderten Bitmaps zu und zeichne sie auf die Oberfläche (e.Graphics.DrawImage())

Was spricht denn gegen diesen Ansatz?

23.10.2008 - 13:03 Uhr

Ähm - dann verlieren ich doch jeden Vorteil der Parallelisierung, wenn ich dann doch wieder nur im Hauptthread zeichne?!?

Ich überlege a) Pen kopieren oder b) locken.. alles andere macht doch keinen Sinn?

22.10.2008 - 17:35 Uhr

Hm. Ich habe eine Exception bekommen, etwa: "Das Objekte wird bereits an andere Stelle verwendet" und zwar für einen Pen. Wenn ich mit einem Pen etwas zeichne, ist das doch nur ein lesender Zugriff, oder etwa nicht?

[System.InvalidOperationException] = {"Das Objekt wird bereits an anderer Stelle verwendet."}
StackTrace = " bei System.Drawing.Graphics.CheckErrorStatus(Int32 status)\r\n bei System.Drawing.Graphics.DrawRectangle(Pen pen, Int32 x, Int32 y, Int32 width, Int32 height)\r\n bei System.Drawing.Graphics.DrawRectangle(Pen pen, Rectangle rect)\r\n bei MapEdit.N...

Die Pen-Objekte änderns sich bei mir nicht. Für jede Art (z.B. Autobahn) erzeuge ich zu beginn aus einer Art Stylesheet meine Pens und gebe die dann mit..
Dann kann ich mir auch das volatile, sparen? (So wie ich das verstanden habe ist das nur wichtig bei sich ändernden Variablen?)

Edith hat gesagt, ich soll nochmal Debuggen und die Exception hinschreiben.

22.10.2008 - 17:27 Uhr

Sodala.

Ich hab ein wenig experimentiert, sowohl mit Threads als auch mit Parallel.For.
Es scheiterte erstmal daran, dass ich einige gemeinsame Ressourcen benutze (R-Tree mit den Datenobjekten der zu zeichnenden Objekte und die Pens und sonstigen draw-Zeug. Das alles Thread-Safe zu machen war mir erstmal zu krass.

Dazu hätte ich jetzt eine Frage: Ich darf jedes Objekt immer nur in einem Thread verwenden, sobald mehrere Threads damit arbeiten, muss ich locking-Mechanismen einbauen? Und zwar bei lesen uns schreiben?

Das erreiche ich am besten über lock(){} statements, oder?

Zu deiner Idee mit den Tiles und zoomen. Das möchte ich auf jeden Fall vermeiden, denn für jede Zoomstufe soll sepeat gerendert werden. Sonst passt das mit der Linienstärke und vielen anderen Sachen nicht gut und sieht teilweise nicht gut aus.
Außerdem habe ich dann auch ein Problem um z.B. beim Mausklick einen Hit-Test durchzuführen.

Die Informationsstufen (die auch geplant sind) kann ich ja in jedem Ansatz verwenden. Ob nun immer on-the-fly gerendert wird (parallel oder nicht) oder auch mit caching.

20.10.2008 - 14:20 Uhr

Hm, beim Zoom haben wir uns glaube ich falsch verstanden.

Ich dachte daran, die gerenderten Tiles auf der Platte zu cachen! Das wäre bei stufenlosen Zoom ziemlich viel.. Und die wiederverwendbarkeit ist auch eingeschränkt, denn der User merkt keinen Unterschied zwischen Zoom 3.2143 und 3.2144, die Tiles kann ich jedoch nicht wiederverwenden.

Aber ich merke, dir ging es auch gar nicht nur ums Cachen, sondern darum alle Kerne (bei mir sinds 4 😉 ) zu nutzen.

Nun, für was genau die Parallel Lib mit den Prios?

Ich hätte einfach für jedes (nicht vorhandenen) tile einen render-Job angestoßen (Thread) und wenn der fertig ist gezeichnet.

Meinst du die Prios um erst die Bildmitte, dann den Rest und dann evtl. rundrum zu rendern?

Eigentlich wollte ich beim .Net 2.0 bleiben, für eine mögliche Ausführung mit Mono unter Linux - gut, evtl muss ich das sausen lassen.

20.10.2008 - 13:08 Uhr

Ja, so machen das ja auch Google Maps, Yahoo, dieses MS Live Kartendings.. Virtual Earth Tiles: MSDN: Virtual Earth Tile System

Nur wollte ich eigtl. einen stufenlosen Zoom, und da is nix mit Pre-Rendering. Aber evtl. sollte ich mich davon verabschieden.

Nunja, ein andere Ansatz war, einen Filter einzuführen und bei großen Ausschnitten nur wichtige Sachen darzustellen - das wäre nochmal ein immenser Performance-Boost.
Aber es wäre schon gut auch max. Details auch bei großen Ausschnitten sehen zu können.

Zu den "Tiles":
Es wäre gar keine große Sache, denn einen Background-Viewer für Tiles im entsprechenden Format habe ich bereits eingebaut. Auf die Idee, die tatsächlichen Infos auch als Tiles auszulagern bin ich noch gar nicht gkommen. Müsste nur statt die tiles vom Web zu laden, einen Render-Job anstoßen...

Muss ich direkt mal ausprobieren!

20.10.2008 - 10:47 Uhr

Hallo SirSydom,

wenn ich mich richtig erinnere wird im benannten
>
in einer Schleife über alle existirende Objekte iteriert und an jedem die "Draw"-Methode aufgerufen.
Das kann je nach Menge der Objekte (auch je nach der Größe/Komplexität der GraphicPath) massive Performanceprobleme verursachen. Das Clipping des Graphics-Objektes ist da schon recht hilfreich, aber es wäre noch besser wenn man in der Schleife ausschliesslich über die Objekte iterieren kann die im ViewPort (sichtbaren Bereich) liegen. Um das performant machen zu können sollte deine Datenhaltung so aufgebaut sein dass sie schnelle Abfragen erlaubt wie: "Gib mir alle Objekte die im ViewPort Rechteck liegen". Um also mit GDI+ performant zeichnen zu können sollte man folgendes umsetzen:

1.) Clipping des Graphics-Objectes auf den ViewPort
2.) Performantes finden der Objecte die im ViewPort komplett und teilweise sichtbar sind

Zu 1)
ViewPort höre ich zum ersten Mal, ich nehme an du meinst das ClipRectangle der PaintEventArgs? Das habe ich zwar eingeplant, aber noch nicht implementiert. Das liegt daran, dass ich zZ aufgrund der Operationen sowieso das ganze Bild neu zeichnen muss! (Zoom, verschieben des Bildbereiches) Fallsdas Fenster nur verschoben wird oder minimiert/nicht sichbar und sich an meinen "Stammdaten" nichts verändert hat, zeichne ich nur einfach das Bitmap wieder - geht sehr schnell.

Zu 2)
Ich habe zigtausende Objekte (Geodaten) die ich nicht alle einfach zeichne. Ich bin doch nicht doof 🙂 Die liegen alle in einem R*-Tree und sind sauber nach Lat/Lon indexiert.
Ich hole mir also nur die Objekte, deren BoundingBox sich mit der sichtbaren Fäche überschneidet. Aufgund dessen, dass eine BoundingBox immer rechteckig ist, heißt das aber nicht das das tatsächliche Objekt wirklich sichtbar ist.
Das funktioniert so gut, dass in dem oben angesprochnen Fall mit 3000ms nur 11 Objekte zu zeichnen sind, die jweils zwischen 10 und 500 Punkt haben. Das Problem ist aber wie gesagt die schiere Länge der gestrichelten Linie.

3.) Bei Änderungen der Objektgeometrie nur die Region neuzeichnen die sich tatsächlich verändert hatte (siehe
>
)

Bei Punkt 3. gibt es noch zu beachten dass mehrere richtig große Objekte (hunderte von Points im GraphicsPath) nur teilweise im ViewPort liegen können. Hier wird es teuer wenn das ganze Objekt gezeichnet wird. An dieser Stelle würde ich versuchen die Schnittpunkte des Paths und des ViewPorts zu berechnen und einen temporären GraphicsPath zu erstellen, welches das OriginalPath an genau diesen Schnittpunkten "abschneidet". Es bietet sich an diese Logik in den Objekten auszuimplementieren und beim "Draw" noch zusätzlich den ViewPort-Rectangle mit zu übergeben.

Genau darum geht es. Ich dachte es gäbe evtl. eine Methode das "automatisiert" zu machen, ein Property zu setzen und fertig.
Gut, mein GraphicsPath besteht idR nur aus Linien, ich kann also tatsächlich recht einfach ausrechnen ob sichtbar oder nicht. Wie herbivore das ja schon angesprochen hat. Nur auch das kostet auch wieder Laufzeit. Ich zeichne zum Teil zig-Tausende Linien..
Und zwar immer, für jede Linie. Und das wollte ich vermeiden...

Um mal etwas Bildlich zu sprechen, habe ich ein paar Screenshots gemacht: (hier in voller Pracht als png, als Anhang auf 256kB JPG-komprimiert)

Bild 1
Bild 2
Bild 3

20.10.2008 - 01:19 Uhr

Nun, ich habe die Ursache für meine Performance-Einbrüche erkannt.

Es scheint gar kein zeitliches Problem zu sein, eine Linie mit Länge von 500.000 pixeln zu zeichnen, die außerhalb des sichtbaren Bereichs liegt.

Wenn diese Linie jedoch mit einem Pen mit DashStyle.Custom oder Dotted versehen ist, wird das wohl alles TROTZDEM berechnet, obwohl es nie tatsächlich gezeichnet wird.

Jetzt brauche ich einen Ansatz, wie ich herausfinden kann ob ein TEIL eines GraphicPaths sichtbar ist und tatsächlich gezeichnet werden muss und wie ich diesen dann auch nur teilweise zeichnen kann..

19.10.2008 - 22:43 Uhr

Grundsätzlich ist bei mir GDI schon schnell genug - der Flaschenhals ist nicht das Ding auf den Monitor zu bekommen, sondern das Bild zu erzeugen.

Und so wie ich das verstanden habe, hilft mir da DirectX usw auch nicht so viel weiter.

WPF - nutzt das eine Form von Hardwarebeschleunigung für Zeichenoperationen? Oder wie funktioniert das da? Gibts da evtl ein schönen Tutorial hier?

19.10.2008 - 20:08 Uhr

Hallo,

Kurz gesagt: Ich zeichne Geodaten. Die liegen in einer Datenstruktur, die geospatial indexiert ist. Das hat aber zur Folge, das ich (in niedrigen Zoomleveln) riesige Objekte bekomme die gar nicht angeziegt wird.

Auf jeden Fall habe ich da ein echtes Problem. Das Zeichnen weit außerhalb des Bildes (ich zeichne in ein Graphics Objekt eines Bitmaps) z.B. x -164000, y 80000 dauert EWIG.

Ich dachte GDI wäre so schlau und würde das merken ob ein Objekt außerhalb des Bereichs liegt und damit sogar schneller werden als wenn es innerhlab des Bereichs läge..

Aber irgendwo liegt der Hund begraben..
für 11 Paths mit max. 500 Punkten brauchts dann bis zu 3000ms.

Lösungsvorschläge?

Achja, ich gehe ähnlich vor wie in den Tutorials ([Tutorial] Gezeichnete Objekte mit der Maus verschieben) hier.

Ich erstelle einen Path und zeichne diesen dann..

12.09.2008 - 18:56 Uhr

Hallo,

für mein Projekt will ich sehr große XML-Dateien (500MB) parsen, laden uns bearbeiten können. Meine Datenstruktur gibt das her, vorrausgetzt es ist genügend Hauptspeicher vorhanden. Bisher habe ich ein per XML-Schema und von xsd erzeugte Klassen geparsed, aber das ist ja DOM basierned, braucht ewig lange und ewig viel Speicher.

Was kann man als Alternative verwenden?
Ich habe sax.net gefunden, kennt das jemand und hat es erfolgreich im Einsatz?

Oder hat jemand einen anderen Vorschlag oder Idee?

17.07.2008 - 12:20 Uhr

Hi,

es ist ja bekannt, dass das Zeichnen mit GDI+ wesentlich beschleunigt werden kann, wenn man statt lauter einzelnen DrawLine, DrawRectangle usw DrawRectangles usw verwendet.

Bei Rectangles hat das einwandfrei hin, DrawLines jedoch erwartet nicht etwa ein Array mit Linien, sondern eine Punktmenge, die dann verbunden wird. Dies ist jedoch nicht das Verhalten, welches ich benötige. Ich will viele Linien zeichnen, die alle durch 2 Punkte definiert sind. Gibt es hierfür eine Lösung oder muss ich wohl oder übel mehrfach DrawLine ausführen?

01.07.2008 - 10:21 Uhr

Also ich habe lange über dem Quadtree gegrübelt, und der ist für meine Bedürfnisse nicht wirklich passend. Bei meiner Recherche bin ich auch R-Bäume, bzw R+ oder R* Bäume gestoßen, die genau dafür entwickelt wurden, was ich machen möchte.

Evtl gibts eine freie Implementierung von R*-Bäumen in C# - mal sehen. Ich poste dann nochmal..

28.06.2008 - 23:43 Uhr

Ich hab heute einiges ausprobiert und getestet.

Fakt ist, dass ich dem UserControl (auch wenn ich es explizit aufrufe) nicht den Focus geben kann, wenn es Controls hat. Denn den Focus bekommen dann diese (bzw. das erste in der TabIndex Liste)

WndProc hab ich auch ausprobiert. Ich kann das MouseWheel deaktivieren, aber das Event dann an das UserControl "runter" zu geben habe ich nicht geschafft.

Außerdem habe ich noch probiert OnMouseWheel der Trackbar zu überschreiben, und dann eben base.OnMouseWheel NICHT zu rufen und stattdessen das Event des Usercontrols auslösen. Überschreiben und runtergeben hat geklappt, aber die Trackbar hat sich trotzdem bewegt.. Also auch irgendwie komisch. Ich hab mich fürs erste für eine Andere Lösung entschieden, aber mal sehen, vielleicht findet sich noch eine Lösung.

28.06.2008 - 01:31 Uhr

Hi,

ich habe ein Control erstellt, welches von UserControl erbt.
Da fange ich erstmal nur ein paar MouseEvents und Zeichne.

Um das MouseWheel-Event zuverlässig zu bekommen, rufe ich im Eventhandler MouseEnter Focus().

Bisher klappt alles wunderbar. Nun habe ich dem Control eine Trackbar hinzugefügt.
MouseWheel-Events kommen nun nicht mehr im Controll an, stattdessen wheelt die Trackbar fröhlich rum. Nun gut, fange ich halt das Event der Trackbar. Haut hin.

Nur besteht jetzt ein anderes Problem: Wenn die Maus das Control verlässt, hat es immer noch Focus. Ich merke mir in der Logik das und werte das MouseWheel Event nicht mehr aus. Die Trackbar jedoch macht fröhlich weiter..

Geht es - und wenn ja wie - dass die TrackBar das Wheel-Event gar nicht bekommt und stattdessen wieder beim Control ankommt? Kann man da irgendwie was abkoppelen?

27.06.2008 - 21:38 Uhr

Das ist es. Zumindest ist es ein Workaround. Danke!