Laden...

Forenbeiträge von Schattenkanzler Ingesamt 238 Beiträge

25.08.2010 - 13:26 Uhr

Hallo zusammen!

Ich habe mich ein wenig mit der Skype-API beschäftigt und auch erfolgreich ein erstes Programm entwickelt, das mit Skype zusammenarbeitet.
Eine Sache würde ich gerne noch machen, weiß aber leider nicht wie und konnte bisher auch keine Lösung finden:

Ich würde gerne eine eingehende Nachricht, wenn diese mit einem bestimmten Trigger beginnt, verändern, bevor diese angezeigt wird.

Als Beispiel:

Wenn User A an User B die Nachricht "#trigger#XYZ" schickt, dann möchte ich das umwandeln in z.B. "XYZ". Der Trigger soll also nicht mehr angezeigt werden. 

Ziel der Sache ist eine Funktion, die letztendlich nichts anderes tut, als Abkürzungen wie AFAIK, IMHO, etc. automatisch übersetzt, damit man unbekannte Abkürzungen nicht immer googlen muss 🙂

Bei ausgehenden Nachrichten ist das kein Problem, im entsprechenden Handler kann man den Message-Body abändern, bei eingehenden Nachrichten geht das aber nicht so ohne weiteres.

Kennt jemand einen Weg, das zu realisieren?

Ich würde mich über eine Antwort sehr freuen!

Vielen Dank im Voraus - SK

09.02.2010 - 18:17 Uhr

Also ich habe mal eine Weile in einem kleinen Unternehmen als Praktikant gearbeitet, dessen Datenbank aus sehr (!) vielen Quellen aufgebaut wurde. Die haben bei einem Redesign GUIDs als PK verwendet, um das Zusammenführen komfortabel zu gestalten, lief auch gut, gab keine Probleme.
Allerdings kam es da auch nicht wirklich auf die Performance an (muss jedoch sagen, dass das System - trotz sehr umfangreicher DB - nicht langsam war).

Meistens ist das allerdings Overkill.

Greets - SK

09.02.2010 - 16:53 Uhr

verwendetes Datenbanksystem: db4o 7.4

Hallo zusammen!

Ich habe ein Problem mit der db4o-Objektdatenbank und hoffe, dass mir hier weitergeholfen werden kann.

Ich arbeite gerade an einer Art Plugin-System, welches den Plugins auch einen Data-Manager bereitstellt. Über diesen können die Plugins dann eben Daten (selbst definierter Datentypen) aus der Datenbank des Plugin-Systems lesen bzw. in die Datenbank des Systems schreiben.

Dazu stelle ich generische Methoden Save<T> und Query<T> bereit, wobei für T nur Typen zugelassen sind, die von einem - ebenfalls vom Pluginsystem bereit gestellten - Interface erben.

Leider verhält sich das Ganze etwas merkwürdig. Ist keine Datenbank vorhanden und starte ich meinen Test (ein Plugin speichert eine Instanz eines eigenen Datentyps), wird die Instanz gespeichert, nachdem die Datenbank erzeugt wurde und kann auch wieder ausgelesen werden. Starte ich die Anwendung danach erneut, wird eine InvalidCastException geworfen:

System.InvalidCastException: Unable to cast object of type 'SamplePlugin.TestType' to type 'Db4objects.Db4o.Reflect.Generic.GenericObject'.

Beim Auslesen tritt dieselbe Exception auf (natürlich sind dann die Typen vertauscht).

Dieses Verhalten ist auch reproduzierbar, also wenn ich die Datenbank dann lösche und es nochmal versuche, klappt wieder nur der erste Versuch, der zweite schlägt fehl.

Ich habe dann mal mittels

_meinObjectContainer.Query<object>()

alle Objekte aus der Datenbank geholt und dort das hier gefunden:

1. Db4objects.Db4o.Reflect.Generic.GenericObject, String representation: (G) SamplePlugin.TestType, SamplePlugin
2. System.Guid

Im Debug-Modus habe ich mir das 1. Objekt mal näher betrachtet, es handelt sich definitiv um die gespeicherte Instanz.

Ich gehe davon aus, dass das Problem daher kommt, dass sich der zu speichernde/lesende Datentyp und die ausführenden Methoden in zwei verschiedenen Assemblies befinden und beim Laden der Plugin-Assembly irgendetwas passiert, was das Casting-Problem auslöst. Nur was?

Weiß jemand, wie ich meine Einstellungen/Methoden ändern, bzw. was ich tun muss, um die Plugins erfolgreich Lesen und Schreiben zu lassen?

Ich würde mich sehr über eine Antwort freuen und hoffe, dass mein Problem deutlich geworden ist!

MFG und Danke im Voraus - SK

05.01.2010 - 15:01 Uhr

Hey Regenwurm,

ich weiß nicht, ob ich dich richtig verstehe, aber wenn ja, dann versuch doch mal Folgendes:

Erstelle eine Klasse "ListBoxItem" (oder wie auch immer du sie nennen willst). Gib ihr all die Properties, die du von deinen Items erwartest (z.B. "Text" oder so) und überschreib die ToString()-Methode, damit die string-Repräsentation der Items deinen Vorstellungen entspricht.

Du kannst dann Instanzen der Klasse einfach direkt zur Liste hinzufügen.

Hier ein bisschen Code (quick'n'dirty):


public class ListBoxItem
{
    public string Text { get; set; }

    public ListBoxItem(string text) { this.Text = text; }
    public ListBoxItem() : this("ListBoxItem") { }

    public override string ToString()
    {
        return "Cool LBI: " + Text;
    }
}

und in einer Form mit ListBox:


private void Form1_Load(object sender, EventArgs e)
{
     for (int i = 0; i < 10; i++)
     {
         ListBoxItem lbi = new ListBoxItem("ITEM " + i.ToString());
         this.listBox1.Items.Add(lbi);
     }
}

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
     this.Text = this.listBox1.SelectedItem.ToString();
}

Hilft dir das weiter?

Falls du wirklich unbedingt ein neues Control bauen willst, dann würde ich spontan so herangehen:

Die Property "Items" würde ich auf eine (eigene) Collection-Klasse zeigen lassen. Also so was:

class MyCollection : List { ... }

class MyListBox : ListBox
{
    public MyCollection Items { get; set; }
}

Damit wärst du dann in der Lage so Sachen zu machen wie

MyListBox box = new MyListBox();
box.Items.IrgendeineMethode()

Irgendeine Alarmglocke klingelt da grad bei mir...kann es aber nicht greifen.

Greets - SK

05.01.2010 - 14:45 Uhr

@tom-essen: Ja, das Programm kenn ich, aber leider fehlt da der Quellcode, der ist es, der mich hauptsächlich interessiert...

Bastele gerade selbst an einem GoL und habe ein paar Probleme mit Flackern usw., also wäre die ein oder andere Anregung in Quellcode-Form natürlich sehr schick 😃

Hmm...also wenn jemand das Archiv noch haben sollte - immer her damit 😉

Greets und Danke - SK

04.01.2010 - 21:24 Uhr

Hi zusammen!

Ich bin vor einer ganzen Weile mal über diesen Beitrag gestolpert und fand das GoL von vbtricks ziemlich super, wenn ich mich recht erinnere...leider kann man die Seite nicht mehr aufrufen - hat irgendwer noch das Programm bzw. den Quelltext?

Würde mich sehr freuen, wenn mir jemand helfen könnte!

Greets - SK

06.02.2009 - 15:18 Uhr

Wow, toller Artikel! 👍 Bin ich jetzt gerade erst drauf gestoßen (leider nach einer Menge Arbeit...na ja, besser spät als nie).

Eine Ergänzung und eine Frage hab ich aber, hoffe, das sprengt den Rahmen nicht...

Ergänzung: Maximieren

Wenn man in borderoverride.zip (von egrath) doppelt auf die Titelleiste klickt, passiert - anders als normalerweise - nichts. Könnte mir vorstellen, dass das den ein oder anderen stört und möchte da mal meinen Senf dazu abgeben...

Das Verhalten kann man ganz leicht realiseren, indem man der Methode WndProc(ref Message) den folgenden case-Block hinzufügt:

case WM_NCLBUTTONDBLCLK:
    this.WindowState = this.WindowState.Equals(FormWindowState.Maximized) ? FormWindowState.Normal : FormWindowState.Maximized;
    break;

Die neue Konstante muss man natürlich noch angeben:

private const int WM_NCLBUTTONDBLCLK = 0x00A3;

