Laden...
P
Pulpapex myCSharp.de - Member
Java-Entwickler Rostock Dabei seit 22.07.2003 939 Beiträge
Benutzerbeschreibung

Forenbeiträge von Pulpapex Ingesamt 939 Beiträge

09.06.2005 - 14:17 Uhr

Damit der Benutzer nicht als Admin angemeldet sein muss, dürfen Benutzerdaten nicht im Programmverzeichnis abgelegt werden. Benutzerdaten sollten im Home-Verzeichnis des Benutzers gespeichert werden - "Dokumente und Einstellungen". Siehe auch System.Environment.SpecialFolder-Enum.

Tut mit Diskussion zum Thema:
Das neue Konfigurationsmodell im .NET Framework 2.0

Gruss
Pulpapex

08.06.2005 - 22:26 Uhr

Hi,

in .Net 2.0 hat PictureBox eine ImageLocation-Eigenschaft. Da kann eine beliebige URL angegeben werden. Mehr ist nicht erforderlich, die PictureBox zeigt das Bild ohne weiteres Zutun an.

In .Net 1.1 ist es auch leicht machbar. Wie schon gehabt, mit WebClient.OpenRead einen Stream öffnen, mit dem Stream als Konstruktor-Parameter ein Bitmap instanziieren und dieses Bitmap der PictureBox.Image-Eigenschaft zuweisen.

Gruss
Pulpapex

08.06.2005 - 15:08 Uhr

Was heisst es lässt alles durch? Gibt es Treffer oder nicht?

