Skript
Transcription
Skript
Visuelle Programmierung mit C# Prof. Dr. Bayerlein Schritt- für- Schritt Anleitung MS 2010 C# Prof. Dr. Bayerlein WS 2012/13 Version 4.6 vom 15. Nov. 2012 Inhalt Literatur .........................................................................................................................................2 Kurs Intro ......................................................................................................................................3 Erste Schritte Programm „Hello World“ ...................................................................................4 Vorbereitungen ......................................................................................................................5 Portieren der exe- Datei auf andere PC ....................................................................................8 Löschen von Komponenten und Source Code ..........................................................................8 Kurs 1 Spiel ...................................................................................................................................9 Zur Transparenz einige Infos: .............................................................................................15 Kurs 2 Rechnen, Multiwindowing ..............................................................................................17 Komma- Problematik ..............................................................................................................19 Mehrere Fenster.......................................................................................................................20 Kurs 3 Professionelles Design.....................................................................................................26 Menüs ......................................................................................................................................26 PopUp-Menüs mit ContextMenuStrip ....................................................................................27 StatusBar mit StatusStrip ........................................................................................................27 Hints mit ToolTips ..................................................................................................................28 Kurs 4 weitere Komponenten ......................................................................................................29 ToolStrip..................................................................................................................................29 TabControl ..............................................................................................................................30 Komponenten zur Gruppierung und Selektion........................................................................32 Kurs5 Textverarbeitung mit Stringlisten ....................................................................................34 Der Typ String .........................................................................................................................34 Der mehrzeilige Text ...............................................................................................................35 Sortieren ..................................................................................................................................38 Leerzeilen weg ........................................................................................................................38 Größe von StringListen ...........................................................................................................39 Wörter zählen ..........................................................................................................................40 Kurs 6 Projekt Diashow ..............................................................................................................41 Projektaufgabe 1 Diashowprogramm ..................................................................................43 Kurs 7 Zeichnen mit dem Graphics - Objekt ..............................................................................44 Das Graphics-Objekt ...............................................................................................................44 Kurs 8 Chart2D ...........................................................................................................................52 Kurs 9 DataTools - Einbinden von Tool- Units ..........................................................................56 Kurs 9a Zeichnen von Kurven mit Chart DotNet 4.0 .................................................................58 Kurs 10 Weitere Komponenten ...................................................................................................59 WebBrowser ............................................................................................................................59 Mediaplayer .............................................................................................................................60 Kurs 11 Email- Programm ..........................................................................................................62 Kurs 12 TreeView .......................................................................................................................62 Kurs 13 Drucken .........................................................................................................................66 Kurs 14 DLL ...............................................................................................................................68 Zusammenfassung AD- DA mit dll für ME2600, USB Orlowski: .........................................72 ME2600 ...............................................................................................................................72 USB- Orlowski – Karte – alte USB 1.1 - Version ..............................................................72 File: Kurs MS10C# Bayerlein4.6.docx Seite 1 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Neue DLL / Klassenbibliothek mit C# erzeugen ....................................................................73 Kurs 15 Zeitmessung und 1ms Timer .........................................................................................74 Kurs 16 RS232 ............................................................................................................................76 Kurs 17 bis 20 entfernt ................................................................................................................79 Kurs 21 DataGridView................................................................................................................79 Kurs 22 C# DirectX.....................................................................................................................82 Kurs 23 MySql und C#................................................................................................................82 Kurs 24 Meilhaus ME 4660 ........................................................................................................83 Kurs 25 NI mit NIDAQmx..........................................................................................................83 Kurs 26 USB- Orlowski 2.0 ........................................................................................................84 Kurs 27 Interface mit TCP/IP......................................................................................................84 WindfC#, mein großes Regelungstechnik- Toolprogramm. ......................................................85 Einige Hinweise ..........................................................................................................................86 Problematik mit Dock .............................................................................................................86 Parameter in Funktionsaufrufen und Arrays ...........................................................................86 Zeilennummern im Editor .......................................................................................................87 Literatur [1]. Andreas Kühnel. Visual C# 2008 oder neuer. Galileo Computing. [2]. Jürgen Bayer. Das C# 2008 Codebook oder neuer. Addison Wesley. [3]. Frank Eller. Visual C# 2008 oder neuer. Addison Wesley. [4]. Bernhard Volz. Einstieg in Visual C# 2008 oder neuer. Galileo Computing. File: Kurs MS10C# Bayerlein4.6.docx Seite 2 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs Intro Alle Scrreenshots siind mit dem m MS Studioo 2008 IDE Visual C#, Prof. Versiion in deutscher Menüveersion auf eiinem Vista-- Laptop auffgenommen n worden. Aktuell A benuutzte Versio on .NET 3.5 !! Start deer IDE (Entw wicklungsum mgebung) m mit Dann inn Datei Neu N Projeekt im folgeenden Bild Window ws Forms-A Anwendung wählen. gespeichertees Projekt zu u laden, mu uss man die Datei *.sln Um ein angefangennes und abg w Studio o 2008 geöfffnet. Nur daann sieht („Solutiion“ = Projeektmappe“) doppelklickken. Dann wird man nocch keine Daatei. Um den n Form undd den Code – Editor zu öffnen, öffn fne man mit Menu „Ansichht“ den „Proojektmappen n - Explorerr“. Darin kaann man dan nn entweder er die Form1 1.cs anwähleen durch Dooppelklick. Dann sieht man das Fo ormular. Miit F7 öffnet man dann den d CodeEditor. Noch eiin Hinweis zum z Editor: er unterstüützt die Blocckbildung von v Strukturrblöcken z.B B. von einer if oder for- Anweisung. A Das D Einrückken wird au utomatisch durchgeführ d rt, so dass durch d diese Scchreibweisee das Prograamm besser lesbar wird d. if ...c condition. ...) { ... .statement t... } File: Kuurs MS10C## Bayerlein n4.6.docx Seite 3 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Setzt man den Curssor vor einee geschweiffte Klammer „{„ oder hinter h eine geschlossen ne Klammeer „}“, so werden w die beiden b zu e inem Block k gehörigen Klammernn grau eingefärbt und stehen ddirekt untereeinander. Die D folgendee oft gesehen ne Syntax- Form lehnee ich ab: if ...c condition. ...){ ...statem ment... } Erste Schritte e Program mm „Helllo World d“ Man sieeht dann folgendes Bild d: Komponnentenpalettte oder Too olbox Eigenscchaften Fensster zur Verränderung vvon Eigenscchaften / Eig genschaftenn von Komp ponenten Leeres F Formular. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 4 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Vorbereitungen n Zu Begiinn sollte daas Projekt geespeichert und u ein Pfad festgelegt werden. Der Naame des Pro ojektes wird ansschließend der d Program mmname der exeDatei. Bitte niccht auf ein über ü Netz anngeschlosseenes Laufwerrk, sondern immer auf llokaler Festtplatte arbeiten n, da z.T. doch große unnd viele Datteien hin und her geschoben werden. Bei mir wird in eineem Pfad D:M MSC#/Kurss 0/ gespeich hert, der auttomatische N Name ist Window wsApplicatio on9. Unit- Soource Code Alle Deesign- Inform mationen dees Formularrs Jetzt kannn die erstee Komponen nte auf das F Formular pllatziert werd den. Dazu m muss die To oolbox geöffnett werden (M Menü Ansicht Toolboox) Wir függen einen Laabel und ein nen Button hhinzu und setzen sie irg gendwo auff das leere Formular F Das Ergebnis: E File: Kuurs MS10C## Bayerlein n4.6.docx Seite 5 Visuellee Programm mierung mit C# B Prof. Dr. Bayerlein Mit dem m Eigenschaaften Fensteer können nnun Eigenschaften der einzelnen e K Komponenteen sichtbarr und veränddert werden n. Im Beispiiel ist der bu utton1 angew wählt (Quaddratpunkte als Objjektmarkieru ungen) undd wir haben die Eigenschaft „T Text“ veränddert auf „Ersster Tesst“. Z. B. ist Text immer er die Besch hriftung eineer Komponeente, (Namee) der Namee, der CNam menskonven ntionen entssprechen mu uss (z. B. kein ne Leer- odeer Sonderzeeichen). Mitt Name kan nn die Komp ponenten im m C- Sourcee-code ang gesprochen werden. w Diee ersten wicchtigsten Eigenscchaften: Top op und Lefft geben diee Pixel- Enttfernung des obersten llinken Pixells der Ko omponente zzu der ConttainerKo omponente aan (Contain ner ist hieer das Form mular), Wiidth und Heeight sind diie Dimensio onen der Ko omponente iin Pixel. Diese Werte kkönnen allerrdings im Eig genschaftenn Fenster niicht direkt ein ngegeben w werden, sond dern dort nu ur über die E Eigenschafteen Size un nd Location.. Im Program mm können dabei sowohl übeer Left usw w. als auch über Size oder o Lo ocation Werrte veränderrt werden, es ist Geschm mackssache. Selbstverständdlich werdeen auch dies e Werte soffort verändeert, wenn ma man per Mau us mit „Annfassen“ derr Komponen nte die Lagee oder Größ ße in gew wohnter Weiise verstellt.. Die Wertee werden dan nn autoomatisch akttualisiert. Nocch ist keine einzige e Zeille C eingegeeben wordeen. Dies gescchieht jetzt. Gew wünschte Fu unktion: bei Druck auf die Taste so oll im Labeel- Text derr Schriftzug „Hello Woorld“ erscheeinen. Allee Funktionen n der Prograamme werdden über Ereeignisse (Eveents) gesteu uert. Jede Ko omponente hat eine Lisste von mögglichen Ereiignissen, diee in dem Eiggenschaften n- Fenster angeesprochen werden w könn nen. Wir beenötigen den n ClickEreiignis von bu utton1. Man n erzeugt auutomatisch eine e Ereigniss- Behandluungs- Funkttion durch D Doppelklick k auf den reechten Eintrrag neben deem Event: Symboll für die Ereeignisse- Seite Doppelkklick Es öffneet sich der Editor E für deen C#- Sourrce- Code und u man kan nn jetzt denn C#- Sourcee eingebeen, der ablauufen soll, wenn der Useer später im m laufenden Programm auf die Taste klickt. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 6 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Wir gebben folgenden rot umraandeten Texxt ein: Nun kannn das erstee Programm m kompiliertt werden, en ntweder mit F5 ooder mit Kliick auf oder über Menü: Das Prograamm wird neu n abgespeichhert, kompiliert, gelinkt undd anschließend gestartet. M Man erhält letztendlicch folgendess Ergebnis: Vor Kliick: Nach N Klick M Es sindd nun eine Menge neuer D Dateien auff der Festplaatte gelandeet: Die exxe ist jetzt daas ausfühhrbare Progrramm, wohl loogo. Die andderen Dateieen enthalten n weitere Proojektinfos, welche, spielt hier erstt mal keine Rolle. X gescchlossen werden. Das Prrogramm soollte normall über die X-Taste Niemaals über denn Task- Man nager, denn dann komm mt die IDE (Interg grated Deveelopment En nviroment) von v C# durc rcheinander und muss neu geestartet werdden. Bei En ndlosschleiffen, die vom m IDE gestaartet werdenn, ist ein Abbruch mit Shift + F F5 oder übber Menü Deebuggen/Deebugging beeenden mög glich. Noch eiin paar Tippps zum Zureechtfinden: Öffnen des Source-- Codes mitt Menü Ansiicht Cod de (F7) Öffnen des Form- Designers D mit m Menü Annsicht Deesigner (Shiift+F7) File: Kuurs MS10C## Bayerlein n4.6.docx Seite 7 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Öffnen der Toolboxx mit den Komponente K en: Ansicht Toolbox x (Strg+w, ddann x) Öffnen des Eigenscchaftenfenstters mit Annsicht Eig genschaften nfenster (Strrg+w, dann p) Portie eren der exe- Dattei auf a ndere PC C Die Dattei erwartet einige DLL L und die .N Net- Umgebung auf dem m Zielrechnner, die sie auf a einem andern P PC ohne .N Net nicht find det. Will maan sein Prog gramm anderen Usern ohne C# zu ur Verfüguung stellen, so muss maan alle Dateeien des Verrzeichnissess „bin“ kopiiert mitliefeern und .Net. fallls auf Zielrrechner nich ht vorhandeen als Redisttributable (k kostenlos voon MS) mitt liefern. Lösch hen von Kompon nenten un nd Sourc ce Code Will maan Komponenten löschen, so ist ess einfach: Markieren M un nd Taste „E Entf“ / „Del““. Nur: Hat mann Event – Source für diiese Kompoonenten geschrieben, bleiben diesee erhalten und u man hat totenn Source in seinem Pro ogramm, deer nie wieder benutzt wird. Hat maan Programm mtext geschrieeben, der auuf Eigenschaften dieserr Komponen nten zugreifft, dann wirrd es beim Kompilieren Fehlermeldungen n geben. Also am m Besten: Errst alle Verw weise auf diiese Kompo onente lösch hen, dann allle Event- functions fu leeren, ddann erst diie Komponeente entfernnen. Achtungg : Niemals Source löschen, den ddie IDE auto omatisch erzzeugt hat. N Nur Ihren Teext, den Sie einggegeben habben löschen, sonst wirdd es schwierrig. Also: inn obigem Prrogramm nu ur die Zeile Label1-->Caption= ="Hello Worrld"; löschenn, sonst nichhts mehr! k geelöscht habeen, erscheint nach F5 Wenn ees nun doch passiert ist und Sie diee Funktion komplett folg gende linke Fehlermeld dung. Jetzzt mit Strg+ +z (Undo) deen gelö öschten Texxt wiederholen und nur Ihren Text löschen. muss erst im m Diee function m Eigenschaftenffenster im Event E Clicck entfernt w werden, z. B. B durch u dann Reeset wählen. rechten Mausklick auf Click und a OK. Danach ist wieder alles Ü Jetzt nooch ein paar einfache Übungen: Veerändern vo on Lage unnd Position des Buuttons per Programm P übber Top / Lef eft usw. Das Gleeiche über Size S und Loccation, der C Code wird etwas e komp plizierter: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 8 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Man kannn jetzt sehhr gut die heervorragendde Unterstützzung mit deem „Code C Completion Window“ nutzen. Jedes Mal, wenn man Code eingibbt, dann weerden intelligente Vorscchläge gemacht, die dann miit den Tasteen Up/down n selektiert uund mit der Return-Tasste ausgewäählt werden können. Gibt maan in dieser Eventfuncttion/Ereigniisfunktion die d neue Zeile label1. .Text = bu utton1.Siz ze.Height. .ToString g(); ein, so bbraucht mann nur einen Buchstabenn eingeben und u schon erhält e man ssinnvoll Vorschläge. Z.B B. Nach Ein ngabe von „ll“ sieht man n linkes Billd. Nur durcch Taste „Re Return“ wähllt man jetzzt label1 aus. Nach dem m Punkt sieh ht man dan nn den näch hsten Vorschhlag usw. Kurs 1 Spiell In dieseem Kurs soll gezeigt weerden, wie eeinfach und d schnell und d mit wie w wenig echtem m C#Code scchon funktioonierende Programme P ggeschrieben n werden kö önnen. Wir schhließen alless Vorherige und startenn eine neue Applikation A n (DateiN NeuProjekkt), dann Geben w wir folgende Daten im Fenster “N Neues Projek kt“ ein und wähhlen Window ws Forms-A Anwendungg. Dann wird d alles in dem V Verzeichniss C:\Kurs1 Game gesppeichert. Jetzt braauchen wir 2 Bilder, diie vom ftp--server gelad den und aucch dort auf die d Festplattte kopiert w werden sollteen. Es können selbstverstäändlich auch h eigene Biilder sein, ab ber nicht allle Formate arbeiten korrrekt. Hinteergrundbild:: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 9 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Blumen.JPG aus meinem m FTP P- Verzeichnnis MS Stud dio2008 C#//Kurs1# Spiiel und das Mohrhuuhn grHuhnn5 echt.bmp. Wer sicch das fertigge Spiel vorh her mal anssehen und au usprobieren n möchte, deer lade sich die Datei Window wsApplicatioon1.exe aus dem VerzeeichnisWind dowsApplica ation1/bin/D Debug vom Server und starrte es. Man kann jetzt nach n Taste „„Start“ versuchen, auf das d sich bew wegende Moorhuhn M zu klickken. Die Treeffer und diee Fehlversuuche werden n gezählt. Die Zeit zwisschen zwei Beweguungen und die d Größe dees Moorhuhhnes können n verstellt werden. w Dieses S Spiel wollenn wir jetzt programmie p eren. Dazu brauchen b wiir einige Koomponenten n, die wir auf das leere Formuular ziehen:: Erstt zwei Kom mponenten P PictureBox von v der Seitte Allgemeiine Steuerellemente. picttureBox1 so oll das Hinteergrundbild d werden, wir aktivieren die d Eigenscchaft Imagee im Objjektinspekto or durch Kliicken auf diie Taste mit den drei Pu unkten und kkönnen nun n unser Bild d Blumen.JP PG mit „Lok okale Ressou urce“ und Imp portieren lad den. Nach Laaden sehen wir in der Komponnente einenn Ausschnittt des geladeenen Bildes.. Erst ganz zum z Schlus s wollen wiir dieses Bild untter das ganzze komplette Formular legen. Die D zweite piictureBox2 füllen wir mit m dem Moorhuhn. M Wenn W es nacch dem ersteen Bild au uf das Form mular gezogeen wurde, dann d liegt ess über dem ersten e Bild.. Man M kann diee Reihenfollge aber in dem d Po opUp-Menu u jeder Kom mponente leicht veerändern: Dort D kann maan „In den V Vordergrun nd“ oder „IIn den Hinteergrund“ wä wählen. Das Moorhuhn M muss m vor dem m Hintergru undbild liegen. Soll dass Bild die piictureBox vollkommenn ausfüllen, so setzt man n die Eigennschaften SizzeMode auf StreechImage. Den D gleichen n Effekt erhhält man, weenn man auf den kleineen Pfeil obeen rechts in der P PictureBox klickt k und dann d die SizzeMode/Grö ößenmodus entsprechennd wählt. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 10 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Übrigenns können Eigenschafte E en der Sortee Bool mit einem Dopp pelklick auff true oder false f in die jeweeils andere Eigenschaft E t geschaltet werden. Will maan jetzt das Hintergrund dbild formaatfüllend in der Form darstellen, auuch dort diee SizeModde auf StrecchImage steellen und diee Dock- Pro operty auf „F Fill“ stellenn. Soll dass Programm m den Bildscchirm kompplett füllen, dann setzt man m in der FForm die Eiigenschaft Window wsState auf Maximized. M Diese Voreeinstellungeen kann man n auch proggrammieren n, das sieht daann so aus: Hinter ppublic Form m1() kann man m Initialisiierungen du urchführen, jedoch kannn man die Form F erst auf Maxximized stelllen, wenn sie s aktiviert ist. Die Ereeignisfunktion Form1_A _Activated erzeugt e man durrch Markierren von Forrm1, selekti eren der Ev vents im Pro operty Manaager und daann Doppelkklick hinterr Activated. Jetzt füllt ddas Bild mit den Blumeen allerdingss noch nicht die volle Foorm aus, da es noch niccht „gestrechhed“ wurdee. Also auch h in PictureB Box1 die SiizeMode anpasseen. Jetzt weerden noch benötigt: b 2 Labels, Transparrent geht no och nicht, Foont-Eigenscchaft nach Geschmack G (ich mag ComicS SansMS), Scchriftgröße auf 14pt. Scchriftfarbe Rot R stellt man m in der E Eigenschaft ForeCoolor ein. Diee gleichzeitiige Verändeerung von E Eigenschafteen von mehrreren Kompponenten geeht, wenn man diee Komponennten gemein nsam anwähhlt. Die Anffasspunkte werden w dann nn grau. Dass gemeinssame Anwäählen geht mit m z. B. geddrückter Shiift- Taste od der mit andeeren Windo owstypischeen Wegen. Den D Text au uf Hits=0 unnd Misses= =0 in Eigenschaft Text ändern. Weiter 2 Buttons, eine e Name= =buttonStartt, Text=Starrt, die anderre Taste Naame=buttonStop, Text=Sttop. Dann brrauchen wirr zwei Verstteller für Zaahlen, zu fin nden in Allg gemeine Steeuerelementte, dort NumericcUpDown. Den voreingestellten W Wert von Nu umericUpDown1 in Vaalue auf 100 00 ändern. Das gehht auf Anhieeb nicht, da der Maxim malwert in Maximum M au uf 100 steht.. Den also erst e auf 2000 unnd dann Vallue auf 1000 0 und Increm ment auf 10 00. Und den n Value vonn NumericU UpDown2 auf 100 verstellen. Beide mit einem e Labeel beschrifteen mit „ms“ und „size inn %“.Ergeb bnis: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 11 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Userfreuundliche Prrogrammiereer spendiereen noch ein ne Close-Tasste. Diese isst mit einem m Button leicht zuu erreichen.. Habe diesee Taste butttonClose geenannt, Text auf Close uund in Imag ge das Bild cloose.jpg einbinden, TextA Align auf M MiddleRight und ImageA Align auf M MiddleLeft. In I der Click Fuunktion dannn folgenden n Text: Will maan aber mehhrere solcher Buttons m mit Icons hab ben, so warrte man auf die dafür viiel bessere Komponennte ToolStrip p. Noch eiinen Hinweiis für Freun nde der Steuuerung überr Tastatur. Macht M man iirgendwelch he Bediensschritte imm mer wieder, dann ist dass Bedienen über Tastattur einfach sschneller un nd bequem mer als mit Maus. M Dies wird w auch hhier unterstü ützt. Man sieht unten inn der Close-- Taste, dass dass C unterstrrichen ist. Scchreibt mann in der Eigeenschaft Texxt ein & vorr dem Buch hstaben C, definierrt man dieseen Buchstab ben als Shorrt-Cut- Taste. Wollen wir w z. B. in uunserer Anw wendung die Starrt-Taste mit der Tastatu ur über „a“ sschnell ansp prechen (un nd bei Stop zz. B. mit „o o“), so schreibeen wir in Teext vor dieseen Buchstabben ein „&““. Wir haben n jetzt: Diese T Tasten lassenn sich jetzt z. z B. mit AL LT+“o“ bed dienen. Die Eig genschaft Do ock führt einne automatiische Plazieru ung und Verrgrößerung von Komponenten durch. Man M kann die d Seiten deer Komponeenten damit an n die Seiten n des „Contaainers“ kleb ben. Bei uns ist die d Form1 der d Containner. Mit Klicck auf den Pfeil un nten in der Eigenschaft E Dock öffneet sich ein Fensterchen mit ein nigen Tasteen. Klickt man m z.B. auf die Taste, auf die d der rote Pfeil zeigt, dann wird Do ock auf Leftt gestellt unnd bei der Komponente wird z. B. die linnke, obere und u untere bbar. Wir w wollen alle vier v Seite ann den Container geklebtt, die rechtee Seite ist frrei verschieb Seiten kkleben, das geht g mit Klick auf die mittlere gro oße Taste, Dock D wird ddann= Fill. Macht M man dieeses im Eigeenschaftenfe fenster, hat ddas den Nacchteil, dass schon in deer IDE das Formular F ausgefüüllt wird undd die Form durch d Ankliicken nicht mehr selektiert werdenn kann. Bessser man klebt erst nach dem m Start des Programms, P , z. B. in dem dafür besstens geeignneten Eventt „Form__Activated“,, wie oben bereits b schoon gezeigt. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 12 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Danach sollte alles wie gewün nscht aussehhen, nur es funktioniert f t noch nichtts. Zu einem m Spiel wirrd es erst mit den nächssten Schritteen. Was solll passieren: Nach Startt soll die Poosition von PictureBox2 P 2 mit einem m Zufallsgen nerator verändeert werden. Klickt K der User U auf dass Bild Pictu ureBox2, solll ein Zählerr inkrementtiert werden,, trifft er danneben (also o auf PictureeBox1), solllen diese veerfehlten Treeffer gezähllt werden. Bei Stopp soll alles anhalten, beei Start die Z Zähler wied der auf null gesetzt werrden. Dazu brrauchen wirr eine Timerr-Komponennte, die regelmäßige Ereignisse zuum Verstelllen der Positionn erzeugen kann. k Diesee finden wirr in der Toollbox unter „Komponen „ nten“ als Tim mer. Er hat die E Eigenschaftt „Enabled““, die im Eiggenschaftsfeenster auf False F gesetzzt wird. Wen nn Enabledd auf True steht, s dann erzeugt e er aalle in Intervval spezifiziierten Millissekunden den Event Tick. Allso folgendee Schritte siind zu tun: timer1 aauf Form1 ziehen, z Ena abled auf Faalse, Interva al auf 1000. Jetzt Staart und Stopp- Taste pro ogrammierenn mit Dopp pelklick auf die jeweiligge Taste und d füllen der Clicck- Funktionn mit untensstehendem rrot umrahm mtem Text. Im Ereiggnis timer1_Tick wird mit dem Zuufallszahlen ngenerator Random() R di die Position des oberen P Pixels vom Moorhuhn in PictureB Box2 im erlaaubten Bereeich verändeert. Der erlaaubte Bereichh berechnet sich aus derr freien inneeren Dimen nsion der Fo orm1 (abgeffragt in ActiveF Form.ClientSSize.Width und u …Heigght) abzüglicch der Dimension derP PictureBox2 2. Der volllständige Code in timer1_Tick lauutet: Random r rand = new Random(); R pictureB Box2.Left = rand.Next(Fo orm1.ActiveF Form.ClientS Size.Width - pictureBox x2.Width); pictureB Box2.Top = rand.Next(For r rm1.ActiveFo orm.ClientSi ize.Height - pictureBox x2.Height); Mit der Methode .N Next(zahl) wird w eine Zuufallszahl zw wischen 0 und u zahl-1 eerzeugt. oorhuhn muuss nach Staart über den Bildschirm m springen. Jetzt austesten mit F5. Das Mo Jetzt fehhlen noch Zähler Z und Ergebnisaus E sgabe und Veränderung V g der Beweguungsgeschw windigkeit. Letztes L ist einfach: im ValueChang V ged- Ereignnis von numericcUpDown1kkopiere man n den Wert von numeriicUpDown1 1 .Value nacch Timer1.IInterval. Code: private e void num mericUpDow wn1_ValueC Changed(object sender, Even ntArgs e) { time er1.Interv val = (int t) numericUpDown1.Value; } Das exppliziete Castting auf int ist nötig, daa Value ein Typ „Decim mal“ ist. Den Zähhler realisieert man mit zwei Variabblen außerh halb der Fun nktionen. Diieses sind keine k globalenn Variablenn (gibt es in C# nicht m mehr), sondeern zwei Varriablen des Objektes Form1. . File: Kuurs MS10C## Bayerlein n4.6.docx Seite 13 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Ich macche es mit den d beiden Variablen V cnntOK und cntNOK. c Also beei der Start- Taste auf null n setzen, bbei Click au uf pictureBox1 (danebeen) cntNOK K ++, bei Click auuf pictureBoox2 Treffer cntOK++ uund Ergebniis in label1 / 2 anzeigenn mit der Methode M ToStringg(), die denn Intergerweert in einen String umw wandelt. Fertigerr Source: In timerr1_Tick: l label1.Tex xt = "Hits s= " + cnt tOK.ToStri ing(); l label2.Tex xt = "Miss ses= " + c cntNOK.ToS String(); In pictuureBox2_Cliick cntOK++ +; In pictuureBox1_Cliick cntNOK+ ++; hüsse auf nuull bleiben, wenn Nun hatt diese Proggrammierweeise den Nacchteil, dass die Fehlsch man nicchts tut. Wertet man ein n Nichtstun auch als Feehlschuss, muss m das Proogramm etw was abgeänddert werdenn. Zudem sollte in einem m Durchgan ng nur ein Klick K gezähllt werden, z.Zt. z kann man proo Durchgangg mehrere Treffer T auslöösen. Im Tiimer wird in n einer Booll- Variable namens „free“ eein Schuss freigegeben f und schon m mal ein Feh hlschuss gezzählt. Nur inn pictureBo ox2_Click wird jettzt ein Trefffer gezählt, der Zähler ffür die Fehllschüsse korrrigiert und weiter Schü üsse blockierrt (siehe Koommentar). Im neueen Source siind timer1_ _Tick und piictureBox2_ _Click unten n abgebildett. Die Reiheenfolge im Sourrce ist beliebbig verändeerbar. Im Edditor kann man m vor jedeer Funktionn mit den + oder o – Zeichenn mit quadraatischem Raahmen den C Code verbeergen oder öffnen. ö File: Kuurs MS10C## Bayerlein n4.6.docx Seite 14 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Zum Abbschluss dieeses ersten kleinen k Projjektes wird jetzt noch die d Größe ddes Zieles vaariiert mit numericUp pDown2. D Dort soll einee Prozentzah hl die tatsäcchliche Größ ße bestimmen n. Steht dort rt 50, so solllen Height uund Width eben e nur 50 0% der ursprrünglichen Größe besittzen. Im Exp xplorer kann n man die Größe ddes Bildes erkennen e miit 117* 226 Pixel. Im Ereignis E Cha anged von nnumericUpD Down2 wird dannn folgendeer Text hinzzugefügt: Man beachte, dass vor Start diie Originalw werte Heigh ht=226 und Width=117 in pictureB Box2 stehen ssollten und dass d die Eig genschaft SiizeMode au uf StrechIma age steht, soonst geht ess nicht. Code: private e void num mericUpDow wn2_ValueC Changed(object sender, Even ntArgs e) { pict tureBox2.W Width = 11 17 / 100 * (int)numericUpDo own2.Value e; 226 / 100 * (int)numericUpD pict tureBox2.H Height = 2 Down2.Valu ue; } Ein letzzter Schönheeitsfehler wird w beseitiggt. Wenn maan die Beweegung des Z Zieles beobaachtet, so erscheinnt ganz kurzz aber sichtb bar das Ziell erst horizo ontal neben der alten Poosition. Dass liegt daran, ddass erst Lefft und dann Top verstelllt wird. Abändeerung durch das Verstelllen von Loccation, dann n werden x und y- Kooordinate gleichzeitig verstelltt. Code inn timer1_Ticck: int lef ft= rand.N Next(Form1 1.ActiveFo orm.ClientSize.Wid dth - pict tureBox2.W Width); rm.ClientSize.Height - pict int top p= rand.Ne ext(Form1. .ActiveFor tureBox2.H Height); Point l loc1 =new Point(lef ft,top); picture eBox2.Loca ation = lo oc1; Weitereer Variationen wie z. B. High Scorre Liste, ein nstellbare Laaufzeit, mehhrere Ziele sind s keine G Grenzen geseetzt. Stellt m man die Zeit auf <700 ms, m so wird ees schon seh hr schwierig g, alle Zielee zu treffen. Alle ferrtigen Dateien sind auf dem ftp-Seerver unter „Kurs1#Spi „ el“ zu findeen. Dort hab be ich auch nooch den Titeel der Form (in Form1.T Text) geänd dert. Jetzt fehhlt eine kleiine Schönheeitskorrektuur: Es ist diee Transparen nz der Labeel und des Zieles, Z was nichht so triviall ist. Z Zur Transp parenz os: e inige Info Eiine Form haat die Eiigenschaft Opacity, O diie zwischen n 0 und 1000% eingesstellt w werden kann n. Damit w werden alle Elemente E m mehr oder weniger duurchscheineend. Bei 500% sieht daas Spiel z..B. so aus und der Innhalt dahinter File: Kuurs MS10C## Bayerlein n4.6.docx Seite 15 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B schimm mert schon mächtig m durcch. Dies ist für Auf- un nd Abblendu ungen beim m Start wohl mal ganz witzig. Stellt man m die Eig genschaft TrransparencyyKey z.B. auf Wh hite, dann bekommt diee Anwendun ng an allen Stellen, S die weiß w sind, L Löcher und der Hintergrund ist zu u sehen. Sow wohl in der Überscchrift als auch die numeericUpDow wn sind jetzt sttellenweise durchsichtigg. Selbst die Maus klickt durch d die Löcher L durchh. Das Close- Kreuz ist auch durchsich htig! Nur leidder gilt dies nicht für eiin BMP, da s in eine picctureBox geeladen ist. Transpaarenz ist mitt BMP- Bild dern nicht m möglich. Ab ber dafür kaann man giff und png- Bilder B laden, uund die bringgen eine Trransparenz- Eigenschafft mit. Ich habe das Mooorhuhn- Bild in ein GIF konnvertiert und die Außen nfarbe als T Transparenzz Farbe deklariert (das ggeht mit einschläägigen Bildbbearbeitung gsprogramm men, z. B. ULead U Photo oimpact). Ess heißt jetzt grHuhn5 echtweiß iß3.gif. Dann muss man n noch BackkColor von PictureBoxx2 auf Transsparent stelllen, dann sollte ess gehen. Den TranpareencyKey derr Form wied der auf eine Farbe stelleen, die nich ht vorkom mmt, z.B. redd. Nun solllte es gehenn. Damit beim Bewegeen des Moorrhuhns kein ne weißen Feelder zu seh hen sind, stellt maan dann nocch die Eigen nschaft DouubleBuffered d von Form m1 auf true.. Die Label L werdeen mit folgeendem Schritt gegen das Blumenbild B transparentt: pictureBo ox1 lösch hen samt aller Verweisee darauf. Daas Bild wird als Hinterg grundbild deer Form n so, wie im Bild setzenn. Dann in allen a eingebuunden. Dazuu setzt man dort die Eiggenschaften Labels ddie Eigenschaft BackC Color auf Traansparent setzen. s Diese ist unterr „WEB“ zuu finden. Ich h hab die Faarbe in ForeeColor auf Yellow w gesetzt, dann sieht ein Label so aus: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 16 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs 2 Rech hnen, Multiwind dowing Es wirdd die Berechhnung, die Ein-sowie E A Ausgabe von n Zahlen gezzeigt sowie der Umgan ng von Projekteen mit mehrreren Fensteern. Start miit neuer Anw wendung. Es E werden zw wei TextBox- Kompon nenten mit zzwei Beschrriftungen (Label) auf das leerre Formularr platziert. B Bei mir ist es e WindowssApplicationn11. Ändere Ä Labeel->Text Inhhalte und Ed dit->Text Eigenschafte E en wie linkss gezeigt. Nach N Eingab be einer Zahhl in Feld Radius R soll die d Fläche au usgegeben w werden und d nach Eingabe E der Fläche in A Area soll derr Radius berechnet b weerden. Die FFormeln lau uten bekanntlich: b A= A πr2 sowiee r=(A/π). Nun muuss überlegtt werden, in welchem E Ereignis die Berechnun ng durchgefü führt werden n soll. Es soll keinn Button zuum Start derr Berechnunng geben. Möglichhkeiten: 1. TextCanged T d der textBoox- Kompon nenten. Nachteil: gibt m man falsche Werte ein (z. B B. Buchstabben) führt diie Berechnuung sofort zu u Fehlermeldung, da jaa sofort der Stringinnhalt des Tex ext- Feldes (.Text ( ist einne Zeichenk kette, Typ String) in einne Zahl kon nvertiert wird unnd der User keine k Chance hat, es zuu korrigiereen. Die Kon nversion dess Strings in eine Floatingg- Point – Zahl Z geht miit Double.Pa Parse() oderr mit Conveert.ToDoublle(). Auspro obieren: Code: private e void tex xtBoxRadiu us_TextCha anged(object sender, EventA Args e) { doub ble radius s=Double.P Parse(text tBoxRadius s.Text); doub ble area = radius*r radius*Mat th.PI; text tBoxArea.T Text = are ea.ToStrin ng(); } Hinweisse zur Berecchnung: Diee Ein- und A Ausgabe erffolgt über die d Text- Eiggenschaft vo om Typ String. E Es muss dannn eine Kon nvertierung von Float nach n String und umgekkehrt durchg geführt werden.. Es wird hiier der Floatting-Point T Typ „doublee“ benutzt (cca. 15 Stelleen), der viel genauer ist als flloat (7 Stelllen). Die Ko onstante π isst in der maathematischeen Bibliotheek Math zu finden. 2. Leavee: Dann wirrd das Ereig gnis ausgelööst, sobald der d Focus au uf eine andeere Kompon nente übergehht, z. B. durcch Klick des Benutzerss auf textBo ox2. Nur derr User musss das wissen n. Also Änndern von OnChange O auf a Leave. D Das geht so,, dass man das d Feld hinnter dem Ereignis Leave ddoppelklicktt, im Code den d Inhalt vvon TextCha anged in diee neue Funkktion Leave schiebt. Jetzt niccht im Cod de den Funk ktionsaufruff löschen, so ondern den Eintrag E im E Eigenschaft ftsfenster unter TeextChangedd. Dann wird d in der IDE E automatissch der Funk ktionsaufruff gelöscht. private e void tex xtBoxRadiu us_TextCha anged(object sender, EventA Args e) { NICHT LÖSCHEN L !! ! } private e void tex xtBoxRadiu us_Leave(o object sender, EventArgs e) { d double rad dius = Dou uble.Parse e(textBoxR Radius.Text); d double are ea = radiu us * radiu us * Math. .PI; t textBoxAre ea.Text = area.ToSt tring(); } File: Kuurs MS10C## Bayerlein n4.6.docx Seite 17 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Diesen Einntrag Lösch hen ! Oder Cursoor auf TextC Change, rechter Mauusknopf, daann « Zurückseetzen » 3. Mögllichkeit. Naach Druck der d Eingabee- Taste (aucch return- Taste T genannnt) auf dem Keyboaard soll Bereechnung durrchgeführt w werden. Daas ist nicht mit m dem Ereeignis Enterr zu realisierren (Enter wird w ausgelö öst, wenn diie jeweiligee Komponen nte den Focuus bekomm mt). Dazu giibt es das Erreignis KeyP Press. In deem Header der d Funktio on wird im PParameter e der Char-W Wert der Tastte in e.KeyC Char überggeben, der besagt, welch he Taste geedrückt word den ist. Die retuurn / Eingabbe- Taste haat den Wert HEX 0D. Also A Code: private e void tex xtBoxRadiu us_KeyPres ss(object sender, KeyPressE EventArgs e) { if (e.KeyChar ( r == 0x0d) ) textBoxR Radius_Lea ave(this,e e); } Oder private void textB BoxRadius_K KeyPress(ob bject sender, KeyPress sEventArgs e) { if (e.KeyChar == = (char)Key ys.Return) t textBoxRadi ius_Leave(tthis, e); } Hinter dder if- Abfraage wird nu un die Berecchnung ausg gelöst. Hier könnte einee Kopie derr Zeilen unter Leeave folgen, aber man kann k auch eeine existierrende Ereign nisfunktionn direkt aufrrufen. Im Zeiger „„sender“ wiird die Adreesse des auffrufenden Containers C üb bergeben. Vervollständigen Sie S das Prog gramm zur B Berechnung g auch noch des Radiuss aus der Flääche nach Druck aauf die Einggabe- Taste, wenn die T Textbox für „area“ den Focus hat. Ein Hinnweis sei nooch getan: Die D Ausgabee einer Floatting- point Zahl Z kann aauch formattiert erfolgenn, indem maan in der Methode ToS String(IForm matProvider) den IForm matProviderr benutzt. Beispielle: Ausgabee von in einer Teextbox mit ergibt x.ToString(); K Keine Forma atierung x.ToString("f2"); F Festkomma 2 2 Stellen x.ToString("g2"); 2 2 Stellen „ „general“ File: Kuurs MS10C## Bayerlein n4.6.docx Seite 18 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B x.ToString("c2"); „ „Currency“ 2 Stellen x.ToString("e2"); „ „exponentia al“ x.ToString("p2"); P Prozent Dann giibt es noch die Buchstaaben „d“ fürr Dezimalau usgabe, dann muss x jeedoch ein Ty yp „decimaal“ sein. Hexadeezimalausgaabe: x=255 führt mit xx.ToString("x10"); zuu Und mitt x.ToStringg("X10"); zu Das Erggebnis bis hierhin ist in n Kurs 2a# B Berechnung g auf dem ftp p zu findenn. Komm ma- Prob blematik Wenn m man Texte / Strings in Fließkomma F azahlen um mwandelt, gib bt es ein gruundsätzliches Problem m: Auf deutsschen PCs ist i der Dezim maltrenner ein Kommaa, der Punktt ist für Tausenddergruppierrung vorgeseehen. Bei U US- Rechnerrn ist es gen nau umgekeehrt. Da bei uns auch meine P Programme von US- Sttudierendenn benutzt weerden sollen n, muss das PProgramm mit beiden V Versionen klarkommen k n. Werden T Textdateien n zwischen beiden b Natioonalitäten ausgetauuscht, dannn gibt es imm mer wieder Konflikte genau g deshaalb. Der deuutsche Rechn ner erzeugt Zahlen mitt Kommas z.B. z 1,234, ddie dann von n US- Rech hnern als Taausendertren nnzeichen gelesen werden undd diese Zah hl als 1234 liiest. bstgeschriebbene eigene ConvertToDouble- Fuunktion. Weenn in Eine Löösung bietett meine selb einer Zaahl nur ein Trennzeiche T en auftauchht, wird dies als Dezimaaltrenner auufgefasst. Wenn W mehr als ein T Trenner aufftaucht, so isst das rechtee immer derr Dezimaltrenner, die lilinken immeer Tausenddergruppierrungen. Also o egal ob 1,,234.78 odeer 1.234,56 beide b Zahleen werden riichtig als 1234 Kommma 78 interrpretiert, wo obei Komma dden Dezimalltrenner meint. Dabei i st es egal, auf a was für eineem Dezimalttrenner der PC gestellt ist, dies wiird vorher von der Funkktion geprüft. Der einzzige nichtlöösbare Konfflikt taucht aauf, wenn der d einzige Trenner T in eeiner Zahl ein Tausenddertrenner sein s soll. Beei dieser Funnktion wird d er immer als a Dezimalttrenner geleesen. Also egal ob 1,234 oder 1.234, diese Zahl wirdd dann immer als 1 Komm ma 234 gelessen. Beispiellanwendungg: Neues P Projekt nachh Kurs 2c# erzeugen. e Z Zum Projektt Hinzufügeen die Datei DataToolsM Mini.cs: Dann diiese Datei DataToolsM D Mini.cs sucheen und ausw wählen. Außerhaalb einer fuunction jetzt eine neue IInstanz von DataTools erzeugen, iindem man das Wort DataToools eintippt und rechte Maustaste Auflösen n wählt: Dann w wird automattischer der namespace n von DataTo ools hinzugeefügt, nämllich WINDF F7CSharp. Weiter: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 19 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B DataTools dt t = new Dat taTools(); Nun einne Textbox und u ein Lab bel hinzufüggen. Hinter ddem Click- Ereignis des Labels daann folgendeen Code erg gänzen: double e X = 0; dt.Con nvertToDoub ble(textBox x1.Text, ref f X); label1 1.Text = X. .ToString() ; Dann kaann man das Programm m ausprobieeren. Mehre ere Fens ster Ein Projjekt hat norrmalerweisee mehr als e in Fenster. Wir wollen n jetzt ein Prrojekt mit drei Fensternn generierenn. Ein Fenstter soll das eben entwicckelte sein, ein weiterees soll das Hauptfeenster werdeen, von dem m dieses geööffnet wird und u ein dritttes soll ein Infofensterr sein. Dazu füügen wir zw wei Forms zu u unserm Prrojekt hinzu u. Am besten öffnet maan dazu den Projektm mappen-Expplorer (Strg g+w,s). Dortt kann man das Projektt selektierenn (bei mir Window wsApplicatiion11), dann n im Popup wählen „H Hinzufügen“, dann „Neuues Element“, dann eine Wiindows Form m selektiereen. Die zweei Male wied derholen. Nun N alle Form ms mit neueem Namen versehen, so s dass anscchließend w wie im Bild die d drei gew wünschten FForms zu seh hen sind. nnen“ auch aauf Die Abffrage, ob daas „Übernen Verweisse wirken sooll, natürlich bejahen. Name soowie Text der d zweiten Form: Form mMain, Nam me sowie Text T der dritttten Form: FormInfo. F Größen und Positioon etwa so wie w im nächhsten Screen nshot. Nun wirrd allerdinggs beim Starrt immer no ch das alte Circle- Fen nster geöffneet, nicht wiee gewünscht FormM Main. Dieses kann man äändern in deer Datei Pro ogram.cs, ddie wir jetzt öffnen. Dort in der Funktioon Main() siieht man follgenden Co ode: s static voi id Main() { Appl lication.E EnableVisu ualStyles( (); Appl lication.S SetCompati ibleTextRe enderingDe efault(fal lse); Appl lication.R Run(new Ci ircle()); } Im rotenn Rahmen steht s der Naame der Form m, die als erstes e sichtbar wird. Hieer einfach auf a FormMain ändern. Dann öffneet sich nachh Start unserr FormMain n: Applica ation.Run( (new FormM Main()); Bevor w wir jetzt weiitermachen,, sollte erstm mal die Location der Fo ormulare auuf verschied dene Werte ggestellt werdden, sonst liiegen alle F Fenster genaau übereinan nder. Also LLocation vo on FormM Main lassen auf a (0;0), Fo ormInfo auff (200;200) und FormC Circle auf (1100;100). File: Kuurs MS10C## Bayerlein n4.6.docx Seite 20 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Jetzt zw wei Buttons auf das Hau uptfenster, aalso in Form mMain plazzieren, bescchriften mit Circle und Infoo. Mit „Circcle“ soll jetzzt unser urspprünglichess Fenster geeöffnet werdden und zwaar „nichtm modal“, d. h.. der User kann k in andeere Fenster klicken. k Daas Info-Fensster soll „mo odal“ geöffnett werden, d.h. der Userr muss erst ddieses Fensster schließeen, bevor err andere Fen nster der Applikaation erreichhen kann. Welche W Sortee sinnvoll isst, bestimmen Sie als PProgrammieerer. Die Methodden zum Öfffnen der Forrms heißen einfach Sho ow() und Sh howDialog() ().Code: FormInf fo frminfo o = new Fo ormInfo(); ; Circle frmCircle e = new Ci ircle(); private bject sender, EventArgs e) e void but ttonCircle e_Click(ob { frmC Circle.Sho ow(); } private e void but ttoninfo_C Click(obje Args e) ect sender, EventA { frmi info.ShowD Dialog(); } Erst werrden Instanzzen der Forrmulare erzeeugt mit new w, dann kan nn man dies e Formulare ansprechen mit denn beiden Show- Methodden. Die Insstanziierung g muss dabeei außerhalb b einer Funktioon erfolgen, damit der Name N der Innstanz (also z.B. frminffo) für andeere Funktion nen erreichbbar ist. Jetzt solllte das Proggramm wie gewünschtt funktionierren. Auspro obieren. Man kannn jetzt beliiebig zwisch hen Circle uund FormM Main hin und d her springgen, aber Fo ormInfo muss geeschlossen werden, w um m wieder an Circle oderr FormMain n zu gelangeen. Wird Fo ormMain geschlossen, werdeen die anderren Fenster auch geschlossen und aus dem Sppeicher entfe fernt. Nun gibt es eein Problem m. Schließt man m die Info fo- Form, daann kann maan sie beliebbig oft wied der öffnen, die Instanz wird beim Schließen nnicht entfern nt, sondern nur unsichttbar. Öffnet man aber eine Forrm mit Show w() und sch hließt diese m mit Close(), dann wird die Instanzz aus dem Speicher File: Kuurs MS10C## Bayerlein n4.6.docx Seite 21 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B entferntt. Beim nächhsten Klick auf die Tasste circle gib bt es dann eine e Fehlerm meldung, daa auf eine Instanz zugegriffenn wird, die es e nicht mehhr gibt: Übrigenns jetzt überr Menü Deb bug nach Stoop Debuggiing gehen un nd Program mm beenden n. Abhilfe 1: Man verrlegt die Insstanziierungg in die Clicck- Funktion n des Buttonns. Ergebnis ist, dass nach jeddem Wiederröffnen von n circle die D Daten weg sind s und sch hlimmer beei jedem Kliick auf circle eiin neues Fennster aufgem macht wird.. Im Bild un nten gibt es jetzt 3 Fensster. Abhilfe 2: Man speendiert einee Close- Tasste auf Circlle, in der nu ur die Form unsichtbar gemacht wird w mit Aufruf dder Methodde Hide().Co ode in Circlle: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 22 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B private e void but ttonClose_ _Click(obj ject send der, EventArgs e) { C Circle.Act tiveForm.H Hide(); } Dann soollte man abber die Closse- Taste im m Kopf des Windows-R W Rahmens aucch verschwiinden lassen zz. B. mit derr Property ControllBox der Foorm, die dan nn auf False geesetzt wird. Noch beesser: ContrrolBox lasseen (der Useer erwartet das d ja irgend dwie und keennt es) und d den Close- B Befehl abfanngen mit fo olgendem Evvent: private e void frm mCircle_Fo ormClosing g(object sender, FormClosin ngEventArg gs e) { e.Ca ancel = tr rue; Visi ible = fal lse; } Dann geeht es. Schaut m man jetzt auuf unser Pro ojektverzeicchnis, so erk kennt man folgende f Daateien links. Jedes Fensteer hat eine .cs - Datei fü für den Sourrce, eine .Desig gner.cs für das d Design der Oberflääche, eine .resx. Im Pfad „bin“ findet m man dann diie exeDatei.. Bitte die .D Designer.css nicht öffneen und nicht verändern. Es ist eine vvom IDE matisch erzeugte Textdaatei, die dass autom graph hische Desig gn festlegt. Zwiscchen Code (.cs) ( und Deesign nur mit Menü View umschalten n. In FormIInfo soll miit Druck auff einen Button der d Inhalt voon textBoxR Radius.Text von Circle herüberg geholt werde den. Realisieerung folgendeermaßen: Der Zugriff von einner Form auff nts Propertiees, Methodeen und Even anderer Forms F ist m möglich, sofe fern man von der Main M Form auf die dorrt instanzieerten Formss zugreifen will. w Also im obigeen Beispiel kkann man von v FormMa ain auf frmC Circe und frrmInfo zugreifeen. Was muuss man tun:: Beispiel: A Auf FormM Main soll mitt einem Buttton „buttonTransfer“ der d Inhalt (.T Text) von laabel1 auf Fo ormInfo verrändert werdden. Versuccht man 24 File: Kuurs MS10C## Bayerlein n4.6.docx Seite 23 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B es, so geeschieht ersst einmal folgendes: Einn Zugriff au uf frminfo.la abel1 ist niccht möglich h und wird im CodeeCompletioon- Fenster nicht n angebboten. Das liiegt daran, dass d die Koomponente label1 l als „privatee“ deklariertt ist. Diese muss m auf „ppublic“ geän ndert werdeen. Dies ist m mit der Prop perty „.Modiffiers“ des laabel1möglicch. Also in F FormInfo diiesen Modiffiers auf Puublic umstellen. Dann ist ein Z Zugriff auf label1 l mögllich. Jetzt wirrd in FormM Main ein Zu ugriff auf label1 an ngeboten. FFertiger Cod de: private e void but ttonTransf fer_Click( k(object sender, EventArgs e e) { frmi info.label l1.Text = "This Message com mes from F FormMain"; } Somit isst also ein Zugriff Z vom m Hauptproggramm, in dem d der Kon nstruktor miit dem Schlüsselwort new auffgerufen wirrd, problem mlos möglichh. Aber wiie kann jetzzt vom Sub- Fenster (Foorminfo odeer Circle) au uf das Form mMain oder von Sub nach Suub zugegrifffen werden. Das geht foolgendermaaßen. Für deen Zugriff bbraucht das Program mm in der SubS Form eine Referennz (ist natürlich so etwaas wie ein PPointer / Zeiiger). Diese R Referenz muuss vom Maain an die Suub- Fenster übergeben werden. Dazu w wollen wir jeetzt folgendees Beispiel realisieren. Ein Tasten ndruck auf FFormInfo so oll jetzt den Inhalt einer TeextBox auf FormMain F aauslesen in ein Label. Ein E zweiter Tastendrucck soll aus Circle dden Radius aus a der entssprechendenn Textbox auslesen a und d in ein Labbel in FormIInfo schreibeen. In Form mMain folgeende Veränd derung durchfüühren: In Fo ormInfo folgende Veräänderung durchführen: FormInf fo frminfo o; Form mMain mein nMain; public FormMain( () { In nitializeC Component( (); frminfo o = new Fo ormInfo(th his); } publ lic FormIn nfo(FormMa ain m) { Initia alizeCompo onent(); meinMa ain = m; } File: Kuurs MS10C## Bayerlein n4.6.docx Seite 24 Visuelle Programmierung mit C# In der ersten Zeile wird ein globaler Zeiger auf FormInfo ohne Konstruktor deklariert. Im Konstruktor (nach new) wird jetzt mit Schlüsselwort this der Zeiger auf FormMain an den Konstruktor in FormInfo übergeben Prof. Dr. Bayerlein In der ersten Zeile wird ein globaler Zeiger auf FormMain ohne Konstruktor deklariert. In der zweiten Zeile wird this in m übergeben und in der Zeile meinMain=m wird der globale Zeiger auf FormMain gestellt. Ab dann ist FormMain über meinMain erreichbar. Mit der Zeile label1.Text = meinMain.textBox1.Text; Kann dann in FormInfo die Textbox auf FormMain ausgelesen werden. Der Zugriff von FormInfo auf Circle geht jetzt nicht direkt, sondern über FormMain. Will man den Radius von Circle nach FormInfo auslesen, geht das einfach mit label1.Text =meinMain.frmCircle.textBoxRadius.Text ; Das war‘s. File: Kurs MS10C# Bayerlein4.6.docx Seite 25 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs 3 Profe essione elles Des sign In dieseem Kurs werden die Ko omponentenn StatusBar,, Menu, Pop pupMenu m mit einigen wichtigen w Eigenscchaften wie ToolTips (ffrüher: Hint) t) vorgestelllt. Menü üs Wir wo ollen mit deem Ende dess letzten Ku urses startenn. Die Dateien sind verfügb bar auf dem m FTP- Serv ver studpub.ffh-luebeck.dde unter bayyerlej/MS Studio2 2008/kurs2bb# Multiwin ndows. Wir wo ollen als ersstes dem Haauptfenster FormMain F eein MenuSttrip hinzufüügen. Diese Komponentte ist in der Toolbox „M Menüs & Sy ymbolleisteen“ zu findeen. Jetzt wird miit einem Dooppelklick au uf diese Koomponente der d Menü- Designer D geeöffnet. Hier kann man jetzzt seine Meenüstruktur bequem b deffinieren. Wir wolllen zur Übuung einfach h mal die errsten Einträg ge des Menü üs vom C# abkupfern, allerdinngs vorerst mal m ohne Ico ons. Bevor man ein Meenü definierrt, muss maan sich als mmierer sehhr genau diee Bedienphillosophie üb berlegen. Diieses ist natüürlich nichtt Program Gegensttand dieser Vorlesung, wie man daas macht. Also A erst maal das Menüü unter „Datei“ ansehenn und dann nach n und naach eingebeen: Unter Datei findeen sich die Einträg äge Neu, Öff ffnen, Hinzuf ufügen, Schlließen, Quersttrich (einfacch Rechte Mausttaste, dann Separator S einfüggen) usw. Man M gebe diese N Namen sukzzessive ein. Daas Menü istt im IDE sofort auszutesten n. Es fehlen nocch die beideen Pfeile hin nter Neu und Öffneen, die ein SSubMenu öfffnen. Dort dann n weiter die entsprechen nden Menüeintrräge eingebben. Die Verkn nüpfungen ssind einzeln ne Eigenschaaften der Meenüeinträgee: ShortcutK Keys. Dort kkann man in n einer Liste den gewünschteen wählen. Das Meenü ist natürrlich noch ohne o Funktioon. Jetzt mu uss für jeden n Menüeintr trag natürlicch noch ein OnC Click- Ereiggnis definierrt werden. E Entweder macht man eiinen Doppel elklick auf einen e Menüeintrag, so daass die IDE ein Funktioonsaufruf errzeugt oder man wählt in der Ereig gnisListe einn vorhandennes Ereignis aus. Wir eergänzen ein nen dritten Hauptmenü H üeintrag „An nsicht“ und erzeeugen darunnter die beid den Menüs „Circle“ un nd „Info“. Diesen D ordnee man dann die den bisheriggen Tasten buttonCircle b e oder buttoonInfo_Clicck zugehörig gen Click- E Ereignis zu. Dann können wir auch mit m dem Men nü die beideen anderen Fenster F öffn nen. Einige zzusätzliche Möglichkeiiten: Ein Meenü lässt sicch als Ein/ Ausschalter A r verwenden n. Dann muss diie Eigenschaaft CheckOn nClick auf T True stehen n. Bei jedem m Klick auf ddiesen Men nupunkt wird dannn die Eigeenschaft Cheecked zwiscchen true un nd false umg geschaltet, eerkennbar an a einem Häkchen vor dem Eintrag. E File: Kuurs MS10C## Bayerlein n4.6.docx Seite 26 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Jeder M Menüeintrag kann wie im m Vorbild m mit einem Iccon verseheen werden. D Diese Iconss werden mit Imaage einzeln geladen g . (IImageList auus Componeents funktio oniert hier leeider nicht wie w bei BCB). F Für ein Mennü sollten diiese Icons nnicht zu groß sein, sonsst sieht es häässlich aus. Ich habe als Beisspiel aus einnem Window ws- Ordner einige Icon ns mit der Größe G 16*166 Pixel zusamm mengesucht. Diese sind d im Ordner Icons diesees Kurses zu u finden. PopUp Up-Menüs s mit Con ntextMen nuStrip Die Arbbeit mit PoppUps ist sehr ähnlich. S Soll Ihr Projekt solcher Art Menüs bekommen n, dann muss deer User das natürlich wissen. w Er m muss dies ja mit m einem rechten r Mauusklick aktiv vieren. Ich hatte mal ein Toolprogram T mm mit solchhen Popupss geschriebeen, aber aus Unwissenh heit hat keiner ddiese genutzzt. Also jetzzt ein ContexxtMenuStrip p hinzufügeen (aus Mennüs & Toollbars). Auch hiier kann maan leider keiine ImageLiist daran kn nüpfen. Daa nun jede Komponente K e ein eigenees PopUpMeenü haben kann, k muss m man Kompo onenten übeer die Eigen nschaft ConntextMenuSttrip verrbinden. Do ort kann mann vorhanden ne sellektieren. Wir W wählen F FormMain. Nach Pro ogrammstarrt mit F5 kan ann man mitt Rechtsklick au uf FormMaiin das PopU Up-Menü auffrufen. Status sBar mitt StatusS Strip Diese Kom mponente ist bei den meeisten üblichhen Program mmen auch vorhannden. Man findet sie in n Menüs & T Toolbars. Man M ziehe eine auf dass Hauptform mular FormM Main. Die E Eigenschaftt Dock steht autom matisch auf Bottom, B som mit ist sie glleich an der richtigen Stelle. Willl man sie niccht weiter unterteilen u in so genann nte Panels, P dannn kann man n den Ausgaabetext in ddie Eigensch haft Text schreiben. A Aber meisteens nutzt maan die Unteerteilung in mehrere m Abschnitte. A . Diese kann n man hinzu ufügen mit ddem rot um mkreisten Symboll. Es werdenn vier Typen n von Abschhnitten angeboten. Wirr fügen 2 SttatusLabel zur z Ausgabe von Text hinzu, dann n eine ProgrressBar und d ein DropD DownButtonn. StatusLab bel1 bekomm mt den festeen Text (hierr „Version 1.0“in Eigenschaft Texxt), dann im m nächsten die d aktuellee Uhrzeit (errstmal „timee“). In die D DropDownB Buttons gebe man ein ppaar Einträg ge an, einer soollte „Start Progress“ P heeißen. Ergebbnis: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 27 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Mit Dopppelklick auuf „Start Pro ogress“ gebben wir dortt folgenden Text in die Click-Funk ktion ein: private e void ghi iToolStrip pMenuItem_ m_Click(object send der, Event tArgs e) { tool lStripProg gressBar1. .Value += 10; } So wirdd bei jedem Klick auf diesen d Eintraag zur Lauffzeit der Pro ogress- Balkken weiter nach n links wandernn. Einen P Panel- Text erreicht e man n mit der Syyntax toolS StripStatu usLabel2.T Text…. Hinter „„Label“ stehht die Numm mer des Pannels beginneend links mit 1. Die Uhhrzeit wird alle a Sekundee mit einem m Standard- Timer (in „„Komponen nten“) im TimerTick- E Ereignis- zum m Panel geschrieeben. Timerr- Eigenschaaften: Intervval auf 1000, Enabled auf true. Voom System erhält man diee Systemzeit mit DateT Time.Now, ddiese muss dann d noch in einen Striing konvertiert werden:: Code: private e void tim mer1_Tick( (object se ender, Ev ventArgs e) { tool lStripStat tusLabel2. .Text = DateTime.N D ing(); ow.ToStri } Hints mit ToollTips Viele W Windows- Sttandardprog gramme wiee z. B. Word d oder Paintt sind mit de den kleinen gelben g Hinweisteexten (=Hin nts oder Too oltips) ausgeestattet, die beim „Hooverinng“, also beim Bewegen des Mausszeigers z.B B. über Tasten, kuurz erschein nen und dem m Benutzer H Hilfestellun ng leisten sollen (sieehe Beispiell Paint). D Dieses wirdd auch von C# C unterstüttzt. Alle Tooltip--fähigen Koomponenten n, also alle ssichtbaren, haben ddie Eigenschhaft ToolTip p, in der einn Hilfetext stehen kkann, das abber erst, wen nn die Anw wendung diee Komponnente ToolT Tip aus „Alllgemeine Steuerellemente“ beekommt. Jettzt bei den bbeiden Buttonss irgendeineen sinnvollen n Text in To ToolTip on toolTip1 eiingeben, z. bb. in der Inffo- Taste: Dieser wird mit gelbem m Minifensster angezeigt, wenn die E Eigenschaft isBallon auf true steeht, in Balloon- Design. Jedes Prog gramm solltee meiner Meinung M eine Mögliichkeit habeen, diese gelben Dinger ausszuschalten.. Den erfahrrenen User nerveen sie nur. H Hat das Projekt aber viele 1000 Komponennten mit ebeenso File: Kuurs MS10C## Bayerlein n4.6.docx Seite 28 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B vielen H Hint- Textenn, ist es müh hsam. Will man z. B. alle a Tooltipss der gesamt mten Applikaation an / und ausschalten, daann muss man m nur die E Eigenschaftt Active in der d Komponnente Tooltip ip auf false settzen. Will maan per Progrramm den Inhalt des TooolTips verrändern so gibt g es abhän ängig von deer Komponnente zwei Versionen, wie das gehht: 1. Steht im Eig genschaften n- Editor „T ToolTip on toolTip1“, t dann d geht daas mit der Methode M SetToolTip( object,striing); Beispiiel: t toolTip1.S SetToolTip p(Button1, , "Schließ ßen"); 2. Steht im Eiggenschaften n- Editor TooolTipText, dann einfach z.B. T ToolButton n11LoadFil le.ToolTip pText = "L Lade Datei"; Mit folggendem Codde kann derr ToolTip- T Text auch z..B. in der Sttatusleiste aangezeigt werden: Tip1_Popup( (object sen nder, PopupEventArgs e e) private void toolT { tripStatusL Label1.Text t = toolTip1 1.GetToolTi ip(e.AssociiatedControl); toolSt } Das gehht aber leideer nicht, wen nn die toolT Tips inaktiv v sind (Activ ve=false). D D.h. wenn eiiner diese ToolTipps abgeschaaltet hat, steh ht auch nichhts in der Sttatusleiste. Kurs 4 weite ere Kom mponentten ToolS Strip Start dieeses Kursess mit leerer neuer n Anweendung. Will maan auch einee ToolBar wie w z. B. in W Word haben n, so ist dass leicht mögglich. Ich haab sie im unteren Bild mal inn der ersten Zeile hinzuugefügt. Siee ist aber verraltet. Modeerner ist diee Komponnente ToolS Strip. Wir fü ügen sie hinnzu. Dort kannn man (sieehe jetzt im Bild in der zweiten Zeeile) mit hüb bschen Verllaufsfarben ein modernnes Design bekommen. b Von links nnach rechts sichtbar diee Möglichkeeiten der Ellemente: toolStrippButton (noormale Tastte wie Toolbbar, jedoch ohne ImageeList- Mögllichkeit, son ndern mit Einzelbildchen), tooolStripLabeel für Textaausgabe / Beeschriftungeen, dann tooolStripSplitB Button und toolStripDropD DownButton n, mit denenn man ein Menübaum M designen d unnd öffnen kaann. Den ht erkannt, eerscheint miit identischeer Funktion.. Dann sind d noch Unterscchied hab ichh noch nich toolStrippTextBox und toolStrip pProgressB Bar möglich mit entspreechender Fuunktion. Da ist XP – und Vissta- Design leicht möglich. Hinzu kkommt einee ComboBo ox- Möglichhkeit. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 29 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Beim H Hinzufügen von v Images zwei Hinw weise: Zum Einen E muss die Bildgrööße passend d sein zur Bildgröße Imagesizze in der To oolStrip- Koomponente, dann solltee sie als pngg oder gif mit m transparrenter Außeenfarbe verssehen werdeen. Zum annderen musss man sich überlegen, ü oob diese Bild dchen nichtt bei größereen Projekten mehrfacch Verwenddung finden. Dann solltte man sie in n die „Projeektresourcenndatei“ ein nfügen und stehht dann überall im Projekt zur Verrfügung. Naach Klick au uf eigenschaaft „Image““ des Buttonss dann so: TabCo ontrol Mit der TabConntrol- Kompponente kön nnen Sie in eeinem Fenster die Oberrfläche mehhrfach nutzeen. Das Umschaalten geschiieht wie in einem e Karteeikasten. So o kann man solche Obeerflächen wiie in typischeen Windowsprogramm men program mmieren. Also auus dem Folder Containeer eine TabC Control auf das Formullar ziehen. N Normalerweeise wird diese Komponente nach unten n gedockt. D Damit autom matisch bei Fenstergrößßenänderun ng die einzelneen Elementee sich vernü ünftig mit änndern, solltee man folgeende Strateggie anwendeen (hab File: Kuurs MS10C## Bayerlein n4.6.docx Seite 30 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B noch einn Panel als reservierte r Fläche F für T Tasten oderr andere Elemente auf ddas Formulaar gezogenn): Oben ToolBar auf To op, dann ToolS Strip auf 1. Dock = Top T Top, dann d 2. Dock = Top Panell (eigener Contaainer aus 33. Dock = Top T „Conttainers“) wiedeer Top, der kllebt dann unter dem ToolS Strip. Dann n StatussStrip auf 5. Dockk = Fill Bottom m und zum Schluß S 44. Dock = Bottom B TabC Control auf Fill. Nun wieder w zurück zur TabC Control. Neue Paages werdenn mit rechteem Mausklicck PopUp UpMenu erzeeugt, dort „R Registerkarrte hinzufüggen“. Bitte jetzt j mal 7 neue n Pages erzeugen. Diese D heißeen automatissch tabpagee1 bis 7. Jetzt achhte man darrauf, wie maan einzelne Pages im ID DE anwähltt. Erst Klickk auf den Anfasser A (Tab), ddann ist aberr die TabCo ontrol angew wählt. Dann n nochmal unten u auf diie Seite klicken. Man achte auuf die weißeen kleinen Punkte. P Erstt dann ist diie Page selek ktiert (Konttrolle im Eigenscchaftenfenstter). TabControl selektieert Multilinne = false Page seleektiert Multiline M = true Reicht ddie Seitengrröße für allee Pages nichht aus, so errscheinen diie von anderren Anwend dungen gewohnnten beiden Pfeile zur Verschiebun V ng der Anfaasser. Will man m bei zu eengem Platzz mehrere Zeilen ffür die Anfaasser vorseh hen, so setzee man in derr TabControl (erst seleektieren!) diie Eigenscchaft MultiL Line auf truee. Hier müüssen Imagees per ImageList ergänzzt werden, die d Auswah hl der Icons in den einzzelnen Seiten w wieder mit der d Eigensch haft ImageIIndex. Also vorher einee ImageListt auf die Forrm ziehen und mitt einer Listee von Bildch hen füllen. D Die Größe der d Icons in ImageList einstellen. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 31 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Komp ponenten n zur Gru uppierun ng und Se elektion Jetzt solllen Kompoonenten zur Gruppierunng und Seleektion gezeig gt werden. Wir függen auf tabP Page1 hinzu u (alles Stanndard): 1 Gro oupBox 1 Pan nel Auf taabPage1 3**RadioButto on1-3 Auf groupBox1 g 3*RadioBu utton4-6 Auf das d Panel3** RadioButto on7-9 Beweegt man nunn einen „Con ntainer“, z. B. das Panel, ddann beweg gen sich mente die daarauf befinddlichen Elem mit. Zuordnung Z ggeht mit Hinen nschieben, Die CheckBox-e C en lassen ein ne einzelne Auswahhl zu. Ob an ngewählt C zu sehen. oder niccht, ist in Eiigenschaft Checked Die RaddioButton haben h auch eine Eigensschaft Checkked, jedoch gilt hier: auuf einem Co ontainer kann nuur immer einn RadioButtton angewähhlt sein. Wäählt man ein n anderes, w wird automaatisch der andere ddeselektiert. Dieser Zusammenhanng besteht nicht n zwisch hen RadioBuuttons anderer Containner, wodurchh der nützliche Sinn deer Containerr wohl hier zu erkennenn ist. Panel uund GroupB Box untersch heiden sich eeigentlich nur n in der Überschrift dder GroupBo ox. Das Ausseheen des Randdes von Pan nel kann maan leider niccht gleich deem der GrooupBox macchen, dann nehme m man halt einne Group- Box B und lössche die Besschriftung in n Text. Auf tabP Page2 weittere Selektio onsmechaniismen: Weiteree Selektionsskomponentten sind ListtBox, Comb boBox aus Standard S unnd CheckLisstBox aus „Allgemein „ ne Steuerelem mente“. Alle A drei Koomponenten n enthalten e alls Textinhalt eine Collection C ooder „Auflisstung“ namens n Item ms. Alle Fun nktionen, die d mit Colllections getan werden w könnnen, sind au uch hier möglich m (daazu siehe sp päteres Kapitel). K Füüllen der ein nzelnen selektierbaren Zeileen mit dem Collectioneeditor im Eigenscchaftenfenstter unter Items. Hier maal ein paar Zeilen Z Quatschhtext in alle drei Komponenten einngeben. Bei der ComboBoxx sieht man das selektieerte Elemen nt oben im EditE Feld. E Es benötigt nur wenig Platzz, man muss es halt miit einem zusätzlicheem Mausklicck aufmachhen. Bei der LisstBox sieht man m alle M Möglichkeiten, wenn die Kompo onente groß genug ist. SSonst gibt es e einen Scrollbalkeen. Mit der Eigenschaft E ft Sorted=tru ue lassen sich die Ein nträge alphaabetisch sorrtieren. Wen nn File: Kuurs MS10C## Bayerlein n4.6.docx Seite 32 Visuelle Programmierung mit C# Prof. Dr. Bayerlein SelectionMode auf One steht, dann kann man nur ein Element selektieren. Bei MultiSimple wird jede Zeile selektierbar und die Selektion toggelt, bei MultiExtended selektiert man wie beim Explorer gewohnt, die Shift und Strg- Tasten sind dann auch möglich. Die Abfrage, welche Zeile selektiert ist, kann man mit der Eigenschaft SelectedIndices[] durchführen. Es ist eine Eigenschaft vom Typ int- Array und ist im Eigenschaftenfenster nicht zu sehen. Jede Zeile startet bei Nr. 0. Ist z.B. Zeile 3 selektiert, dann ist der Wert von SelectedIndices.Count gleich 1 und in SelectedIndices[0] steht die Nummer der Zeile, also 2. Dieses mache man sich deutlich mit folgendem einfachen Code in dem Ereignis SelectedValueChanged. private void listBox1_SelectedValueChanged(object sender, EventArgs e) { label1.Text = listBox1.SelectedIndices[0].ToString(); label2.Text = listBox1.SelectedIndices.Count.ToString(); } In label1 wird die Nummer der ersten selektierten Zeile und in label2 die Anzahl der selektierten Zeilen dargestellt. Die CheckListBox ist ähnlich, nur man sieht vor jeder Zeile ein CheckBox- Feld. Diese kann man wie bei einer CheckBox bei jedem Klick toggeln. Abfrage nun allerdings über CheckedIndices[], auch hier ein Int Array mit den Zeilennummern. Auch ein kleines Programm dazu: Nur wenn die dritte Zeile einen Pfeil trägt, ist die Farbe der tabPage rot, sonst weiß.Code: private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e) { if ((checkedListBox1.CheckedIndices.Count==1)&& (checkedListBox1.CheckedIndices[0] == 2)) tabPage2.BackColor=Color.Red; else tabPage2.BackColor=Color.Transparent; } Der Zugriff auf den Text der Zeilen geht mit .Items[0] wie bei einem Array, die Nummer wird einem NumericUpDown der Eigenschaft Value entnommen : label2.Text = listBox1.Items[(int)numericUpDown1.Value].ToString(); label3.Text = checkedListBox1.Items[(int)numericUpDown1.Value].ToString(); Bei der CheckListBox kann man das Kästchen mit folgendem Befehl direkt setzen (true) oder zurücksetzen (false): checkedListBox1.SetItemChecked((int)numericUpDown1.Value, true); Abfragen mit checkedListBox1.GetItemChecked((int)numericUpDown1.Value) liefert bool- Wert zurück. Ergebnis: Siehe Kurs4# weitere Kompos. File: Kurs MS10C# Bayerlein4.6.docx Seite 33 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Kurs5 Textverarbeitung mit Stringlisten Das Visual C# - Entwicklungswerkzeug verfügt über mächtige Objekte zur Textverarbeitung. Diese sind teilweise einfach aus der Verwandtschaft zu Borland entstanden. Ansi-C kennt nur die Zeichenketten in Form von Char- Arrays, Textverarbeitung damit wird sehr mühsam. Zum Start dieses Kurses öffnen Sie bitte eine neue Applikation und fügen eine TabControl hinzu, Dock=Bottom, dann 4 pages hinzufügen. Namen alle so lassen. Abspeichern, bei mir heißt diese „Projektmappe“ WindowsApplication14. Der Typ String Auf der ersten Seite TabPage1 werden zum Testen einiger Stringeigenschaften 8 Label untereinander plaziert. Mit Doppelklick auf Label1 eine Click-Event-Funktion erzeugen, in der einiges gemacht werden soll. Die Tooltip- oder Text- Eigenschaften der Komponenten sind auch Eigenschaften vom Typ string. Will man eigene Variablen deklarieren, so verwende man den Typbezeichner string (wohlgemerkt mit kleinem s!), String gibt es auch, ist Name der Klasse!). Als erstes folgende Zeilen in diese label1Click() eingeben, grüner Text kann natürlich weg, dient nur zur Info, was nicht geht. private void label1_Click(object sender, EventArgs e) { //char a[20]="12345678901234567890"; funktioniert in C# nicht char[] a ={ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2' }; string b = new String(a); label1.Text=b; // ...=a; // ...=a.ToString(); funktioniert nicht String... } Es wird in der ersten Zeile ein Char-Array deklariert und initialisiert. In der zweiten Zeile wird dieses Array dem String b zugewiesen. Erst dann kann man diese Zeichenkette nach Text von Label1 zuweisen. Die Zuweisung anders herum geht allerdings so nicht. Versucht man dem char- Array einen String zuzuweisen, geht es schief, da "a" ein Zeiger ist. Diese Zuweisung geht nur mit der Methode ToCharArray etwa so: a = b.ToCharArray(); Der ganz große Nachteil von Char- Arrays in Standard herkömmlichen C ist die statische Größe. Das ist jetzt in C# anders. Das Char- Array wird mit dynamischer Größe gemanaged!!! Siehe dazu folgender Code: Die Länge eines Strings wird auch dynamisch verwaltet. Er kann beliebig lang sein. Beispiel: Eine Schleife addiert immer 20 Zeichen hinzu. Der Operator „+“ ist ein einfacher Verkettungsoperator, der zwei Strings zu einem neuen einfach verknüpfen kann. Folgender Code liefert folgendes Ergebnis: char[] a ={ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2' }; string b = new String(a); label1.Text=b; // ...=a; // ...=a.ToString(); funktioniert nicht a = b.ToCharArray(); label2.Text = "dies ist ein probetext"; label3.Text = b + "geht dies auch?"; for (int i = 0; i < 1000; i++) label4.Text = label4.Text + b; label5.Text = label4.Text.Length.ToString(); File: Kurs MS10C# Bayerlein4.6.docx Seite 34 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B a = la abel4.Text t.ToCharAr rray(); label6 6.Text = a.Length.T a ToString() ); D Der String b mit 12 Zeeichen wird d 1000 m mal zu label4 4.Text hiinzuaddiert,, dieser haat anschließ ßend (mit Leength ) erm mittelt 122006 Zeicheen. A Anschließend d wird laabel4 in das CharA Array kopiert, auch nn die diieses hat dan 122006 Zeicheen. Wichtigge Methodenn der String gs sind nochh .Substring g(x,y), wobei hier ein Teeilstring als Ergebniis herauskom mmt mit Staartzeichen bbei x anfang gend mit 0 und u Länge yy. Also liefeert label7. .Text = la abel2.Text t.Substrin ng(13, 5); als Ergeebnis das Wort W “probe””. Die Methhode IndexO Of(„suchstrin ng“) kann ddie Position eines Teilstrinngs suchen. So liefert die d Zeile label8. .Text = la abel2.Text t.IndexOf( ("probe").ToString(); die Zahll 13, da in label2 l der Teilstring T „pprobe“ bei Zeichen Z 13 beginnt. b Weiteree Methoden finden Sie in der Hilfee: Cursor au uf das Wort string, dannn F1: ToLoweer() ersetzt alle a Großbu uchstaben duurch kleine ToUppeer() dito durrch Großbucchstaben Replacee() ersetzt eiinen Teilstrring. Fazit strrings: niem mals wieder sich mit Chhar-Arrays herumquäle h n. Der m mehrzeilig ge Text Die StriingList direkkt wie bei Borland B gibtt es in C# oder o .NET nicht. Aber äähnliche Strrukturen sind mööglich. So giibt es die Klasse K Collecctions, die als a Collectio on beliebigeer Typen arrbeiten kann, allso auch fürr strings. Daann sind einne Vielzahl von v Method den möglichh wie Insertt(), Removee() Containss() Clear() usw. u Man kkann es dann n einfach alss ein dynam misch verwaaltetes Array vvon AnsiStriings betrach hten. Jede Z Zeile dieser Collection ist i wieder eein beliebig langer String m mit allen Meethoden wiee oben beschhrieben. Ab b .NET V3 gibt es auchh die ArrayList mit ähnlicheen Methodeen und Eigenschaften. M Man kann aber a auch einfach ein SStringarray benutzen: b string[] abc = new w string[5] ]; Nur ist ddie Anzahl der Elemen nte dann fesst auf 5 und kann nicht verändert w werden. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 35 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Besser wäre dann die Collection: Collection<string> strcoll = new Collection<string>(); Fügt man diese Zeile in C# ein, so kennt es erstmal das Schlüsselwort Collection nicht, es ist schwarz. Dann kann man aber mit rechtem Mausklick „Auflösen“ wählen und er fügt automatisch die fehlende using hinzu, in diesem Fall using System.Collections.ObjectModel; Hinzufügen eines Elementes mit : strcoll.Add("12345"); Zugriff wie Array mit label2.Text = strcoll[(int)numericUpDown1.Value]; Die Größe wird dynamisch verwaltet. Nun zu Komponenten mit mehrzeiligem Text: Die TextBox wird mehrzeilig, wenn man die Eigenschaft Multiline auf true stellt. Wir ziehen eine textBox auf tabPage2, und ein RichTextBox auf tabPage3 und setzen beide Dock=Fill. Schauen wir uns zuerst einmal textBox1 an. Einige wichtige Eigenschaften: ->ReadOnly bestimmt, ob der User Text verändern kann (false) oder nur angezeigt wird (true) ->Font bestimmt Schriftart Farbe etc ->ScrollBars bestimmt, ob diese vorhanden sind. Es sollte immer eine Vertikale ScrollBar eingestellt werden ->WordWrap, wenn true, dann werden längere Zeilen umgebrochen, sonst verschwinden sie rechts, sind mit Scrollbar aber zu erreichen: ich würde immer auf false stellen, dann bleiben die Zeilenumbrüche von Originaltexten erhalten. Maxlength, steht defaultmäßig auf 32767, begrenzt die Anzahl der Zeichen des Users auf diese Zahl. Sollte auf 0 stehen, dann ist die Grenze bei 2^32 = 4GByte Zeichen. Die Vorbelegung des Textbereiches geschieht per Eigenschaftenfenster bei der Eigenschaft Lines. Damit öffnet sich ein Texteditor zum Eingeben des Starttextes. Wichtig zu wissen: Der Inhalt wird immer in einem einzigen string, nämlich Text gespeichert. Ruft man die Eigenschaft .Lines auf, so wird intern der Einzelstring in ein Textarray umgebrochen, was bei großen Texten sehr zeitraubend sein kann. Will man oft auf große Texte per Lines zugreifen, dann am Besten vorher einmalig einen Umbruch erzwingen und dann auf das lokale Textarray zugreifen: string [] LocalArray = textBoxRadius.Lines; Wird der Text verändert, muss man dieses natürlich wiederholen. Für das Programm in diesem Kurs sind zum Laden und Speichern noch zwei Dialoge wichtig: in Dialogs findet man die Komponenten OpenDialog und SaveDialog. Bitte jetzt zwei Tasten oben auf die Form, Name Load und Save. Dann die beiden Dialoge hinzufügen. In der Click- Funktion von Load folgt jetzt der Standard- Code zum Öffnen von DateiAuswahl- Boxen, die dem üblichen Windows- Design entsprechen: if (openFileDialog1.ShowDialog() == DialogResult.OK) { // ………. Öffnen der Datei, Einlesen Abspeichern etc } Die Methode ShowDialog() öfffnet das typische Auswahlfenster. Nur wenn der User auf die OK- Taste klickt, wird die Aktion ausgeführt, bei Taste Abbruch nicht. Das Laden einer Text-Datei in die Textbox geschieht nun über die Klasse StreamReader mit folgendem Code: (vorher oben mit using…): using System.IO; StreamReader myStream1 = new StreamReader(openFileDialog1.OpenFile()); textBox1.Text = myStream1.ReadToEnd(); File: Kurs MS10C# Bayerlein4.6.docx Seite 36 Visuelle Programmierung mit C# Prof. Dr. Bayerlein myStream1.Close(); Mit der Methode ReadToEnd() wird dann der Textinhalt der Datei (muss eine ASCII sein) in die textBox eingelesen. Problem mit dem Text gibt es allerdings mit den deutschen Sonderzeichen ü, ö ä ß, die einfach ausgelassen werden. Dieses kann man verhindern, wenn man die Instanziierung nach new mit folgender Ergänzung durchführt: …new StreamReader(openFileDialog1.OpenFile(),Encoding.Default); Tipp: Bei großen Texten dauert insbesondere das “scrolling“ der sich füllenden textbox sehr lange, besser vor Einlesen Textbox Visible auf false, danach wieder auf true. Geht so viel schneller. Abspeichern mit der Save- Taste geht so: if (saveFileDialog1.ShowDialog() == DialogResult.OK) { StreamWriter myStream1 = new StreamWriter(saveFileDialog1.OpenFile(),Encoding.Default); myStream1.WriteLine(textBox1.Text); myStream1.Close(); } Die Dialoge sollten noch etwas angepasst werden: im openDialog1 folgende Eigenschaften setzen: Auf jeden Fall sollten die Filter gesetzt werden, z. B. so wie links. Immer sollte ein Filter „Alle“ mit *.* dabei sein, damit man immer sehen kann, was alles auf dem Verzeichnis vorhanden ist. Die Syntax ist: (*Bezeichner*)|*.xxx|(*Bezeichner*)|*.yyy usw. Also für Text und C#- Files z. B. Filter=Text|*.txt|C#|*.cs|All|*.*. In InitialDir kann das Startverzeichnis gewählt werden, in Title die Überschrift der FileSelectBox und in FileName der voreingestellt Name. Ganz wichtig in der SaveDialog- Komponente ist DefaultExt, die den Suffix bestimmt, wenn der User keinen eintippt. Dort sollte also immer .txt stehen, dann wird die Datei ohne Angabe eine txt- Datei. Ganz wichtig: der OverwritePrompt in Options sollte immer auf true gestellt werden, damit der User vor Überschreiben gewarnt wird. label9.Text = "Char= "+textBox1.Text.Length.ToString(); label10.Text = "Lines= " + textBox1.Lines.Length.ToString(); Mit den beiden oberen Zeilen werden sowohl Anzahl der Zeichen in Label9 und Anzahl der Zeilen in Label10 ausgegeben. Lenght ist eine Eigenschaft vom typ int. Man kann jetzt einzelne Zeilen erreichen durch Ansprechen der Eigenschaft Lines in der Textbox. Dabei benutzt man die Array- Indizierung mit [ ]. Folgender Code liest die Zeile in eine zweite textBox2, dessen Zeilennummer startend mit Null von einem numericUpDown eingestellt wird. Um Zugriffsfehler zu vermeiden, sollte vorher immer der Maximalwert des UpDown auf die Zeilenzahl -1 gestellt werden. private void numericUpDown1_ValueChanged(object sender, EventArgs e) { numericUpDown1.Maximum = textBox1.Lines.Length-1; File: Kurs MS10C# Bayerlein4.6.docx Seite 37 Visuelle Programmierung mit C# Prof. Dr. Bayerlein textBox2.Text = textBox1.Lines[(int)numericUpDown1.Value]; } Die textBox kann nur alle Zeichen mit einen einzigen Font darstellen, die RichTextBox dagegen lässt Formatierungen für jedes einzelne Zeichen zu. Nun noch ein bisschen Textverarbeitung: Sortieren Es sollen alle Zeilen alphabetisch sortiert werden. Nun lässt die Textbox dies direkt nicht zu. Also muss man den Umweg über z.B. die Listbox machen, die kann sortieren. Eine Collection leider auch nicht. Damit das nicht sichtbar wird, kann man die Listbox mit Visible=false unsichtbar machen. Und natürlich in der Listbox die Eigenschaft Sorted=true. Source hinter einer Taste Sort: 1 listBox1.Items.Clear(); 2 for (int i = 0; i < textBox1.Lines.Length; i++) 3 { 4 label10.Text = "Lines= " + i.ToString(); 5 listBox1.Items.Add(textBox1.Lines[i]); 6 Application.DoEvents(); 7 } 8 textBox1.Clear(); textBox1.Visible = false; 9 for (int i = 0; i < listBox1.Items.Count-1; i++) 10 textBox1.AppendText(listBox1.Items[i] + "\x0d" + "\x0a"); 11textBox1.AppendText(listBox1.Items[listBox1.Items.Count - 1].ToString()); Kommentar dazu: Zeile 1: Zwischenspeicher Listbox leeren. Zeile 2: for- Schleife zum Umschaufeln und gleichzeitigem Sortieren Zeile 4: Fortschrittsanzeige, sinnvoll bei langen Texten, dann dauert es sehr lange Zeile 5: Umschaufeln Zeile 6: Dieser Befehl arbeitet alle Ereignisse ab, die während der Schleife auflaufen. Damit wird auch ein Neuzeichnen des label10 erzwungen, sonst würde man den Fortschritt nicht sehen. Zeile 8 Start Zurüchschaufeln mit Leeren. Gleichzeitig wird die Textbox unsichtbar gemacht, um das sehr zeitaufwendige Scrollen zu vermeiden. Zeile 9: Schleife zum Zurückschaufeln Zeile 10: Zurückschaufeln, leider hat Textbox kein .Add(), geht nur mit TextAppend, dann muss aber Zeilenende mit CR und Linefeed per Escape Sequenz programmiert werden. Zeil1 11: Die letzte Zeile des Textes soll kein Linefeed bekommen. Leerzeilen weg Code hinter einer Taste mit Namen „Leerzeilen weg“. Es wird als Zwischenspeicher hier mal eine „Collection“ benutzt. Ginge aber auch mit Listbox wie oben. Collection<string> strcoll = new Collection<string>(); for (int i = 0; i < textBox1.Lines.Length; i++) if (textBox1.Lines[i].Length > 0) strcoll.Add(textBox1.Lines[i]); textBox1.Clear();// copy Back to Textbox for (int i = 0; i < strcoll.Count - 1; i++) textBox1.AppendText(strcoll[i] + "\x0d" + "\x0a"); textBox1.AppendText(strcoll[strcoll.Count - 1]); // last line File: Kurs MS10C# Bayerlein4.6.docx Seite 38 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Größe e von StrringListe en Die Grööße ist im Prrinzip nichtt begrenzt. W Wir fügen Taste T hinzu, die textBoxx1 über ListBoxx1immer verrdoppelt. Allso kopiere textbox1 naach Listbox1 1 und zurücck ohne zu sortieren s und Texxtbox zu leeeren. Anzeig ge der Zeileen in Label9 9 und der Zeeichenzahl iin Label10: listBox x1.Items.C Clear(); listBox1.S l Sorted = false; s.Length; i++) for (in nt i = 0; i < textB Box1.Lines { i.ToString(); l label10.Te ext = "Lin nes= " + i .Lines[i]); l listBox1.I Items.Add( (textBox1. A Applicatio on.DoEvent ts(); } textBox x1.Visible e = false; ; for (in nt i = 0; i < listB Box1.Items ms.Count - 1; i++) t textBox1.A AppendText t(listBox1 1.Items[i] + "\x0d d" + "\x0a a"); textBox x1.AppendT Text(listB Box1.Items ms[listBox1.Items.Count - 1] .ToString g()); textBox x1.Visible e = true; label9. .Text = "C Char= " + textBox1. .Text.Length.ToString(); x1.Lines.Length.ToString(); label10 0.Text = "Lines= " " + textBox Beschleeunigen eventuell mit string [] LocalArr ray = textB BoxRadius.L Lines; TextBoxx und RichT TextBox speiichern den T Text in eineem String[]] Array nam mens .Lines. Es gibt zw war eine Methodde .CopyTo() (), aber der Befehl B textBox x1.Lines.C CopyTo(ric chTextBox1 1.Lines, 0); wird ohhne Fehler kompiliert, k aber a es passsiert nicht daas erwartetee Kopieren, sondern nichts!!. ListBoxx hat seine String S in Item ms, das scheeint eine Collection zu z sein. Dortt gibt es einne CopyTo()) String C – Methoode, sie funkktioniert ab ber nicht so w wie man daas als User wünscht. w Collect tion<strin ng> strcol ll = new C Collection<string>(); ;// syntax error listBox x1.Items.C CopyTo(str rcoll, 0); wird miit einer Fehllermeldung abgebrocheen und nich ht kompiliert. Wieso niccht?? Noch eiin Tip, wie man m herausbekommt, w welche Usin ng – Anweisung nötig iist. Gibt maan die oberste Zeile mit „C Collection““ ein, so ist ddas Wort zu unächst schw warz, da diee nötige Usiing – Anweisuung fehlt. Mit M Rechtsk klick auf dass Wort kann n man im Po opUp unter „Auflösen““ die passendde using- Annweisung „S System.Col lections.Ob bjectModel““ automatiscch hinzufüg gen lassen. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 39 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Leider auch hier: eine Kopiermethode wie AddStrings oder meinetwegen auch CopyTo() von String[] Array nach Collection gibt es nicht. Dabei sind die Daten einfach nur mehrzeilige Texte. Wörter zählen Noch ein Codebeispiel, das oft nützlich ist: das Auffinden von Teilstrings. Damit kann man z.B. zählen, wie oft ein Wort in einem Text vorkommt. Dazu ist die Methode .Substring(a,b) der Strings noch zu beschreiben. Sie liefert einen String zurück, der im Ausgangsstring bei Buchstabe an Position a (Start von Null) beginnt und b Zeichen enthält. Also nach Ausführung folgenden Codes label2.Text = "dies ist ein probetext"; label7.Text = label2.Text.Substring(13, 5); steht in label7 das Wort “probe”. Ein Zeilenumbruch in Text sind zusätzlich noch einmal 2 Zeichen (\n\r). Hinter der Taste z.B. „Item Search“ steht folgender Code, der in Textbox1 nachzählt, wie oft dort der Begriff vorkommt, der in Textbox2 steht. string item = textBox2.Text; int len=item.Length; int cnt = 0; for (int j = 0; j < textBox1.Text.Length-len+1; j++) if (textBox1.Text.Substring(j, len) == item) cnt++; label9.Text = "Hits= " + cnt.ToString(); Das dauert aber leider bei großen Texten sehr lange. Sucht man in Bibel.txt (Auf ftp bei mir zu finden) nach dem Wort „Gott“, so dauert es Stunden. Etwa 5 sec dauert gleiche Suche mit folgendem leicht modifiziertem Programm: string item = textBox2.Text; string text = textBox1.Text; int len=item.Length; int textlen=text.Length-len+1; int cnt = 0; for (int j = 0; j < textlen; j++) if (text.Substring(j, len) == item) { cnt++; label9.Text = j.ToString(); label10.Text = cnt.ToString(); Application.DoEvents(); } label9.Text = "Hits= " + cnt.ToString(); In der Schleife mit dem ca 4,6 Millionen Zeichen der Bibel wird nur in einem einfachen string gesucht. Dauert bei meinem Lap ca. 5s. Eine andere Alternative ist die Methode .IndexOf(a,b), die sehr schnell ist. Außerdem sind jetzt die Ausgaben in die Label, die auch sehr zeitintensiv sind, weg. Neue for- Schleife: for (int j = 0; j < textlen; j++) { startindex=text.IndexOf(item,j); if (startindex >=0) { cnt++; j = startindex+1; } File: Kurs MS10C# Bayerlein4.6.docx Seite 40 Visuelle Programmierung mit C# Prof. Dr. Bayerlein } Jetzt merkt man die Rechenzeit kaum. Alle diese Teilprogramme sind in dem Verzeichnis Kurs 5# Strings zu finden. Kurs 6 Projekt Diashow Ehemals früher als Hausaufgabe, jetzt als Projekt1 wollen wir ein Programm schreiben, das aus einer Serie von Fotos (JPG, gif, Png in einem beliebigen Verzeichnis) in einer Diashow darstellen. Dazu braucht man als erstes einen Zugriff auf das Filesystem des Rechners. Dazu sind Komponenten nützlich, die auch in Visual Basic benutzt wurden. Diese sind nicht Standard in der Toolbox und man muss sie erst aktivieren. Das geht über das Menü „Extras Toolboxelemente auswählen“. Im kleinen Check-Kästchen markieren: FileListBox, DirListBox und DriveListBox. Sie sind zwar schon etwas altbacken, aber die notwendigen Funktionen für unseren Zweck stellen sie zur Verfügung. Meines Wissens will .NET diese Komponenten nicht mehr unterstützen, es gibt aber auch keine Alternative: Danke liebe MS-Informatiker! Die Plazierung der Komponenten soll jetzt so geschehen, dass ein automatisches Resizing erfolgt, und der User selbst die Aufteilung noch mit der Maus per Splitter verändern kann. Also folgendes Vorgehen ist zu tun: FileListBox auf neue Seite eines TabControl, Dock=Left. Dann Komponenten Splitter (Alle Windows Forms), voreingestellt ist schon passende Dock=Left. Mit einem Panel den Rest der Seite mit Dock=Fill ausfüllen. Auf dieses Panel dann eine DirListBox plazieren, Dock=Top. Darunter auf das Panel dann die Komponente DriveComboBox. Die drei File- system- Kompos müssen noch verbunden werden. Das geht leider nicht mehr wie bei Borland mit einfachem Setzen der Eigenschaften im Eigenschaftenfenster, sondern nur noch programmiert z. B. in dem Ereignis Form_Activated. Warum einfach, wenn es auch komplizert geht: Danke MS- Informatiker! In dem Ereignis private void driveListBox1_TextChanged(object sender, EventArgs e) { dirListBox1.Path = driveListBox1.Drive; } schreibt man das gewählte Laufwerk (es heißt nicht drive, sondern path!) nach dirListBox. Um jetzt die Dateien im selektierten Verzeichnis darzustellen, muss man wieder tricksen. Die Komponente dirListBox liefert zwei Informationen: in .Path den geöffneten (nicht selektierten Path) und in .Text den selektierten Text ohne Pfadangabe. Daraus kann man dann mit folgendem Programm im Ereignis den selektierten Pfad errechnen und nach fileListBox schreiben. Man hat ja sonst nichts zu tun. Warum sollten die Informatiker auch diese Information gleich fertig zur Verfügung stellen. Man muss dann eben schnell folgendes Programm schreiben: privatevoid dirListBox1_SelectedValueChanged(object sender, EventArgs e) { // in Text appears text of the selected line // in path appears the open path. the selected path can now be constructed: // if I select a path under open path: selpath=Path+/+Text // if I select a path above open path: selpath= find pos of text, delete // after text. string selpath; int pos=dirListBox1.Path.IndexOf(dirListBox1.Text); File: Kurs MS10C# Bayerlein4.6.docx Seite 41 Visuelle Programmierung mit C# Prof. Dr. Bayerlein //pos is Position of text, if -1 not found if (pos < 0) selpath = dirListBox1.Path + "\\" + dirListBox1.Text; else selpath = dirListBox1.Path.Substring(0, pos + dirListBox1.Text.Length); fileListBox1.Path = selpath; } Will man an die Daten in der FileListBox drankommen, so geht das mit der Eigenschaft Items. Folgende for- Schleife kopiert alle Dateien in eine TextBox: for (int i=0;i<fileListBox1.Items.Count;i++) textBox1.AppendText(fileListBox1.Items[i].ToString()+ "\x0d" + "\x0a"); Jetzt soll ein kleines Vorschaufenster programmiert werden. Wenn man auf eine Datei in fileListBox1 klickt, soll in einer PictureBox eine Bildvorschau zu sehen sein. Also Plazieren eines PictureBoxauf die Seite mit den obigen Komponenten. Größe 100*100 Pixel. In fileListBox1.SelectedItem steht die Nummer der selektierten (blau eingefärbten) Datei. Jetzt kann man in einem Event FileListBox1Click diese Bilddatei nach PictureBox1laden. Syntax: string fn = fileListBox1.Text; // selected Line int len=fn.Length; string ext = fn.Substring(len - 4, 4).ToLower(); if ((ext == ".jpg") || (ext == ".png") || (ext == ".bmp")) { pictureBox1.Load(fileListBox1.Path + "\\" + fn); } es wird zuvor abgefragt, ob es sich um eine Bilddatei handelt. Die Methode .ToLower() wandelt alle Großbuchstaben in kleine um. Der Substring- Befehl schneidet die letzten vier zeichen heraus. Der Dateiname wird mit fileListBox1.Text ausgelesen. Mit der Methode Load kann eine Bilddatei vom Typ *.ico, *.bmp oder *.jpg in die pictureBox1 gelesen werden. Die Bilder werden jetzt alle nur mit 100*100 Pixel angezeigt, man sieht nur einen Ausschnitt. Das ganze Bild sieht man mit der Eigenschaft pictureBox1->SizeMode=StrechImage; Die Originalbildgröße kann mit label1.Text = pictureBox1.Image.Height.ToString(); label2.Text = pictureBox1.Image.Width.ToString(); in zwei Label dargestellt werden. Das Bild ist zwar in pictureBox1gestaucht, aber im Speicher noch in Originalgröße erhalten. Will man jetzt noch das Seitenverhältnis erhalten, dann stelle man die Eigenschaft „SizeMode“ der pictureBox1 auf Zoom. Will man jetzt noch bei Verstellung der Selektion mit den Up- oder Down- Tasten ein neues Bild sehen, dann wähle man in den Ereignissen der fileListBox1 „SelectedIndexChanged“ die schon existierende Ereignisfunktion fileListBox1_Click. Testen Sie das Ergebnis. Wenn jetzt eine Bilddatei gewählt ist, wird sie in pictureBox1 angezeigt. Wenn man mit den Pfeiltasten die Selektion hoch und herunterbewegt, wird jeweils das aktuelle Bild angezeigt. Lädt man allerdings eine Datei mit einer anderen als der erlaubten Endung, passiert natürlich nichts. Siehe fertiges Programm in Kurs 6# Prepare HW1. File: Kurs MS10C# Bayerlein4.6.docx Seite 42 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Projektaufgabe 1 Diashowprogramm Schreiben sie jetzt ein Programm, dass alle Dateien aus dem gewählten Pfad in entweder einstellbarer Zeit (mit einem Timer und mit in einem numericalUpDpwn- wählbaren Sekunden) oder auf Mausklick hintereinander endlos möglichst groß (also in einem neuen Formular) anzeigt. Abbruch mit einem ContextMenuStrip- Menu, das mit einem Eintrag „end“ das Formular wieder schließt. Hinweise: Eigenschaften des neuen Formulars: Name=“FormDia“, FormBorderStyle=None; BackColor auf Schwarz. WindowState=wsMaximized. Achtung, bevor Sie es starten und mit Show() aufrufen, müssen Sie das Beenden programmiert haben (das ContextMenuStrip an das Formular binden), da das Fenster nun keine Tasten dafür mehr hat. Sonst geht es nur über Alt F4 oder andere Maßnamen, z. B. „Debugging beenden“ mit Shift + F5! Beenden mit ContextMenuStrip- Menu. Ein Eintrag „end“, mit Doppelklick in der Ereignisfunktion Click() das Schließen des Fensters auslösen z.B. mit Close();. In dem Ereignis von FormDia namens FormClosing dann wie oben schon erwähnt den Befehl e.Cancel=true; programmieren, damit wird das Schließen und Löschen der Instanz verhindert. Stattdessen dort Hide(); programmieren. Um den Zugriff von FormDia zurück auf das Hauptformular zu ermöglichen, muss man diese Schritte tun: In Form1, dem Hauptformular: public Form1() { InitializeComponent(); frm2 = new FormDia(this); } FormDia frm2; In FormDia: Bei den using muss der Namespace von Form1 angegeben werden. In meinem Beispiel – kann bei ihnen anders heißen- : namespace WindowsApplication14 Also in Form Dia: using WindowsApplication14; Wenn nicht der namespace von FormDia nicht sowieso schon den gleichen namen hat. Dann dort im Konstruktor die rot gerahmten Zeilen/ Teile ergänzen: Form1 meinmain; public FormDia(Form1 m) { InitializeComponent(); meinmain = m; } Auf FormDia eine pictureBox- Komponente ziehen, diese mit Dock=fill auf das ganze Formular ausdehnen. Dann auch an pictureBox1das ContextMenuStrip dranlinken. Jetzt kann man in einem Ereignis MouseClick ein Bild aus der Liste von FileListBox laden. Um an diese dranzukommen, muss sie erst im Modifier auf public gestellt werden. Benötigt wird noch ein public int diacnt = 0; mit dem der index der Filelistbox hochgezählt wird. File: Kurs MS10C# Bayerlein4.6.docx Seite 43 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Das Laden erfolgt wie schon gehabt, alles hinter ereignis MouseClick: string fn = meinmain.fileListBox1.get_Items(diacnt); // selected Line int len = fn.Length; string ext = fn.Substring(len ‐ 4, 4).ToLower(); if ((ext == ".jpg") || (ext == ".png") || (ext == ".bmp")) { pictureBox1.Load(meinmain.fileListBox1.Path + "\\" + fn); } diacnt++; if (diacnt >= meinmain.fileListBox1.Items.Count) diacnt = 0; Jetzt sollte es schon gehen, nur in der FileListBox sollte das Pattern so gestellt werden, dass dort nur Bilder drin stehen, also =*.jpg;*.png;*.bmp. Damit gleich nach Druck auf Start-Buttom ein Bild gezeigt wird, im Click- Ereignis des Buttons das MouseClick- Ereignis von FormDia aufrufen. Das geht erst, wenn man dieses Ereignis public macht: public void FormDia_MouseClick(object sender, MouseEventArgs e) dann in buttonStartDia_Click(…. . frm2.FormDia_MouseClick(null, null); Benötigt wird auf FormDia noch ein Timer, Interval=2000, Modifier=public, damit er von Form1 aus erreicht und aktiviert werden kann. FormDia, dort picturebox1.Sizemode=Zoom; Will man mit der ESC- Taste (Code 27) schließen, muss man auf dem Formular FormDia eine KeyPress- Ereignisfunktion erzeugen und dort if (e.KeyChar == 27) Visible=false ; programmieren. Nach Klick auf die Start- Taste muss der Timer bei aktivierter CheckBox für den Timer auf Enabled=true geschaltet werden. Nun nur noch im Timer_Tick – Ereignis das mouseClick- Ereigniss aufrufen. FormDia_MouseClick(null, null); Beispiel des fertigen Programms in dem Verzeichnis HA1NeuV1, dort natürlich ohne Source. Damit in der FileListBox nur Bilddateien aufgelistet werden, sollte vorher die Eigenschaft .Pattern von der FileListBox auf ein passendes Filter gesetzt werden. Das Format dafür: *.jpg , wenn ein Typ zugelassen werden soll, wenn es mehrere sind, mit Semikolon trennen: *.jpg;*.gif;*.png;*.bmp. Ein Problem sollte noch abgefangen werden: Wenn gar kein Bild in der FileListBox ist, gibt es eine Fehlermeldung, diese wird noch nicht abgefangen. Kurs 7 Zeichnen mit dem Graphics - Objekt Das Graphics-Objekt Das Objekt Graphics dient zum pixelorientierten Zeichnen auf Komponenten als Ausgabeeinheiten. Jeder einzelne Pixel kann individuell definiert werden, mit komfortablen Methoden ist ein Zeichnen von fast beliebigen Figuren (Linien, Rechtecken, Kreisen usw.) File: Kurs MS10C# Bayerlein4.6.docx Seite 44 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B möglichh. Auch Texxt kann der Zeichnung hinzugefüg gt werden. Mit M diesem O Objekt lässtt sich ein eigenes Paint- Proggramm leich ht selber schhreiben. Es gibt einige Kom mponenten, die d ein Grapphics- Objeekt haben: P Panel P PictureBox F Form Will maan auf dem Bildschirm B eine Grafikk erzeugen, so nehme man m am bestten direkt die d Graphiccs der Form m, will man später sein Werk als Bitmap speicchern, so muuss man erst eine Bitmap definieren, doch dazu später. Diesse Bitmap verfügt v dann n über die M Methoden Load() und Save(). Also plaatzieren wirr eine PicturreBox auf eeine neue Fo orm einer neeuen Anwenndung. Obeen wird wieder eein Panel1 und Dock=Top als Berreich für Taasten definieert, die pictuureBox1 fülllt den Rest derr Form (Dock=Fill). Wollen wir auf einem hübscheen Hintergruund malen, so laden wiir das Bild ((im Eigenscchaftenfenstter die Eigen nschaft Imaage) zu Beginn mit eineem Hintergrrundbild, z. B. Wolkenn.bmp (in Pffad bayerlej\ MS Studioo2008 C#\ Images\). I Am alleereinfachsteen zeichnet man m im Painnt-Ereignis, sofern in der d Komponnente vorhaanden. Einige B Beispiele: erzeugt von folgenddem Prograamm. private e void pic ctureBox1_ _Paint(obj ject send der, PaintEventArgs s e) { S SolidBrush h pbrush = new Soli idBrush(Co olor.Blue); e e.Graphics s.FillRect tangle(pbr rush, 5, 5, 5 100, 100); } In den P PaintEventA Args wird deer Bezug auuf das Graph hics- Objek kt von der Picturebbox1 übergeeben. Die Zeichenmeth Z hoden mit Fill F vor dem Namen erwartenn ein SolidB Brush, mit dem d die Fülllung definieert wird. Daas Rechteckk selbst kann mit divversen Param metern definniert werden n, hier mit den d beiden Koordinnaten der Ecckpunkte ob ben links (5 ,5) und unteen rechts (100,100). Oder Ähhnliches miit dem Butto on (auch derr hat ein Paaint- Event):: Pen p = new Pen( (Color.Red d, 3); Point p poi1 = new w Point(0, , 5); Point p poi2 = new w Point(80 0, 15); e.Graph hics.DrawL Line(p, po oi1, poi2) ); DrawLiine() zeichnnet eine Liniie, hier mit dder Eigenscchaft von Peen, der mit FFarbe und Strichdiicke definieert ist. Die Koordinaten K n diesmal mit zwei Poin nt- Objektenn. p1: Oder maal in einem StatusStrip Pen p = new Pen( (Color.Gre een, 1); Rectang gle rec = new Recta angle(200, , 3, 250, 15); e.Graph hics.DrawR Rectangle( (p, rec); In Draw wRectangle steht mit (2 200,3) die K Koordinate oben o links und u dann follgt Width und Height. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 45 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Allen diiesen Figureen werden jetzt sofort zzu Anfang beim b Start gezeichnet, g denn dann wird der Paint- E Ereignis ausgelöst. Will maan in einem anderen Erreignis zeichhnen, z.B. in n einem Cliick des Butttons, so gibtt es natürlich die PaintE EventArgs nicht. n Dannn kann der Bezug B folgen ndermaßen erzeugt werden: private evoid butt tonLine_Cl lick(objec ct sender, EventArgs e) { G Graphics gPB g = Grap phics.From mHwnd(pict tureBox1.Handle); S SolidBrush h pbrush = new Soli idBrush(Co olor.LightSkyBlue); ; g gPB.FillRe ectangle(p pbrush, 0, , 0, 100,1 100); } es wird eine lokale Instanz von n Graphics (gPB) erzeu ugt, die per Handle auff die pictureeBox1 zeigt. D Der Rest gehht wie gehab bt. Jetzt wirdd auf Click ein Rechtecck gezeichnnet. Die erstte Zeile mit der Methode .F FromHwnd kann auch vvöllig gleich hbedeutend d mit der Altternativcodiierung werden. Beiides erfüllt den d gleicheen Zweck: ersetzt w Graphic cs gPB = pictureBox p x1.CreateG Graphics(); Bei eineer solchen lookalen Instaanz sollte m man nach deem Zeichenv vorgang diee Graphics- Instanz gPB wieeder entfernnen mit gPB.Dis spose(); Die Insttanziierung von gPB kaann auch gllobal erfolgeen, dann können andere re Ereignisfu unktionen auch daarauf zugreiffen: Erst gloobal- also auußerhalb ein ner functionn, deklariereen: public partial class c Form m1 : Form m { G Graphics gPB; g S SolidBrush h pbrush = new Soli idBrush(Co olor.Blue); ....... Dann innstanziieren: public Form1() { Init tializeCom mponent(); ; gPB = Graphic cs.FromHwn nd(picture eBox1.Hand dle); pbru ush = new SolidBrus sh(Color.LightSkyBlue); B mit zweii Trackbars wird ein Piie gezeichnet, dessen U Umrandung eine Dann beenutzen, z. B. Ellipse iist und die Randbegren R nzungen weerden mit ein nem Winkeel (0-360°) ddefiniert, wo obei 0° nach recchts zeigt, von v dort starrtet ein Kucchenstück mit m der Wink kelbreite einngestellt miit trackBaar2: private void v track kBar1_Scro oll(object t sender, EventArgs s e) { pbrush.Co olor=Color r.Red; gPB.FillP Pie(pbrush h, 20, 30, 100, 200 0, trackBa ar1.Value, trackBar2.Value); Links steht trackBar1 etwa auf 5°° und trackB Bar2 auf 90°° Nun wird direkt d auf diie Komponeenten gezeicchnet. Will m man eine Zeichnung Z erzeugen, die d man absppeichern kaann, so muss man mit eeiner Bitmap p File: Kuurs MS10C## Bayerlein n4.6.docx Seite 46 Visuelle Programmierung mit C# Prof. Dr. Bayerlein arbeiten. Der erste Versuch bietet sich an: Man nehme die fertige BitMap von PictureBox1 namens Image. Man kann zur Laufzeit ein Bild wie gehabt laden mit pictureBox1.Load("Wolken.BMP"); wobei jetzt natürlich das Bild „Wolken.bmp“ im aktuellen Verzeichnis ….Debug stehen muss. Führt man diese Zeile aus, so wird gleich wieder das blaue Rechteck darüber gemalt, da dies in der Paint- Ereignisfunktion pictureBox1_Paint so programmiert ist. Beim Laden wird diese natürlich ausgeführt. Will man jetzt das Bild mit Zeichnung abspeichern, so stellt man erstaunt fest, dass pictureBox1 keine Save- Methode hat. Man findet aber bei Image ein .Save, nur das funktioniert nicht, warum weiß ich zurzeit nicht: pictureBox1.Image.Save("test.bmp"); // Fehlermeldung Mal ein Versuch mit einer Bitmap, z. B. so : Bitmap pic = new Bitmap(200, 200); erzeugt eine leere 200*200 Pixel große Bitmap, Bitmap pic = new Bitmap("Blumen.jpg" ); lädt das Bild aus dem aktuellen Verzeichnis und definiert eine Bitmap in der Größe des Bildes. Es darf kein indiziertes Farbformat sein (wie z.B. „Wolken.BMP“), dann gibt es einen Laufzeitfehler. Es müssen TrueColor- Bilder sein. Wie zeichnet man nun in eine Bitmap und speichert sie dann folgendermaßen ab: Z.B. in einer Click-Funktion könnte man schreiben: Graphics g1 = Graphics.FromImage(pic); Rectangle rec = new Rectangle(0, 3, 25, 15); g1.FillRectangle(pbrush, rec); Jetzt wird ein Rechteck nach g1 gezeichnet, nur man sieht nichts. Man kann es aber abspeichern, z. B. mit folgender Zeile: pic.Save("testa.bmp", System.Drawing.Imaging.ImageFormat.Bmp); Mit dem ImageFormat teilt man der Save- Methode mit, in welchem Format man es denn gerne hätte. Als .jpg- Datei geht dann so: pic.Save("testa.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); Wenn man sich diese Dateien mit Windows-Programmen ansieht, dann ist das Rechteck zu erkennen, der Hintergrund ist aber schwarz, wenn man mit Bitmap(200,200) eröffnet hat, sonst eben das geladene Bild. Will man die Zeichnung sehen, so muss man in ein Graphics- Object zeichnen, das zu einer sichtbaren Komponente gehört, z.B. unser gPB, das auf die pictureBox1 zeichnet. Der Code dazu lautet: gPB.DrawImage(pic,10,10); File: Kurs MS10C# Bayerlein4.6.docx Seite 47 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B wobei ddie beiden Koordinaten K n in diesem A Aufruf den linken oberren Punkt vo von pic festlegen. Will maan jetzt g1 von v oben niccht auf einee Bitmap, so ondern auf das d Image- O Object von pictureB Box1 legen, so geht dass leider auchh nicht: Lau ufzeitfehler Graphic cs g1PB = Graphics. .FromImage e(pictureBox1.Image);// ->L Laufzeitfe ehler Man kannn nun Zeicchenfiguren n mit verschhiedenen Meethoden erzeugen. Die wichtigsten n sind: D DrawLine(iint X, int Y, int x1, int Y Y1); zeichneet Linie von n (X,Y) bis ((X1,Y1). Mit M 4 vverschiedennen überladeenen Param meterlisten, siehe s CodeC Completionn- Fenster. D DrawRectangle(int X1, int Y1, int X2, int Y2); Zeichnet ein e Rechtecck mit Ecke oben llinks bei X11,Y1 und un nten rechts bbei X2,Y2. Mit 3 verscchiedenen üüberladenen n P Parameterliisten, siehe CodeComppletion- Fenster. FillRecctangle ähnnlich mit Fü üllung D DrawEllipsse(int X1, in nt Y1, int X22, int Y2); Zeichnet Kreeis oder Elliipse mit uumgebendeem Rechteck k mit den K Koordinaten wie beim Rectangle. R D DrawPie(innt X1, int Y1 1, int X2, intt Y2, int X3,, int Y3, int X4, int Y4);;s.o. W Weitere Meethoden von n Graphics ssiehe CodeC Completion n D Die Methodden mit „Drraw…..“ erw warten einen n Pen, der mit m new defi finiert werdeen muss uund legt denn Rand fest. Die Methooden mit „F Fill….“ Erw warten einenn Brush oderr SolidBrush, ebenfalls mit m new deffiniert, der die d Fülleigeenschaften ffestlegt. Man sehe in dden Beispieelcode hineiin. Wir schhreiben nun zwei kleinee Programm me, die folgeendes macheen: Mit Mauusklick folg gt der Pen der Mauus und zeichhnet eine freeihändige F Figur. Mit Tastendruck T auf „Artwoork“ Start/StopBetrieb wird die Zeeichenflächee mit einer Serie von Rechtecken R gefüllt (mitt Timer gestteuert), Größe und Position und Farbe mit eeinem Zufallsgeneratorr erzeugt weerden. Mit einer e deren G Taste Saave soll dass Werk dann n abgespeichhert werden n. Wir braauchen vier Tasten mit Text Artwoork, Save Picc, Pen-Colo or und Fill-C Color. Zum Abspeicchern ist einn SaveDialo og1 nötig, füür die Farbw wahl ein ColorDialog, für die Stricchdicke File: Kuurs MS10C## Bayerlein n4.6.docx Seite 48 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B braucheen wir noch ein numericUpDown- Element, Default D Wertt für Value= =1. Das sieh ht dann so aus: Die Kom mponenten haben folgeende Ereignnisfunktioneen: Artworrk(Button1): Schaltet den d timer1 aan und aus, Vorher V timeer1.Enabledd=false; als Startzusstand festleggen. if (tim mer1.Enabl led) timer r1.Enabled d = false; else timer1.Enab bled = tru ue; Button2), es wird als .jp pg abgespeicchert: Save (B if (sav veFileDial log1.ShowD Dialog() = == Dialog gResult.OK) pic.Sav ve(saveFil leDialog1. .FileName, ,System.D Drawing.Im maging.Ima ageFormat.Jpeg); PenCollor und Bru ushColor: Hinter H Buttoon3 und Buttton4 wird die d Farbe dees Stiftes un nd des Pinsels eingestellt, p und pbrush sind globbale Instanzzen von Pen n und SolidB Brush: if (col lorDialog1 1.ShowDial log() == D DialogResult.OK) alog1.Color; p.Color = colorDia if (col lorDialog1 1.ShowDial log() == D DialogResult.OK) lorDialog pbrush.Co olor = col g1.Color; Mit dem m OnChangge-Event wirrd die Stiftddicke gewäh hlt: private e void num mericUpDow wn1_ValueC Changed(object sender, Even ntArgs e) { p p.Width = (int)nume ericUpDown wn1.Value; } Zuerst jetzt die Freeihandmalfu unktion. Dazzu lernen wir w die Maussevents kennnen. Das Zeeichnen gnis MouseM Move, der Aufruf A sieht so aus: selbst geschieht miit dem Ereig private e void pic ctureBox1_ _MouseMove ve(object sender, MouseEvent M tArgs e) { if (d draw) { P Point endp p = e.Loca ation; g g1pic.Draw wLine(p, start, s end dp); c.Width, pic.Height); // Dr g gPB.DrawIm mage(pic, 0, 0, pic raw on scr reen s start = en ndp; } Die aktuuellen Mouse Koordinaaten werdenn in e überg geben, z.B. in i e.X und ee.Y oder in e.Locatiion. Diese Funktion F wiird jedes Maal aufgerufeen, wenn die Maus sichh bewegt. Also A wird auch geezeichnet, wenn w man keeine Maustaaste drückt, also immerr. Deswegenn gibt es nun n eine b Variab blen draw. Sie wird im m MouseDow wn- Ereigniis auf true und u im Steueruung mit der boolMouseU Up- Ereigniss zurück auff false gesettzt. Dann w wird wie obeen beschrieb ben erst mit g1pic in die Bitmap pic p gezeichnnet und dann n mit gPB in picturreBox1, dam mit es auf den d Bildschiirm gelangt. Es wirdd immer einee Linie von start nach eendp gezeicchnet, wenn draw true iist. Desweg gen muss jetzt nocch im Ereiggnis MouseD Down die gllobale Variaable start au uf die aktueellen Mauskooordinaten gesetzt g werd den mit: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 49 Visuelle Programmierung mit C# Prof. Dr. Bayerlein private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { draw = true; start = e.Location; } Ein paar Bemerkungen: Die Zeichenfläche wird beim ersten Zeichnen festgelegt. Ändert man sie hinterher, findet keine Größenänderung mehr statt. Lädt man als Hintergrund das Bild „Wolken.BMP“, so gibt es einen Laufzeitfehler. Das liegt daran, weil dieses Bild ein 256- Index-Farben-Bild ist. Wandelt man es in truecolor, so geht es. Das Bild darf nicht auf SizeMode =StrechImage; gestellt werden, da dann die Mauskoordinaten nicht mit der Position übereinstimmen. Nun das Artwork. Im Timer sollen per Random- Generator farbige Rechtecke erzeugt werden. In der Timer- Funktion steht bei mir: Random r = new Random(); int int int int x1 y1 x2 y2 = = = = r.Next(0, r.Next(0, r.Next(0, r.Next(0, pic.Width); pic.Height); pic.Width-x1); pic.Height-y1); //x point top left // y point top left // width // height Rectangle rect = new Rectangle(x1, y1, x2, y2); int red = r.Next(0, 255); int green = r.Next(0, 255); int blue = r.Next(0, 255); //int alpha = r.Next(0, 255); // this value with trackbar1 pbrush.Color = Color.FromArgb(alpha,red, green, blue); int red2 = r.Next(0, 255); int green2 = r.Next(0, 255); int blue2 = r.Next(0, 255); p.Color = Color.FromArgb(alpha, red2, green2, blue2); p.Width = r.Next(1, 10); g1pic.FillRectangle(pbrush,rect); g1pic.DrawRectangle(p, rect); gPB.DrawImage(pic,0,0, pic.Width, pic.Height);//Draw on screen File: Kurs MS10C# Bayerlein4.6.docx Seite 50 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Die Recchtecke orieentieren sich h an der Grööße von pic. Stellt man n Interval voom timer1 auf a 100 ms, dannn werden allle Sekundee 10 Rechteccke erzeugtt. Die Farbben werdenn mit .FromA Argb() erzeeugt. Schön ist auch, daass der Trannsparentwerrt alpha hier aucch geändert werden kan nn. alpha=0 heißt voll transparent, t also unsichhtbar, alphaa = 255 nicht traansparent. Im fertigen Programm P vverändert man m alpha mit m dem linke ken trackBarr1. Das Program mm zeichnet erst die Fü üllung und ddann einen Rahmen miit anderer Faarbe. Die ferttigen Dateieen finden Sie in Kurs7## Graphics. Viel Spaß bei weiteeren Experimenten. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 51 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs 8 Charrt2D Siehe H Hinweis auf die in DotN Net 4.0 neu vverfügbare Komponen nte Chart ab S. 85. In dieseem und dem m nächsten Kurs K wird diie mächtigee Komponen nte Chart2D D vorgestelltt. Diese Komponnente ist ann der FHL neeu entwickeelt worden und u vollstän ndig in C# ggeschrieben n. Sie ersetzt ddie alte bishher seit Jahrren benutztee Komponen nte Chartfx,, die bei Bor orland Verw wendung fand. Daamit ist der ganze Ärgeer mit ActivveX usw. en ndlich vom Tisch. Der Souurcecode lieegt auch vorr und Erweiiterungen sind damit jederzeit mögglich. Einige E Eigenschaftten: Hauptzw weck ist dass Zeichnen von Diagraammen anhaand von z. B. B Messdaaten. Es können maximal 10 farbigge Kurven mit m einer belliebigen Punnktzahl gezzeichnet werden.. Es gibt einne Autoskalierung und mehrere To oolbuttons, mit denen ddie Darstelllung angepassst werden kann. k Eine Zoomfunkti Z ion, eine Ko oordinatenaanzeige sow wie eine Umschaltung in einenn Punkteditoor per DataG Grid rundenn die Funktionen ab. Hiier ein Beisppielscreensh hot: u Reloadeen sowie einn Ausdruck sind vorgessehen. Ich bbenutze diesse Das Abspeichern und Komponnente in meeinem Großp projekt WinndfC#. Das erste Regellungstechnikk Praktikum m damit ist ohnee Probleme gelaufen g un nd die Kindeerkrankheiten sind beseeitigt. Es sinnd für diesee Komponnente 2 separate Dokum mente verfüügbar. Auf studpub s find det sich in bayerlejj\ MS Studioo2008 C#\ Kurs K 8 neu Chart2D vo on Lars Seckler\ die Dateei Benutzerooberfläche von v Chart2D D_2.pdf . Diese D besch hreibt für Annwender ein nes Program mms die Beddienung derr Benutzerooberfläche. Die Dattei Verwenddung der Ko omponente C Chart2D in C_2.pdf beeschreibt füür den Program mmierer, wiie man diesee Komponennte einbindet in seinen n eigenen C##- Code. Deeswegen soll hierr nur kurz beispielhaft b die Verwenndung besch hrieben werden, weiteree Details en ntnehme man dieesen Dokum menten. Zur Insttallation bennötigt man die d Datei Chhart2D.vsi. Diese darf nur bei aussgeschaltetem Visual Studio ggestartet weerden. Danaach sollte diee Komponeente in der Toolbox T ersccheinen. Das Erggebnis bei MS M Studio 2010 2 sieht soo aus: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 52 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Erstes kkleines Beispiel: In einem m neuen Proojekt erst ein n Panel mitt Dock Top uns dann diiese Kompoonente auf die d Form ziehen m mit Dock Fiill. Dann eiinen Buttonn mit Namen n ButtonSinn mit text sin n ergänzen. Hinter dem m Clickereig gnis dieser C Code: int i, , nb = 100, , serie = 1 1; i = 0; i < nb; i++) for (i { hart2D1.set tPoint(0, i i, Math.Sin(i / 16.0 * * serie)); ch } 2D1.startDr rawing(); chart2 2D1.autoSca aling(); chart2 Es siehtt nach Ausfü führung dann n so aus: Mit Setppoint wird das d interne dynamisch d verwaltete Datenarray gefüllt. Diee erste Zahll ist die Nummeer der Kurvee (von 0 biss 9), die zweeite der x- Wert W und diee dritte Zahhl der y- Weert eines Punktess. Mit dem Befehl B startD Drawing() w wird die Ku urve gezeich hnet. Mit auutoScaling()) findet eine auttomatische Skalierung S statt. Die Anzzahl der Punnkte pro Ku urve ist belieebig und kaann für jede Kurve indiividuell versschieden sein. Drückt m man diese Taste T sin jed doch ein zw weites Mal, so s erscheintt eine blaueer Querstrich h. Das liegt einnfach daran,, dass jetzt zwei z gleichee Kurven im m Speicher hintereinannder liegen und u alle File: Kuurs MS10C## Bayerlein n4.6.docx Seite 53 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Punkte verbunden werden. Also wird der letzte Punkt der ersten Sin- Kurve mit dem ersten Punkt der zweiten verbunden. Um dies zu vermeiden, sollte vor dem Neuzeichnen erst alter Inhalt einer Kurve mit der Methode clearLast() gelöscht werden. Eine einfache Variation liegt jetzt hinter einer neuen Taste namens buttonMulti. Folgender Code zeichnet immer neue Kurven: Außerhalb einer function: short serie = 1; Dann innerhalb der Click-funktion: int i, nb = 100; for (i = 0; i < nb; i++) { chart2D1.setPoint(serie ‐ 1, i, Math.Sin(i / 16.0 * serie)); } chart2D1.startDrawing(); chart2D1.autoScaling(); serie++; Nach der 10. ten Kurve wird nicht mehr gezeichnet. Jetzt testen wir mal die Echtzeitzeichenfunktion: Hinzufügen eines Timers (Interval=20, Enabled=false) und einer Taste ButStart. Hinter diese Taste: if (timer1.Enabled) timer1.Enabled = false; else { timer1.Enabled = true; chart2D1.clearAll(); chart2D1.XMax = 100; chart2D1.XGap = 10; chart2D1.YMax = 1; chart2D1.YMin = ‐1; chart2D1.YGap = 0.2; serie = 1; } Außerhalb: int itemp = 0; In timer1_Tick: chart2D1.realTimeChart((serie ‐ 1), itemp, Math.Sin(itemp / 16.0 * serie)); itemp++; if (itemp > 100) { itemp = 0; serie++; } if (serie > 5) { serie = 1; chart2D1.clearAll(); } Dann werden nacheinander 5 Kurven in Echtzeit gezeichnet: File: Kurs MS10C# Bayerlein4.6.docx Seite 54 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B debeispiele: Jetzt nooch einige eiinfache Cod Änderunng eines Kuurvennamen ns: chart2 2D1.CurveNa ames[0] = " Kurve 1"; 2D1.updateN Names(); chart2 Titel: chhart2D1.ToppTitle = "Top Header TTitle"; Löschenn der letztenn Kurve: chart2D1.cleaarLast(); Ausblennden z.B. deer ToolTaste“ Lösche aalle Kurven n“: chart2D1.AllClearBuutton = fallse; Abfragee der Anzahhl von Kurven: Counterr, keine Kurrve: -1 Abfragee der Punktee pro Kurvee: in CurveP Points[], es ist i ein int- Array. A Abfragee von Punkttkoordinaten n: einmal geetPoint(i,j), wobei i diee Kurvennum mmer und j die Punktnuummer ist beide b starten nd mit Null.. Beispiel: double e[] xy; chart2D1.ge etPoint((in nt)nudKurve.Value, (in nt)nudPunktt.Value); xy = c labelX Xval.Text = = xy[0].ToS String(); Yval.Text = = xy[1].ToS String(); labelY Natürlicch dürfen diie Werte in i und j die A Arraygrößen nicht überrschreiten, ssonst Fehlerr. i und j werden im Beispiell mit je eineem NumericcalUpDown n eingestelltt. Der Typ vvon Value isst dort ein decimall, deswegenn das „typecast“ mit (innt). kdarstellungg mit der altten chartFX in C# (Balkken, Will maan übrigens eine Grafik Kuchenndiagrammee auch in 3D D) so lese m man diesen Skript S in ein ner Version 3. Ab Versiion 4 ist sie verschwunden, da die dort benutzte A ActiveX groß ße Installationsproblem me verursach ht und außerdeem ein 64-B Bit programm mierung verrhindert. Ich h bin froh, dass d ich sie los bin. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 55 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs 9 DataT Tools - Einbind den von n Tool- Units U In meinnem Regelunngstechnik- Tool- Proggramm WindfC# benutze ich Unitss zu finden dort in DataTools.cs, mit deren d Hilfe man z.B. dden Inhalt eiiner Textbox x, falls die eein bestimm mtes Format aufweist, komplett k als Kurve darsstellen kann n. Das Form mat sollte so sein, dass pro p Punkt u y in ein ner Zeile steehen und miit einem Sep parator (kannn Komma,, Tab oder die Kooordinaten x und Leerzeicchen sein) getrennt g sind. Vorgeheensweise ähhnlich schon n wie im Kuurs 2c#: Neues P Projekt nachh Kurs 9# ab bspeichern. Der Forrm ein Paneel mit Dock Top hinzuffügen. Zweitess Panel mit dock d Left hinzufügen h Chart2D D mit Dock Fill hinzufü ügen. Auf pannel1 ButtonT TB2Chart hinzufügen h m mit Text TB B to Chart Auf pannel2 Textbox hinzufügeen mit Dockk Fill. Resultatt: gen (außerhhalb des Konstruktors von v Form1)): Nun follgende Instaanzen erzeug DataTools d dt = new Da ataTools(); LoadOpt lo o = new Loa adOpt(); CHMinMax m mm = new CH HMinMax(); Im Konnstruktor dannn : public For rm1() { alizeCompon nent(); Initia it(); lo.ini it(); mm.ini } Hinter dder Clickfunnction des Button B folgeenden Codee: dt.ConvertTB2Cha artAdd(ref chart2D1, textBox1,re ef mm, lo); ; File: Kuurs MS10C## Bayerlein n4.6.docx Seite 56 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Jetzt maal folgendenn Inhalt in die d rechte Teextbox tippen oder kop pieren: 00 11 23 35 43 50 Ergebniis: Nun kannn man gannze Dateien mit Messw werten laden und so einffach grafiscch anzeigen.. Dazu ein Load- B Button spenddieren, noch h einen opennFileDialog g1 hinzufüg gen und hintter die Clickfunnctions des Loadbutton ns dann wiee schon oben n in Kurs 5# # erklärt einne Datei lad den mit: if (op penFileDial log1.ShowDi ialog() == D DialogResul lt.OK) { treamReader r myStream1 1 = new Stre eamReader(o openFileDiaalog1.OpenFile(), St ; Encoding.Default); extBox1.Tex xt = myStre eam1.ReadToEnd(); te } Als Beispiel ist im Kurs 9 die Datei 2PT11_2.sim zu finden. f Die Grafik siehht dann so au us: In den L LoadOptionns kann man n dann auchh andere Datteiformate, logarithmissche Skalierrung etc voreinsttellen. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 57 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs 9a Zeic chnen von v Kurrven mitt Chart DotNet 4.0 Seit DottNet 4.0 gibbt es nun en ndlich eine K Komponentte zum Zeich hnen beliebbiger Grafik ken von Microsooft: Die Kom mponente Chart: C Man ffindet sie in n der Toolbo ox unter Daaten: Wenn m man diese auuf das Form mular zieht, ssieht es so aus: a Die Beffüllung mit Daten gesch hieht so (Sinnuskurve mit m 100 Punk kten): int i, , nb = 100, , serie = 1 1; chart1 1.Series[0] ].ChartType e = SeriesChartType.Li ine; for (i i = 0; i < nb; i++) { hart1.Serie es[0].Point ts.AddXY(i, Math.Sin(i i / 16.0 * serie)); ch } Will maan eine neuee Kurve (geenannt serie)) hinzufügeen, so muss man dies m machen: chart1.Series.Add( ("Kurve 1); ; chart1.Series[1].C ChartType = = SeriesCha artType.Line e; Die einzzelnen Kurvven werden dann wie eein Array mit .Series[i] erreichbar. Nur leidder gibt es die d Toolbar nicht, die ddem User beei einem fertigen Progrramm auch Möglichhkeiten gibtt, seine Darsstellung wäährend der Laufzeit L zu ändern. ä Alleerdings sind d die Darstelllungsmöglicchkeiten dieeser Chart – Komponen nte gigantisch. Will maan nicht nurr Kurven, sondernn beliebige Grafiken G daarstellen, so muss man sich mit dieeser sehr kom omplexen File: Kuurs MS10C## Bayerlein n4.6.docx Seite 58 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Komponnenten auseeinander settzen. Eine seehr gute Ein nführung beekommt man an mit einem m Tutoriall, das ich beei Microsoftt gefunden hhabe und ess auf studpu ub zur Verfüügung gesteellt habe: Siehe baayerlej\ MSS Studio2010 0 C# WS20112_13\ DotN NetChart\. Entpackkt man die dort d zu findeende Datei WinSampleesChart von MSDN(1).zzip, so kann n man das Program mm WinForrmsChartSamples.exe sstarten und bekommt b eiine Einführuung in alle Möglichhkeiten mit passenden Source – Coode Zeilen. Besser kan nn man ein T Tutorial niccht aufbaueen und ich kann k dem niichts mehr hhinzufügen. Ich werde sicher auchh demnächstt mein Toolproogramm Winndfc# damit ausstattenn, da insbeso ondere auch h Bodediagrramme damit sehr gut darsstellbar werden, was bisher nicht gging. Folgeende Tabellee soll Entschheidungshillfe geben, welche Komponente man wan nn nehmen kkönnte: Chart2D von Herrn Seckler Source Code verfüggbar und daadurch anpassbbar an eigenne Wünsche Toolbarr für User während w Lau ufzeit Einfachhes Interfacee Nur Kurrven, max. 10 Keine B Bodediagram mme art in DotN Net 4.0 Cha Anp passbar durcch tausendee Optionen Kein ne Toolbar Kom mplexes Inteerface Beliiebige Grafi fiken Bod dediagramm me möglich In Arbeeit ist zurzeit ein Projek kt, welches ddie Vorteilee beider Kom mponenten vereint. Es existiert schon eiine Komponnente, die der d DotNet- Chart mein ne Toolbar verpasst. v Ess fehlt noch eine Erweiteerung des Innterfaces, so o dass ich inn meinen Pro ogrammen einen einfacchen Austau usch vornehm men kann, ohne o dort tau usende Ändderungen vo orzunehmen n. Das könnt nte ein nettess Studiereenden – Proojekt sein. Bei B Interessee bitte meld den. Kurs 10 Weitere Ko ompone enten WebB Browser Mit der Komponennte WebBrow wser (in Alllgemeine Stteuerelemen nte) kann m man sich sein nen eigenenn Browser basteln. In Anwendunge A en kann man n dann dam mit auf seinee eigene Hom mepage verweissen oder Hillfetexte anbieten. Da inn der Regel ein pdf- Reeader installiliert ist, kann man mit diesser Komponnente dann auch a pdf- D Dateien in seeiner Anwen ndung anzeiigen. Wir sttarten mit einer neeuen Anwenndung und platzieren p inn der oberen n Hälfte ein Panel (Docck auf Top) für die Bedieneelemente unnseres Brow wsers und daarunter mit Dock D auf Fiill den WebB Browser. Mit M einer textBoxx1 und einiggen Buttons lässt sich gganz einfach h ein Browser zusammeenstellen. Hinter dder Go- Tasste: webBrow wser1.Navi igate(text tBox1.Text t); Hinter dder Forwardd- Taste: webBrow wser1.GoFo orward(); Hinter dder Back- Taste: T webBrow wser1.GoBa ack(); Hinter dder Home- Taste: T webBrow wser1.GoHo ome(); File: Kuurs MS10C## Bayerlein n4.6.docx Seite 59 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Hinter der Browse- Taste: if (openFileDialog1.ShowDialog() == DialogResult.OK) { webBrowser1.Navigate(openFileDialog1.FileName); } Die Home- Seite ist die, die beim Internet- Explorer als Home definiert ist, die Browse- Taste setzt eine Komponente openFileDialog1 voraus. Es läuft im Hintergrund wie zu erwarten eine eingebettete Form des auf dem PC installierten IE in der entsprechenden Version. Lädt man mit der Browse- Taste Dateien der Art pdf, doc, jpg usw., so wird je nach Installation auf dem Rechner entweder die Anwendung selbst geöffnet, die der Datei zugeordnet ist oder ein Viewer im IE wird aufgerufen und man verlässt die Anwendung nicht. Mediaplayer Es gibt nun keine Extra- Komponente als Mediaplayer, sondern nur ein Objekt, mit dem man Mediendateien abspielen kann. In .NET heißt es SoundPlayer und ist verfügbar nach Hinzufügen von dem Namespace System.Media : using System.Media; Hat man seinem Projekt eine Dialogkomponente openFileDialog1 hinzugefügt, dann kann man mit folgendem Code eine *.wav- Datei laden und abspielen: if (openFileDialog1.ShowDialog() == DialogResult.OK) { SoundPlayer player = new SoundPlayer(); player.SoundLocation = openFileDialog1.FileName; player.Load(); player.Play(); } mp3 oder videos gehen aber nicht. Die gehen aber mit einem eingebetteten Widows- Media –Player. Dann kann man alles machen, was der Media- Player auch kann: Vorgehen: 1. Toolboxelemente auswählen COM , dort WindowsMediaPlayer suchen und wählen. File: Kurs MS10C# Bayerlein4.6.docx Seite 60 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B 2. D Dann Kompponente Windows Meddia Player in n Toolbox suchen, s bei m mir ganz un nten, auf F Form ziehen 3. D Dann ladenn einer Mediia- Datei annd abspielen n mit if (ope enFileDial log1.ShowD Dialog() = == Dialog gResult.OK) { axWindows sMediaPlay yer1.URL=openFileDialog1.Fi ileName; axWindows sMediaPlay yer1.Ctlcontrols.play(); } Der spieelt insbesonndere auch mp3, m aber auuch Videos ab. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 61 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs 11 Ema ail- Prog gramm Inzwiscchen hat ein Diplomand d Erfahrunggen gesamm melt mit dem m Versendenn von Emaills ohne externe Klassen. Ess ist jetzt mit m DotNet- K Klassen mö öglich. Sie finden f einfac ache Beispiellprogrammee in StudPu ub in MS Stuudio 2012 im m Kurs 11. Dort sind eein einfachees Sendeund Em mpfangs- Proogramm zu finden. Zum m Test müsssen Sie allerdings eigenne Zugangssdaten ihrer Em mail- Konten eingeben,, sonst geht es natürlich h nicht. In einer e Diplom marbeit ist unter u anderem m ein kleinees Emailprog gramm (Veerzeichnis Email) E erarbeitet wordenn, in dem au uch eine Adressliste, ein HT TML- Editor und die A Arbeit mit Atttachments zum Einsattz kommen. Ein Test dieses P Programmess ist allerdin ngs noch niccht erfolgt, eine Fehlerfreiheit kannn nicht garaantiert werden.. Kurs 12 Tree eView Eine sehhr leistungsfähige Kom mponente istt TreeView. Damit kan nn man seinnen eigenen Explorer bauen. IIn einem Prrojekt hab icch damit einn vereinfach htes Dateisy ystem benuttzt mit nur zwei z Ebenen (Anfänger-- Version). Wir öffn fnen ein neuues Projekt (ProTreeVie ( ew) und plaatzieren ein Panel (Docck Top) eineen TreeVieew (Dock Left) L und ein ne FileListB Box (erst über Menü „E Extras -> Tooolboxelemeente auswählen“ hinzufü fügen, wenn n nicht in TooolBox bereeits verfügbar) mit Docck Fill. m Projekt hab h ich von A Andreas Kü ühnel übern nommen. Die Ideeen zu diesem Hinter ein nem Buttonn wird nun der d folgende Text gelegtt: string[ [] drives = Directo ory.GetLog gicalDriv ves(); TreeNod de node; foreach h (string drv in dr rives) { e = treeVi iew1.Nodes s.Add(drv v); node if (drv ( == "C C:\\") // C: selektiere s en t treeView1. .SelectedN dNode = node; Dann errfolgt nach Tastendruck T k obige Reaaktion, alle Drives werd den untereinnander angeezeigt. Die Klaasse Directoory wird erstt möglich nnach Einbind dung von ussing System m.IO . Zuerst werden alle Lauufwerke in das d Stringarrray drives eeingelesen, dann wird mit m foreach dieses Strin ngarray File: Kuurs MS10C## Bayerlein n4.6.docx Seite 62 Visuelle Programmierung mit C# Prof. Dr. Bayerlein durchgearbeitet. Mit .Add(drv) werden Einträge hinzugefügt, in drv stehen die einzelnen Elemente des Stringarays. Nach Einlesen wird noch der Node mit C: selektiert. Jetzt generieren wir eine Funktion „ReadSubDirs“, die für jeden Knoten im Parameteraufruf alle Unterverzeichnisse einliest. Code. privatevoid ReadSubDirs(TreeNode node) { DirectoryInfo[] arrDirInfo; // Array für Subdirectories DirectoryInfo dirinfo = new DirectoryInfo(node.FullPath); try { arrDirInfo = dirinfo.GetDirectories(); } catch { return; } foreach (DirectoryInfo DI in arrDirInfo) { node.Nodes.Add(DI.Name); } } DirectoryInfo enthält dabei den vollen Namen eines Pfades, den man sich aus dem Node auslesen kann mit .FullPath. Bindet man jetzt diese Funktion in die obere foreach- Schleife ein, so sieht der Code so aus: Die Button Click- Funktion hab ich entfernt, alles wird jetzt im Konstruktor von Form1() ausgeführt. public Form1() { InitializeComponent(); treeView1.Sorted = true; string[] drives = Directory.GetLogicalDrives(); TreeNode node; foreach (string drv in drives) { node = treeView1.Nodes.Add(drv); ReadSubDirs(node); if (drv == "C:\\") // C: selektieren treeView1.SelectedNode = node; } } File: Kurs MS10C# Bayerlein4.6.docx Seite 63 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Außerdeem wird diee Sortieren- Eigenschafft von TreeV View aktiviiert. Nach PProgrammstaart sieht es dann so aus, die „plus“ Kässtchen öffneen dann Untterverzeichn nisse der erssten Baumeebene. Jetzt kannn man im Click- Ereig gnis von TrreeView allee Dateien des selektiert rten Pfades in i FileListtBox anzeiggen lassen mit m private e void tre eeView1_Cl lick(objec ct sender, EventArgs e) { TreeNod de node; node = treeVie ew1.Select tedNode; fileL de.FullPath; ListBox1.P Path = nod fileL ListBox1.U Update(); } Dann siieht man recchts die Datteien der sellektierten Pfade. Nur ganz zuverläässig funktio oniert es nicht, deenn manchm mal muss man m zweimaal klicken. Der D Ereigniss scheint niccht der richttige zu sein. Beesser ist der Ereignis: private e void tre eeView1_No odeMouseCl lick(object sender, TreeNod deMouseCli ickEventAr rgs e) { file .Node.FullPath; eListBox1. .Path = e. file eListBox1. .Update(); ; } dann wiird in e der angeklicktee Knoten übbergeben. Dann funktio oniert es sichher. Jetzt feehlen noch zwei Diinge, dann ist der Minieexplorer ferrtig. Bei jed dem Öffnen eines Knote tens sollten die Unterveerzeichnissee dieses Kno otens eingellesen werdeen, so dass man m sich duurch den gessamten Baum bbewegen kannn. Das geschieht in deem folgendeen Ereignis so: private e void tre eeView1_Be eforeExpan nd(object sender,TreeViewCa ancelEvent tArgs e) { fore each (Tree eNode node e in e.Nod de.Nodes) { ReadSubDi irs(node); ; } } File: Kuurs MS10C## Bayerlein n4.6.docx Seite 64 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Jetzt függen wir nocch hübsche Bildchen B hiinzu. Dies geschieht g miit einer ImaageListKomponnente, die mit m der TreeeView- Kom mponente veerlinkt wird in der Eigeenschaft „Im mageList“ von treeeView1. Bei mir sieht die im mageList1 so aus: Jetzt bekkommen scchon mal allle Einträge ddas Icon miit Nummer 0. Will mann bei geöffn netem Directorry das grüne Icon anzeigen, dann m muss man allen a Knoten n, die man m mit Add hin nzufügt, mit e.No ode.Select tedImageIn ndex = 1; dieses m mitteilen. Ich hab diese Zeile im C Click- Ereign nis ergänzt. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 65 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs 13 Drucken Diesen K Kurs habe ich i mehr od der weniger direkt von Andreas Kü ühnel [1], B Beispiel 18 übernom mmen. Was muss man tun: 1. H Hinzufügenn der Print- Komponentten 2. u using Syst tem.Drawin ng.Printin ng; 3. IIm Konstruuktor:print tDialog1.P PrinterSet ttings = new n Printe erSettings s(); 4. D Deklarationn folgender Variablen: p privateint t startSei ite; p privateint t anzahlSe eiten; p privateint t seitenNu ummer; p privatestr ring strPr rintText; p privatestr ring strDa ateiName; // Anza ahl der Dr ruckseiten n // / aktuell le Seitenz zahl // / zu druc ckender Te ext ten Datei // der r Name der geöffnet 5. IIn einer Druuck- Funktion (hinter eeinem Butto on Druck od der so): printDi ialog1.All lowSomePag ges = true e; if (pri intDialog1 1.ShowDial log() == D DialogResult.OK) { p printDocum ment1.Docu umentName = "Dokume ent"; sieren / // Startwe erte abhän ngig vom z zu drucken nden Text initialis s switch (pr rintDialog g1.Printer rSettings. .PrintRange) { case e PrintRan nge.AllPag ges: ox1.Text; str rPrintText t = textBo sta artSeite = 1; Dialog1.PrinterSettings.Max anz zahlSeiten n = printD ximumPage; bre eak; case e PrintRan nge.SomePa ages: str rPrintText t = textBo ox1.Text; sta artSeite = printDia alog1.Prin nterSettin ngs.FromPa age; anz zahlSeiten n =printDi ialog1.PrinterSettings.ToPa age-startS Seite+1; bre eak; } / // Drucken n starten seitenNu ummer = 1; ; printDoc cument1.Pr rint(); } 6. IIn dem Ereiignis von PrrintDocumeent1_PrintPage() folg genden Codde tringForm StringF Format str ringFormat t = new St mat(); Rectang gleF rectF FPapier, rectFText; r ; int int tChars, in ntLines; // Ermi den gesam itteln des s Rectangl les, das d mten Druckbereich // besc chreibt (i inklusive Kopf- und d Fusszeile) r rectFPapie er = e.Mar rginBounds ds; // Ermi itteln des s Rectangl les, das d den Bereich für den h Kopf- und Fusszeile) // Text t beschrei ibt (aussc chließlich rectFTe ext = Rect tangleF.In nflate(rec ctFPapier, 0, -2 * s)); textBox x1.Font.Ge etHeight(e e.Graphics // eine ilen ermitteln e gerade Anzahl A von n Druckzei r(rectFText.Height / int anz zahlZeilen n = (int)M Math.Floor s)); textBox x1.Font.Ge etHeight(e e.Graphics File: Kuurs MS10C## Bayerlein n4.6.docx Seite 66 Visuelle Programmierung mit C# Prof. Dr. Bayerlein // die Höhe die textbeinhaltenden Rechtecks festlegen, damit die // letzte Druckzeile nicht abgeschnitten wird rectFText.Height = anzahlZeilen * textBox1.Font.GetHeight(e.Graphics); // das StringFormat-Objekt festlegen, um den Text in einem Rechteck // anzuzeigen - Text bis zum nächstliegenden Wort verkürzen stringFormat.Trimming = StringTrimming.Word; // legt die Druckstartseite fest, wenn es sich nicht um die // erste Dokumentenseite handelt while ((seitenNummer < startSeite) && (strPrintText.Length > 0)) { e.Graphics.MeasureString(strPrintText, textBox1.Font, rectFText.Size, stringFormat, out intChars, out intLines); strPrintText = strPrintText.Substring(intChars); seitenNummer++; } // Druckjob beenden, wenn es keinen Text zum Drucken mehr gibt if (strPrintText.Length == 0) { e.Cancel = true; return; } // den Text an das Graphics-Objekt übergeben e.Graphics.DrawString(strPrintText, textBox1.Font, Brushes.Black, rectFText, stringFormat); // Text für die nächste Seite // intChars - Anzahl der Zeichen in der Zeichenfolge // intLines - Anzahl der Zeilen in der Zeichenfolge e.Graphics.MeasureString(strPrintText, textBox1.Font, rectFText.Size, stringFormat, out intChars, out intLines); strPrintText = strPrintText.Substring(intChars); // StringFormat restaurieren stringFormat = new StringFormat(); // Dateiname in der Kopfzeile anzeigen stringFormat.Alignment = StringAlignment.Center; e.Graphics.DrawString(this.strDateiName, textBox1.Font, Brushes.Black, rectFPapier, stringFormat); // Seitennummer in der Fusszeile anzeigen stringFormat.LineAlignment = StringAlignment.Far; e.Graphics.DrawString("Page " + seitenNummer, textBox1.Font, Brushes.Black, rectFPapier, stringFormat); // ermitteln, ob weitere Seiten zu drucken sind seitenNummer++; e.HasMorePages = (strPrintText.Length > 0) && (seitenNummer < startSeite + anzahlSeiten); // Neuinitialisierung if (!e.HasMorePages) { strPrintText = textBox1.Text; startSeite = 1; anzahlSeiten = printDialog1.PrinterSettings.MaximumPage; seitenNummer = 1; } File: Kurs MS10C# Bayerlein4.6.docx Seite 67 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Zuvor m müssen nochh bei den Komponenten K n printDialog1, printP PreviewDiallog1 und pageSettupDialog1 die Eigenscchaft Docum ment auf prrintDocumen nt1 gestellt werden. Kurs 14 DLL L Das Einnbinden vonn DLL – ist relativ einfa fach, wobei ich feststelllen muss, daass es verscchiedene Typen vvon DLL- Dateien D gibt. Ich zeige zzuerst die Methode, M diee für die Dlll geeignet ist, die für Nutzungg unter Visuual C++ odeer Borland C C++ geschrrieben wurd den. Dazu geehören in deer Regel auch diee Interface – DLL von AD- Kartenn wie Orlow wski- USB Karte, K Velleemann USB B- Karte, oder anddere Hardw wareergänzu ungen. Wennn allerdingss, wie vermeehrt zu beobbachten aucch C# DLLs ggeliefert werrden, benutzzt man natür ürlich diese. Dazu zuuerst einmall der Hinweeis auf die uunterschiedliche Bezeicchnung der V Variablenty ypen in C/C++ uund C#. Hieer ein Auszu ug aus Frannk Eller [3]: C#- Typen n h die gannzzahligen Datentypen D in C/C++: Im Gegensatz dazuu sehen Sie hier File: Kuurs MS10C## Bayerlein n4.6.docx Seite 68 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Die Funnktionsaufruufe der DLL L sind in derr Regel mit den C++ Datentypen D ddeklariert, da d muss man dannn aufpasseen. Z.B. ist der d char in C ist 8 bit, der d char in n C# ist 16 B Bit. Die Heaader Dateienn, die meistt mit den DL LL geliefertt werden, sind leider füür C# nicht direkt d nutzbar. Am sicherrsten ist die Erzeugungg einer Lib- Datei aus der DLL, auss der man dann d genau eentnehmen kann, k welch he Funktioneen wirklich in der DLL L verborgenn sind. using S System.Run ntime.Inte eropServic ces; Dann auußerhalb einner Funktion n im Deklarrationsteil: [DllImp port("Proj jecttestSq qr.DLL")] public extern st tatic doub ble sqr(do double x); File: Kuurs MS10C## Bayerlein n4.6.docx Seite 69 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Diese D Datei muss das d Program mm finden kkönnen, desh halb am Ein nfachsten koopieren nach Projekt…\bin\debuug. Sollte nu un der Fall aauftreten, daass C# diesee Funktion ssqr nicht fin nden kann, obbwohl Sie sicher s sind, dass diese F Funktion drrin sein musss, dann hilfft nur die Möglichhkeit, diese Dll zu unteersuchen. Icch habe in Foren den Hinweis auf eein Freewarre Tool namens DependenccyWalker gefunden, m mit dem eine DLL analy ysiert werdeen kann. Maan lädt die DLL unnd er listet alle a möglich hen exportieerten Funktiionen auf. Beispiel: B Hab ab mit dem „alten „ C++ Buuilder eine Dll D erzeugt mit m folgenddem Code: double ___declspec((dllexport) sqr(doublee x) { retuurn (x*x); } Also einne einfache Quadratur der übergebbenen Zahl x. Daraus hab ich die DLL nameens ProjecttTestSqr.d dll erzeugt.. In C# führrte dann derr normale A Aufruf wie oben o beschriieben zu derr Fehlermelldung Erst einne Suche mitt Dependen ncyWalker bbrachte des Rätsels Lössung: Screennshot: Der Nam me der Funkktion ist dorrt mit „@sqqr$qd“ angeegeben. Dam mit führte daann folgend der Aufruf zum Erffolg: [DllImp port("Proj jectTestSq qr.dll",En ntryPoint="@sqr$qd d")] public extern st tatic doub ble sqr(do double x); private e void but tton1_Clic ck(object sender, EventArgs e) { d double y = Convert. .ToDouble( (textBox1. .Text); t textBox1.T Text = sqr r(y).ToStr ring("F5") ); So zeigtte sich, dasss die DLL für f das USB B- ADC- Intterfaceboard d von Prof. Dr. Orlowsski (in FH erhältlicche) namenss „USBCard dFH2.dll“ j etzt alle Naamen mit ein nem Untersstrich davor wieder findet: S Screenshot Dependency D yWalker dieeser Dll: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 70 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B d DLL der Vellemannn – USB- Karte K mit deer DLL K80055D liefertte Die Anbbindungen der folgenddes Bild, allee Namen tau uchen wie iin der Doku u auf: mbar, wie ddie Parameterübergabe definiert istt, dass muss der Natürlicch ist hier nicht entnehm Doku odder der Heaader – Dateii der Dll enttnommen werden. w File: Kuurs MS10C## Bayerlein n4.6.docx Seite 71 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Zusammenfassung AD- DA mit dll für ME2600, USB Orlowski: ME2600 Vorher einbinden von ME2600.dll. und using System.Runtime.InteropServices; DA und AD haben 12 Bit Auflösung. Die übergebenen Werte bilden -10 bis +10 Volt ab in iValue 0 bis 4095. Initialisieren [DllImport("ME2600.DLL")] public extern static int me2600AOSetMode(int iBoardNumber, int iChannel, int iRange, int iMode); Beispiel ex=me2600AOSetMode(0, 0, me2600Def.AO2600_MINUS_10, me2600Def.AO2600_TRANSPARENT); Auf DA Schreiben [DllImport("ME2600.DLL")] public extern static int me2600AOSingle (int iBoardNumber, int iChannel, short iValue); Beispiel short outval = (short)numericUpDown1.Value; int ex=me2600AOSingle(0, 0, outval); Von DA Lesen [DllImport("ME2600.DLL")] public extern static int me2600AISingle(int iBoardNumber, int iChannel, int iMode, refshort iValue); Beispiel short val=0; int ex=me2600AISingle(0, (int)numericUpDownADChan.Value, me2600Def.AI2600_MINUS_10 + me2600Def.AI2600_SINGLE_ENDED, ref val); USB- Orlowski – Karte – alte USB 1.1 - Version Vorher einbinden von der USBCardFH2.dll und using System.Runtime.InteropServices; Initialisieren [DllImport("USBCardFH2.dll")] public extern static bool _Init(); [DllImport("USBCardFH2.dll")] public extern static bool _SetKanal2Bereich(byte a); [DllImport("USBCardFH2.dll")] public extern static bool _SetMode(byte a); Beispiel bool OK = _Init(); _SetKanal2Bereich(1);//bip1_4V=1, bipolar -4 bis +4Volt _SetMode(2); //StartRealtime=2 File: Kurs MS10C# Bayerlein4.6.docx Seite 72 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Auf DA A Schreib ben [DllImp port("USBC CardFH2.dl ll")] public extern st tatic bool l _SetAnal logOut1(ushort a); Beispiel ushort Ua1=3000; ; _SetAna alogOut1(U Ua1); // / Einstell len einer Spannung in 3V am m D/A-Ausg gang 1 Von D DA Lesen [DllImp port("USBC CardFH2.dl ll")] meData(ref float x); public extern st tatic bool l _Realtim Beispiel float [ [] buf = new n float [8]; double fak = 10. .0 / 4096. .0; _Realti holen der Messwerte von Kan imeData(re ef buf[0]) ); // Abh nal 2; fak).ToString("F3") + " V"; label2. .Text = "U Ua= " + (b buf[1] * f Neue DLL / Kllassenbib bliothek mit C# erzeugen e n Um einee eigenen neue Dll zu erzeugen, e ö ffne man eiin neues Pro ojekt mit deer Eigenschaaft Klassennbibliothek. Ich habee dort die glleiche DLL L mit der Quuadratfunktiion erzeugt wie mit dem m Borland CBuilder: C Syntax: namespa ace ClassL Library1 { p public cla ass Class1 1 { publ lic static c double s sqrCSharp( (double x) ) { return (x * x); } } } Wichtigg ist vor derr Methodend definition daas Schlüsseelwort staticc, erst dann wird die Fu unktion sqrCShaarp exportieert und benu utzbar. Nach „B Build Projecct“ ist eine DLL D verfüggbar. Mit deefault – Nam men sieht ess jetzt so aus: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 73 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B LL in einem anderen Prrojekt benuttzen, so fügee man sie alls Verweis hinzu: h Will maan diese DL (rechte M Maus auf Verweise, V daann Verweiss hinzufügeen, dann kom mmt linkes Bild.) anschlieeßend ist daann die Funk ktion sqrCSSarp verfügb bar und kan nn benutzt w werden: Beispiell: double y = Conve ert.ToDoub ble(textBo ox1.Text); textBox ss1.sqrCSharp(y).ToString(" F5"); ; x1.Text = ClassLibr rary1.Clas Kurs 15 Zeittmessun ng und 1ms Tim mer Die Zeittmessung kann k sehr geenau mit derr Klasse Sto opwatch durrchgeführt w werden. Mitt Stopwat tch stopwa atch1 = ne ew Stopwat tch(); e Mit der Eigensschaft Stopw watch.Freq quency kan nn abgefrag gt werden, wird einne Instanz erzeugt. mit welccher Frequeenz der Zäh hler dieser S Stopwatch hochläuft. Bei mir auf ddem PC warren es 2,6 GHz !!! Diese Zahll ist Motherrboard- abhäängig. Mit der d Method de .Start() lääuft der Zäh hler los, op() bleibt err stehen. Diie Eigenschhaft .Elapsed dTicks enthäält dann diee Anzahl derr Takte mit .Stop zwischeen Start undd Abfrage . Die D Zeit in sec bekom mmt man dan nn heraus duurch Divisio on von ElapseddTicks durchh Frequencyy. Laufzeiteen kann man n dann messsen, indem man vor un nd nach dem zu messendenn Befehl .Ela apsedTicks abfragt. Beispiel: long dtstart = sto opwatch1.El lapsedTicks s; dann koommt der Beefehl, von dem d man diee Laufzeit messen m will… long dtend = stop pwatch1.Ela apsedTicks; dann long dt = (dtend ‐ dtstart) ); Anzeigee in Millisekkunden: double dtsec = dt/ / (double)S Stopwatch.F requency * 1000; ufzeit= " + + dtsec.ToS String("f2"); Label1.Text = "Lau File: Kuurs MS10C## Bayerlein n4.6.docx Seite 74 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Im Projekt „Test SttandardTim mer mit Zeitm messung Ba ay“ wird nun n die Perioddendauer dees SystemTimers gemessen. Dabei D läuft stopwatch endlos vor sich hin und d im TimerTTick wird err lediglich periodissch abgefraggt, die Absttände der Tiicks berechn net und in einem e Speiccher TimeAv vr aufakkuumuliert, um m den Durch hschnittsweert zu bestim mmen. Mit einem e zweitten Timer wird w dann zweimaal in der Sekkunde das Ergebnis E anggezeigt. Man steellt fest, dass der System m - Timer kkeine 1ms – Auflösung g besitzt. Diie Periode kann k nur in grobeen Schrittenn verstellt werden. w Bei m meinem Deesktop ist dies etwa 15 ms, die Inteervallzeit kann nuur ein Vielfaaches dieserr 15 ms betrragen. Ich fragge mich, wiee es möglich h ist, dass ddie C# -Entw wickler wirk klich einfachh nicht in der d Lage sind, dieesen Timer auf 1 ms geenau hinzubbekommen. Seit Jahrzeehnten (schoon bei Borland) bietet m man einen Tiimer an, in dem das Inttervall auf 1 ms verstelllt werden kkann, tatsäch hlich ist er in Wiirklichkeit nur 10 – 15 5 ms genau. Ich bin froh, dass es e meinem Drittherstell D ler Mario Prrantl (mario [email protected]) genausoo geht wie mir. m Er hattee für Borlannd einen 1 ms m Timer en ntwickelt, isst inzwischeen auch auf C# uumgestiegenn und bietett auch dafürr seinen 1 ms m Multimed diatimer ann. Die FH haat eine Campusslizenz für 150 1 € gekau uft. Industrieenutzer müsssen sich eine eigene L Lizenz besorrgen. Dieser T Timer ist alss DLL verfü ügbar. Mann fügt ihn wiie in Kurs 14 schon besschrieben als Referennz hinzu. Im m Projekt „T Test MMTim mer mit Zeitm messung Ba ay“ findet m man dann deen um ddiesen Timeer erweiterteen Code. Naach Ergänzeen von u using MPS; ; iinstanziiert man m ihn mit T TMultimedi iaTimer MM MTimer1; u und initia alisiert ihn i mit M MMTimer1 = new TMul ltimediaTi imer(null) ); E Er verfügt ebenfalls e über die Eigennschaft .Inteerval und wird gestartet mit der d Methodee .Enabled() (). Interessan nt sind der Zugriff Z undd die Erzeug gung der D es ja kein ne Komponnente ist, son ndern nur eiin Objekt eiiner Klasse,, kann Ereignissfunktion. Da man aucch auf keinee Eigenschaaften und Erreignisse im m Property – oder Eigennschaftsfensster zugreifeen. Bei denn Email – Obbjekten ging g dies mit pop3.On nWork +=ne ew TWorkEv vent(this. .Work); mit dem m das Ereignnis Work daann verfügbbar war. Hier wirrd dies mit „Delegates““, einem neeuen Konzep pt von C# reealisiert. Daas Konzept ist schwierrig zu versteehen (an dieeser Stelle nnicht nötig) die Durchfü ührung siehht furchtbar einfach aus. Mitt MMTi imer1.OnTi imer = Eve ventVomMMTimer; wird diee Ereignisfuunktion EventVomMMTi mer erzeug gt und kann dann wie ddie beim Staandard – Timer bbekannte _T Tick( ) – Ereeignisfunktiion benutzt werden: void Ev ventVomMMT Timer(TMul ltimediaTi imer send der) { …… … } Im Projekt erkennt man, dass jetzt j der Muultimediatim mer eine Au uflösung vonn 1 ms besitzt. Eine gennaue Überpprüfung diesser Periodenndauer mit gemessener g r Zeit und eiinem eventu uell vorhanddenen Jitter (Schwanku ung der Periiodendauer)) ist möglich h, wenn mann mit diesem m Timer über einne AD- Kartte, die schnell genug isst, in jedem Event einen n Impuls auuf einem DA AAusganng erzeugt unnd mit einem m Digitalsccope misst. Dies wird in n dem Projeekt MMTim mer mit File: Kuurs MS10C## Bayerlein n4.6.docx Seite 75 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B DA Imppuls auf ME E2600 realisiiert. Dies Prrogramm lääuft natürlich nur mit eiiner ME260 00 – Meilhauuskarte im PC. P Aber mit einer andderen Karte (keiner USB B, USB ist nnicht schnell genug) ginge ess natürlich auch. a Das Verhalten V istt identisch dem d Multim mediatimer uunter Borlan nd CBuildeer. Es gibt eine e von derr Last von W Windows ab bhängigen Schwankung S g, und statt 1 ms sind es 10244 usec Perioddendauer au uf einem „B BlueChip – PC. P Kurs 16 RS2 232 Eine Veerbindung mit m einer serriellen Schnnittstelle lässst sich sehr einnfach aufbau uen. Man beenutzt dazu die Kompo onente „SerialP Port“. Über eine 3- Draaht- Verbinddung kann man m jetzt eine Vooll- Duplex- Verbindun ng zweier Geeräte erreich hen. Dies bedeuteet eine gleich hzeitige Üb bertragung vvon Daten in n beide Richtunngen. Man muss m nur darauf achtenn, dass ersten ns der Sendeausg gang („Trannsmit“) des einen Gerättes mit dem m Sendeeingang („Receive““) des anderren Gerätess zusammen ngeschaltet ssind. Zwei TransmitT Ausgänge dürfen auf keinen Falll miteinandeer verbundeen werden. Bei B dem 9 –poligen SubS D Steccker eines PC sind dies die PIN 3 (Ausgang Transmit) T und PIN 2 (Eingang R Receive). Die D Ground- PIN müsseen natürlich auch verbunden n werden (P PIN 5). Will man 2 PCs miteiinander verb binden, dan nn benötigt m man ein „Nullmodeemkabel“, bbei dem PIN N 2 und 3 üb ber Kreuz vverbunden sind: PIN 5 PIN 3 PIN 5 PIN 3 PIN 2 PIN 2 Damit ddie Geräte sich aber syn nchronisiereen können, müssen die „Sendefreqquenzen“ glleich sein. Diese w werden mit der d Eigensch haft BaudR Rate eingesteellt, Standarrdwert sind 9600 Baud d, das sind 9600 Biits pro Sekuunde. Ebensso müssen P Parity (Nonee,Odd, Even n, Mark, Sppace) und Anzahl A der StopBitss (One, Twoo, OnePointtFive) und die DataBits (7 oder 8) übereinstiimmen. Dann giibt es noch Geräte (z.B B. die Mikroocontroller) die nur eineen 0-5V TT TL- Pegel au uf der seriellenn Leitung haben, die geenormte RS S232 hat abeer einen Peg gel von +155 V bis – 15V und ist invertiert zu dem 0-5V 0 -Pegel. Will man ssolche Gerääte verbindeen, ist ein Peegelwandleer (z.B. der Maxx232) nötig. Dort sind 2 Wandler ffür 2 Schnitttstellen mitt integrierteer Spannunngserzeuguung zu finden. (Conrad Elektronik 1,50 €). Hat ein PC keinen COM- Portt (das ist dieese serielle RS232) R meh hr, dann kannn man sich h einen USB- Seriell – Adaapter kaufen n (z.B. DIG GITUS USB 2.0 SERIELL ADAPT TER, bei Co onrad 10 €). Bevor m man startet, kann man mit m foreach h (string s in Seri ialPort.Ge etPortNam mes()) cbPort. .Items.Add d(s); z.B. in eeine CombooBox cbPortt alle auf deem PC verfü ügbaren CO OM- Ports errmitteln. Diie tatsächlich angeschhlossene mu uss dann in dder Eigenscchaft „PortN Name“ eingeestellt werd den, also z.B. serialP Port1.Port tName =“CO OM1“ Dann kaann dieser Port P mit .Op pen() geöffnnet werden. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 76 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Steht einn Text in eiinem string tx, so kann man nun eiinfach Dateen senden m mit serialP Port1.Writ te(tx); Benutztt man WriteeLine, so wiird dem Texxt ein LineF Feed (Hex0aa) anghängt,t, allerding kein k CarriageeReturn (Heex0d). In einer Textboxx wird dann n kein Zeilenvorschub ggemacht. Also A am Besten nnur Write() benutzen und u ggf. eineen Zeilenvo orschub mit „\x0d“ undd „\x0a“ anh hängen. Empfanngene Datenn lesen kann n man mit .R ReadByte() oder .ReadC Char(). Dam mit keine Daten verlorenn gehen, weenn der Eing gangsbufferr voll ist, sollte man dieeses in einem m Timer peeriodisch z.B. allee 100 ms duurchführen. Erwartet m man nur Tex xt, so benutzzt man ReaddChar(), beei binären Daten (zz.B. aus unsserem Scope) muss maan mit Read dByte() lesen n. Also in eiinem Timerr_Tick – Event (iinp ist eine globale string- Variablle): if (ser rialPort1. .BytesToRe ead > 0) { for (int i = 0; i < se erialPort1 1.BytesToR Read; i++) ) { h=(char) s serialPort t1.ReadByt te(); char ch inp=inp p+ch; } textBox x1.AppendT Text(inp); ; inp = ""; " } Voreinggestellt ist eine e ASCII – Codierungg, das heißt, deutsche Sonderzeich S hen gehen verloren, v im Emppfangenen Text T steht do ort ein “?”. W nen, dann Will an diese Sonderzeeichen auchh lesen könn muss z.B B. nach Inittialisierung der Befehl serialP Port1.Enco oding = En ncoding.De efault; ausgefüührt werden.. In der bbool - Eigennschaft .IsOp pen kann m man abfragen n, ob ein Öfffnen geklapppt hat, denn andere Prozesse können jaa auch einen n COM- Porrt belegen. B veerändern, muss m zuvor der d Prot gescchlossen weerden mit Will maan Eigenschhaften wie BaudRate .Close()). Noch eiin Hinweis zur z TextBoxx. Schreibt m man die em mpfangenen Zeichen in die Textboxx mit AppenddText(), so wird w dort nur eine neue Zeile gezeiichnet, wenn n die Sondeerzeichen „\x0d“ „ und „\x00a“ hintereiinander aufttauchen odeer nur LineF Feed („\x0a““) auftauchtt. Löst man dann aber denn Text mit .Lines in ein n String- arrray auf, dan nn wird in diiesem Strinngarray auch h schon bei eineem CarriageeReturn - Zeeichen („\x00d“ ) eine neeue Zeile errzeugt. Willl man also auf a einzelnee Zeilen zuggreifen, kan nn man sich verzählen. Beispiel: Schreeibt man „H Hello World d“ + „\x0d“ +„Hello W World“ in ein ne textB Box1, so siehht man auf dem d Bildsch hirm linkes Bild, aber sowohl s in textB Box1.Lines[00] als auch in textBox1.Lines[1]steeht dann „H Hello Worlld“. Will maan unsere Sccopes (z.B. Phillips Scoope PM339 94 oder baug gleich PM 33380) auslessen, dann muss m man zuerst eiinen Befehl z.B. QW0001 mit einem m anschließ ßenden CarrriageReturn („\x0d“) senden (kein LineF Feed!!! hintterher). Die Nummer nach n QW gib bt die Kanaalnummer an n, 001 steht fürr Kanal a ussw. Dann w wird bei Fehllerfreiheit ein e „0“ mit C CarriageRetturn gesend det, anschlieeßend komm mt ein ASCII – Header auus 17 mit Ko omma getreennten Inforrmationen. Siehe S dazu H Handbuch Kapitel K 6 ab Seitee 6-33. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 77 Visuelle Programmierung mit C# Prof. Dr. Bayerlein Anschließend nach diesem Header werden die Werte der Abtastpunkte in Binärform übertragen. Das erste Byte ist ein vorzeichenbehaftetes High-Byte (Type sbyte), das zweite das vorzeichenlose low-Byte (type byte). Der Spannungswert des Punktes ergibt sich zu Y_zero+Y_resolution*(High*256+low) und der Zeitwert errechnet sich zu t=X_zero + X_resolution*num, wobei num die Nummer des Abtastpunktes ist. Das Auslesen der seriellen Schnittstelle muss hier mit ReadByte() durchgeführt werden. Manche Multimeter benötigen als Sparversion für eine Pegelwandlung auf dem DTR- Signal (PIN 4) eine positive Spannung, sonst geht gar nichts. Dies kann man erreichen, wenn man serialPort1.DtrEnable = true; einmal ausführt Auszug aus Scope – Bedienanleitung siehe nächste Seite. File: Kurs MS10C# Bayerlein4.6.docx Seite 78 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Kurs 17 bis 20 entfe ernt Kurs 21 Data aGridViiew In dieseem Kurs soll die recht komplexe k K Komponentee DatDataGridView einngeführt weerden. Dazu starten wir eiin neues Pro ojekt im Orddner Kurs 20# 2 und nen nnen das Proojekt TestGrridView. Dann eiine Komponnente DataG GidView auuf das Formu ular ziehen mit Dock T Top. Wir öffn fnen den Spaalteneditor im i Eigenschhaftenfensteer, dort unteer „Columnns“ die Aufliistung öffnen: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 79 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Dann füünf Spalten hinzufügen n: Das Forrmular siehtt dann so au us: ponente mit fest program ammierter Es soll ddiese Komp Informaation gefülltt werden. Dazu den näcchsten Program mmabschnittt in ihr Prog gramm außeerhalb des Konstruuktors einfüg gen: string[] row0 = { "11 1/22/1968", "29", "Revolu tion 9", "Bea atles", "The Beatles [Whiite Album]" }; string[] row1 = { "19 960", "6", "F Fools Rush In ","Frank Sina atra", "Nice 'N' Easy" };; string[] row2 = { "11 1/11/1971", "1", "One of These Days", "Pink Floyd" ", "Meddle" }}; string[] row3 = { "19 988", "7", "W Where Is My M ind?", "Pixie es", "Surfer Rosa" }; string[] row4 = { "5/ /1981", "9", "Can't Find MMy Mind","Cra amps", "Psych hedelic Junglle" }; string[] row5 = { "6/ /10/2003", "1 13", "Scatter brain. (As De ead As Leaves s.)","Radioheead","Hail to o Thief"}; string[] row6 = { "6/ /30/1992", "3 3", "Dress", "P J Harvey", "Dry" }; Damit w werden 7 strring- Arrayss vorbelegt mit je 5 Eleementen. Hinter eeiner Taste mit m Namen buttonLoadd dann folgeenden Text kopieren: dataGr ridView1.Ro ows.Add(row w0); ridView1.Ro ows.Add(row w1); dataGr dataGr ridView1.Ro ows.Add(row w2); ridView1.Ro ows.Add(row w3); dataGr dataGr ridView1.Ro ows.Add(row w4); ridView1.Ro ows.Add(row w5); dataGr ridView1.Ro ows.Add(row w6); dataGr ridView1.Co olumns[1].H HeaderText = = "Name1"; dataGr Nach Sttart und Klick auf dieseen button siieht dann die Form so aus: a Man beachte, wie die d Spaltenü überschrift dder zweiten n Spalte mit dem Befehhl dataGridView1.Colu umns[1].Hea aderText = "Name1"; verändeert werden kann, k also Zählung Z vonn Null. File: Kuurs MS10C## Bayerlein n4.6.docx Seite 80 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Fügt maan folgendee Zeile hinzu u: dataGridView1.Rows s[3].Header rCell.Value e = "Zeile4"; Dann D wird sso auch einee Zeilenbescchriftung gaanz rechts möglich. m Man M kann ddie Größe au utomatisch einstellen e laassen mit z.B. Oder O man giibt in der Eigenschaft „RowHeade „ erWidth“ diie Größe ng: in Pixell an. Das geht aber nur so mit „EnaableResizin Jetzt solllen die Datten aus der Komponent K te ausgeleseen werden. Wie W kommtt man an diee Inhalte dran: daazu bitte einne label3 un nd eine textB Box1 hinzuffügen und einen e Eventh thandler hin nter einem CellClicck erzeugenn. Dann folg genden Codde dort eingeeben: Außerhaalb der funcction: int c=0, r=0; Innerhaalb: c = e.ColumnIndex; ; r = e.RowIndex; label3.Text="click ked Row= "+ +r.ToString g()+" Col= "+c.ToStri ing(); )&&(c<dataG GridView1.C ColumnCount)&&(r<dataG GridView1.RRowCount)) if ((c>=0)&&(r>=0) textBox1.Tex xt = dataGr ridView1[c, r].Value.To oString(); In dem Parameter e kann man den Spaltenn- und Zeileenindex abffragen, diesee werden naach c und r geschrrieben und in i label3 ausgegeben. D Das Ausleseen geschieht wie bei einnem zweidim mensionalenn Array mit …[c,r] per Eigenschafft Value. Ein Beispiel erkennnt man im nächsten n Scrreenshot, au uch da hat die d Zelle obeen links diee Zeile Null N und die Spalte Nulll: Man M kann jettzt z. B. in j eder Zelle einen e eiigenen Font einstellen. Beispielpro ogramm daazu hinter einer Taste bbuttonFont, vorher eiinen FontDiialog auf diee Form zieh hen: if (fontDialog1.ShowDialog g() == Dial logResult.OK) aGridView1[ [c, r].Styl le.Font = fo ontDialog1. .Font; data t Comic San ns MS, Schr riftgröße 12 : Z.B. Zelle 2,2 mit File: Kuurs MS10C## Bayerlein n4.6.docx Seite 81 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Man muuss darauf achten, a dass keine Zellee angesprocchen wird, die d es nicht ggibt, denn sonst s bricht ddas Program mm mit Fehlermeldung ab. Da bieteet sich eine try – catch – Abfrage an. Soll derr User Zeileen hinzufügeen können, dann muss folgende Eiigenschaft aauf true gesetzt werden:: dataGridView1.Allo owUserToAdd dRows = tru ue; dann gibbt es eine Leerzeile L am m Ende der T Tabelle. Weenn dort etw was hineingeeschrieben wird, w sieht es so aus: Nur dannn gibt es beei einem Klick in diesee neue Zeilee sofort einee Fehlermelddung, da deer Inhalt sofort inn die Textboox geschrieb ben werdenn soll. Dieseer existiert aber a noch niicht. Die Eigenschaft RowCouunt ist schoon um eins erhöht e wordden, aber fürr den Inhalt ist noch keein Speicherrbereich zugewieesen wordenn. Das kann n man abfanngen mit follgendem if: if (dataG GridView1[c, r].Value!=nu ull) textBox1 .Text = dataG GridView1[c, r].Value.ToSString(); Erst wennn die Zeilee verlassen wird, wird dder Inhalt aktualisiert a und u der Sterrn verschwiindet. Kurs 22 C# DirectX D Hier sinnd alle Inforrmationen und u ein kleinnes Beispiellprogramm auf der Seitite http://w www.fhluebeckk.de/Inhalt/003_Hochsch hulangehoerrige_Ch031/04_FB_Elektrotechnikk/04_Laborre_und_In stitute/663_Labor_E ESA_RT/Visual-C_/DirrectX_mit_ _C_/index.httml zu findeen. Es wird eine x- Datei angezeiggt, die natürllich die 3D-- Bildinform mation enthäält. Solche D Dateien kannn man mit dem Freew wareprogram mm Googlesketch erstelllen, das maan im Internett findet. Auff der Seite sind s Screensshots des C# - Program mmes und veergleichsweeise eines DirektX X- Viewers zusehen. z Kurs 23 MyS Sql und C# Auf derr Seite http:///www.fhluebeckk.de/Inhalt/003_Hochsch hulangehoerrige_Ch031/04_FB_Elektrotechnikk/04_Laborre_und_In stitute/663_Labor_E ESA_RT/Visual-C_/MY YSQL/index.html findet m man alles, was w man wissen muss, uum mit C# eine e mySL- Datenbankk anzusprech hen. Dies wurde inn einer Diplomarbeit von v Frau Yaannan Shen erarbeitet, die d dort aucch zur Verfü ügung gestellt wird. Ein Beispielprog B gramm vervvollständigt das Angebo ot. Dort ist eein File: Kuurs MS10C## Bayerlein n4.6.docx Seite 82 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Anweseenheitszähleer mit Sourcce zu findenn, der es erm möglicht, in einer Verannstaltung mit m Studiereenden den Barcode B dess Ausweisess zu scannen n. Die Anwesenheitszeeit und Datu um werden dann in einner MySQL-- Tabelle unnd die Studiierendendatten in einer zweiten tab belle einer Datenbaank abgeleggt. Kurs 24 Meilhaus ME M 4660 0 Inzwiscchen sind auuch moderneere Versionnen der Meillhauskarte (ME ( 4660) uund der Orlowskkikarte (US SB 2.0 – Verrsion) entstaanden und im i Labor veerfügbar. Ichh habe die Anleitunngen dazu im i Internet veröffentliccht. ME46600: (geht sow wohl mit 32 2.Bit als aucch mit 64 BitB Window ws!) http://w www.fhluebeckk.de/Inhalt/003_Hochsch hulangehoerrige_Ch031/04_FB_Elektrotechnikk/04_Laborre_und_In stitute/663_Labor_E ESA_RT/Visual-C_/Kuurs_24_AD_ _Meilhaus_ _4660/indexx.html Kurs 25 NI mit m NIDA AQmx Ab Winn7 ist nur nooch die neuee Interface- Version miit DAQmx zu z verwendden, die veraaltete NI – traditiional darf niicht mehr benutzt werdden. Diese hatte h zu Beg ginn den Naachteil, dasss die Rechenzzeit im Verggleich zu „ttraditional“ gut um den n Faktor 10 größer ist. D Dauert einee SingleAD-Abffrage mit „ttraditional“ ca 300 µsecc, so dauertte es auf dem m gleichen PPC mit gleiicher Karte 2--3 ms. Ein Takten T mit 1 ms ist dannn unmöglicch. Dies lag g aber darann, dass ein Fehler F bei unserem m Programm m vorhanden n war. Eine Task muss gestartet werden, w dannn gehen die AD- DA – Wanddlungen schnneller. Wir hatten den S Startbefehl nicht gegeb ben, so hat ddas Interface bei jeder W Wandlung diee Task gestaartet und daanach beend det. Und ein n Start dauerrt halt ein paar p msec. Eine ricchtige Lösunng für DAQ Qmx gibt es in meinem Windfc#- Projekt P an V Version 7.4.15 in der Datei „H Hardwaretoools /DAQm mx_Basics_N NChannel.ccs“, siehe do ort. Dazu zuuerst zwei Verweise V hin nzufügen: Anschliießend musss dann im Projektmapp P pen-Exploreer dann folgendes steheen: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 83 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Dann using NationalInst truments.DA AQmx; Und dannn sind folggende Befeh hle möglich : AD ausllesen: double val = rscha an.ReadSing gleSample() ; Ausgabe auf DA wschan.WriteSingle eSample(tru ue, val); zuvor m muss man diie beiden Taasks rschan und wschan n „kreieren““ mit AnalogSing gleChannelR Reader rsch han; gleChannelW Writer wsch han; AnalogSing Und dass geht so: Erst E die Instaanziierung dder AD- Tassks: (DA geeht ähnlich, siehe Dateii .cs): Task taskAI = new Task("abci i"); dann taskAI.A AIChannels.CreateVolt tageChannel l(actdev+"/a ai0", "aiCh hannel0", A AITerminalC Configurati ion.Rse,Min nI, MaxI, AIVoltageUni its.Volts); Dann rschan = new Analo ogSingleCha annelReader r(taskAI.Stream); dann soollte es nachh taskAI.Staart(); gehenn. Weiteree Hinweise kann k man auf a den Interrnetseiten von v mir zu diesem d Punkkt finden. Kurs 26 USB B- Orlow wski 2.0 0 USB – O Orlowski USB U 2.0 Verrsion: (geht nur auf 32. Bit Window ws) http://w www.fhluebeckk.de/Inhalt/003_Hochsch hulangehoerrige_Ch031/04_FB_Elektrotechnikk/04_Laborre_und_In stitute/663_Labor_E ESA_RT/Visual-C_/Kuurs_26_AD--_USB_-_K Karte_2_0_O Orlowski/in ndex.html Kurs 27 Inte erface mit m TCP//IP Viele G Geräte komm munizieren heute h über eeine schnellle Ethernet- Verbindunng oder überr Internet. Das wirrd in C# aucch gut unterrstützt. Als B Beispiel solll die Komm munikation m mit einer WAGOW Klemmee gezeigt werden, w die in der Indusstrie als Anaalog – und DigitalD Inteerface Verw wendung findet. Man bennötigt Zugrriff auf dieseen Namespaace: using System.Net.S Sockets; dann kaann man einnen TCP – Client C instannziieren: TcpClient tcpClien ntWAGO = ne ew TcpClien nt(); Hinter eeinem Buttoon „Connectt“ kann mann dann mit folgendem f Programm P eeine Verbin ndung aufbaueen: File: Kuurs MS10C## Bayerlein n4.6.docx Seite 84 Visuelle Programmierung mit C# Prof. Dr. Bayerlein try { if (!tcpClientWAGO.Connected) { tcpClientWAGO.Connect("192.168.0.2",502);//tcpClient.Connect("193.175.124.132", 502); if (tcpClientWAGO.Connected) toolStripStatusLabel1.Text = "Wago is connected"; } else MessageBox.Show("Verbindung besteht bereits","TCP Connection Info", MessageBoxButtons.OK); } catch (SocketException) { MessageBox.Show("Verb.‐aufbau nicht möglich","TCP Connection Error", MessageBoxButtons.OK); } Dabei wird eine Nachricht in ein toolStripStatusLabel geschrieben, ein StatusStrip muss natürlich dann vorhanden sein. Wenn eine Verbindung gelungen ist, kann man Lesen und Schreiben mit einem NetworkStream: NetworkStream netStreamWAGO; Den muss man mit der Verbindung zusammenführen. Das Schreiben geht so: netStreamWAGO = tcpClientWAGO.GetStream(); if (netStreamWAGO.CanWrite) { byte[] sendBytes = new byte[12]; //lokales Array mit Daten netStreamWAGO.Write(sendBytes, 0, sendBytes.Length); } Das Lesen geht so: netStreamWAGO = tcpClientWAGO.GetStream(); if (netStreamWAGO.CanRead) { byte[] readBytes = new byte[tcpClientWAGO.ReceiveBufferSize]; netStreamWAGO.Read(readBytes, 0, (int)tcpClientWAGO.ReceiveBufferSize); } Anschließend sind im Byte –Array die Daten. Um jetzt mit den Wago –Klemmen einen DA- Wert auszugeben, muss man das Mod- Bus – Protokoll bedienen. Bei anderen Geräten muss man dann das entsprechend Protokoll den Datenblättern entnehmen. Das Wago- Protokoll ist den Versuchsunterlagen zu entnehmen und wird am Versuchstag zur Verfügung gestellt. WindfC#, mein großes Regelungstechnik- Toolprogramm. Weitere Informationen kann man erhalten, wenn man sich das folgende Projekt, das auch als Source- Code in C# erhältlich sind - quasi als Freeware – anschaut: http://www.fhluebeck.de/Inhalt/03_Hochschulangehoerige_Ch031/04_FB_Elektrotechnik/04_Labore_und_In stitute/63_Labor_ESA_RT/WindfCSharp/index.html File: Kurs MS10C# Bayerlein4.6.docx Seite 85 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Einig ge Hinw weise Proble ematik mit m Dock Werdenn zwei Elem mente mit Do ock auf Topp gesetzt, errhebt sich diie Frage, weelcher wirkllich zuerst ooben und weelche dann darunter d plaatziert wird.. Beispiel ToolStrip und nd Panel: So soll ees sein. Manchmal abeer passiert ess, dass bei beiden b Elem menten, die auf Docksty yle.Top gesetzt w werden, einne falsche Platzierung eerfolgt, z.B.. so: Es hänggt von der Reihenfolge R ab, mit der diese Elem mente der Fo orm bzw. deem Containeer hinzugeefügt worden sind. Wiee kann man diese nachtträglich veräändern? So:: Man muss die Datei „designner“, die norrmalerweisee nicht angeefasst wird, nun n doch öfffnen. In deem Teil, derr oben rechts aausgeschnittten ist, kann n man die Zuuordnung erkennen. e Das Element,, das unter dem d anderenn steht, gewiinnt! Param meter in Funktion F nsaufrufe en und Arrays A Dort gibbt es einige Änderungeen gegenübeer C++: Beispielle: Deklaraation von Arrrays: C++ double C# xein[maxx2n] doubl e[] xein = new dou uble[max2n n] Funktioonsaufruf C++ void xr__db(double& & xrr, doub ble p[10], double& & q[10], intt m) File: Kuurs MS10C## Bayerlein n4.6.docx C# void xr_db(ref double e xrr, dou uble[] p, ref double[] q, in nt m) Seite 86 Visuellee Programm mierung mit C# Prof. Dr. Bayerlein B Xrr wirdd referenzieert aufgerufe fen, damit köönnen Wertte zurückgegeben werdden, es wird d nur der Pointer übergeben. Das Array p wird in ddie Funktion n hineingegeeben und voon der Funk ktion nicht verändeert. Das Arryy q wird wieder referennziert, also lediglich mit m Pointer üb übergeben un nd kann von der Funktion verändert v weerden. Zeilen nnummern im Ed ditor Manchm mal helfen Zeilennumm Z mern im Texxteditor. Siee aktiviert man m mit Mennü Debuggeen O Optionen… D Dann im Tex xt-Editor Alle Spracchen D Dort Klick au uf Zeilennu ummern: W Weitere Projekte werde ich auf denn Internetseiiten unter www.fhh-Luebeck.dde, Studieerende FB B EI Lab bore & Institute, Labbor Regelunngstechnik Visual-C C# -Page odder Windfc# # demnäcchst in loser Folge veröffentlichen.. Stand N November 2012 Prof. Drr. Bayerleinn File: Kuurs MS10C## Bayerlein n4.6.docx Seite 87