So, nun zu meiner Frage.

Wenn die Form maximiert ist, kann man sie immer noch verschieben. Das widerspricht IMHO dem Verhalten einer "normalen" Windows-Form. Muss man dieses Verhalten einfach nachbauen (nach dem Motto "wenn maximiert, dann nicht bewegbar") oder gibt es da einen nativeren bzw. eleganteren Weg über die API?

Würde mich wirklich interessieren, da ich momentan (nebenbei) eine Form alá Office 2007 bastele und dazu diese Techniken benutzen möchte.

Greets - SK

14.11.2008 - 14:48 Uhr

Hi svenson! Danke erstmal für deine Antwort.

Wenn ich dich richtig verstanden habe, dann kann ich zunächst mal alle Algorithmen unter dem folgenden Interface abhaken:

public interface ICryptoAlgorithm
{
    byte[] Encrypt(byte[] data, byte[] password);
    byte[] Decryp(byte[] data, byte[] password);
}

Muss nur eben bei Scherzen wie IVs diese berechnen (z.B. wie du gesagt hast über Hashing-Algorithmen).

Jetzt wüsst ich nur noch gerne, ob man das bei allen (im Sinne von "die meisten") kryptographischen Verfahren so machen kann, oder ob ich noch irgendwo einen Haken übersehe?

Was deine Vorschläge zur Architektur angeht:

Ich hatte mir ein System wie das folgende vorgestellt:

Der Benutzer kann eine "Joblist" anlegen, also eine Liste von Aufgaben, die nacheinander bzw. in mehreren Threads parallel ablaufen. Ein Job kann z.B. sein: Datei ver-/entschlüsseln, Text ver-/entschlüsseln und das gleiche noch mal für Hashes.
Ein Job/Task (wie man es nennen will) besitzt dann Informationen über die auszuführende Aktion und den dazu zu verwendenden Algorithmus. Daher brauche ich halt dieses gemeinsame Interface. Wie genau die einzelnen Algorithmen arbeiten, ist dann natürlich in den konkreten Implementierungen geregelt, also beispielsweise das Auffüllen der Daten, falls notwendig.
Dateien/Daten ein- und auslesen übernimmt das Hauptprogramm. Jetzt verstehe ich auch, was du mit der 10GB-Datei meinst...da müsste man dann eben einen Teil auslesen, verschlüsseln, zwischenspeichern, etc.

Ok, hab ich noch was übersehen? Würde sonst eben schon mal anfangen...

Ja, danke erstmal!

Greets - SK

13.11.2008 - 22:08 Uhr

Hallo zusammen!

Ich habe zwei Fragen, die mich seit einer Weile beschäftigen und die ich hier gerne stellen möchte.

Zunächst kurz der Hintergrund, aus dem diese Fragen gewachsen sind: für einen Kurs in der Uni schreibe ich ein kleines Tool, welches verschiedene kryptographische Verfahren bereitstellen soll. Am liebsten würde ich das mit einem Plugin-System machen (daher die zweite Frage). Also der Gedanke war: Das Programm an sich kann letztendlich nicht viel mehr als Ein- und Ausgabe, während die Plugins sich um die Ver- und Entschlüsselung von Daten kümmern.

So, nun zu meiner ersten Frage. Die bezieht sich auf die Rijndael-Verschlüsselung. In allen Beispielen, die ich gefunden habe (bisher) muss man dem Algorithmus einen Schlüssel und einen Vektor übergeben. Soweit alles klar, nur frage ich mich: In allen Programmen, die ich zu dem Thema bisher kennengelernt habe, gibt man - unabhängig vom verwendeten Algorithmus - immer nur ein Passwort für die Verschlüsselung an, mehr nicht.
Ich würde das auch gerne so machen (ein PW weitergeben ist schließlich weitaus komfortabler, als auch noch einen IV mitzugeben...), frage mich nur, wie man - obwohl man eben nur diese eine Eingabe (das Passwort) hat - dennoch einen sicheren IV berechnet?

Oder kürzer: Errechnet man einen IV aus dem angegebenen Passwort oder wie wird das im Allgemeinen gemacht? Würde ungern einen Standard-IV hart codieren, klingt zu sehr nach Sicherheitslücke...

Die zweite Frage ergibt sich eigentlich schon aus der ersten. Wie bereits erwähnt, würde ich gerne über Plugins die kryptographischen Verfahren realisieren. Als ich mir einen kleinen Überblick über die verschiedenen Verfahren verschafft habe, wurde mir klar, dass es verschiedene Eingaben gibt, also man nicht einfach ein Interface machen kann wie:


public interface ICryptoAlgorithm
{
    byte[] Encrypt(byte[] data, byte[] password);
    byte[] Decryp(byte[] data, byte[] password);
}

Will sagen: Der eine Algorithmus braucht vielleicht nur ein Passwort, der andere ein Passwort und einen Vektor, wieder andere (Caesar z.B.) eigentlich nur eine Zahl, etc. pp.

Deshalb bin ich schon eine Weile am Grübeln, wie ich am besten ein möglichst allgemeines gemeinsames Interface realisieren kann und würde gern mal eure Meinung dazu hören. Vielleicht hatte ja schonmal jemand ein ähnliches Problem und kann mir unter die Arme greifen?

Also nochmal zusammenfassend:

  1. Wie realisiere ich AES/Rijndael sicher, obwohl "nur" ein Passwort angegeben werden muss/kann?

und

  1. Habt ihr eine Idee für ein möglichst allgemeines Interface bzw. eine Vorgehensweise/Architektur (bin nicht zwingend an Interfaces gebunden), mit dem/der möglichst viele kryptographische Verfahren abgedeckt sind?

Soweit meine Fragen. Ich hoffe, sie sind soweit verständlich (falls nicht, gebe ich natürlich gerne Auskunft) und ihr könnt mir helfen.

Greets und schonmal danke - SK

P.S: Natürlich bin ich auch für jeden Link-Tipp zum Thema Kryptographie mit .NET und anderen Themen, die zur Fragestellung passen dankbar! 🙂

28.08.2008 - 17:40 Uhr

Hallo zusammen!

Ich bin jetzt schon eine Weile auf der Suche nach leicht verständlichen Quellen zum Thema automatisches Layout von Graphen.
So was hier würde ich gerne haben/machen: Beispiel (es muss nicht genau das sein, aber das Prinzip sollte klar sein, oder?).

Leider bin ich bisher immer nur auf closed-source u.ä. gestoßen, was mir nicht sehr viel bringt, da der Layout-Algorithmus in meine eigene Anwendung mit rein soll...

Hat jemand von euch eine gute Quelle für solche Informationen?

Würde mich sehr über Hilfe freuen!

Greets - SK

P.S: Wenn jemand einen eigenen Algorithmus hat, immer gerne 🙂

23.08.2008 - 09:28 Uhr

Hmm, das ist ja mal schade.

Na dann werd ich wohl bei Texten nicht mehr den Path zeichnen, sondern eben direkt über das Graphics-Objekt.

Der Pfad dient mir auch hauptsächlich zur Bestimmung von Überschneidungen und Klicks, etc.

(Und wenn ich den string zum Pfad hinzufüge, aber nicht den Pfad, sondern eben "traditionell" zeichne, dann sollte das ja immer noch gehen, oder? Berichtigt mich, falls ich daneben liegen sollte...)

Danke euch erstmal!

Falls noch jemand eine Idee hat immer her damit 🙂

Greets - SK

22.08.2008 - 20:23 Uhr

Hallo zusammen!

Ich arbeite gerade an einem Steuerelement, welches u.a. auch strings grafisch darstellt.

Habe dazu verschiedene Klassen gebaut, die die ganzen grafischen Elemente zeichnen, funktioniert auch soweit.
Was mir nur aufgefallen ist: Wenn ich einen string mittels


this.Path.AddString("meinString",
                this.Style.Font.FontFamily,
                (int)this.Style.Font.Style,
                this.Style.Font.Size,
                new RectangleF(this.Position, this.Size), 
                myStringFormat
            );
graphics.FillPath(this.Style.FillBrush, this._path);

zeichne, dass er dann leider vollkommen anders aussieht (so unscharf), als wenn ich ihn direkt über ein Graphics-Objekt zeichne.
Habe ein Bild angehängt, damit klar ist, was ich meine...die beiden Ausgaben haben den gleichen Font und nutzen das gleiche Graphics-Objekt.