Versuch es hiermit: (@"^+?(\d[\d\s]*)"

Der Ausdruck findet eine Ziffer, gefolgt von einer Folge aus Ziffern und Leerzeichen.

Gültig:
"1234"
"+123 342"
"123 4323"
"1234Gb" // matcht nur "1234"

Ungültig:
"-123"
"+132+3" // matcht nur "+132"

Ansonsten gibt es vielleicht hier den passenden Ausdruck:

http://www.regxlib.com/Search.aspx?k=telephone

08.06.2005 - 14:49 Uhr

Man könnte es auch so schreiben, dann wird es vielleicht deutlicher:

typeof(Beispiel).GetProperty("getAttribut").GetValue(bsp, new object[]{});

Das getAttribut-Property ist in der Beispiel-Klasse definiert, nicht in der bsp-Instanz. Deshalb muss die Instanz mit angegeben werden, deren getAttribut-Wert abgefragt werden soll.

Gruss
Pulpapex

08.06.2005 - 14:38 Uhr

"^+?(\d)+" erkennt z.B. "+123". Bei "+123 45" wird nur "+123" gematcht. Sollen Leerzeichen zwischen Ziffern möglich sein? "-123" liefert keinen Treffer.

Wenn du den Regex abänderst in: "^+?(\d+)" bekommst du in Gruppe 1 übrigens die ganze Zahl, statt nur eine einzelne Ziffer. Weiss nicht ob das gewünscht ist.

08.06.2005 - 12:32 Uhr

Die "wahre Lösung" ist, nicht Einzelbilder als Video abzuspielen. Am besten wäre ein streaming-fähiges Videoformat, bei dem ja nur das aktuell angezeigte Frame entpackt wird. Ist auf jeden Fall speicherschonender und braucht weniger CPU-Leistung.

08.06.2005 - 10:45 Uhr

Den verlinkten Thread solltest du nicht zum Lernen nehmen. Ich hab da ständig "^" und "§" verwechselt.

www.regular-expressions.info ist eine gute Seite.

@"text" ist in C# ein sogenannter Verbatim-String, ein vorformatierter String. Das bedeutet, dass Escapesequenzen wie "\r\n" nicht verarbeitet werden, "\r\n" bleibt genauso im String erhalten.

Ohne Verbatim-Strings müsste man in regulären Ausdrücken alle Backslashes extra escapen, damit sie erhalten bleiben. Beispiel: @"\d*" hat die gleiche Bedeutung wie "\d*".

Gruss
Pulpapex

07.06.2005 - 16:38 Uhr

Ein Button-Klick auf einer Webseite ist nichts anderes Submit. D.h. es wird ein Http-Request an eine Url gesendet. Parameter wie Benutzername und Passwort werden per GET- oder POST-Methode übertragen. Wenn es GET ist, stehen die Parameter in der Addressleiste. Für POST benötigt man einen Http-Sniffer, um die Http-Header mitschneiden zu können.

Such hier im Board, das Thema gab es schon mal.

Gruss
Pulpapex

07.06.2005 - 15:48 Uhr

Oder nimm' decimal.

Die Abweichungen kommen zustande, weil eine Zahl in Dezimaldarstellung eine andere Anzahl Nachkommastellen haben kann als in Binärdarstellung. Eine Zahl mit einer Nachkommastelle im Dezimalsystem kann im Binärsystem periodisch sein, also unendlich viele Nachkommastellen haben.

Mal gucken ob ich eine Seite finde, wo etwas darüber steht.

Gruss
Pulpapex

//Edit: Hier z.B: http://www.mpdvc.de/artikel/FloatingPoint.htm

Beispiel: 0.3 kann nicht exakt als double-Wert angegeben werden.

double v = 0.3;
Console.WriteLine(v); // Müsste 0.29999999999 ausgeben.
07.06.2005 - 15:10 Uhr

Man muss auch bedenken, dass Bilder im Arbeitsspeicher bedeutend mehr Speicher belegen, da sie unkomprimiert vorliegen.

Ein Bild mit der Auflösung 1024*768 und 24 Bit Farbtiefe belegt beispielsweise schon 2,25 Mb. Das Jpeg dazu hat vielleicht 200kb.

Gruss
Pulpapex

07.06.2005 - 14:49 Uhr

Hi avlbger,

auf ein Graphics-Objekt wird nicht gezeichnet. Die Klasse bietet nur die Funktionen an, um auf einem Graphics-Kontext zu zeichnen.

Ein Graphics-Kontext kann auch ein Image-Objekt sein:

Image image = new Bitmap("bild.jpg");
using(Graphics g = Graphics.FromImage(image)) {
   g.Draw...;
}

Am besten benutzt man Graphics im using-Block, da es begrenzte Betriebssystem-Resourcen sind. Das bekritzelte Bild kann dann im Anschluss wieder gespeichert werden.

Gruss
Pulpapex

07.06.2005 - 12:39 Uhr

Das hängt mit der Z-Order, der Reihenfolge der TextBoxes in der Controls-Collection, zusammen. Wie es genau sein muss, weiss ich auch nicht genau. Ist ein wenig hakelig. Wahrscheinlich müssen neue TextBoxes nicht am Ende, sondern am Anfang in die Controls-Collection eingefügt werden. Einfach mal ausprobieren.

Gruss
Pulpapex

07.06.2005 - 10:28 Uhr

Hmm, ist dann wohl kein purer Parser. Parsen und Aktionen scheinen durchmischt zu sein. Wer weiss was da noch alles ausgeführt wird. Unschön.

Vielleicht gibt es den Html-Parser der Gecko-Engine auch einzeln? Wäre ne Alternative.

07.06.2005 - 09:50 Uhr

Woher weisst du denn welche neu definierten Eigenschaften die Forms haben? Ich würde ein Interface oder eine Basisklasse vorgeben, von der alle Forms ableiten müssen.

Wenn du alle Form-Klassen kennst, kannst du es auch so machen.

FormA formA = null; 
FormB formB = null; 
FormC formC = null; 

foreach(Type t in formTypes) {
    object o = Activator.CreateInstance(t);

    if(o is FormA) {
        formA = (FormA)o;
    } else if(o is FormB) {
        formB = (FormB)o;
    } else if(o is FormC) {
        formC = (FormC)o;
    }
}

Gruss
Pulpapex

07.06.2005 - 09:31 Uhr

@herbivore
Jemand, der REs nicht kennt, findet es auch einfacher, alles eigenhändig zu programmieren. Grammatik-Regeln sind einfach nur aufgebohrte, reguläre Ausdrücke. Die Lexer-Regeln sind sogar pure REs.

Natürlich ist es trotzdem schwer eine Grammatik zu konstruieren. Besonders, wenn man es noch nie gemacht hat. Aber nach ner Weile hat man den Dreh raus, denke ich. Und dann ist man mit einem Parser Generator viel schneller. Statt ellenlangen Programmcode schreibt man nur noch ein paar kurze Grammatik-Regeln, die man auch schnell wieder abändern kann. Ich denke so kommt man schneller zu einem fehlerfreien und robusten Html-Parser (der auf Anhieb auch effizient ist).

Noch schneller geht es natürlich mit der mshtml.dll.

Gruss
Pulpapex

07.06.2005 - 00:24 Uhr

Das mit den kontextfreien Sprachen stimmt natürlich. Man kann Html nicht mit einem RE ohne zusätzlichen Programmcode parsen.

Zwei weitere Vorschläge (neben den Links von Shaderman):

ANTLR ist ein Parser-Generator. Der erstellt aus einer Grammatik-Datei (BNF-ähnliche Notation, gespikt mit Aktionscode) einen Parser und einen Lexer als .Net-Klassen (normalerweise Java-Klassen, aber kann auch .Net-Code generieren). Für sehr rudimentäres Html sollte damit ein Parser hinzubekommen sein.

Ansonsten kann man in .Net auch die Html-Engine des IEs einbinden. Siehe dazu dieser Thread: HTML Code Parsen

Gruss
Pulpapex

07.06.2005 - 00:04 Uhr

Controls können in Z-Order (übereinander) angeordnet werden. Du kannst also im Hintergrund eine PictureBox haben und andere Steuerelemente davor anordnen.

Eine andere Möglichkeit ist, die Control.BackgroundImage-Eigenschaft zu verwenden. Die PictureBox fällt weg. Also bei deiner Form BackgroundImage zuweisen und die Steuerelemente wie gewohnt platzieren.

Gruss
Pulpapex

06.06.2005 - 20:00 Uhr

Herbivores Vorschlag klingt nach DAO-Pattern - Data Access Objects.

-> Eine DAO-Klasse oder vielmehr DAO-Interface dient als zentraler Punkt für den Datenbankzugriff. Es definiert Finder-Methoden für alle benötigten Anfragen, dazu noch Delete- und Insert/Update-Methoden (alternativ: Save-Methoden). Parameter- und Rückgabetypen sind (Werte-)Objekte oder Structs.

Meistens gibt es ein DAO pro Datenbanktabelle. ... es sei denn, eine Tabelle B ist abhängig von einer Tabelle A, dann können beide Tabellen in einem DAO zusammengefasst werden. Beziehungstabellen haben natürlich auch kein DAO. Beispiel Ist-Bestandteil Beziehung: ein Buch hat viele Seiten -> Buch-Tabelle, Seite-Tabelle, eine Seite existiert nicht ohne ein Buch. Es gibt dann ein Buch-DAO, aber kein Seiten-DAO. Wird ein Buch geladen, werden die Seiten automatisch mitgeladen. Alternativ können die Seiten auch verzögert beim ersten Zugriff nachgeladen werden. Oder per DAO-Methode: BuchDAO.ladeSeiten(Buch b).

Das DAO-Pattern abstrahiert vollständig von der Datenbanksicht. Es gibt keine Tabellen, kein SQL, einfach nur Objekte und eine Schnittstelle. Zu welcher Datenbank wann eine Verbindung (Stichwort: ConnectionString) aufgebaut wird, ist Sache der DAO-Implementierung (es muss nicht mal unbedingt eine Datenbank sein).

Eine konkrete Implementierung wird am besten per Factory-Pattern ausgewählt. Die abstrakte DAO-Factory definiert Create-Methoden für die verschiedenen DAOs. Die konkret verwendete Factory-Implementierung kann dann z.B. in der App-Config eingetragen sein, genauso der ConnectionString.

Gruss
Pulpapex

02.06.2005 - 16:49 Uhr

Könnte sein, dass wir aneinander vorbeireden. Ich meine nicht die while(true)-Schleife. In ReadCallback gibt es eine unendliche Rekursion.

Zur Funktionsweise von AsyncCallback:
Du musst dir die Receive-Methode aufgespalten vorstellen in Aufruf mit Parameterübergabe (BeginReceive) und Ergebnisrückgabe (EndReceive). Über den AsyncCallback wird signalisiert, dass die Methode abgearbeitet wurde und ein Ergebnis bereitsteht. Deine ReadCallback-Methode wird also wirklich nur einmal pro BeginReceive-Aufruf aufgerufen.

Wie gesagt, schreib das ganze erstmal ohne Threading. Später kann man immer noch eine asynchrone Variante hinzufügen. So hat man die Wahl ob der Code synchron oder asynchron arbeiten soll. Ausserdem ist es auch viel einfacher.

public class SnmpReader {

   // Synchrones Read
   public void Read() {
      // Straight forward implementation.
   }

   // Später hinzufügen ...
   public IAsyncResult BeginRead() {
      // Read asynchron aufrufen.
      // Stichwort: asynchrone Delegaten
   }

   // Später hinzufügen ...
   public void EndRead(IAsyncResult ar) {
      // Read-Aufruf abschliessen.
   }
}

Gruss
Pulpapex

02.06.2005 - 15:27 Uhr

Wave-Dateien sind PCM kodiert. Eine analoge Soundkurve wird mit fester Amplitudenabtastrate gesampled.

Diagramm, eine senkrechte Linie entspricht einem Samplewert:


Amp
|            ||
|  ||       ||||
| ||||     ||||||
+------------------ Zeit
       |||       ||
        |         |

Samples sind also schon die Amplitudenwerte/Lautstärkeangaben. Aus den Werten muss geeignet eine Gesamtlautstärke ermittelt werden. Als Vorschlag, man berechnet die aktuelle Gesamtlautstärke als Durchschnittswert der Absolutbeträge einer kleinen Samplefolge.

int[] samples = // .. ;
int vol = Avg(Abs(samples));

Ich weiss aber nicht ob das normalerweise so gemacht wird.

Gruss
Pulpapex

02.06.2005 - 14:22 Uhr

Die ReadCallback-Methode ist schrottig, ist eine Endlosschleife (der Code ist allgemein konfus).

Der Socket wird auch nicht wirklich asynchron gelesen. Der aufrufende Thread blockiert an receiveDone.WaitOne() bis der Lesevorgang abgeschlossen wurde (was wie gesagt nie passiert). Das Verhalten erreicht man viel einfacher ohne asynchrone Aufrufe.

Programmiere das ganze erst ohne Threads und asynchrone Methoden. Wenn das funktioniert kann später immer noch Asynchronität hinzugefügt werden, die auf der synchronen Implementierung basiert.

Gruss
Pulpapex

02.06.2005 - 14:03 Uhr

Hi Angren,

versuch' es mit SetLength. Die Methode müsste bei FileStream implementiert sein.

Gruss
Pulpapex

01.06.2005 - 22:42 Uhr

Hi Shaderman,

damit sind wahrscheinlich der normale lock-Block und die anderen Synchronsierungsmechanismen von .Net gemeint. Der Thread befindet sich in einer Synchronisation Domain bedeutet soviel wie der Thread hat den Lock/den exklusiven Zugriff.

WaitHandle.WaitAny blockiert einen Thread für längere Zeit. Wenn der Thread selbst schon einen Lock hält, können weitere Threads blockiert werden, was unschön ist, da es zu Starvations oder gar Deathlocks führen kann. Gibt man für den dritten Parameter (exitContext) true an, gibt der Thread zeitweilig seinen Lock ab. Ein anderer Thread kann dann für die Zeit den Lock akquirieren.

Ich glaube zumindest, dass es so funktioniert. So ganz sicher bin ich mir da nicht. Irgendwie kommt mir die Sache schwer handhabbar und fehleranfällig vor.
Szenario: ein Thread ändert teilweise Daten in einem kritischen Pfad, legt sich an WaitAny lahm und lässt einen zweiten Thread den kritischen Pfad betreten. Der zweite Thread modifizert seinerseits die Daten. Im Anschluss setzt Thread 1 seine Bearbeitung fort, und zwar mit den falschen Daten. Also da muss man aufpassen.

Also: wenn dein Thread selbst keinen Lock hält, ist der exitContext-Parameter wirkungslos. Wenn doch, würde ich standardmäßig erstmal immer false angeben.

Gruss
Pulpapex

01.06.2005 - 15:38 Uhr

Hi knopper,

du kannst Byte.Parse verwenden, um jeweils zwei Zeichen als ein Byte-Wert zu parsen.

Ungefähr so:

string str="0123456789abcd";
byte[] key = new byte[str.Length / 2];

// Key-Array füllen.
for(int i = 0; i < key.Length; i++) {

   // Jeweils zwei Zeichen als Byte parsen.
   string bString = str.Substring(2*i, 2);
   byte b = Byte.Parse(bString, NumberStyles.HexNumber);

   // Geparstes Byte ablegen.
   key[i] = b;
}

Gruss
Pulpapex

01.06.2005 - 14:55 Uhr

Dein Ausdruck muss übrigens sehr viel backtracken und ist dadurch langsam.

Das "(.)*" konsumiert erstmal soviele Zeichen, wie es kriegen kann. Also auch "</Beschreibung>". Im Anschluss schlägt der Match auf "</Beschreibung>" fehl, der Text ist ja schon konsumiert worden. Deshalb wird ein Zeichen "backgetrackt". Schlägt immer noch fehl, noch ein Zeichen zurück, schlägt immer noch fehl, noch ein Zeichen, usw, bis er wieder bei "<" angekommen ist. Erst dann kann "</Beschreibung>" erfolgreich gematcht werden.

Ändere es ab in:
"<Beschreibung>([^<]*)</Beschreibung>"

Gruss
Pulpapex

01.06.2005 - 13:26 Uhr

Wenn du den Code so belassen möchtest:

Regex.Match(
   xmlString, 
   "<Beschreibung>(.*)</Beschreibung>", 
   RegexOptions.Singleline);

Ich würde dir aber wie gesagt empfehlen, den Regex statisch zu definieren, so:

public class A {
   
   private static Regex beschreibungRegex = new Regex(
      "<Beschreibung>(.*)</Beschreibung>",
      RegexOptions.Compiled | RegexOptions.Singleline);

}

Gruss
Pulpapex

01.06.2005 - 12:58 Uhr

Hi st@tic,

du musst RegexOptions.Singleline verwenden. Ohne diese Option wird "." interpretiert als "Jedes Zeichen ausser \n". Mit der Option entspricht "." wirklich jedem Zeichen, wie es in deinem Fall gewünscht ist.

Den Regex-Ausdruck (doppelt gemoppelt) würde ich statisch in der Klasse definieren, er ändert sich ja nicht. So wie du es jetzt hast, muss der vom Regex intern verwendete Zustandsautomat ständig neu erzeugt werden, was aufwändig ist.

Gruss
Pulpapex

30.05.2005 - 15:45 Uhr

Der Server schickt eine Antwort, das ist klar. Das ändert aber nichts daran, dass man etwas senden muss, um den Verbindungsstatus festzustellen.

Mit der Socket.Connected-Eigenschaft kann abgefragt werden ob die letzte Datenübertragung erfolgreich war. Das entspricht einem empfangenen ACK-Bestätigungspaket, wie du es in Etheral gesehen hast.

Im Vorfeld einer Datenübertragung zu prüfen ob die Verbindung noch besteht, macht wenig Sinn. Also in der Art:

if(IsServerRespondig) {
   SubmitData();
}

Die Verbindung kann ja direkt nach der Überprüfung mit IsServerRespondig getrennt werden. Deshalb einfach senden und empfangen und auf eventuell auftretende Exceptions reagieren. Um festzustellen ob eine Nachricht vollständig ist, bietet es sich an, am Anfang immer die Nachrichtenlänge mitzusenden. So weiss man auch ob die Verbindung noch besteht und ob noch Daten empfangen werden müssen.

Den Verbindungsabbruch beim Lesen festzustellen, funktioniert auch. Jedenfalls, wenn der entfernte Socket ordnungsgemäß geschlossen wird. Ein blockierender, auf Daten wartender NetworkStream.Read-Aufruf liefert in dem Fall 0 Bytes zurück. Ich weiss allerdings nicht was passiert, wenn die Remote-Anwendung abrupt beendet wird, ohne den Socket zu schliessen.

Gruss
Pulpapex

27.05.2005 - 09:34 Uhr

Gibt es in deiner Anwendung ein oder mehrere Fenster?

Wenn es nur ein Fenster ist, versuch es mal so:

private void meiSummer_Click(object sender, System.EventArgs e) {

   // Hintergrundfarbe im Anwendungsfenster ändern.
   this.BackColor = Color.Lavender;

   // ..
}

ActiveForm ist aber auch bei mehreren Fenstern verkehrt. Es soll ja die Hintergrundfarbe eines bestimmten Fensters geändert werden und nicht die von irgend einem zufälligerweise aktiven.

Gruss
Pulpapex

20.05.2005 - 20:25 Uhr

Die NullReferenceException tritt auf, wenn bei einer Variablen, die null ist, versucht wird, auf Eigenschaften oder Methoden zuzugreifen.

Beispiel:

string a = null; // String a ist null.
int length = a.Length;  // löst eine NullReferenceException aus.

In deiner Codezeile gibt es zwei potenzielle Objekte, die null sein könnten, entweder frmSms oder das Objekt in frmSms.ActiveForm.

frmSms.ActiveForm.BackColor = Color.Lavender;

Um die Exception zu umgehen, muss man vor dem Zugriff auf ungleich null prüfen (ich nehme mal an frmSms ist immer ungleich null):

if(frmSms.ActiveForm != null) {
   frmSms.ActiveForm.BackColor = Color.Lavender;
}

Gruss
Pulpapex

20.05.2005 - 20:03 Uhr

das funktioniert leider nicht so ganz. Da ich dann nicht alle Daten vom IRC Server bekomme.

Hast du herausbekommen, warum das so ist? An der neuen MainMessageLoop kann es eigentlich nicht liegen. Die überprüft nur ob ein lesender Zugriff blockieren würde, weil keine Daten im Empfangspuffer sind. Weil nichts da ist, wird auch nicht versucht was zu lesen.

Beim nächsten Schleifendurchlauf könnte wieder was angekommen sein. Auch gleich mehrere Textzeilen. Die werden dann in mehreren Schleifendurchläufen zur RichTextBox hinzugefügt. Ich sehe nicht wie dabei Daten unterschlagen werden können.

20.05.2005 - 17:35 Uhr

Ich habe mal einen CodeProject-Artikel rausgesucht. Da wird u.a. beschrieben wie man den Form-Border ausblenden kann. Im Artikel geht es zwar um MdiForms, es sollte aber auch bei unabhängigen Forms funktionieren:

Getting a "Handle" on the MDI Client

20.05.2005 - 17:14 Uhr

Das liegt wahrscheinlich daran, dass die Abbruch-Bedingung der while-Schleife gar nicht geprüft werden kann. Vorher blockiert sr.ReadLine und wartet auf die nächste Textzeile.

Für den Anfang versuch es mal so:

public void MainMessageLoop() {

   NetworkStream stream = (NetworkStream)sr.BaseStream;

   while(status==true) {

      // Sind Bytes verfügbar (auch eine ganze Zeile??)
      if(stream.DataAvailable) {
         rich_Status.AppendText(sr.ReadLine() + "\\n");

      // Wenn nicht, nicht versuchen zu lesen, das würde blockieren.
      // Thread stattdessen pausieren.
      } else {
         Thread.Sleep(500);
      }
   }
}

Zu der anderen Frage: der C#-Compiler und die IDEs können auch DLLs ausgeben (/target:library). Allerdings können diese dann nicht einfach in einer C++ Anwendung verwendet werden. Da es .Net-DLLs sind, wird die .Net-Runtime benötigt.

Gruss
Pulpapex

20.05.2005 - 16:50 Uhr

1.) ref auf ne ArrayList ist doppelt gemoppelt, da es eh ein Referenztyp ist.

