Bei der Portierung von C Quelltext ist man manchmal am überlegen wie man eine bestimmte Stelle wohl syntaktisch nach C# bringt. Möchte man eine automatische prototypische Quelltextkonvertierung für solche Sachen so sollte man sich mal die Webseite http://code2code.net/ anschauen.
Dort kann man C Quellcode eingeben und bekommt ihn in C# oder Visual Basic.NET zurück. Je nach Eingabedaten kann die Konvertierung dabei allerdings unterschiedlichster Qualität sein. Um das Nachdenken kommt man also nicht herum
Ich betreibe einen Minecraft Server und ab und an kommt es vor das man ein paar neue Dinge zur Welt hinzufügt. Manchmal kommt es dabei zu unschönen Fehlern, welche z.B. die Bedrockschicht beschädigen. Da ich nun natürlich nicht alles von Hand nachbessern möchte habe ich ein kleines Tool geschrieben. Dieses hört dabei auf den Namen „Minecraft maintenance tool“ und ist unter http://mcmt.googlecode.com zu finden. Das Tool steht dabei unter GPLv3 Lizenz und sollte unter Linux und Windows laufen.
Mit dem Tool sind im Moment folgende Dinge möglich:
- Entfernen von Entities
- Ersetzen von Blöcken
- Erzeugen einer flachen Welt
- Neuberechnung der Beleuchtung
- Reparieren der Bedrockschicht
Wenn jemand Ideen hat was es noch alles können soll, kann diese in den Kommentaren loswerden. Das Tool selbst setzt auf der Substrate Bibliothek (unter MIT Lizenz) auf welche unter http://substrate-minecraft.googlecode.com zu finden ist.
Weitere Informationen gibt es unter:
http://de.wikipedia.org/wiki/Minecraft
http://www.minecraftforum.net/topic/245996-sdk-substrate-map-editing-library-for-cnet-103/
Manchmal kann einen die Softwareentwicklung schon in den Wahnsinn treiben, vor allem wenn es um triviale Dinge geht. So sollte es ja eigentlich selbstverständlich sein, das der Debugger an einem Haltepunkt hält. Mein erster Gedanke war, das es daran liegt das ich das Projekt im Debugmodus auf „Any CPU“ eingestellt habe. Sobald ich es auf „x86“ oder „x64“ gestellt habe, hielt der Debugger an der gewünschten Stelle. Allerdings hatte ich ein ähnliches Projekt mit fast den selben Einstellungen (auch „Any CPU“), doch dort funktionierte es mit dem Debugger. Also sollte es ein Vergleich der Projektdateien richten. Nach einiger Zeit war hier auch kein Erfolg zu melden.
Beim Starten des Projektes fiel mir allerdings auf das die Haltepunkte ausgeblendet wurden:
Im Tooltip zu den Haltepunkten stand dann:
No symbols have been loaded for this document
Dies brachte mich dazu in das „bin/Debug“ Verzeichnis zu schauen und siehe da, es gab keine pdb Dateien für das Projekt. Um die pdb Dateien für das Projekt anzulegen, geht man in die Projekteinstellungen, dort auf „Build“ und dann auf „Advanced“.
In dem sich darauf öffnenden Dialog stellt man die „Debug info“ auf „full“. Damit sollten die PDB Dateien erzeugt werden und das debuggen wieder funktionieren.
Weitere Informationen gibt es unter:
http://en.wikipedia.org/wiki/Program_database
http://msdn.microsoft.com/en-us/library/yd4f8bd1%28v=vs.71%29.aspx
http://geekswithblogs.net/dbutscher/archive/2007/06/26/113472.aspx
http://www.wintellect.com/CS/blogs/jrobbins/archive/2009/05/11/pdb-files-what-every-developer-must-know.aspx
Wenn man in MonoDevelop eine GTK# Anwendung schreibt und sie zwingt auf „jeder CPU“ zu laufen so wird diese Anwendung beim Start abstürzten. Meist sieht das dann so aus:
Unbehandelte Ausnahme: System.TypeInitializationException: Der Typeninitialisierer für "Gtk.Application" hat eine Ausnahme verursacht. System.BadImageFormatException: Es wurde versucht, eine Datei mit einem falschen Format zu laden. (Ausnahme von HRESULT: 0x8007000B) bei GLib.Thread.glibsharp_g_thread_supported() bei GLib.Thread.get_Supported() bei Gtk.Application..cctor() --- Ende der internen Ausnahmestapelüberwachung --- bei Gtk.Application.Init() bei testapp.MainClass.Main(String[] args) in d:\testapp\Main.cs:Zeile 10.
Das Problem ist wohl das es noch keine x64 GTK# Bibliothek für Windows gibt. Aus diesem Grund sollte man seine Assemblys auf x86 stellen, dann klappt es auch mit Windows 7.
Weitere Informationen gibt es unter:
http://mono.1490590.n4.nabble.com/windows-7-x64-and-gtk-app-td1516626.html
Auf Sourceforge gibt es das Projekt Midi Sheet Music (http://sourceforge.net/projects/midisheetmusic/, http://midisheetmusic.sourceforge.net/). Dabei handelt es sich um eine Software in welche man eine MIDI Datei einladen kann und anschließend eine Notenansicht bekommt. Beim Abspielen zeigt die Software dann an welche Tasten(kombinationen) für welche Noten gespielt werden müssen. Die Software läuft dabei auf Windows, Linux und MacOS, ist in C# geschrieben und steht unter der GPL.
Weitere Informationen gibt es unter:
http://de.wikipedia.org/wiki/MIDI
Man nehme folgendes Stück C# Quelltext:
HashSet test=new HashSet();
Das Problem an einem solchen HashSet ist, das man nicht mittels eines Indicies auf dieses zugreifen können. Die Zeile:
string tmp=test[5];
würde also nicht funktionieren. Abhilfe schafft hier die Klasse SortedSet:
SortedSettest=new SortedSet();
Nun kann man mittels ElementAt über einen Indice selektiert werden:
string tmp=test.ElementAt(5);
Wichtig ist dabei das der Namesspace System.Linq eingebunden ist da diese Funktionalität über eine Extension implementiert wird.
Für ein Windows Forms Menü wollte ich einen Shortcut key (für die MFC kundigen auch Accelerator genannt) setzen. Das funktioniert im Normalfall auch immer ohne Probleme. Nur bei den Tasten Keys.NumPad0 - Keys.NumPad9 funktioniert das nicht.
Auch eine manuelle Zuweisung:
topToolStripMenuItem.ShortcutKeys = Keys.NumPad5;
schlägt mit einer Exception fehl. Der Trick hier ist es die nummerischen Tasten des Numpad immer mit Strg oder Alt zu benutzen. So ist es ohne Probleme möglich dem Menüpunkt den Shortcut key Alt + Numpad 5 zuzuweisen. Ich tippe mal das hängt bei diesen Tasten mit der Doppelbelegung (Num aus/an) zusammen.
Der freie Passwortmanager KeePass ist vor kurzem in der neuen Version 2.16 erschienen. Im Gegensatz zu 1er Serie ist die 2er Serie komplett neugeschrieben worden und basiert auf .NET bzw. Mono. Sie läuft somit ohne Probleme auch unter Linux. Damit kann der Manager auch plattformübergreifend eingesetzt werden. Die Software steht dabei unter GPLv2 und kann unter http://keepass.info/download.html bezogen werden.
Es gibt unter http://code.google.com/p/lib3ds/ ein Google Code Projekt welches eine Bibliothek zum lesen und schreiben von 3DS implementiert. Leider gab es bis vor kurzem keine freie 3DS Bibliothek für .NET respektive Mono. Nun gibt es unter http://code.google.com/p/lib3dsnet/ eine Portierung der lib3ds, welche wie das Original unter LGPL steht.
Die Bibliothek unterstützt dabei nicht nur das lesen und schreiben, sondern auch alle möglichen Arten von 3DS Nodes wie Kameras oder Meshes. Auch die Transformation der Objekte zueinander wird in dieser Bibliothek vorgenommen. In Grenzen kommt lib3ds.Net auch mit defekten 3DS Dateien zurecht. Nach den ersten Tests funktioniert die Bibliothek tadellos
Weitere Informationen gibt es unter:
http://en.wikipedia.org/wiki/.3ds
Unter .NET bzw. Windows Forms gibt es für das Abfragen von Tasten die Events KeyDown, KeyUp und KeyPress, welche am Formular hängen bzw. an den Controls. In meinem Fall hängen sie an einem Formular bei welchem die KeyPreview Eigenschaft auf true gesetzt ist.
Mit diesen Events kann man problemlos fast alle Tasten abfangen. Problematisch wird es aber bei den Cursortasten. Hier bekomme ich nur ein KeyUp Event. Nun gibt es eine Möglichkeit diese Tasten trotzdem abzufragen in dem die Funktion ProcessCmdKey überladen wird:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
bool shift=(keyData&Keys.Shift)!=0;
bool control=(keyData&Keys.Control)!=0;
bool alt=(keyData&Keys.Alt)!=0;
Keys unmodifiedKey=(keyData&Keys.KeyCode);
if(unmodifiedKey==Keys.Up) DoFoobar(unmodifiedKey);
return base.ProcessCmdKey(ref msg, keyData);
}
Allerdings funktionierte diese Methode nicht wie gewünscht. Eine andere Methode ist die Überladung der Funktion IsInputKey. Dort wird dann festgelegt das die Cursortasten wie normale Eingabetasten behandelt werden. Allerdings brachte es nichts, diese Funktion im Hauptformular zu überladen, da sie dort nie erreicht wurde. Deshalb wurde sie in dem im Formular befindlichen OpenGL Control überladen:
protected override bool IsInputKey(System.Windows.Forms.Keys keyData)
{
if((keyData&Keys.KeyCode)==Keys.Up) return true;
if((keyData&Keys.KeyCode)==Keys.Right) return true;
if((keyData&Keys.KeyCode)==Keys.Left) return true;
if((keyData&Keys.KeyCode)==Keys.Down) return true;
return base.IsInputKey(keyData);
}
Damit kamen die Events für die Cursortasten ganz normal bei den entsprechenden Events des Hauptformulares an.
Weitere Informationen gibt es unter:
http://stackoverflow.com/questions/2434834/processcmdkey-wait-for-keyup
http://familie-ottenhaus.de/simon/blog/2009/12/csharp-eigenes-control-keys-up-down-left-right-onkeydown-onkeypress-vs-processcmdkey/
Wer mal schnell die Syntax einer Visual Basic Anwendung nach C# bringen möchte, der sollte sich mal die Code Converter anschauen welche von developerFusion unter http://www.developerfusion.com/tools/ angeboten wird. Dort kann man den Code direkt auf der Webseite eingeben und bekommt dann die „Übersetzung“ des selben.
Ein Singleton ist grob gesagt eine Klasse welche nur einmal initialisiert werden kann. Dies ist ganz praktisch für globale Objekte wie z.B. einen ID Generator, der nur einmal existieren darf. Doch wie schreibt man ein solches Singleton? Laut MSDN-Mag sieht das ganze so aus:
sealed class Singleton
{
private Singleton() {}
public static readonly Singleton Instance = new Singleton() ;
}
Diese Klasse kann man nun über Singleton.Instance aufrufen. Sie wird dabei bei der ersten Benutzung initialisiert. Da der Konstruktor private ist, kann sie von keiner anderen Klasse initialisiert werden. So wird dafür gesorgt das es nur eine Instanz gibt.
Weitere Informationen gibt es unter:
http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)
Ich nutze bei der Entwicklung ein sehr hilfreiches Tool namens Resource Refactoring Tool. Normalerweise taucht dieses im Menü Refactor als Extract to Resource auf. Bei mir ist es allerdings einfach verschwunden. Hier hilft es das Addin zu resetten. Dazu geht man in den Ordner C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE und öffnet dort eine Kommandozeile. In diese gibt man dann
devenv.exe /resetaddin Microsoft.VSPowerToys.ResourceRefactor.Connect
ein und schon ist das Problem gelöst
Weitere Informationen gibt es unter:
http://seeseekey.net/blog/1038
Die Übersetzung von .NET Programmen gestaltet sich doch recht schwierig. Wobei schwierig in diesem Fall das falsche Wort ist. Umständlich trifft es in diesem Fall besser. Vor allem wenn als Entwickler das Qt Übersetzungssystem mit Qt Linguist kennenlernen dürfte. Ein Problem bei der Übersetzung ist, dass man zu jedem Programm mehrere Ressourcen (resx) Dateien in den unterschiedlichsten Sprachen hat z.B. translate.resx, translate.de.resx und translate.nl.resx.
An dieser Stelle ist ein Tool wünschenswert welches diese ganzen Dateien nebeneinander darstellt und einigen Komfort bei der Bearbeitung bietet. Basierend auf dem Resx Resource Translator (http://resxtranslator.codeplex.com) von Hakan Lindestaf habe ich dabei ein Tool namens Vertimas (litauisch für Übersetzung) geschaffen welches einem diesem Arbeit leichter von der Hand gehen lässt.
Vertimas ist dabei ein Open Source Projekt welches unter der GPL steht. Die offizielle Projektseite ist dabei unter vertimas.googlecode.com zu finden. Über Feedback, Verbesserungen und Kritik freue ich mich
Manchmal sucht man den Fehler an der falschen Stelle, wie ich gestern bei einem Quelltext feststellen dürfte welcher auf .NET und Mono laufen sollte. Man nehme folgenden C# Code:
Bitmap bmp=new Bitmap((int)width, (int)height, PixelFormat.Format32bppArgb);
BitmapData data=bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(intern.imageData, 0, data.Scan0, (int)(width*height*4));
bmp.UnlockBits(data);
data=null;
return bmp;
Dieser Code kopiert Daten in ein Bitmap. Unter .NET funktioniert dies tadellos. Also lag der Gedanke nah das dies ein Mono Problem ist. Nach etlichen Tests ergab sich dann aber das es genau umgekehrt ist. Es liegt an der Zeile:
BitmapData data=bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
und zwar speziell an dem ImageLockMode.ReadOnly. Dort könnte z.B. ImageLockMode.ReadWrite stehen und schon würde es unter .NET und Mono funktionieren. Doch warum geht es nun bei .NET trotzdem mit der falschen Variante? Die .NET API reicht die Parameter korrekt an die GDI+ weiter, diese ignoriert sie aber. Aus diesem Grund funktionierte es unter .NET. Sprich Mono hat alles richtig gemacht