Kann man das irgendwie ändern? Ich würde gerne den mittels GraphicsPath gezeichneten string genau so aussehen lassen wie den blauen im Bild, der über Graphics gezeichnet wurde. Hab ich eine Einstellung vergessen? Bin mit meinem Latein langsam am Ende...

Würde mich sehr über eure Hilfe freuen!

Greets - SK

27.06.2008 - 10:12 Uhr

Hallo,

ich habe es jetzt etwas anders gelöst. Und zwar hat das Projekt nun noch eine neue Assembly bei sich, die sich um die Persistenz der Daten kümmert.
Darin gibt es eine abstrakte Basis, den "APersister", der - momentan - eine Save und eine Load-Methode hat.

Davon abgeleitet gibt es - momentan - einen XmlPersister, der sich um die Speicherung der Objekte im XML-Format kümmert und sie gegen ein Schema validiert.

So kann ich später ggf. neue Persister implementieren, die z.B. nach SQL Server speichern oder wohin immer ich will.

Um den Thread nicht vollends sinnlos zu machen, hier noch ein kleines Beispiel, wie die Erzeugung des XML vonstatten geht:


public override XElement ToXML(XNamespace targetNamespace)
{
    XElement xml = new XElement(targetNamespace + "document",
                new XAttribute("name", this.Name),
                new XAttribute("guid", this.ID));

    return xml;
}

Die neue XML-API ist durchaus schick, kann ich nur empfehlen 🙂

Danke trotzdem - SK

23.06.2008 - 22:51 Uhr

Hallo zusammen!

Ich muss für ein größeres Projekt ein doch recht komplexes Objekt serialisieren (und später auch wieder deserialisieren). Eigentlich hatte ich es mir schön einfach vorgestellt, der XmlSerializer ist ja eigentlich auch sehr komfortabel.

Was ich dabei aber nicht bedacht hatte (wusste es einfach nicht): Die Properties mit unterschiedlichen Accessoren. Die lassen sich ja leider nicht mit dem XmlSerializer serialisieren und führen zu Compilerfehler CS0200.

Beispiel:

public class Speichermich
{
    private string _irgendwas;

    public string Irgendwas
    {
        get { return this._irgendwas; }
        set { this._irgendwas = value; }
    }
}

Lässt sich einwandfrei serialisieren.

Nur habe ich die Problematik, dass die von mir zu serialisierenden Klassen größtenteils Properties der folgenden Form haben:

public class Problemklasse : Basisklasse
{
    private List<AndereBasisklasse> _elemente;

    public List<AndereBasisklasse> Elemente
    {
        get { return this._elemente; }
        internal set { this._elemente = value; }
    }
}

Hintergrund ist der, dass die Problemklassen eine Hierarchie aufbauen, die zwingend erforderlich ist. Von außen (außerhalb ihrer Assembly) soll man sie nicht erzeugen oder per set auf ihre Properties zugreifen können. Entsprechend sind auch die Konstruktoren dieser Klassen internal.

Und da fangen die Probleme an 🙁

Ich frage mich jetzt, wie ich das Problem lösen kann...mir sind dazu nach Recherche diese vier Möglichkeiten in den Sinn gekommen:

  • Properties allesamt konsequent auf public setzen
  • Anderen (ggf. veralteten ?) Serialisierungs-Mechanismus benutzen
  • Eigene XmlSerializer-Klasse implementieren
  • Wrapper-Klassen schreiben

Möglichkeit 1 fällt weg, da die Properties ja von außen nicht setzbar sein sollen, von innen aber schon.
Vor Möglichkeit 3 scheue ich mich sehr, da ich denke, dass die Performance und die Zuverlässigkeit einer solchen Klasse wahrscheinlich etwas hinken würde.

Bleiben also Möglichkeit 2 und Möglichkeit 4.

Nummer 4 muss ich vielleicht kurz erklären.

Ich habe bei meiner Suche auf einer Seite im Netz irgendwo einen entsprechenden Hinweis gelesen. Man könne einfach eine Klasse schreiben, die der zu serialisierenden Klasse entspricht, nur eben eine reine Datenhaltung betreibt und alle Methoden weglässt.
Der Problemklasse gibt man dann einfach eine Save()-Methode, die eine solche Wrapperklasse erzeugt (eben ein Abbild von sich selbst), das dann serialisiert und fertig. Bei der Deserialisierung funktioniert es dann entsprechend umgekehrt.

Halte ich für meinen Teil für etwas...unsauber...beim Gedanken daran hab ich ein ungutes Gefühl in der Magengegend...

Was Möglichkeit 2 angeht: Der Output soll in jedem Fall als XML vorliegen und ich kenne bisher nur die binäre Serialisierung. Da wäre ich für Hinweise, etc. sehr dankbar...

Hat jemand ein paar Tipps/Tricks für mich auf Lager und/oder kann mir etwas zu meinen Möglichkeiten sagen? Wie gesagt, ich würde gerne den vorhandenen XmlSerializer verwenden, falls möglich. Falls nötig auch mit Tricks und Hintertürchen, aber eben nicht unsauber...

Ich hoffe einfach, dass ich nichts vergessen habe und dass mir jemand helfen kann 🙂

Danke im Voraus - SK

29.02.2008 - 10:30 Uhr

Hallo zusammen!

Ich stehe vor dem Problem, dass ich in NHibernate (mit Spring.NET, also HibernateTemplate) auf eine Sicht auf einem MSSQL 2005 Server zugreifen möchte. Geht das? Wenn ja wie?

Dazu zunächst einmal die Frage: Ist das sinnvoll oder eher Blödsinn? Also ich meine, bringt es mir mehr Vor- als Nachteile (es geht um einen DataReader, also vorerst nur lesende Zugriffe)?

So, dann wüsste ich gerne, wie ich das Mapping machen soll. Muss ich die erstellte View mit allen enthaltenen Spalten mappen oder einfach nur die Mappingklassen benutzen, die die in der View enthaltenen Tabellen darstellen oder wie gehe ich vor?

Würde mich über eine Antwort sehr freuen - mache das zum ersten Mal 😁

Greets - SK

29.02.2008 - 10:21 Uhr

@GarlandGreene: Ja, das stimmt, der Dialekt war leider total falsch.

Habe mittlerweile den Schwenk auf Spring.NET mit NHibernate gemacht und bin damit sehr zufrieden (auch wenn es an manchen Stellen gerne mal komische Fehlermeldungen gibt...)

Greets - SK

21.02.2008 - 12:34 Uhr

Danke euch, das werd ich mal ausprobieren. Ist glücklicherweise nur ein optionaler Test, von daher ist das auch nicht so schlimm, wenn es nicht klappen sollte...

Danke auf jeden Fall.

Greets - SK

21.02.2008 - 12:21 Uhr

Hmm, sowas dachte ich mir schon...schade, das.

Das mit dem Interface - irgendwie steh ich da gerade auf dem Schlauch...wie würde das aussehen? Also ganz allgemein?

Greets und Danke - SK

21.02.2008 - 11:48 Uhr

Hallo zusammen!

Ich stehe vor dem Problem, dass ich über Reflection eine Liste von Typen aus einem Namespace einer Assembly auslese und jeden einzelnen der Typen als Parameter an eine generische Methode übergeben möchte / muss.

Leider habe ich keine Ahnung, wie das funktioniert...hier erstmal die etwa zehnte Variante meines Versuchs:

///snip
Type[] types = asm2.GetTypes();

foreach(Type t in types)
{
    //Hier die Methode aufrufen (s.u.)

}
//snip

und hier die generische Methode:


private TestResult TestType<T>(Type t)
    {
    try
        {
            T lst = DAOManager.Instance.FindById<T>(1);

            return lst == null ? TestResult.Empty : TestResult.Error;
        }
    catch
    {
        return TestResult.Error;
    }
}

Ich denke, es ist klar, was passieren soll: Die Klasse DAOManager hat eine generische Methode FindById<T>(int), die eben einen Typ erwartet (einen der Typen, die ich im oberen Snippet ausgelesen habe).

Das hier ist auch schon die dritte oder vierte Version.

Mein Problem: Wo im ersten Snippet steht "hier die Methode aufrufen", habe ich jetzt schon einige Sachen ausprobiert, die aber alle zu Compilerfehlern führen, beispielsweise:

TestResult tr = this.TestType < t.GetType() > (t);

Krieg ich das irgendwie (anders) hin? Also für jeden gefundenen Typen die generische Methode mit ihm als generischen Parameter aufzurufen?