Da gibt es schon einen Unterschied. In dem Fall ist ref aber wirklich unnötig, da das ArrayList-Objekt nicht geändert wird und nicht zurückgegeben werden soll.

Ständig RichTextBox.Text neu zu zuweisen ist deshalb aufwändig, weil jedes Mal die Darstellung neu gezeichnet wird.

Was man auch nicht machen darf, ist, in einer Schleife Strings mit dem +-Operator zusammen bauen. Du konkatenierst 10.000 Zeichen, d.h. es werden 10.000 String-Objekte erstellt, jedes ein Zeichen länger als das vorhergehende. Das verbraucht 250Mb an Arbeitsspeicher, obwohl nur das letzte String-Objekt mit 210.000 Bytes wirklich benötigt wird. Für sowas immer den StringBuilder verwenden.

Gruss
Pulpapex

20.05.2005 - 16:28 Uhr

So wie es aussieht, gar nicht. Der Rahmen wird nativ gezeichnet, genau wie die Titelleiste. Ich wüsste nicht wie man da mit .Net-Mitteln rankommen könnte.

Das ClientArea der Form selbst neu festzulegen, brauchst du gar nicht erst versuchen. Wird nicht funktionieren,
siehe: Size vs. ClientSize bei eigenem Control

Bleibt noch, Rahmen und Titelleiste ganz zu deaktivieren und alles selbst zu zeichnen. Oder am XP-Style rumzudrehen, auf www.codeproject.com gibt es ein paar Artikel zu dem Thema.

