<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>KeenTech &#187; C#</title>
	<atom:link href="http://www.keentech.de/blog/category/programmierung/csharp/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.keentech.de/blog</link>
	<description>Fakten, Erlebnisse, Gedanken und Erkenntnisse</description>
	<lastBuildDate>Thu, 29 Jul 2010 14:14:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Authentifizierung an Netzwerkfreigaben via C#</title>
		<link>http://www.keentech.de/blog/2009/04/authentifizierung-an-netzwerkfreigaben-via-c/</link>
		<comments>http://www.keentech.de/blog/2009/04/authentifizierung-an-netzwerkfreigaben-via-c/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 12:00:47 +0000</pubDate>
		<dc:creator>FireFox</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Benutzer]]></category>
		<category><![CDATA[Freigabe]]></category>
		<category><![CDATA[Netzwerk]]></category>
		<category><![CDATA[Passwort]]></category>
		<category><![CDATA[Schare]]></category>
		<category><![CDATA[Zugriff]]></category>

		<guid isPermaLink="false">http://www.keentech.de/blog/?p=2183</guid>
		<description><![CDATA[Eine Mail erreichte mich heute, in der ich gefragt wurde, wie man zB. mein Programm easyLiveSync, oder eigene Implementierungen dazu bewegen könnte, auf Netzlaufwerke bzw. Freigaben zuzugreifen, bei denen sich explizit angemeldet werden muss. Ursache aus der Mail war, dass die Synchronisierung von bzw. auf Netzlaufwerke geschehen sollte, diese aber des Öfteren im Explorer als  <a href="http://www.keentech.de/blog/2009/04/authentifizierung-an-netzwerkfreigaben-via-c/" class="more-link">Mehr &#62;</a>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Eine Mail erreichte mich heute, in der ich gefragt wurde, wie man zB. mein Programm <a href="http://www.keentech.de/blog/2009/02/programm-easylivesync/" target="_blank">easyLiveSync</a>, oder eigene Implementierungen dazu bewegen könnte, auf Netzlaufwerke bzw. Freigaben zuzugreifen, bei denen sich explizit angemeldet werden muss. Ursache aus der Mail war, dass die Synchronisierung von bzw. auf Netzlaufwerke geschehen sollte, diese aber des Öfteren im Explorer als &#8220;Getrennt&#8221; angezeigt werden, obwohl ein Doppelklick darauf die Verbindung aufbaut. Ebenso, wenn das Laufwerk getrennt ist, wird aus anderen Programmen heraus der Zugriff verweigert.</p>
<p style="text-align: justify;">Ich bin ein <a href="http://www.krecklow.de/blog/?p=208#comment-193" target="_blank">Freund von Boardmitteln</a>, wo sie denn sinnvoll und zeiteinsparend sind. Und unter C# und Co. kann man auch die Boardmittel nutzen, um zumindest vorerst eine Verbindung unter Nutzung von Nutzer und Passwort auf eine Freigabe zu erreichen.</p>
<p style="text-align: justify;">Der Befehl unter Windows lautet: <span class="pln"><em>net </em></span><span class="kwd"><em>use</em></span><span class="pln"> <strong>SERVERNAME</strong></span><span class="pun"><strong>\</strong></span><span class="pln"><strong>IPC$</strong> </span><span class="pun"><em>/</em></span><span class="pln"><em>user</em></span><span class="pun">:</span><span class="pln"><strong>USERNAME PASSWORD</strong>. Alternativ kann man auch die Freigabe vorher auf ein Laufwerksbuchstaben mappen mittels: <span class="pln"><em>net </em></span><span class="kwd"><em>use</em></span><span class="pln"> <strong>FreierLaufWerksbuchstabe</strong>: </span><span class="pln"><strong>\\SERVERNAME</strong><span class="pln"><strong>\FREIGABE</strong><span class="pln"> </span><span class="pun"><em>/</em></span><span class="pln"><em>user</em></span><span class="pun">:</span><span class="pln"><strong>USERNAME PASSWORD</strong>. Danach kann man über den neu belegten Laufwerksbuchstaben auf die entfernten Daten zugreifen.</span></span></span></span></p>
<p style="text-align: justify;"><span class="pln"><span class="pln"><span class="pln"><span class="pln">Will man dies nun via C# realisieren, existieren zwar einige Boardmittel, aber mittels eines Sechszeilers geht das Ganze recht einfach von der Hand. Folgender Quellcode-Ausschnitt zeigt dies auf:</span></span></span></span></p>
<p style="text-align: justify;"><span class="pln"></span></p>
<blockquote><p><span style="font-family: -webkit-monospace; "><span class="typ">P<span style="font-family: 'Courier New';">rocessStartInfo</span></span><span class="pln"><span style="font-family: 'Courier New';"> psi </span></span><span class="pun"><span style="font-family: 'Courier New';">=</span></span><span class="pln"><span style="font-family: 'Courier New';"> </span></span><span class="kwd"><span style="font-family: 'Courier New';">new</span></span><span class="pln"><span style="font-family: 'Courier New';"> </span></span><span class="typ"><span style="font-family: 'Courier New';">ProcessStartInfo</span></span><span class="pun"><span style="font-family: 'Courier New';">(&#8220;</span></span><span class="str"><span style="font-family: 'Courier New';">net&#8221;</span></span><span class="pun"><span style="font-family: 'Courier New';">,&#8221;</span></span><span class="str"><span style="font-family: 'Courier New';">use &#8220; </span></span><span class="pun"><span style="font-family: 'Courier New';">+ </span></span><span class="pln"><span style="font-family: 'Courier New';">SERVERNAME </span></span><span class="pun"><span style="font-family: 'Courier New';">+</span></span><span class="pln"><span style="font-family: 'Courier New';"> @&#8221;</span></span><span class="str"><span style="font-family: 'Courier New';">\IPC$ /user:&#8221;</span></span><span class="pln"><span style="font-family: 'Courier New';"> </span></span><span class="pun"><span style="font-family: 'Courier New';">+</span></span><span class="pln"><span style="font-family: 'Courier New';"> USERNAME </span></span><span class="pun"><span style="font-family: 'Courier New';">+</span></span><span class="pln"><span style="font-family: 'Courier New';"> &#8221;</span></span><span class="str"><span style="font-family: 'Courier New';"> &#8221;</span></span><span class="pln"><span style="font-family: 'Courier New';"> </span></span><span class="pun"><span style="font-family: 'Courier New';">+</span></span><span class="pln"><span style="font-family: 'Courier New';"> PASSWORD</span></span><span class="pun"><span style="font-family: 'Courier New';">);<br />
<span style="font-family: -webkit-monospace; "><span class="typ">Process</span><span class="pln"> proc </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Process</span><span class="pun">();<br />
<span class="pun">proc.</span><span class="typ">StartInfo</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> psi; <span class="pun">proc.</span><span class="typ">Start</span><span class="pun">();<br />
<span class="pun">proc.</span><span class="typ">WaitForExit</span><span class="pun">();<br />
<span class="pun">proc.</span><span class="typ">Close</span><span class="pun">();</span></span></span></span></span></span></span></span></span></p></blockquote>
<p style="text-align: justify;">SERVERNAME, USERNAME und PASSWORD sind in diesem Fall Variablen des Typs string. Danach kann man problemlos den Zugriff via UNC auf die Freigabe des Server realisieren und seine &#8220;Dummheiten&#8221; mit anstellen. Ebenso ist durch Abänderung der ersten Quellcode-Zeile die Anbindung auf ein Laufwerksbuchstaben möglich:</p>
<blockquote style="text-align: justify;"><p><span class="typ">ProcessStartInfo</span><span class="pln"> psi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ProcessStartInfo</span><span class="pun">(</span><span class="str">&#8220;net</span><span class="pun">&#8220;,</span><span class="str">&#8220;use Laufwerk: \\\\<span class="str">&#8220; </span><span class="pun">+ </span><span class="pln">SERVERNAME </span><span class="pun">+</span><span class="pln"> @</span><span class="str">&#8220;\Freigabe /user:&#8221;</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> USERNAME </span><span class="pun">+</span><span class="pln"> </span><span class="str">&#8221; &#8220;</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> PASSWORD</span><span class="pun">);</span></span></p></blockquote>
<p style="text-align: justify;"><span class="pun">Der Rest sollte dann nach Schema F ablaufen.</span></p>
<p style="text-align: justify;"> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.keentech.de/blog/2009/04/authentifizierung-an-netzwerkfreigaben-via-c/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Update &#8211; Programm: easyLiveSync</title>
		<link>http://www.keentech.de/blog/2009/02/programm-easylivesync/</link>
		<comments>http://www.keentech.de/blog/2009/02/programm-easylivesync/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 21:05:52 +0000</pubDate>
		<dc:creator>FireFox</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Hard & Software]]></category>
		<category><![CDATA[Hilfe]]></category>
		<category><![CDATA[PC]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[easyLiveSync]]></category>
		<category><![CDATA[Freeware]]></category>
		<category><![CDATA[Programm]]></category>
		<category><![CDATA[Quellen]]></category>
		<category><![CDATA[Sync]]></category>
		<category><![CDATA[Synchronisation]]></category>

		<guid isPermaLink="false">http://www.keentech.de/blog/?p=1723</guid>
		<description><![CDATA[Ich habe mal etwas in meinen Projekten gekramt und ein Programm, welches ich mal für unterschiedliche Bekannte geschrieben habe, herausgepickt. Ursache war erneut eine Anfrage eines weiteren Bekannten, ob es nicht möglich ist, Dateien und Verzeichnisse in &#8220;Echtzeit&#8221; auf ein Ziel der Wahl zu synchronisieren, damit im Ernstfall eine Wiederherstellung dieser Dateien möglich ist. Ich  <a href="http://www.keentech.de/blog/2009/02/programm-easylivesync/" class="more-link">Mehr &#62;</a>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">
<a href="http://www.keentech.de/blog/wp-content/myfotos/kt-programs/easylivesync.jpg" title="" class="thickbox" rel="singlepic1076" >
	<img class="ngg-singlepic ngg-left" src="http://www.keentech.de/blog/wp-content/myfotos/cache/1076_web20_128x128_easylivesync.jpg" alt="easylivesync.jpg" title="easylivesync.jpg" />
</a>
Ich habe mal etwas in meinen Projekten gekramt und ein Programm, welches ich mal für unterschiedliche Bekannte geschrieben habe, herausgepickt. Ursache war erneut eine Anfrage eines weiteren Bekannten, ob es nicht möglich ist, Dateien und Verzeichnisse in &#8220;Echtzeit&#8221; auf ein Ziel der Wahl zu synchronisieren, damit im Ernstfall eine Wiederherstellung dieser Dateien möglich ist. Ich bitte hier an dieser Stelle das Wort &#8220;Ernstfall&#8221; nicht zu ernst zu nehmen, denn 100%ige Sicherheit gibt es nicht &#8211; auch nicht bei meinen Anwendungen <img src='http://www.keentech.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p style="text-align: justify;">Es passiert viel zu oft, dass Dateien zB. von Netzlaufwerken irrtümlich gelöscht werden. Da Windows keinerlei Netzlaufwerk-Papierkörbe kennt, ebenso wenig Mac OS X bei Zugriff auf SMB-Shares, ist dieses Programm vor 2 Jahren entstanden. Es synchronisiert die Quelle zum Ziel (zB. ein eigener &#8220;Papierkorb&#8221; oder Backup-Ordner auf dem Netzwerk) und verweilt zur Laufzeit im Hintergrund, überprüft die Zugriffe auf die jeweiligen Dateien und Ordner und synchronisiert das Ganze dementsprechend. Wird eine Datei erzeugt, wird diese auch am Ziel umgehend erzeugt. Wird eine Datei geändert, geschieht dies auch am Ziel. Beim Löschen und Umbenennen passiert ebenso das Gleiche am Ziel. (Löschen kann in dieser Version abgeschaltet werden).</p>
<p style="text-align: justify;">Sicherlich gibt es genügend Backup-Programme &#8211; kostenfrei und käuflich &#8211; aber diese halfen nicht bei oben genanntem Problem, wenn eine Datei erzeugt, aber Minuten oder Stunden später irrtümlich, durch DAU-Verhalten oder Layer-8 Problem, gelöscht wurden. Normale Backup- oder Syncprogramme laufen entweder immer nach einer Zeit X in Minuten oder gar nur einmal täglich.</p>
<p style="text-align: justify;">Ich habe das Programm noch einmal auf die Schnelle etwas bearbeitet (Menüs, Dialoge) und diese ebenso einem Test unter Windows XP und Windows Vista unterzogen. Voraussetzung ist .Net Framework 3.5, aber bei Bedarf kann ich auch das Ganze für 2.0 anbieten.</p>
<p style="text-align: justify;"><strong>Technischer Hintergrund</strong>: Das Ganze basiert auf der FileSystemWatcher-Klasse des .Net Frameworks, welches Created, Changed, Renamed und Deleted-Ereignisse verarbeitet und diese Information an das Ziel weitergibt. Es ist einstellbar, ob Deleted-Ereignisse verarbeitet werden sollen, oder nicht. Ebenso sind mehrere Sync-Jobs parallel möglich, um mehrere Ordner zu überwachen und zu sichern.</p>
<p style="text-align: justify;">Es wird dringend davon abgeraten, eine komplette Festplatte (zB. Laufwerk C:) überwachen zu lassen. Die Auslagerungsdatei, der Windows-, wie auch weitere systemrelevante Ordner, schreiben gern und viel in ihre Dateien und Ordner herum. Das würde das Programm und somit den Rechner nur unnötig ausbremsen und für eventuell daraus resultierende &#8220;Schäden&#8221; übernehme ich definitiv keine Haftung. Apropos Haftung: Die Nutzung, der hier kostenfrei zur Verfügung gestellten Anwendung, unterliegt eigener Verantwortung. Das Programm, wie angeboten, ist &#8220;as is&#8221;, beinhaltet mit Sicherheit den einen oder anderen Fehler und eine 100%ige Funktion kann nicht gewährleistet werden. Das Programm liegt ebenso in den Original-Quellen vor, damit der geneigte Nutzer oder Programmierer sich der Basis annehmen und dann seine eigene Anwendung daraus stricken kann.</p>
<p style="text-align: justify;"><strong>Update</strong>: Bug bereinigt &#8211; in bestimmten Konstellationen wurde das Ziel nicht korrekt geschrieben. Vornehmlich, wenn die Quelle im Vergleich zum bestehenden Ziel kleiner war. Programm + Quellcode in den Links wurden aktualisiert.</p>
<ul style="text-align: justify;">
<li><a href="http://www.keentech.de/blog/wp-content/uploads/2009/02/easylivesync.zip"></a><a href="http://www.keentech.de/blog/wp-content/uploads/2009/02/easylivesync.zip" target="_blank">easyLiveSync V1.0 &#8211; Programm</a></li>
<li><a href="http://www.keentech.de/blog/wp-content/uploads/2009/02/easylivesync-source.zip" target="_blank">easyLiveSync V1.0 &#8211; Sourcecode</a></li>
</ul>
<p style="text-align: justify;">Das Programm startet derzeitig immer im Fenster-Modus. Optionen, um dies zu ändern, existieren <span style="text-decoration: underline;">noch</span> nicht. Ein Doppelklick auf das Symbol in der Tray (das Teil neben der Uhr) blendet das Fenster aus bzw. wieder ein. Die Anwendung kann nur über das Tray-Symbol (rechte Maustaste &#8211; Beenden) beendet werden &#8211; oder aber, indem es mit dem Task-Manager abgeschossen wird &#8211; je nachdem, wie man es gern hat. Über Menüpunkt &#8220;Job -&gt; Anlegen&#8221; kann ein Sync-Job angelegt werden. Um einen Job zu bearbeiten, einfach rechte Maustaste auf den gewünschten Job in der Liste und dann auf &#8220;Job ändern&#8221; klicken. Ebenso verhält es sich, wenn ein Job gelöscht werden soll. </p>
<p style="text-align: justify;">Nachdem ein Job angelegt bzw. geändert wurde (oder aber mit definierten Jobs nach Start von easyLiveSync) wird pro Job jeweils abgefragt, wie weiter vorzugehen ist (Dies wird in einer späteren Version mit hinterlegbaren Job-Optionen geändert werden). Es stehen 3 Möglichkeiten zur Wahl:</p>
<ol style="text-align: justify;">
<li>Zielordner (alles, aber auch wirklich alles darin) löschen, Quelle in Ziel kopieren und danach das Ganze live überwachen,</li>
<li>Zielordner nicht löschen (wenn zB. schon einmal gesynced wurde), Quelle (neue oder geänderte Dateien und Ordner) werden auf das Ziel kopiert und danach das Ganze live überwacht, oder</li>
<li>nichts kopieren, sondern die Änderungen von Quelle auf Ziel übertragen (hier kann es bei Situationen, wo noch niemals vorher das Ziel gefüllt wurde, zu Problemem kommen &#8211; sprich Error).</li>
</ol>
<p style="text-align: justify;">Mehr gibt es eigentlich nicht zu wissen. <img src='http://www.keentech.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p style="text-align: justify;">Für Verbesserungsvorschläge, dumme, negative, wie auch positive Kommentare, bin ich offen &#8211; und mit Sicherheit gibt es etwas zu verbessern (zB. Dateifilter, Überprüfung wann eine Datei an Quelle und Ziel gleich ist usw.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.keentech.de/blog/2009/02/programm-easylivesync/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Die Digital-Uhr in Brandenburg / Havel</title>
		<link>http://www.keentech.de/blog/2007/05/die-digital-uhr-in-brandenburg-havel/</link>
		<comments>http://www.keentech.de/blog/2007/05/die-digital-uhr-in-brandenburg-havel/#comments</comments>
		<pubDate>Wed, 23 May 2007 21:24:29 +0000</pubDate>
		<dc:creator>FireFox</dc:creator>
				<category><![CDATA[Arbeit]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.keentech.de/blog/?p=48</guid>
		<description><![CDATA[Seit geraumer Zeit steht sie in Brandenburg an der Havel und verrichtet fleißig ihren Dienst. Sie vermittelt jedem Nicht-Uhren Besitzer, wie schnell doch die Zeit vergeht und in letzter Zeit vermehren sich die Touristen, die es in die Stadt zieht, vor ihr, um davor abgelichtet zu werden. Die Rede ist von der Digital-Uhr auf dem  <a href="http://www.keentech.de/blog/2007/05/die-digital-uhr-in-brandenburg-havel/" class="more-link">Mehr &#62;</a>]]></description>
			<content:encoded><![CDATA[<p align="justify">Seit geraumer Zeit steht sie in Brandenburg an der Havel und verrichtet fleißig ihren Dienst. Sie vermittelt jedem Nicht-Uhren Besitzer, wie schnell doch die Zeit vergeht und in letzter Zeit vermehren sich die Touristen, die es in die Stadt zieht, vor ihr, um davor abgelichtet zu werden. Die Rede ist von der Digital-Uhr auf dem Neustadt-Markt, deren elektronisches und technisches Innenleben von<a href="http://www.industrieelektronik.de"> Industrieelektronik Brandenburg GmbH (IEB)</a> (meinem Arbeitgeber) gefertigt wurde. Ich selbst durfte an diesem &#8220;Kleinod&#8221; mitwirken: speziell mit der alleinigen Entwicklung einer Windows-Anwendung für die Verwaltung und den Fernzugriff auf das Herzstück &#8211; die Steuerelektronik &#8211; der Uhr.<br />
Wozu, wird der geneigte Interessierte fragen, brauch man einen Fernzugriff. Relativ einfach: Es ist mit Hilfe der Software möglich zeitgesteuert Skripte (Grafiken und Texte) über die 4(!) Laufbandanzeigen unter den 4(!) großen Hauptanzeigen (jede zeigt in eine der Haupthimmelsrichtung) ablaufen zu lassen. Das Ganze wird anwendungsseitig durch eine SQL-Datenbank gestützt. Die Texte, Grafiken und zeitlichen Abfolgen und Laufzeiten werden in der Datenbank abgelegt, um die Menge der übertragenen Daten bei späteren Aktualisierungen so gering wie möglich zu halten und um nicht ausversehen bestimmte Skripte auf der Uhr zu löschen.</p>
<p>Wozu das Ganze? Der Gedanke liegt darin, daß über diesem Wege die Einwohner und auch Besucher der Stadt über Ereignisse informiert werden können, die derzeitig oder in naher Zukunft in Brandenburg aufkommen.</p>
<p>Sollte jemand das Interesse verspühren andere über die Uhr grüßen, Glückwünsche für Hochzeiten, Geburtstage und andere Feierlichkeiten aussprechen, oder Werbung für sein Unternehmen anzeigen lassen zu wollen, kontaktiert einfach <a href="http://www.industrieelektronik.de">IEB</a>.</p>
<p>Anbei noch 3 Bildchen (die Farbgebung und das Design stammt nicht von uns &#8211; wohlbemerkt)</p>

<a href="http://www.keentech.de/blog/wp-content/myfotos/blog_pics/DSCF0340.JPG" title="" class="thickbox" rel="singlepic454" >
	<img class="ngg-singlepic ngg-left" src="http://www.keentech.de/blog/wp-content/myfotos/cache/454__200x200_DSCF0340.JPG" alt="" title="" />
</a>
[singlepic id="455" w="200" h="200" mode="" float="left" ]
<a href="http://www.keentech.de/blog/wp-content/myfotos/blog_pics/DSCF0342.JPG" title="" class="thickbox" rel="singlepic456" >
	<img class="ngg-singlepic ngg-left" src="http://www.keentech.de/blog/wp-content/myfotos/cache/456__200x200_DSCF0342.JPG" alt="" title="" />
</a>

]]></content:encoded>
			<wfw:commentRss>http://www.keentech.de/blog/2007/05/die-digital-uhr-in-brandenburg-havel/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>AntMe! &#8211; die Ameisensimulation</title>
		<link>http://www.keentech.de/blog/2007/04/antme-die-ameisensimulation/</link>
		<comments>http://www.keentech.de/blog/2007/04/antme-die-ameisensimulation/#comments</comments>
		<pubDate>Mon, 16 Apr 2007 16:55:57 +0000</pubDate>
		<dc:creator>FireFox</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.keentech.de/blog/?p=18</guid>
		<description><![CDATA[Im MSDN Bereich von Microsoft ist vor einigen Tagen ein interessantes Projekt vorgestellt worden. Es geht um AntMe! &#8211; eine Ameisensimulation. Ich habe die letzten Tage hier und da einen Blick darauf geworfen und finde, daß es für Einsteiger sehr gut geeignet ist, C# oder VB .Net zu lernen. Das Projekt selbst wird in 2  <a href="http://www.keentech.de/blog/2007/04/antme-die-ameisensimulation/" class="more-link">Mehr &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Im MSDN Bereich von Microsoft ist vor einigen Tagen ein interessantes Projekt vorgestellt worden. Es geht um <a href="http://www.microsoft.com/germany/msdn/coding4fun/antme/default.mspx">AntMe!</a> &#8211; eine Ameisensimulation. Ich habe die letzten Tage hier und da einen Blick darauf geworfen und finde, daß es für Einsteiger sehr gut geeignet ist, <em>C#</em> oder <em>VB .Net</em> zu lernen. Das Projekt selbst wird in 2 Paketen angeboten &#8211; für Einsteiger und Professionelle Entwickler. In der Professional Version ist der komplette Quellcode des Projekts enthalten &#8211; nebst GDI+ und Direct3D Darstellung. Der Quellcode selbst ist ist gut dokumentiert und die Hilfe sollte allen ein guter Einstieg sein.<br />
Es macht sichtlich Spaß seinen Ameisen Leben einzuhauchen und diese mit wohlüberlegten Programmcode auszustatten.</p>
<p><span id="more-18"></span></p>
<p>Ich stelle einfach mal meinen derzeitigen Stand meiner Ameisen (nach effektiven 2 Stunden Überlegen und Ausprobieren) zur Verfügung. Vielleicht hat ja der eine oder andere Interesse daran sich daran zu versuchen.</p>
<p>Der Quelltext selbst ist noch nicht (bis auf den Inhalt aus der Vorlage) dokumentiert.</p>
<p>[source:csharp]<br />
using System;<br />
using System.Collections.Generic;<br />
using System.Text;<br />
using AntMe;</p>
<p>namespace AntMe.Spieler<br />
{</p>
<p>    [Spieler(<br />
        Name = "FireFox",<br />
        Vorname = "Michael",<br />
        Nachname = "Hensel"<br />
    )]</p>
<p>    // Das Typ-Attribut hier erlaubt das Ändern der Ameisen-Eigenschaften. Um hier Änderungen vorzunehmen muss<br />
    // dem neuen Ameisentyp unbedingt ein Name zugewiesen und bei &#8220;BestimmeTyp&#8221; auch angegeben werden.<br />
    // Eine genauere Beschreibung gibts in Lektion 6 des Ameisen-Tutorials<br />
    [Typ(<br />
        Name = "Sammler",<br />
        GeschwindigkeitModifikator = 0,<br />
        DrehgeschwindigkeitModifikator = -1,<br />
        LastModifikator = 1,<br />
        ReichweiteModifikator = 1,<br />
        SichtweiteModifikator = 1,<br />
        EnergieModifikator = -1,<br />
        AngriffModifikator = -1<br />
    )]</p>
<p>    [Typ(<br />
        Name = "Kämpfer",<br />
        GeschwindigkeitModifikator = 0,<br />
        DrehgeschwindigkeitModifikator = -1,<br />
        LastModifikator = -1,<br />
        ReichweiteModifikator = 1,<br />
        SichtweiteModifikator = 0,<br />
        EnergieModifikator = 1,<br />
        AngriffModifikator = 0<br />
    )]</p>
<p>    public class Sammler : Ameise<br />
    {<br />
        int LetzteNahrung = 0;<br />
        Zucker LetzterZucker=null;<br />
        ///<br />
<summary>
        /// Gibt dem Spieler die Möglichkeit, eigene Variablen zu initialisieren.<br />
        /// Wird vor jedem Spiel aufgerufen. Statische Variablen müssen hier<br />
        /// initialisiert werden!<br />
        /// </summary>
<p>        public static void Initialisiere()<br />
        {<br />
        }</p>
<p>        ///<br />
<summary>
        /// Bestimmt den Typ einer neu zu erzeugenden Ameise.<br />
        /// </summary>
<p>        ///
<param name="anzahl">Anzahl der vorhandenen Ameisen pro Typ</param>
        /// <returns>Name des Typs</returns><br />
        public static string BestimmeTyp(Dictionary<string, int> anzahl)<br />
        {<br />
            //if (anzahl["Sammler"] < 60)<br />
            //    return "Sammler";<br />
            //else<br />
            //    return "Kämpfer";<br />
            if (anzahl["Sammler"] == 0)<br />
            {<br />
                return "Sammler";<br />
            }<br />
            else<br />
            {<br />
                // Sollte das Verhältnis Kämpfer/Sammler über 1 steigen (also mehr Kämpfer als Sammler) werden Sammler<br />
                // produziert, ansonsten Kämpfer<br />
                return ((float)anzahl["Kämpfer"] / (float)anzahl["Sammler"] > 1.0f ? &#8220;Sammler&#8221; : &#8220;Kämpfer&#8221;);<br />
            }<br />
        }</p>
<p>        ///<br />
<summary>
        /// Der Ameise Konstruktor.<br />
        /// </summary>
<p>        ///
<param name="volk">Das Volk zu dem die neue Ameise gehört</param>
        ///
<param name="typIndex">Der Typ der neuen Ameise</param>
        public Sammler(Volk volk, int typIndex)<br />
            : base(volk, typIndex)<br />
        {<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise nicht weiss wo sie hingehen soll.<br />
        /// </summary>
<p>        public override void Wartet()<br />
        {<br />
            // Sollte die Ameise außerhalb des Nahrungsmittelradiuses liegen<br />
            if (!(this.Ziel is Bau))<br />
            {<br />
                if (this.EntfernungZuBau > 400)<br />
                {<br />
                    // &#8230;soll sie wieder heim gehen<br />
                    GeheZuBau();<br />
                }<br />
                else<br />
                {<br />
                    // &#8230;ansonsten soll sie sich ein bischen drehen (zufälliger Winkel zwischen -20 und 20 Grad)<br />
                    // und wieder ein paar Schritte laufen<br />
                    DreheUmWinkel(Zufall.Zahl(-20, 20));<br />
                    GeheGeradeaus(20);<br />
                }<br />
            }</p>
<p>            // Wenn die restliche verfügbare Strecke der Ameise (minus einem Puffer von 50 Schritten)<br />
            // kleiner als die Entfernung zum Bau ist&#8230;<br />
            if (this.Reichweite &#8211; this.ZurückgelegteStrecke &#8211; 50 < this.EntfernungZuBau)<br />
            {<br />
                // ...soll sie nach Hause gehen um nicht zu sterben<br />
                GeheZuBau();<br />
            }<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird einmal aufgerufen, sobald die Ameise ein Drittel ihrer maximalen<br />
        /// Reichweite überschritten hat.<br />
        /// </summary>
<p>        public override void WirdMüde()<br />
        {<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise einen Zuckerhaufen sieht.<br />
        /// </summary>
<p>        ///
<param name="zucker">Zuckerhaufen</param>
        public override void Sieht(Zucker zucker)<br />
        {<br />
            //Egal welcher Typ &#8211; Markierung sprühen<br />
            int entfernung, richtung;<br />
            entfernung = Koordinate.BestimmeEntfernung(this, zucker);<br />
            richtung = Koordinate.BestimmeRichtung(this, zucker);<br />
            SprüheMarkierung(2, entfernung);</p>
<p>            //Nur Sammler sollen weiteres tun</p>
<p>            if ((AktuelleLast == 0)&#038;&#038;(this.Typ == &#8220;Sammler&#8221;))<br />
            {<br />
                GeheZuZiel(zucker);<br />
            }<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise ein Stück Obst sieht.<br />
        /// </summary>
<p>        ///
<param name="obst">Obst</param>
        public override void Sieht(Obst obst)<br />
        {<br />
            //Jedes Vieh soll sprühen<br />
            int entfernung, richtung;<br />
            entfernung = Koordinate.BestimmeEntfernung(this, obst);<br />
            richtung = Koordinate.BestimmeRichtung(this, obst);<br />
            SprüheMarkierung(1, entfernung);</p>
<p>            if ((AktuelleLast == 0) &#038;&#038; (BrauchtNochTräger(obst))&#038;&#038;(this.Typ == &#8220;Sammler&#8221;))<br />
            {<br />
                GeheZuZiel(obst);<br />
            }<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise einen Käfer sieht.<br />
        /// </summary>
<p>        ///
<param name="käfer">Käfer</param>
        public override void Sieht(Käfer käfer)<br />
        {<br />
            int entfernung, richtung;<br />
            entfernung = Koordinate.BestimmeEntfernung(this, käfer);<br />
            richtung = Koordinate.BestimmeRichtung(this, käfer);<br />
            SprüheMarkierung(3, entfernung);</p>
<p>            if (this.Typ == &#8220;Kämpfer&#8221;)<br />
            {<br />
                if (this.AktuelleLast == 0)<br />
                {<br />
                    if (this.AnzahlInSichtweite > 5)<br />
                    {<br />
                        GreifeAn(käfer);<br />
                    }<br />
                }<br />
            }<br />
            else if (this.Typ == &#8220;Sammler&#8221;)<br />
            {<br />
                if (this.AnzahlInSichtweite > 5)<br />
                {<br />
                    GreifeAn(käfer);<br />
                }<br />
            }<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise eine Markierung sieht.<br />
        /// </summary>
<p>        ///
<param name="markierung">Markierung</param>
        public override void Sieht(Markierung markierung)<br />
        {<br />
            if (Ziel == null)<br />
            {<br />
                if (this.Typ == &#8220;Kämpfer&#8221;)<br />
                {<br />
                    //es ist ein Käfer<br />
                    if (markierung.Information == 3)<br />
                    {<br />
                        if (this.AnzahlInSichtweite > 5)<br />
                        {<br />
                            DreheInRichtung(Koordinate.BestimmeRichtung(this, markierung));<br />
                            GeheGeradeaus();<br />
                        }<br />
                    }<br />
                }<br />
                else if (this.Typ == &#8220;Sammler&#8221;)<br />
                {<br />
                    //es ist Obst<br />
                    if (markierung.Information == 1)<br />
                    {<br />
                        DreheInRichtung(Koordinate.BestimmeRichtung(this, markierung));<br />
                        GeheGeradeaus();<br />
                    }<br />
                    else if (markierung.Information == 2) //Zucker<br />
                    {<br />
                        DreheInRichtung(Koordinate.BestimmeRichtung(this, markierung));<br />
                        GeheGeradeaus();<br />
                    }<br />
                    else if (markierung.Information == 3)<br />
                    {<br />
                        if (this.AnzahlInSichtweite > 6)<br />
                        {<br />
                            if (this.AktuelleLast == 0)<br />
                            {<br />
                                DreheInRichtung(Koordinate.BestimmeRichtung(this, markierung));<br />
                                GeheGeradeaus();<br />
                            }<br />
                        }<br />
                    }<br />
                }<br />
            }<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise von einem Käfer angegriffen wird.<br />
        /// </summary>
<p>        ///
<param name="käfer">Käfer</param>
        public override void WirdAngegriffen(Käfer käfer)<br />
        {<br />
            if (this.Typ == &#8220;Krieger&#8221;)<br />
            {<br />
                GreifeAn(käfer);<br />
            }<br />
            else if (this.Typ == &#8220;Sammler&#8221;) // Sammler ergreifen die Flucht<br />
            {<br />
                if (this.GetragenesObst != null)<br />
                {<br />
                    LasseNahrungFallen();<br />
                }<br />
                GeheZuBau();<br />
            }<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise bei einem Zuckerhaufen ankommt.<br />
        /// </summary>
<p>        ///
<param name="zucker">Zuckerhaufen</param>
        public override void ZielErreicht(Zucker zucker)<br />
        {<br />
            int entfernung, richtung;<br />
            entfernung = Koordinate.BestimmeEntfernung(this, zucker);<br />
            richtung = Koordinate.BestimmeRichtung(this, zucker);<br />
            SprüheMarkierung(2, entfernung);</p>
<p>            Nimm(zucker);<br />
            LetzterZucker = zucker;</p>
<p>            GeheZuBau();<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise bei einem Stück Obst ankommt.<br />
        /// </summary>
<p>        ///
<param name="obst">Obst</param>
        public override void ZielErreicht(Obst obst)<br />
        {<br />
            int entfernung, richtung;<br />
            entfernung = Koordinate.BestimmeEntfernung(this, obst);<br />
            richtung = Koordinate.BestimmeRichtung(this, obst);<br />
            SprüheMarkierung(1, entfernung);</p>
<p>            if (BrauchtNochTräger(obst))<br />
            {<br />
                Nimm(obst);</p>
<p>                GeheZuBau();<br />
            }<br />
            else<br />
            {<br />
                GeheGeradeaus(5);<br />
            }<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird aufgerufen, wenn die Ameise gestorben ist.<br />
        /// </summary>
<p>        ///
<param name="todesArt">Die Todesart der Ameise</param>
        public override void IstGestorben(TodesArt todesArt)<br />
        {<br />
            System.Diagnostics.Debug.WriteLine(todesArt.ToString());<br />
        }</p>
<p>        ///<br />
<summary>
        /// Wird in jeder Runde aufgerufen.<br />
        /// </summary>
<p>        public override void Tick()<br />
        {<br />
            if (Ziel is Bau &#038;&#038; AktuelleLast > 0 &#038;&#038; GetragenesObst == null)<br />
                SprüheMarkierung(Richtung + 180,20);<br />
            if (Ziel == null)<br />
            {<br />
                if (LetzterZucker != null)<br />
                {<br />
                    if (LetzterZucker.Menge > 10)<br />
                    {<br />
                        GeheZuZiel(LetzterZucker);<br />
                    }<br />
                }<br />
            }<br />
            else if (Ziel is Käfer &#038;&#038; this.AnzahlInSichtweite < 4)<br />
            {<br />
                this.BleibStehen();<br />
            }<br />
        }</p>
<p>    }</p>
<p>}<br />
[/source]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.keentech.de/blog/2007/04/antme-die-ameisensimulation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Animation-Klasse</title>
		<link>http://www.keentech.de/blog/2007/04/animation-klasse/</link>
		<comments>http://www.keentech.de/blog/2007/04/animation-klasse/#comments</comments>
		<pubDate>Sun, 15 Apr 2007 20:40:52 +0000</pubDate>
		<dc:creator>FireFox</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.keentech.de/blog/?p=11</guid>
		<description><![CDATA[Die Animation-Klasse von beta.unclassified.de zeigt ein Anwendungsszenario für die in einem früheren Eintrag angesprochene DelayedCall Klasse. Mit ihr können Controls als auch Forms animiert werden, ohne das ständige Neuzeichnen bei Resize-Operationen im Hintergrund hervorzurufen.

Beispiel:
Ein Form wird in seiner Größe geändert. Im ResizeEnd-Event wird die gewünschte Animation der beinhaltenden Controls aufgerufen.
Die Controls werden über die Animation-Klasse  <a href="http://www.keentech.de/blog/2007/04/animation-klasse/" class="more-link">Mehr &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Die Animation-Klasse von <a target="_blank" href="http://beta.unclassified.de/code/dotnet/animation/">beta.unclassified.de</a> zeigt ein Anwendungsszenario für die in einem früheren Eintrag angesprochene DelayedCall Klasse. Mit ihr können Controls als auch Forms animiert werden, ohne das ständige Neuzeichnen bei Resize-Operationen im Hintergrund hervorzurufen.</p>
<p><span id="more-11"></span></p>
<p>Beispiel:<br />
Ein Form wird in seiner Größe geändert. Im ResizeEnd-Event wird die gewünschte Animation der beinhaltenden Controls aufgerufen.<br />
Die Controls werden über die Animation-Klasse und der DelayedCall auf die jeweils übergebenen Größenänderungen angepasst, so daß eine sanfte Animation erfolgt.</p>
<p>Ein Beispiel sei hier kurz vermerkt, wie die Animation-Klasse angewendet werden kann. <em>ucT</em> ist in diesem Fall ein Control (in meiner Testapplikation ein UserControl mit einigen eingebetteten Controls, wie Buttons, Textbox usw). Für die vertikale Animation wird der Animation-Klasse den Parametern <em>ResizeVert</em>, dem Control (welches animiert werden soll), die letztendliche zu erreichende Höhe, eine Methode die nach Abschluß aufgerufen werden soll und die Dauer der Animation, aufgerufen.</p>
<p>[source:csharp]<br />
private void TestForm_ResizeEnd(object sender, EventArgs e)<br />
{<br />
    new KeenTech.UI.Animation(KeenTech.UI.AnimationTypes.ResizeVert, this.ucT,<br />
    this.ClientSize.Height &#8211; ucT.Height, new KeenTech.UI.AnimationFinishedHandler(Test), 350);<br />
    new KeenTech.UI.Animation(KeenTech.UI.AnimationTypes.ResizeHoriz, this.ucT,<br />
    this.ClientSize.Width &#8211; ucT.Width, new KeenTech.UI.AnimationFinishedHandler(Test), 350);<br />
}<br />
[/source]</p>
<p>Die Animation-Klasse sieht wie folgt aus (Namespace wurde an eigene Begebenheiten angepasst):</p>
<p>[source:csharp]<br />
using System;<br />
using System.Windows.Forms;<br />
using System.Drawing;</p>
<p>// Benötigt die Klasse DelayedCall<br />
//<br />
// Anwendung:<br />
//<br />
// Ausblenden und anschließendes Schließen des Fensters:<br />
// (Close ist Methode des Fensters this)<br />
//<br />
// new Animation(AnimationTypes.FadeOut, this, 0, Close);<br />
//<br />
// Sanftes Ändern der Höhe des Fensters auf 500 Pixel:<br />
// (SomeTaskWhenResized ist die aufzurufende Funktion nach Abschluss der Größenänderung)<br />
//<br />
// new Animation(AnimationTypes.ResizeVert, this, 500 &#8211; Height, SomeTaskWhenResized);<br />
//<br />
// .NET-Kompatibilität: 2.0<br />
//<br />
// Hinweise für .NET 1.1: Als EventHandler muss ein &#8216;new delegate&#8230;&#8217; übergeben werden,<br />
// der Funktionsname allein ist eine Abkürzung, die seit .NET 2.0 möglich ist.</p>
<p>namespace KeenTech.UI<br />
{<br />
    public enum AnimationTypes<br />
    {<br />
        None,<br />
        ResizeHoriz,<br />
        ResizeVert,<br />
        FadeIn,<br />
        FadeOut<br />
    }</p>
<p>    public delegate void AnimationFinishedHandler();</p>
<p>    public class Animation<br />
    {<br />
        AnimationTypes type;<br />
        object target;<br />
        int offset;<br />
        AnimationFinishedHandler handler;<br />
        int start;<br />
        int end;<br />
        int interval;<br />
        int duration;<br />
        int timePassed;<br />
        bool cancellationPending = false;</p>
<p>        public Animation(AnimationTypes type, object target, int offset, AnimationFinishedHandler handler)<br />
        : this(type, target, offset, handler, 0)<br />
        {<br />
        }</p>
<p>        public Animation(AnimationTypes type, object target, int offset, AnimationFinishedHandler handler, int duration)<br />
        {<br />
            this.type = type;<br />
            this.target = target;<br />
            this.offset = offset;<br />
            this.handler = handler;<br />
            this.duration = duration;</p>
<p>            // timings in ms<br />
            interval = 10;<br />
            timePassed = 0;</p>
<p>            Control c;<br />
            Form f;<br />
            switch (type)<br />
            {<br />
                case AnimationTypes.ResizeHoriz:<br />
                    c = target as Control;<br />
                    if (c == null)<br />
                        return;<br />
                    start = c.Width;<br />
                    end = start + offset;<br />
                    if (this.duration == 0)<br />
                        this.duration = 150;<br />
                break;<br />
                case AnimationTypes.ResizeVert:<br />
                    c = target as Control;<br />
                    if (c == null)<br />
                        return;<br />
                    start = c.Height;<br />
                    end = start + offset;<br />
                    if (this.duration == 0)<br />
                        this.duration = 150;<br />
                break;<br />
                case AnimationTypes.FadeIn:<br />
                    f = target as Form;<br />
                    if (f == null)<br />
                        return;<br />
                    start = (int)(f.Opacity * 100);<br />
                    end = start + offset;<br />
                    if (this.duration == 0)<br />
                        this.duration = 250;<br />
                break;<br />
                case AnimationTypes.FadeOut:<br />
                    f = target as Form;<br />
                    if (f == null)<br />
                        return;<br />
                    start = (int)(f.Opacity * 100);<br />
                    end = start + offset;<br />
                    if (this.duration == 0)<br />
                        this.duration = 2000;<br />
                break;<br />
                default:<br />
                return;<br />
            }</p>
<p>            Next();<br />
        }</p>
<p>        public void Cancel()<br />
        {<br />
            cancellationPending = true;<br />
        }</p>
<p>        private double MakeCurve()<br />
        {<br />
            double timePercent = (double)timePassed / (double)duration;</p>
<p>            // we use the sine function from 3pi/2 to 5pi/2<br />
            // scale down linear time percentage from 0&#8230;1 to 3pi/2 to 5pi/2<br />
            double curve = Math.Sin(1.5 * Math.PI + timePercent * Math.PI);<br />
            // translate sine output from -1&#8230;1 to 0&#8230;1<br />
            curve = (curve + 1) / 2;<br />
            // DEBUG: don&#8217;t use curve but linear progress instead<br />
            //curve = timePercent;</p>
<p>            return curve;<br />
        }</p>
<p>        public void Next()<br />
        {<br />
            if (cancellationPending)<br />
                return; // and don&#8217;t come back</p>
<p>            timePassed += interval;<br />
            if (timePassed &gt; duration)<br />
            {<br />
                if (handler != null)<br />
                    handler();<br />
                return;<br />
            }</p>
<p>            Control c;<br />
            Form f;<br />
            Rectangle wa;<br />
            switch (type)<br />
            {<br />
                case AnimationTypes.ResizeVert:<br />
                    c = target as Control;<br />
                    c.Height = start + (int)((end &#8211; start) * MakeCurve());<br />
                    wa = Screen.FromControl(c).WorkingArea;<br />
                    if (c is Form &amp;&amp; c.Bottom &gt; wa.Bottom)<br />
                    {<br />
                        c.Top -= c.Bottom &#8211; wa.Bottom;<br />
                        if (c.Top &lt; wa.Top)<br />
                        {<br />
                            c.Top = wa.Top;<br />
                        }<br />
                    }<br />
                break;<br />
                case AnimationTypes.ResizeHoriz:<br />
                    c = target as Control;<br />
                    c.Width = start + (int)((end &#8211; start) * MakeCurve());<br />
                    wa = Screen.FromControl(c).WorkingArea;<br />
                    if (c is Form &amp;&amp; c.Right &gt; wa.Right)<br />
                    {<br />
                        c.Left -= c.Right &#8211; wa.Right;<br />
                        if (c.Left &lt; wa.Left)<br />
                        {<br />
                            c.Left = wa.Left;<br />
                        }<br />
                    }<br />
                break;<br />
                case AnimationTypes.FadeIn:<br />
                    f = target as Form;<br />
                    f.Opacity = (double)(start + ((end &#8211; start) * MakeCurve())) / 100;<br />
                break;<br />
                case AnimationTypes.FadeOut:<br />
                    f = target as Form;<br />
                    f.Opacity = (double)(start + ((end &#8211; start) * MakeCurve())) / 100;<br />
                break;<br />
            }</p>
<p>            new DelayedCall(new DelayedCall.Function(this.Next), interval);<br />
        }<br />
    }<br />
}</p>
<p>[/source]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.keentech.de/blog/2007/04/animation-klasse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