Wäre nett, wenn mir da jemand unter die Arme greifen könnte...

Greets - SK

29.01.2008 - 11:49 Uhr

Hallo,

nein, der Name des Landes wird nicht als UI genutzt, aber da es ziemlich unwahrscheinlich ist, dass es zwei Länder mit dem gleichen Namen gibt, dürfen halt nicht zwei Länder mit dem gleichen Namen existieren.

Wir haben uns jetzt entschieden, die IDs einfach (na ja, "einfach" ist gut) von Hand weiterzureichen.
Ich arbeite privat an einem Projekt mit ähnlicher Struktur. Sollte ich dazu noch eine bessere Lösung finden, werde ich sie hier posten, da es halt private Sachen sind, die nichts mit dem aktuellen Projekt hier zu tun haben.

Ansonsten werde ich mal sehen, dass ich das jetzt eigenhändig kaskadiere (wenn man das dann noch so nennen darf...).

Danke erstmal - wenn noch jemand eine Idee hat - immer her damit.

Greets - SK

29.01.2008 - 08:30 Uhr

Hallo DaMoe80,

an sich hast du Recht, dass die Annahme nicht sonderlich sinnvoll ist, stimmt, aber der Verdacht drängt sich einem schon auf.

Mittlerweile ist meine Theorie die folgende: NHibernate verhält sich offensichtlich genau richtig, denn es gibt immer nur genau ein Land mit dem Namen "Ein Land", also sind die Namen eindeutig.

Da das BO nicht nur die Daten der enthaltenen Persistenzklassen (also z.B. Name des Landes, Name des Staats, etc.), sondern direkt Objekte davon verwaltet, gehe ich davon aus, dass ein Update eines dieser Objekte zu einem Update aller führt, da sie IMHO auf die gleiche Stelle in der Datenbank/Tabelle zeigen. Ergo ist das Verhalten von NHibernate genau so, wie es sein sollte.

Ich darf leider nichts an Quellcode posten, sorry.

Ich werde jetzt mal versuchen, anstatt der Objekte direkt deren Daten zu benutzen, also die Objekte vollkommen unangetastet zu lassen - vielleicht hilft mir das ja weiter.
Ich sage dann mal meinen Status an, so im Laufe des Nachmittags, denke ich.

Hatte denn vielleicht jemand schon mal ein ähnliches Problem?

Greets und Danke - SK

28.01.2008 - 14:03 Uhr

Hallo zusammen!

Ich habe eine Frage bezüglich NHibernate im Zusammenspiel mit Spring und einem Microsoft SQL Server und dargestellt im DataGridView in einer Windows Form.

Und zwar habe ich ein Businessobjekt, welches eine Adresse kapselt und die Methoden zum Auslesen usw. aus der Datenbank bereitstellt.
Im Code der Form habe ich nun den Inhalt des DGV an eine Liste solcher Objekte gebunden und bekomme auch alle Daten schick angezeigt, alles toll soweit.

Nur wenn ich eine Property in einer Zeile ändere (z.B. "Land"), dann werden gleich alle Zeilen verändert, in denen dieser Name steht...deshalb ist meine Frage - und deshalb steht's in diesem Forum - ob das mit dem Databinding oder NHibernate zusammenhängt oder evtl. sogar mit dem DGV.

Ich habe so den Verdacht, dass NHibernate bei sagen wir 20 Datensätzen, deren Land "Deutschland" ist, jedem dieser Datensätze die gleiche Referenz für das Land gibt. Dann muss man sich ja nicht wundern, wenn das mit den Änderungen nicht klappt. Falls ich damit richtig liege - wie kann man das ändern? Geht das überhaupt?
Falls ich falsch liege: jemand eine Idee?

Greets und schon mal Danke - SK

14.01.2008 - 13:27 Uhr

Hallo,

erstmal: Ja, klar, mit form.Controls komme ich an alle Controls ran. Problem ist nur, dass ich das ganze eben extrem allgemein belassen wollte, also so, dass alles, was sich auf der Form befindet und das Attribut 'Name' und 'Text' besitzt, damit konfigurierbar ist.
Entsprechend kann ich mich auf form.Controls nicht verlassen, da beispielsweise die in einem MenuStrip enthaltenen ToolStripMenuItems nicht als Control zählen und auch in der schönsten Rekursion einfach nicht beachtet werden.

Ich habe mich jetzt dazu entschlossen, es so zu machen:

Für alle von Control abgeleiteten Klassen gibt es das genannte Manager-Objekt, welches sich halt um die genannten Aufgaben kümmert.
Ansonsten werde ich - da ich mit Spring arbeite - noch andere Manager konfigurieren lassen (abgeleitet von einem Basismanager), um Sachen wie ToolStripMenuItems zu konfigurieren. Nicht mehr ganz so allgemein, aber leicht erweiterbar...

Wenn euch dennoch ein Weg einfallen sollte, wie man mein ursprüngliches Vorhaben umsetzen könnte, wäre ich euch jedenfalls sehr dankbar!

Greets und Danke - SK

14.01.2008 - 11:33 Uhr

Hallo zusammen!

Ich erkläre mal kurz mein Problem. Ich schraube gerade an einer Art Konfigurierer für Windows-Forms. Dabei existieren XML-Dateien, die Texte für die Controls der Forms enthalten, auf die ich über eine entsprechende Manager-Klasse zugreife.

Ziel der Sache ist eine Form, die automatisch, ohne dass der Programmierer der Form dies angeben muss, ihre Konfiguration aus der Datei bezieht.

Ich gehe dabei momentan so vor:

  1. Jede Form hat eine Basisklasse, die beim Erstellen den Konfigurierer anweist, dass sie bitte konfiguriert werden will.
    Dabei wird der aufrufende Typ (z.B. Testform) und die aufrufende Assembly übergeben (wird später gebraucht).

  2. Ich habe im Konfigurierer eine Liste erlaubter Typen von Controls, die überhaupt in der Lage sind, sich hier konfigurieren zu lassen.

  3. Die Zeile

FieldInfo fi in form.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)

liefert mir alle Felder der Form, das funktioniert soweit super und auch die Prüfung auf einen erlaubten Typ klappt einwandfrei.

Jetzt kommt das Problem!

Ich muss ja jetzt dem zu konfigurierenden Objekt dessen Property 'Text' neu zuweisen (nachdem der neue Wert vom Manager entsprechend geladen wurde). Wie komme ich denn an die Instanz des Controls heran? Die FieldInfo-Member konnten mir bislang leider noch nicht weiterhelfen, vielleicht wisst ihr ja weiter?

Ich habe die ganze Zeit das Gefühl, dass die Lösung direkt vor meinen Augen liegt, aber anscheinend steh ich grad einfach zu sehr auf dem Schlauch, als dass ich sie erkennen würde...hab ich damit Recht oder ist das doch komplizierter als ich denke?

Greets und Danke im Voraus - SK

05.01.2008 - 09:56 Uhr

Nicht viel. Db-Einstellungen machen. Eine Entity mittels Designer erzeugen. Entityname (= Klassenname) auf SalesPerson, EntitySet-Name (=Collection aller SalesPersons) auf SalesPeople. Die per Default erzeugte SalesPerson-ID zu einem Key machen. Fertig.

Das Mapping erfolgt entweder gegen eine Tabelle pro Entity (vererbte Klassen gehen auf eine Tabelle) oder gegen Stored Procs für Insert/Update/Delete.

Oh je...Designer? Welcher Designer? Kann es sein, dass ich dafür das Visual Studio 2008 brauche? Ich habe momentan nur die Visual C# 2008 Express Edition - kann es sein, dass ich deshalb so verwirrt bin?

Denn dass ich so wie oben vorgehen muss ist mir schon irgendwie klar, nur wie ich das mache ist mir noch immer ein Rätsel...bin auch noch nicht zum Lesen gekommen, also sorry, falls das in dem o.g. Artikel stehen sollte.

Dann werd ich wohl mal die VS 2008 installieren...

Greets - SK

P.S: @xxxprod: Schön, wenn man nicht alleine ist 😁

04.01.2008 - 15:56 Uhr

Ok, dann ist wohl wirklich was an mir vorbeigegangen, da ich auch von Linq noch nie - bis auf die Suche - etwas gehört habe...

Ich glaube, ich habe das langsam etwas klarer vor mir. Aber auch nur etwas.