Gruss
Pulpapex

20.05.2005 - 16:08 Uhr

Was machst du denn mit der Liste? Einfach nur auslesen dauert vielleicht 20 ms, viel länger bestimmt nicht.

Warum muss es eine dynamische Liste sein? Wahrscheinlich löschst du am Anfang oder aus der Mitte oder fügst zwischendurch ein. Sowas ist aufwändig, siehe dazu: Duplikate aus ArrayList entfernen.

Gruss
Pulpapex

19.05.2005 - 13:34 Uhr

Inversion of Control (IoC) ist ein schöner Ansatz, nicht nur interessant im Zusammenhang mit einem speziellen Container oder Framework. Es ist auch ein einfaches Prinzip, das man beim Klassendesign im Hinterkopf haben sollte.

Prinzip: Eine Komponente A benötigt zur Funktion eine andere Komponente B. A holt oder instanziiert B jedoch nicht selbst, sondern bekommt die benötigte Kompoente von aussen in einer Eigenschaft gesetzt.

Vorteil: das Klassendesign wird modularer. Klassen/Komponenten bleiben unabhängig und können leichter wiederverwendet werden. Alles ist austauschbar. Wenn Interfaces verwendet werden, können sogar ganze, zugrundeliegende Technologien getauscht werden.

Und ganz wichtig, das Prinzip vermeidet die viel zu oft eingesetzten, unsäglichen Singletons und statischen Variablen.

Gruss
Pulpapex

18.05.2005 - 13:10 Uhr

Hi kiwi_girl,

translate entspricht dann String.Replace in .Net, instring muss mit String.IndexOf nachgebildet werden.

Gruss
Pulpapex

18.05.2005 - 13:04 Uhr

Hi Dako,

RichTextBox hat eine GetLineFromCharIndex-Methode. Als CharIndex wird SelectionStart übergeben.

Gruss
Pulpapex

// Verschoben nach Windows Froms. Bitte mal selbst drauf achten.

18.05.2005 - 09:52 Uhr

Nur ein return, benötigt zwar zwar mehr Code, der ist aber meiner Meinung nach leichter wartbar.

Ausgehend vom Code mit vielen returns.

public override bool Equals(object a) {

   Class1 other = a as Class1;
   if(other != null) {
      return false;
   }

   bool equals = true;
   equals &= this.PropertyA.Equals(other.PropertyA);
   equals &= this.PropertyB.Equals(other.PropertyB);
   equals &= this.PropertyC.Equals(other.PropertyC);

   for(int i = 0; i < this.List.Count; i++) {
      object thisItem = this.List[i];
      object otherItem = other.List[i];

      equals &= thisItem != null ?
                thisItem.Equals(otherItem) : otherItem == null;

      if(!equals) {
         return false;
      }
   }

   return equals;
}