@Khalid: Ja, die Suche ergibt schon einige Treffer, nur leider habe ich dabei noch nicht gefunden, was man als "Quickstart" nehmen könnte. Die Sachen, die ich gefunden habe (kann auch sein, dass ich was übersehen habe), waren entweder nur News alá "Version soundso ist draußen" oder extrem komplexe Solutions, die das Verständnis nicht unbedingt gefördert haben.

Man ist es ja von MS gewöhnt, meistens excellente Beispiele bzw. gute Quickstart-Projekte zu bekommen, vielleicht ist das das Problem meinerseits. Würde mich aber wundern, wenn man bedenkt, wie groß die Chancen sind, andere OR-Mapper auszustechen, wenn das EF eine breite Fangemeinde bekommt...

Wie gesagt, ich bin noch bei .NET 2.0 hängengeblieben, und Sachen wie Linq sind mir noch total unbekannt. Steige gerade auf 3.5 um und bin in diesem Zuge auch auf das EF gestoßen (also den Begriff).

Hat schon mal jemand was damit gemacht? Also eine Art einfache Beispielanwendung, die man sich mal ansehen könnte?

Versteht mich nicht falsch, ihr sollt mir nicht alles vorkauen, auch Sachen wie

using (CompanyDB db = new CompanyDB())
{
    var salesPeople =
        from c in db.SalesPeople
        select c

    foreach (SalesPerson c in salesPeople)
    {
        ...
    }
}

sind mir recht klar, nur weiß ich eben nicht, wie ich anfangen soll.

Nehmen wir als Beispiel mal folgendes:

MySQL-Datenbank als Backend, Windows-Forms als Frontend. Dazwischen der MySQL-Connector.
Da ist mir alles klar. Ich gebe dem Connector den Befehl, sich mit einem Server zu verbinden und werfe dann mit Queries um mich.

Was mir absolut nicht klar ist: Was muss ich tun, damit das o.g. Codefragment einen Sinn ergibt, bzw. funktioniert? Also auch im Hinblick auf dieses Beispielszenario. Also wie kriege ich eine Verbindung zustande (braucht man den Connector noch, um sich zu einem MySQL-Server zu verbinden?)?

Ich gehe davon aus, dass auch das EF mit Mappings arbeitet? Bei NHibernate sind mir die Mappings halbwegs klar - kann man das vergleichen?

Oh man, irgendwie steh ich bei dem Thema vollkommen auf dem Schlauch...Fragen über Fragen...

Ich werde mir jetzt erstmal das hier zu Gemüte führen und dann mal sehen, ob ich das etwas klarer sehe...für weitere Antworten/Links/etc bin ich aber dennoch mehr als dankbar 😁

Danke euch erstmal - SK

04.01.2008 - 13:21 Uhr

Hallo zusammen!

Ich habe vor kurzer Zeit den Begriff "Microsoft Entity Framework" aufgeschnappt und bin neugierig geworden.
Leider bin ich nach zwei Tagen Suche noch nicht wirklich schlau aus der Sache geworden.
Irgendwas ist an mir vorbeigegangen, glaube ich...

Beispiele konnte ich bisher keine finden, ich habe aber auch den Verdacht, dass "Entity Framework" nicht unbedingt der beste Suchbegriff ist. Ist das das gleiche wie ADO.NET oder hab ich da was falsch verstanden?

Ich hoffe, die Fragen sind nicht so doof, wie ich denke, und hoffentlich kann mir jemand einen kleinen Quickstart geben, würde mir die ganze Sache gern mal ansehen...

Klappt das auch mit MySQL oder nur mit MSSQL? Oh je, ich bin langsam vollkommen verwirrt...

Greets und Danke - SK

08.11.2007 - 23:23 Uhr

Hey, herbivore!

Jetzt, mehr als zwei Jahre nach meiner Frage und deiner Antwort, hat mir dieses längst vergessene Posting erneut weitergeholfen (bin tatsächlich über die Suche drüber gestolpert!)!

Mittlerweile kenn ich mich mit der Hashtable weitaus besser aus als damals und auf einmal ergibt das alles auf Anhieb einen Sinn!

Danke nochmal! 😁

Greets - SK

17.10.2007 - 12:44 Uhr

Hallo zusammen!

Ich wollte mich gerade ein wenig mit NHibernate auseinandersetzen, habe es bisher aber noch nicht einmal geschafft, das Ding irgendwie zum Funktionieren zu kriegen.

Im Hintergrund läuft ein MySQL-Server (XAMPP).

Ich schildere erst mal, was ich habe:

Projektstruktur

[PRE]
    Properties
    
    Verweise
        MySql.Data
        NHibernate
   
    Classes
        Hibernation
            Benutzer.cs
            Benutzer.hbm.xml

    app.config

    Datenbankeditor.cs[/PRE]

In der app.config steht folgendes (ich habe die jetzt ca. 20 Mal verändert, also kann es auch sein, dass hier irgendwo Blödsinn drinsteht):


<?xml version="1.0" encoding="utf-8" ?>

<configuration>
	<configSections>
		<section
		   name="nhibernate"
		   type="System.Configuration.NameValueSectionHandler, System,
          Version=1.0.5000.0,Culture=neutral,
          PublicKeyToken=b77a5c561934e089" />
	</configSections>

	<nhibernate>
		<add key="hibernate.connection.provider"
			 value="NHibernate.Connection.DriverConnectionProvider"
		/>
		<add key="hibernate.dialect"
			 value="NHibernate.Dialect.MySQLDialect"
		/>
		<add key="hibernate.connection.driver_class"
			 value="NHibernate.Driver.SqlClientDriver"
		/>
		<add key="hibernate.connection.connection_string" 
			 value="User ID=root;Password=xxx;Data Source=localhost;Initial Catalog=testdb"/>
		
	</nhibernate>
</configuration>

So, jetzt die Klasse Benutzer, die ich mappen möchte:


using System;
using System.Collections.Generic;
using System.Text;

namespace Datenbankeditor.Classes.Hibernation
{
    public class Benutzer
    {
        private string _userName;
        private string _passHash;
        private string _email;
        private int _eineZahl;

        public string Username
        {
            get { return this._userName; }
            set { this._userName = value; }
        }

        public string PassHash
        {
            get { return this._passHash; }
            set { this._passHash = value; }
        }

        public string Email
        {
            get { return this._email; }
            set { this._email = value; }
        }

        public int EineZahl
        {
            get { return this._eineZahl; }
            set { this._eineZahl = value; }
        }
    }
}

und ihre entsprechende xml-Datei (Benutzer.hbm.xml):


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Datenbankeditor" namespace="Datenbankeditor">
	
	<class name="Datenbankeditor.Classes.Hibernation.Benutzer" table="benutzer">
		<property name="Username" column="name" type="String" length="255"/>
		<property name="PassHash" column="passwort" type="String" length="255"/>
		<property name="Email" column="email" type="String" length="255"/>
		<property name="EineZahl" column="einezahl" type="int"/>
	</class>
</hibernate-mapping>

So, das sind erstmal meine bisherigen Dateien.

In Datenbankeditor.cs ist nun folgendes (Auszug):


private Configuration _hibConfig;

//...

private void InitNHibernate()
{
    try
    {
        this._hibConfig = new Configuration();
        this._hibConfig.AddAssembly(Assembly.GetExecutingAssembly()); //<-- hier kommt die Exception

        //...
    }
    //catch...
}

Tja, bis zur zweitenAnweisung im try-Block komm ich...dann kommt:

{"Datenbankeditor.Classes.Hibernation.Benutzer.hbm.xml(5,4): XML validation error: Das Element 'class' in Namespace 'urn:nhibernate-mapping-2.2' hat ein ungültiges untergeordnetes Element 'property' in Namespace 'urn:nhibernate-mapping-2.2'. Erwartet wurde die Liste möglicher Elemente: 'urn:nhibernate-mapping-2.2:meta urn:nhibernate-mapping-2.2:jcs-cache urn:nhibernate-mapping-2.2:cache urn:nhibernate-mapping-2.2:id urn:nhibernate-mapping-2.2:composite-id'."}
{"Das Element 'class' in Namespace 'urn:nhibernate-mapping-2.2' hat ein ungültiges untergeordnetes Element 'property' in Namespace 'urn:nhibernate-mapping-2.2'. Erwartet wurde die Liste möglicher Elemente: 'urn:nhibernate-mapping-2.2:meta urn:nhibernate-mapping-2.2:jcs-cache urn:nhibernate-mapping-2.2:cache urn:nhibernate-mapping-2.2:id urn:nhibernate-mapping-2.2:composite-id'."}
   bei NHibernate.Cfg.Configuration.LogAndThrow(MappingException me)
   bei NHibernate.Cfg.Configuration.ValidationHandler(Object o, ValidationEventArgs args)
   bei System.Xml.Schema.XmlSchemaValidator.SendValidationEvent(ValidationEventHandler eventHandler, Object sender, XmlSchemaValidationException e, XmlSeverityType severity)
   bei System.Xml.Schema.XmlSchemaValidator.ElementValidationError(XmlQualifiedName name, ValidationState context, ValidationEventHandler eventHandler, Object sender, String sourceUri, Int32 lineNo, Int32 linePos, Boolean getParticles)
   bei System.Xml.Schema.XsdValidator.ValidateChildElement()
   bei System.Xml.Schema.XsdValidator.ValidateElement()
   bei System.Xml.Schema.XsdValidator.Validate()
   bei System.Xml.XmlValidatingReaderImpl.ProcessCoreReaderEvent()
   bei System.Xml.XmlValidatingReaderImpl.Read()
   bei System.Xml.XmlValidatingReader.Read()
   bei System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
   bei System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
   bei System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
   bei System.Xml.XmlDocument.Load(XmlReader reader)
   bei NHibernate.Cfg.Configuration.LoadMappingDocument(XmlTextReader hbmReader, String name)
   bei NHibernate.Cfg.Configuration.AddXmlReader(XmlTextReader hbmReader, String name)
   bei NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream, String name)
   bei NHibernate.Cfg.Configuration.AddResource(String path, Assembly assembly)
   bei NHibernate.Cfg.Configuration.AddResources(Assembly assembly, IList resources, Boolean skipOrdering)
   bei NHibernate.Cfg.Configuration.AddAssembly(Assembly assembly, Boolean skipOrdering)
   bei NHibernate.Cfg.Configuration.AddAssembly(Assembly assembly)
   bei NHibernate.Cfg.Configuration.AddAssembly(String assemblyName)
   bei Datenbankeditor.DatenbankEditor.InitHibernation() in F:\Eigene Dateien\Projekte\Visual Studio\SWPNeu\Datenbankeditor\DatenbankEditor.cs:Zeile 31.
   bei Datenbankeditor.DatenbankEditor.toolStripButton1_Click(Object sender, EventArgs e) in F:\Eigene Dateien\Projekte\Visual Studio\SWPNeu\Datenbankeditor\DatenbankEditor.cs:Zeile 102.
   bei System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
   bei System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
   bei System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
   bei System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
   bei System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
   bei System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
   bei System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
   bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   bei System.Windows.Forms.Control.WndProc(Message& m)
   bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
   bei System.Windows.Forms.ToolStrip.WndProc(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Application.Run(Form mainForm)
   bei Datenbankeditor.Program.Main() in F:\Eigene Dateien\Projekte\Visual Studio\SWPNeu\Datenbankeditor\Program.cs:Zeile 17.
   bei System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
   bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   bei System.Threading.ThreadHelper.ThreadStart()

Kann mir da jemand helfen? Ich versteh leider nicht, was ich gegen diese Exception tun soll.
Ich habe mal diese Liste möglicher Elemente in die Benutzer.hbm.xml anstatt xmlns="urn:nhibernate-mapping-2.2" eingefügt (also anstatt "urn:nhibernate-mapping-2.2"), aber dann kann NHibernate das ValidationScheme nicht finden, wenn ich das richtig verstanden habe...

Noch mal zur Anmerkung: Meine bisherigen Daten wurden zusammengesetzt aus dem QuickStart für NHibernate und verschiedenen Einträgen im Netz...

Was ich hier bisher finden konnte, half mir leider auch nicht weiter...

Würde mich freuen wenn mir jemand ein paar Tipps geben könnte.

Danke im Voraus und Greets - SK

08.09.2007 - 13:50 Uhr

Hallo herbivore,

das dachte ich auch, aber es brachte leider keinerlei Ergebnisse, das Control wurde also nicht neu gezeichnet 🙁

Vielleicht hab ich auch irgendwo im Code nen Fehler (wie gesagt, ich arbeite zum ersten Mal mit BufferedGraphics) gemacht...bin nur über's Wochenende nicht in der Nähe des Rechners, auf dem der Code liegt...

Wie ich schon sagte: Ohne die BufferedGraphics funktionierte das wunderbar, nur die Performance ging in den Keller.
Jetzt, mit BufferedGraphics, läuft es besser, aber dafür wird eben ab und an nicht neu gezeichnet...entsprechend mein Verdacht, dass es an den BufferedGraphics liegt und ich irgendwo einen Fehler drin hab...

Was ich noch probiert hatte:

Das Panel, welches das UserControl enthält:


private void panel1_SizeChanged(object sender, EventArgs e)
{
        this._calendar.Invalidate();           
}

Zusätzlich habe ich im OnPaint() des Controls eine Aufgabe auf Debug eingefügt.

Beim Verändern der Größe der Form, in der das Panel liegt, wird das Control mit vergrößert (habe das über die Hintergrundfarbe gesehen), aber das OnPaint() wird nie aufgerufen...das find ich schon etwas komisch...

Hat da jemand eine Idee?

Wenn jemand Interesse dran hat, würd ich den gesamten Code hier auch hochladen oder per Email raussenden. Kann ja sein, dass jemand den Fehler entdeckt, den ich immer übersehe bzw. auf den ich noch nie aufmerksam wurde. Falls jemand Interesse hat, einfach Bescheid sagen.

Danke euch beiden - SK

07.09.2007 - 10:50 Uhr

Hallo ikaros,

das habe ich auch schon versucht, wie immer mit dem Ergebnis, dass schlicht und ergreifend nichts verändert ist: Das Control (auch die PictureBox) wird in der Größe verändert, aber es wird nicht neu gezeichnet.

Ich habe es jetzt vorerst so gelöst, dass bei allen Änderungen am Control (Inhalte, Größe, etc.) einfach eine Methode namens Render() aufgerufen wird, die das Zeichnen übernimmt - so funktioniert es ganz gut.

Beim (Neu-)zeichnen ist es zwar etwas verzögert (ca. 100ms), dafür ist danach die Darstellung absolut flüssig und stabil (wenn man nix ändert eben).

Danke euch beiden!

Sollte ich letztendlich noch eine bessere/performantere Lösung finden, erfahrt ihr es als Erste!

Greets - SK

05.09.2007 - 15:52 Uhr

Original von herbivore
Hallo Schattenkanzler,

das hat irgendwie nicht so wirklich funktioniert...
aber auch das klappt leider nicht...
siehe
>
Punkt 5.

Na ja, ich hab dir die Beschreibung meiner Vorgehensweise unter mein Statement geschrieben. Und da der "Fehler" immer noch das nicht-neu-zeichnen ist, dachte ich, das wär klar...na ja, is ja auch egal. 😁

Das mit der blockierenden GUI werd ich mir mal genauer zu Gemüte führen, vielleicht bringt das ja wirklich was.

Nur beim Überfliegen des Textes hab ich gelesen, dass die Anwendung blockiert in diesem Fall. Das passiert bei mir jedoch nicht...

Hmm, scheint doch komplizierter zu werden, als ich dachte.

Danke auf jeden Fall, notfalls greif ich auf das Resize() zurück und versuch es damit (einfach neu zeichnen lassen, auch wenn's nicht im OnPaint() ist, sonst klappt's ja nicht).

Greets und Danke nochmal - SK

05.09.2007 - 09:16 Uhr

Hallo herbivore!

Hmm, Invalidate hatte ich schon versucht, das hat irgendwie nicht so wirklich funktioniert...

Ich habe beispielsweise folgendes versucht:


this.userControl.Size = new Size(...);

this.Invalidate();
this.userControl.Invalidate();
this.userControl.PictureBox.Invalidate();

Hat gar nix gebracht, gleiches Ergebnis wie vorher...der Aufruf war innerhalb der Form.

Ich dachte mir auch, dass man evtl. manuell auf ein UserControl_Resize reagieren könnte (also beispielsweise mit einem this.Invalidate()), aber auch das klappt leider nicht...

Bisher hat das Control wirklich nur auf das manuelle Aufrufen der o.g. RePaint()-Methode reagiert.

Noch ne Idee? Habe irgendwie das Gefühl, dass man dem Manager irgendwie mitteilen muss, dass man den GraphicBuffer bitte neu gefüllt haben will oder so was in der Richtung. Aber da ich mich mit BufferedGraphics eben noch nicht so gut auskenne, weiß ich an dieser Stelle nicht mehr weiter...

Ok, das ref werd ich demnächst mal rauswerfen, ist ja auch eigentlich weniger schick...

Danke - SK

05.09.2007 - 08:31 Uhr

Hallo zusammen!

Es geht mal wieder - leider - um ein Problem mit dem Zeichnen...

Erst mal die Ausgangssituation:

Auf einer Form befindet sich in einem Panel ein UserControl, welches im Prinzip nur aus einer PictureBox besteht.
In diese PictureBox zeichne ich mit BufferedGraphics im OnPaint des Controls.

Es ist das erste Mal, dass ich überhaupt mit BufferedGraphics arbeite und an sich bin ich damit schon zufrieden, nur gibt es ein kleines Problem.

Wenn ich die Größe des Controls in der Form ändere (egal ob manuell oder bei DockStyle.Fill über das Resizen der Form), wird diese Größe zwar verändert, jedoch werden die grafischen Elemente nicht entsprechend neu gezeichnet (deren Größe ich aber im OnPaint berechne und dann ja neu zeichnen lasse, also sollte das doch eigentlich passieren, oder?).

Die Objekte vom Typ IGraphicObject sind dem allgemein bekannten Tutorial aus diesem Forum nachempfunden.



///Variablen
//
//this._context  --> BufferedGraphicsContext
//this._graphics --> BufferedGraphics

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    this._context = BufferedGraphicsManager.Current;

    int w = this.imgCanvas.Width <= 0 ? 1 : this.imgCanvas.Width;
    int h = this.imgCanvas.Height <= 0 ? 1 : this.imgCanvas.Height;

    this._canvasBack = new Bitmap(w, h, PixelFormat.Format24bppRgb);

    this.imgCanvas.Image = this._canvasBack;

    this._imgBack = this.imgCanvas.Image;

    this._gBack = Graphics.FromImage(this._canvasBack);
            
    int cw = this.ClientSize.Width <= 0 ? 1 : this.ClientSize.Width;
    int ch = this.ClientSize.Height <= 0 ? 1 : this.ClientSize.Height;

    this._context.MaximumBuffer = new Size(cw, ch);

    this._graphics = this._context.Allocate(this._gBack, new Rectangle(new Point(0,0), new Size(cw, ch)));

    this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
    
    this.BuildGraphicObjects();

    foreach (IGraphicObject obj in this._objects)
    {
         //obj in den Buffer schreiben
         obj.Draw(ref this._graphics);
    }

    //Buffer rendern
    this._graphics.Render(this._gBack);
}