Wo setze ich einen Breakpoint, wenn ich wissen möchte was die Methode als Ergebnis liefert?

Ich möchte noch Logausgaben der Form String.Format("this.Equals(other): {0}", equals) machen, ich möchte noch eine Methode aufrufen, z.B. ein Ereignis feuern, irgendetwas disposen oder eine Variable null setzen, damit sie vom GC getilgt wird. Wie füge ich das am geschicktesten ein?

So sieht es aus mit vielen returns und dazu noch Log-Ausgaben. Der Code wird redundant und dadurch fehleranfälliger und schwerer wartbar:

public override bool Equals(object a) {

   Class1 other = a as Class1;
   if(other != null) {
      string log = "this.Equals(other): false";
      Console.WriteLine(log);
      return false;
   }

   bool equals = true;
   equals &= this.PropertyA.Equals(other.PropertyA);
   equals &= this.PropertyB.Equals(other.PropertyB);
   equals &= this.PropertyC.Equals(other.PropertyC);

   for(int i = 0; i < this.List.Count; i++) {
      object thisItem = this.List[i];
      object otherItem = other.List[i];

      equals &= thisItem != null ?
                thisItem.Equals(otherItem) : otherItem == null;

      if(!equals) {
         string log = "this.Equals(other): false";
         Console.WriteLine(log);
         return false;
      }
   }

   string log = String.Format("this.Equals(other): {0}", equals);
   Console.WriteLine(log);

   return equals;
}

Im Vorfeld kann man gar nicht wissen was später noch abgeändert und hinzugefügt werden muss. Mit vielen returns muss man den gesamten Code umbauen, dass nur ein return am Ende bleibt, oder man fügt vor jedem return identischen Code ein. Mit nur einem return erspart man sich den ganzen Aufwand, musste aber in der ersten Version bisschen mehr tippen.

Gruss
Pulpapex

17.05.2005 - 22:41 Uhr

Also ich mache es lieber so wie Programmierhans, nur ein return am Methodenende.

Wenn die Methode einen Wert berechnen soll, definiere ich am Methodenanfang eine Variable, die, wenn es geht, so heisst wie die Methode selbst. Die Variable wird dann am Ende zurückgegeben. Hier beispielhaft eine Equals-Implementierung:

public override bool Equals(object a) {
   bool equals = false;

   Class1 other = a as Class1;
   if(other != null) {

      equals &= this.PropertyA.Equals(other.PropertyA);
      equals &= this.PropertyB.Equals(other.PropertyB);
      equals &= this.PropertyC.Equals(other.PropertyC);

      for(int i = 0; i < this.List.Count; i++) {
         object thisItem = this.List[i];
         object otherItem = other.List[i];

         equals &= thisItem != null ? 
                   thisItem.Equals(otherItem) : otherItem == null;

         if(!equals) {
            break;
         }
      }
   }

   return equals;
}

Ich finde das so besser lesbar, ein return mitten im Code kann man schnell mal übersehen. Ausserdem ist der Code besser wartbar. Gibt es mehrere returns, muss unter Umständen identischer Code an mehreren Stellen eingefügt werden.

Am Anfang eine Vorbedingung testen und gegebenenfalls sofort zurückkehren, ist noch ok. Aber aus einer Schleife mit return zurückkehren, geht gar nicht (meiner Meinung nach).

Gruss
Pulpapex

17.05.2005 - 10:14 Uhr

Du kannst deiner Anwendung eine App-Config mitgeben. Die Datei befindet sich im Verzeichnis der Exe und ist benannt wie die Exe, nur mit config-Endung. In der App-Config kann eingestellt werden, wo sich eine bestimmte Dll befindet. Ob man auch einen Dll-Suchpfad angeben kann, weiss ich nicht, wäre natürlich einfacher.

Msdn: Specifying an Assembly's Location

Gruss
Pulpapex

12.05.2005 - 15:40 Uhr

Genau,

wenn eine Zeitspanne einen Tag überschreitet, wird die Anzahl der Tage mit angezeigt. Die Stellen für die Tage sind optional.

Hier wird es genauer beschrieben: TimeSpan.ToString

Gruss
Pulpapex

12.05.2005 - 13:40 Uhr

Wenn Graphics.Clip nicht festgelegt ist, gibt es keine "Auswahl". D.h. der Auswahlbereich ist unendlich gross. VisibleClipBounds liefert dann die gesamte Zeichenfläche des Controls.

Ich hab ein Bild angehängt. Es sollte die Bedeutung von VisibleClipBounds veranschaulichen.

Gruss
Pulpapex

12.05.2005 - 13:10 Uhr

Hi dschmoegner,

über die Graphics.Clip-Eigenschaft kann die Zeichenfläche eines Graphics-Objektes auf eine unförmige Region eingeschränkt werden. Das entspricht einer Auswahl in einem Malprogramm. Wenn es im Bild eine Auswahl gibt, wirken sich alle Zeichenoperationen nur noch auf diese Auswahl aus.