Falls sich jemand wundern sollte, warum da ein ref im Aufruf innerhalb der Schleife steht: Ich habe die Konstruktoren und Methoden der Objekte mit ref versehen, damit ich mit einem Objekt vom Typ BufferedGraphics auskomme bzw. weil ich nicht wirklich sicher war, ob das ohne auch so klappen würde.
Sollte das sehr ungünstig sein, bitte darauf hinweisen 🙂

So, nun mal eine konkrete Frage: Was muss ich tun, damit dieses von mir gebastelte Konstrukt endlich auch beim Resize neu gezeichnet wird?
Ich habe es mit Refresh()- und Invalidate()-Aufrufen versucht...

Eine Sache, die zwar klappt, aber einfach nicht sonderlich gut, ist der Aufruf:


//In Form1, die das UserControl beinhaltet
private void Form1_Paint(object sender, PaintEventArgs e)
{
    this._control.RePaint(e);
}


//Die Methode innerhalb des Controls:
public void RePaint(PaintEventArgs e)
{
    this.OnPaint(e);
}

Aber das kann's ja nun nicht sein, oder? Stand im Tutorial nicht was davon, dass man OnPaint nicht selbst aufrufen soll oder so was?

Na wie gesagt, das funktioniert zwar, ist aber deutlich langsam und entsprechend unschön...

Also, wer kann mir helfen?

Greets und Danke - SK

04.09.2007 - 20:32 Uhr

Und wenn du das Flackerproblem nicht anders lösen kannst, schau mal, ob du über Double-Buffering was erreichen kannst (ist eine Eigenschaft der Form, u.a.).

Greets - SK

31.08.2007 - 20:41 Uhr

Mist, hätt ich erklären müssen:

Das Snippet da stammt aus einer Klasse.

this._bounds

ist ein Rectangle, welches die Größe des Objekts festlegt.

Ich habe ein Rechteck gezeichnet, in dem ich den Text zentrieren möchte. Sowohl das Rechteck als auch der Text haben die gleiche Größe und Position (rechteck._bounds == text._bounds, sozusagen).

Deshalb denk ich auch, dass meine Rechnung eigentlich stimmen sollte:

mitteH = Gesamtbreite / 2

Damit wäre ich aber genau in der Mitte des Rechtecks, und der Text wäre zu weit rechts. Also:

mitteH = Gesamtbreite / 2 - Textbreite / 2

Das mit dem ClientRectangle müsstest du mir noch mal erklären, bitte...

Greets und Danke - SK

31.08.2007 - 19:05 Uhr

Hmm, da hab ich auch mal eine Frage...

Ich möchte in einem Rechteck einen String zentrieren, nur leider klappt das absolut nicht.
Was genau mach ich falsch?


SizeF stringSize = new SizeF();
stringSize = g.MeasureString(this._string, this._font);

float leftH = (float)((float)(this._bounds.Width / 2) - (stringSize.Width / 2));
float leftV = (float)((float)(this._bounds.Height / 2) + (stringSize.Height / 2)) ;

SolidBrush b = new SolidBrush(this._color);
                        
g.DrawString(this._string, this._font, b, new PointF(leftH, leftV));

Der String ist dann dummerweise etwas zu weit oben links...das find ich doch reichlich komisch...

Also, was muss ich ändern?

Danke im Voraus!

Greets - SK

16.08.2007 - 13:51 Uhr

Ich hab mal noch eine Frage, die zwar was mit dem Thema zu tun hat, aber sich von meinem letzten Posting abgrenzt, deshalb das doppelte Posting.

Ich habe versucht, das Handle auf den Desktop zu bekommen mittels:


[DllImport("user32.dll", EntryPoint="FindWindowExA",  SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

[DllImport("user32.dll", EntryPoint = "FindWindowExA", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className,  IntPtr windowTitle);
        
[DllImport("user32.dll", EntryPoint="FindWindowA", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

Jedoch kriege ich mit dem Aufruf


IntPtr hProgman = FindWindow("ProgMan", string.Empty);
IntPtr hShellDef = FindWindowEx(hProgman, IntPtr.Zero, "SHELLDLL_DefView", IntPtr.Zero);
IntPtr hDesktop = FindWindowEx(hShellDef, IntPtr.Zero, "SysLitView32", IntPtr.Zero);

Dreimal eine Null heraus.

In der C++-Variante werden die Handles exakt so geholt, bzw:


HWND hProgMan  = FindWindow("ProgMan", NULL);	
HWND hShellDef = FindWindowEx(hProgMan, NULL, "SHELLDLL_DefView", NULL);
hDesktopWnd    = FindWindowEx(hShellDef, NULL, "SysListView32", NULL);

Und da fragt man sich doch, warum das nicht klappt...

Kann mir da jemand helfen?

Greets - SK

16.08.2007 - 01:38 Uhr

Nee, das is ja noch mal ne ganz andere Sache (irgendwo bei CodeProject gibt's das, mal nach dem Begriff 'Shell' suchen).
Eben solche Sachen will ich ja vermeiden. Eben wirklich nur diesen ungenutzten Layer zwischen Background-Picture und Icons nutzbar machen, das will ich...am besten mal das Sample ausprobieren, welches ich weiter oben gepostet habe (das von Angelcode), dann weiß man, was ich meine (den rotierenden Stern auf ein Icon bewegen, der ist dann dahinter).

Greets - SK

15.08.2007 - 20:15 Uhr

Also in meinem Fall, damit der gesamte Desktop weiterhin nutzbar bleibt (Icons, etc.), man jedoch bestimmte Infos (z.B. den Kalender, eine Uhr, irgendwie sowas) dahinter einblenden kann.
Man könnte auch irgendwas entwickeln, was dem Desktop zusätzliche Funktionen gibt (welche auch immer), wobei da eine Shell-"Replacement" vielleicht eleganter wäre...

Na ja, ich werd mir deinen Link mal ansehen, Rumpel, vielleicht löst der mein Problem?!? Danke auf jeden Fall schon mal...

Greets - SK

15.08.2007 - 10:25 Uhr

Na ja, es geht offensichtlich, da ich ein Beispiel in C++ gefunden habe, welches genau das tut, was ich haben möchte. Leider hab ich es bisher nicht geschafft, es anzupassen an C#...

Hier der Link: http://www.angelcode.com/dev/desktopdraw/

Offensichtlich geht das sogar mit DirectX: http://www.angelcode.com/dev/overlay

Kann das jemand nach C# portieren (also das erste, so dass man ein Objekt hat, auf dem man zeichnen kann, welches sich so verhält wie im ersten Beispiel)?

Greets - SK

14.08.2007 - 16:25 Uhr

Nein, leider nicht wirklich, da die Form noch immer vor den Desktop-Icons liegt...und nicht dahinter, so wie ich es gerne hätte...leider...

Greets - SK

16.06.2007 - 16:32 Uhr

Japp, ist mir - leider - klar 😁

Gut, ich schau mal, ob ich mein Vorhaben nicht doch noch mal überdenken sollte...

Danke erstmal...

Greets - SK

16.06.2007 - 15:47 Uhr

Oh man, stimmt, ^ hätt ich nicht nehmen sollen...man kommt aber auch schnell durcheinander 😁

Ja, das mit der Umwandlung sollte an sich nicht das Problem sein, nur wie gesagt: Durch die Schleife kriege ich doch noch immer nicht alle Kombinationen, oder? Ich meine, ich kriege die Anzahl der Möglichkeiten, sicher.

Nur jetzt noch dieses klitzekleine Stück weiter und wirklich diese Kombinationen ausgeben...und ich bin glücklich.

Um es vielleicht noch mal etwas deutlicher zu machen: Ich möchte eine Art Array füllen. Dieses hat eine variable Größe (Parameter länge) und die einzelnen Zellen können bis zu einem bestimmten Maximum (FF [hex]) eben Werte annehmen (Parameter grenze).

Also z.B. so was

 meinArray --> { 00 FF AE 3B 0A 12 08 } 

Es gibt jede Menge solcher Arrays, ich weiß. Über Sinn und Zweck der Übung wollen wir mal nicht streiten.

Ich habe auch schon mal versucht, mir das klar zu machen, bisher leider ohne Erfolg. Wenn man beispielsweise die Binärzahlen aufschreibt, sagen wir alle dreistelligen, dann gehe ich so vor, immer von hinten nach vorne aufzufüllen, also so:

000
001
010
011
100
101
110
111 

Aber irgendwie blockiert mein Hirn, wenn ich das in Quellcode umwandeln will...

Greets und Danke - SK

15.06.2007 - 21:47 Uhr

8o

Ok, den Satz musste ich dreimal lesen, bevor ich ihn kapiert hatte 😁 Hoffe ich zumindest.

Ich versuche mal folgendes:

 for(int i=0; i<(grenze+1)^länge; i++)
{
    //hier i in den String umwandeln
} 

Ist das das, was du meintest?

Damit hab ich aber noch immer nicht die Kombinationen, oder? Damit gebe ich doch einfach nur alle Zahlen von 0 bis (grenze+1)^länge aus.

Dieser nächste Schritt, der jetzt kommen müsste, der macht mir Kopfzerbrechen...damit komm ich einfach kopfmäßig gar nicht klar...

Wäre schön, wenn du mir das auch noch erklären könntest - gerne auch wieder mit einem etwas komplizierteren Satz... 😁

Greets und THX - SK

15.06.2007 - 20:03 Uhr

Hallo!

Irgendwie bin ich für Permutationen zu doof...ich weiß auch nicht.

Angenommen, man möchte auf der von Traumzauberbaum geschriebenen Methode aufbauend eine Methode entwickeln, die folgendes tut:

Man gebe ihr die Länge der zu bauenden Strings (wie ja schon bei Traumzauberbaum), dazu eine obere Grenze (z.B. 1 für Binärzahlen) und eben die Liste der strings.

So, die Methode soll jetzt alle möglichen Permutationen berechnen, die es für die angegebenen Parameter gibt.

Beispiel:

Combine2(3, 1, meineListe)

würde resultieren in

000
001
010
011
100
101
110
111 
Combine2(2, 1, meineListe)

würde resultieren in

00
01
10
11 

Klar, also x hoch n Kombinationen wobei n dem Parameter der Länge entspricht und x der oberen Grenze.

So, nur jetzt müsste ich den Schritt in die Praxis machen...und der will einfach nicht klappen!

Kann mir da jemand helfen, wäre sehr dankbar!

Greets - SK

15.06.2007 - 19:46 Uhr

@langalaxy: Ziemlich schick, das werd ich wahrscheinlich als Grundlage für meine Implementierungsidee nehmen. Danke dir 😁

Dann muss ich mich nur noch in Sachen Drag & Drop schlau machen und evtl. noch so was wie "Magnetic Controls", da die Termine nur zu bestimmten Zeitpunkten anfangen/enden dürfen und ich dem User da unter die Arme greifen will, und schon kann's losgehen!

Sollte dabei was brauchbares rauskommen, erfahrt ihr's zuerst!

Greets - SK

13.06.2007 - 10:15 Uhr

@blackcoin: Na ja, bei Codeproject hab ich mich schon mal umgesehen und zwar immerhin ein nettes Grid gefunden, das aber leider nicht ganz meinen Anforderungen entspricht.

@herbivore: Ja, das hatte ich auch schon überlegt, dürfte auch - AFAIK - der schnellste (im Sinne von Laufzeit-Effizienz) Weg sein, mein Ziel zu erreichen, oder?

@Kabelsalat: MonoCalendar ist - vom Layout und Aufbau - einfach perfekt! Das werd ich mir mal genauer ansehen und dann meinen Status hier melden 😁

@7.e.Q: Ja, da kommen einem doch auf jeden Fall einige Ideen, nicht wahr? Bei mir isses etwas anders, da die Pläne ziemlich strikt vorgegeben sind und man nur sehr eingeschränkte Modifikationen vornehmen kann.

@all: Danke für die schnellen und hilfreichen Antworten! 👍

Greets - SK

P.S: Natürlich bin ich auch für weitere Vorschläge offen, ist klar! 😁

12.06.2007 - 21:56 Uhr

Hallo zusammen!

Ich habe da ein kleines bis mittelschweres Problem. Und zwar möchte ich eine Art Stundenplan (also es handelt sich wirklich um einen Stundenplan) darstellen.

Dabei stehen die Tage (Mo-Fr) als Spalten und die Uhrzeiten (in bestimmten Intervallen) als Zeilen im Plan.
Innerhalb des Plans sollen die "Stunden" oder wie auch immer man die Termine in diesem Plan nennen möchte, per Drag&Drop verschiebbar sein, wodurch man sich sozusagen seinen Plan selbst zusammenstellen kann.

Ich gehe nicht davon aus, dass jemand ein solches Control zur Hand hat? Falls doch wäre ich natürlich froh darüber 😁

Eigentlich würde ich aber gerne einige Ideen sammeln, wie ich das Control realisieren könnte.

Mein bisheriger Ansatz: Die "Stunden" als Rechtecke mit den entsprechenden Informationen zeichnen und dann die Spalten rundherum aufbauen. Aber das ist bisher noch sehr unbefriedigend.

Also, hat jemand eine oder mehrere Ideen?

Danke schonmal!

Greets - SK

27.04.2007 - 09:56 Uhr

Ja, die Typenbezeichnung ist vollständig.

Nach diesem Schema: [Projektname].[Ordner].[Klassenname] also z.B. "MeinProgramm.Types.MeinType". Also so, wie's sein sollte...

@0815Coder: Ich habe ja das Problem, dass ich von diesem Punkt aus nicht weiterkomme...ich kann dieses Objekt leider nicht casten...

Nach der Zeile

Comparable c = (Comparable)obj;

bekomme ich eine NullReferenceException (c == null)

Also jetzt noch mal eine etwas konkretere Frage: Wenn ich eine Methode schreiben will, die es mir ermöglichen soll, aus einem bestimmten Namespace alle von einer bestimmten abstrakten Klasse abgeleiteten Klassen instantziieren zu können, wie gehe ich dann vor?

Die Methode mit dem laden des Typs in die ComboBox hat auch nicht funktioniert...vielleicht bin ich auch nur zu doof...

Greets - SK