VisibleClipBounds liefert das Rechteck um die Clip-Region, beschränkt auf die sichtbare Fläche (der Clip kann ja grösser als der sichtbare Bereich sein). Wenn der Clip unendlich gross ist, liefert VisibleClipBounds das gleiche Rechteck wie Control.ClientRectangle, nehme ich mal an.

Gruss
Pulpapex

12.05.2005 - 13:00 Uhr

Mit Form.KeyPreview = true, kann festgelegt werden, dass Tastatur-Ereignisse zunächst auf Form-Ebene bearbeitet werden sollen (ein bei der Form registrierter EventHandler springt an). Im Anschluss werden die Ereignisse zum jeweiligen Control mit dem Fokus weitergeleitet und dort nochmal ausgelöst. Es sei denn, man markiert das Ereignis als behandelt, e.Handled = true.

public class Form1 : Form {

   public Form1() {
      KeyPreview = true;
      KeyDown += new KeyEventHandler(HandleKeyDown);
   }

   private void HandleKeyDown(object sender, KeyEventArgs e) {
      if(e.KeyCode == Keys.F12) {
          e.Handled = true;
      }
   }
}

Gruss
Pulpapex

// Verschoben nach "Windows Forms"

12.05.2005 - 09:58 Uhr

Geht es um die Darstellung in der Eigenschaftenleiste von VS?

Die kann beeinflusst werden, indem bei der Klasse oder Eigenschaft ein TypeConverter-Attribute gesetzt wird. Über den Weg kann das Ganze auch editierbar gemacht werden.

Hier ein Artikel dazu auf CodeProject: Customized display of collection data in a PropertyGrid

Für weitere Artikel such' auf CodeProject nach "PropertyGrid".

Gruss
Pulpapex

11.05.2005 - 23:19 Uhr

Hi Tokka,

es ist doch eine 3-Tier Anwendung. Wie soll der Benutzer der Middletier denn an die Xml-Files rankommen? Der Zugriff erfolgt doch remote oder nicht? Selbst wenn nicht, sehe ich da kein grosses Problem. Wenn die Anwendung lokal läuft, kann der Benutzer sowieso alles machen was er will. Die Datenbank wird dann auch lokal laufen. Wer stellt schon eine Datenbank öffentlich ins Netz? Und wenn sie lokal läuft, kommt man ohnehin ran. (Ansonsten schildere nochmal dein befürchtetes Szenario. Wahrscheinlich habe ich so einiges nicht richtig bedacht.)

Übrigens der Java O/R-Mapper Hibernate verwendet dieses Prinzip. Das Klassen- zu Tabellen-Mapping wird in Xml-Dateien angegeben. Zusätzlich können auch die Queries zu einer Klasse in der Datei abgelegt werden. Im Code sagt man dann nur noch "GetNamedQuery", setzt die Parameter und schickt ab. Echt vorteilhaft dabei ist auch, dass die Queries angepasst werden können, ohne am Code etwas ändern zu müssen. Einfach mit einem Texteditor editieren und fertig.

Also ich würde es so lassen,

Gruss
Pulpapex

10.05.2005 - 20:02 Uhr

Tja, so eine ToString-Überladung, wo man einen Format-String angeben kann, hat TimeSpan leider nicht. Ich behelfe mir da immer, indem ich den TimeSpan in ein DateTime umwandle. DateTime hat die benötigte ToString-Methode.

TimeSpan dauer = DateTime.Now - ku[i].startzeit;

// dauer in DateTime umwandeln, 
// um ToString(format) verwenden zu können.
DateTime dauerDateTime = new DateTime() + dauer;
string dauerString = dauerDateTime.ToString("hh:mm:ss");

Weiss jemand noch eine bessere Lösung?

Gruss
Pulpapex

10.05.2005 - 16:11 Uhr

Hi wicking,

ich glaube eher du hast es noch nicht ganz verstanden.

Ja, und was ist mit Linux? Wie läufts da? Also wie kann ich ein natives Binary erzeugen, welches ohne .NET- (ok, gibts ja garnicht) bzw ohne Mono-Framework läuft?

Z.B. für kleine Mini-Progrämmchen, die sowieso nur für eine Platform und Betriebssystem geschrieben sind, weil nur da sinnvoll usw.

Das geht nicht. Man kann keine kleinen, nativen Mini-Progrämmchen für .Net/Mono schreiben, die ohne Framework laufen. Man kann höchstens ein Setup-Programm erstellen, das das Framework mit installiert. Das Ganze ist dann aber über 25 Mb gross. Wenn überhaupt kein Framework benötigt werden soll, muss auf andere Sprachen ausgewichen werden. Das hat KRambo gemeint.

Ansonsten empfehle ich dir einen Blick in die Board-FAQ oder gleich die Board-Suche. Das Thema gab es schon zig mal.

Gruss
Pulpapex