Martin Lantzsch
Software Entwickler
26. Oktober 2013

C# WPF AbstractWindow

26. Oktober 2013 - Geschrieben von Martin - Keine Kommentare

Normalerweise erbt die Klasse eines neu erzeugten Fensters (in diesem Fall MainWindow) direkt von System.Windows.Window. Bei meiner Anwendung wollte ich allerdings, dass das Hauptfenster von meiner Klasse ResiWriter.UI.AbstractWindow erbt.

namespace ResiWriter.UI
{
    public abstract class AbstractWindow : System.Windows.Window
    {
 
    }
}

In der MainWindow.xaml.cs Klasse habe ich dann wie gewohnt von der AbstractWindow geerbt:

namespace ResiWriter
{
    public partial class MainWindow : UI.AbstractWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Durch den Umstand, dass MainWindow eine partial Klasse ist, muss nun auch der zweite zugehörige Klassenteil vom AbstractWindow erben. Problematisch an der Sache ist jedoch, dass der zweite Teil der Klasse beim kompilieren aus dem XAML erzeugt wird. Dementsprechend muss dieses XAML angepasst werden um dem Compiler mitzuteilen von welcher Klasse geerbt werden soll.

<src:AbstractWindow x:Class="ResiWriter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:src="clr-namespace:ResiWriter.UI"
        Title="ResiWriter" Height="480" Width="800">
        <Grid></Grid>
</src:AbstractWindow>

Wichtig ist hier, dass der Knoten Window durch src:AbstractWindow getauscht wird. Damit der Compiler auch weiß aus welchem Namespace AbstractWindow stammt wird zusätzlich das Attribut src eingefügt: xmlns:src=“clr-namespace:ResiWriter.UI“

9. Juli 2013

EntityFramework Code First POCO Schnelleinstieg

9. Juli 2013 - Geschrieben von Martin - Keine Kommentare

1. per NuGet das Entity Framework Paket nachinstallieren
EntityFramework NuGet

2. Datenquelle (Connectionstring) in der App.config hinterlegen

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- schnipp -->
  <connectionStrings>
    <add name="UserDatabase"
         providerName="System.Data.SqlServerCe.4.0"
         connectionString="Data Source=User.sdf"/>
  </connectionStrings>
</configuration>

3. Model erstellen

class User
{
    public int Id { get; set; }
    public String Firstname { get; set; }
    public String Lastname { get; set; }
}

4. Context erstellen

class UserContext : DbContext
{
    public UserContext() : base("UserDatabase")
    {}
 
    public DbSet<User> Users { get; set; }
}

5. Verwendung des Contextes zum erstellen eines Datensatzes

using (var context = new UserContext())
{
    User user = new User { Firstname = "Martin", Lastname = "Linux" };
    context.Users.Add(user);
    context.SaveChanges();
    Console.WriteLine(user.Firstname);
    Console.ReadLine();
}

EntityFramework Ausgabe

6. Daten einsehen über den Server Explorer

  • Server Explorer über Ansicht – Server-Explorer öffnen
  • Rechtsklick auf Datenverbindungen dann Verbindung hinzufügen
  • Datenbankdatei aus dem Projektbinverzeichnis wählen

EntityFramework Verbindung hinzufügen
EntityFramework Server Explorer

23. Januar 2013

Die DLL „SQLite.Interop.dll“: Das angegebene Modul wurde nicht gefunden.

23. Januar 2013 - Geschrieben von Martin - Keine Kommentare

Ich habe eine C# Projekt Mappe mit einer WPF Anwendung und einer Konsolen Anwendung. Die WPF Anwendung besitzt alle Klassen, DLLs, etc. Der Konsolen Anwendung habe ich anschließend abhängig von der WPF Anwendung gemacht und die Build Reihenfolge so gestellt, dass die Konsolenanwendung bei erstellen der Projekt Mappe als zweites kompiliert wird.

Beim Debuggen trat dann immer folgender Fehler auf. Allerdings nur beim Debuggen, beim Ausführen der .exe aus dem /bin/Debug Ordner des Projektes gab es keine Probleme.
Die DLL "SQLite.Interop.dll": Das angegebene Modul wurde nicht gefunden.

Ich dachte erst an nicht aufgelöste Abhängigkeiten, also habe ich mir mit dem „Dependency Walker“ die DLL genauer angesehen:
Dependency Walker
Error: Modules with different CPU types were found.
CPU Type, das Problem kommt mir bekannt vor. Also habe ich mein Konsolen Projekt in den Projekteinstellungen von „Zielplattform“ – „Any CPU“ auf „x86“ gestellt und hey, nun startet es. Warum weiß ich leider nicht, ich kann es mir nur so erklären, das er beim kompilieren „Any CPU“ nicht auf die in x86 und x64 DLLs in dem GUI Projekt mappt. Denn das GUI Projekt startet mit „Any CPU“, den selben DLLs und der selben Klasse, die auf die DLLs zugreift.

10. Januar 2013

ResiOS lebt

10. Januar 2013 - Geschrieben von Martin - 2 Kommentare

ResiOS lebt
Eigenen x86 Kernel mit C und Assembler schreiben. Check.

26. Februar 2012

C# Keyboard Delay ändern

26. Februar 2012 - Geschrieben von Martin - Keine Kommentare

Der Keyboard Delay ist die kurze Verzögerung zwischen drücken und halten einer Taste, bis das System akzeptiert das die Taste gehalten wird und das Signal weitergibt.

Das kann zu Problem führen, wenn man wie ich ein Spiel programmieren möchte, welches per halten einer Taste sofort eine Aktion ausführen soll, und nicht erst nach ein paar hundert Millisekunden. Deshalb ändern wir die Property KeyboardDelay auf 0. Leider ist diese via „SystemInformation.KeyboardDelay“ nur Lesbar, deshalb lösen wir das ganze über einen Win32 API Call.

Dazu fügen wir zu unserem Projekt folgendes using hinzu, um DLLs einbinden zu können:

using System.Runtime.InteropServices;

nun gehen wir an den Anfang unserer Klasse und fügen folgendes hinzu um die „user32.dll“ zu laden und als Einstiegspunkt legen wir „SystemParametersInfo“ fest.

[DllImport("user32.dll", EntryPoint = "SystemParametersInfo", SetLastError = true)]

danach binden wir die Methode „SystemParametersInfoSet“ aus der DLL ein:

public static extern bool SystemParametersInfoSet(uint action, int param, int vparam, uint init);

Nun suchen wir uns bei MSDN die IDs der Propertys raus, welche wir ändern wollen. Dann brauchen wir noch „SPIF_SENDCHANGE“ mit der ID 2 um die Änderungen ins Profil schreiben zu können.
Hierzu legen wir uns 2 Konstanten an:

const uint SPI_SETKEYBOARDDELAY = 23;
const uint SPIF_SENDCHANGE = 2;

Jetzt können wir mit folgendem Methodenaufruf den KeyboardDelay ändern:

int newDelay = 0;
SystemParametersInfoSet(SPI_SETKEYBOARDDELAY, newDelay, 0, SPIF_SENDCHANGE);

UND BITTE vergesst nicht vorher den aktuellen Wert mit „SystemInformation.KeyboardDelay“ auszulesen und wegzuspeichern, damit ihr ihn beim schließen des Programms wiederherstellen könnt!

26. Februar 2012

Prüfen ob in einer C# Forms Anwendung zwei Panele kollidieren

26. Februar 2012 - Geschrieben von Martin - 4 Kommentare

Um zu prüfen ob zwei Panele in einer C# Windows Forms Anwendung miteinander kollidieren, habe ich mir eben eine kleine Panel Collider Klasse geschrieben, die anhand der Position sowie Höhe und Breite prüft ob sich zwei Panele berühren.

class panelCollider
{
    public static bool check(Panel one, Panel two)
    {
        if (one.Left == two.Left)
        {
            if (one.Top == two.Top)
            {
                return true;
            }
            else if (one.Top < two.Top)
            {
                if (one.Top + one.Height >= two.Top)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                if (two.Top + two.Height >= one.Top)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        else if (one.Left > two.Left)
        {
            if (two.Left + two.Width >= one.Left)
            {
                if (one.Top == two.Top)
                {
                    return true;
                }
                else if (one.Top < two.Top)
                {
                    if (one.Top + one.Height >= two.Top)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    if (two.Top + two.Height >= one.Top)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            else
            {
                return false;
            }
        }
        else if (one.Left < two.Left)
        {
            if (one.Left + one.Width >= two.Left)
            {
                if (one.Top == two.Top)
                {
                    return true;
                }
                else if (one.Top < two.Top)
                {
                    if (one.Top + one.Height >= two.Top)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    if (two.Top + two.Height >= one.Top)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
}

Soweit ich es in meiner Anwendung testen konnte, funktioniert sie. Sollte doch noch jemandem ein Fehler auffallen, würde ich mich über einen Kommentar freuen.

10. Februar 2012

PDF Viewer mit C# entwickeln

10. Februar 2012 - Geschrieben von Martin - Ein Kommentar

Damit wir das Rad nicht neu erfinden müssen, stellt Adobe mit seinem Acrobat eine DLL bereit, über die man PDF Dokumente direkt in seiner C# Anwendung anzeigen lassen kann. Das ganze greift auf die selbe ActiveX Komponente zurück, wie zum Beispiel die Internet Explorer oder Firefox Erweiterung.

Diese „AcroPDF.dll“ wird folgendermaßen geladen. Im Projektmappen Explorer machen wir einen Recktsklick auf „Verweise“ und wählen „Verweis hinzufügen…“


Dort wählen wir dem „COM“ Tab um das COM Objekt hinzuzufügen

Anschließend klicken wir auf OK und der Verweis wird hinzugefügt (zu finden unter Verweise als „AcroPDFLib“).

Damit es in unserer WinForm eingebettet werden kann, muss es nun noch zur Toolbox hinzugefügt werden. Hierzu machen wir einen Rechtsklick in einem Reiter der Toolbox, in dem wir das Steuerelement haben wollen. Zum Beipsiel „Allgemein“ und wählen „Elemente auswählen…“

Nun wählen wir den Tab „COM-Steuerelemente“ und suchen dort den „Adobe PDF Reader“. Haken setzen und OK klicken.

Nun das neue Steuerelement von der Toolbox in die Form ziehen.

Zum Code fügen wir folgendes using hinzu, um die Acrobat Klasse zu laden:

using AxAcroPDFLib;

Der Einfachkeit halber laden wir beim starten des Programms (also im Konstruktur nach dem Initialisieren der Komponenten) einfach mal eine Beispiel PDF Datei:

public Form1()
{
    InitializeComponent();
    axAcroPDF1.LoadFile("Y:/Ablage/Test.pdf");
}

Damit der Reader auch wieder ordentlich geschlossen wird und nicht nach beenden des Programms noch ewig im Speicher rumdümpelt, erweitern wir den Destruktor:

~ Form1()
{
    axAcroPDF1.Dispose();
}

Das wären die Basics, alles weitere kann man entweder im Acrobat SDK nachschlagen oder IntelliSense bemühen.

3. Dezember 2011

Morse Beeper

3. Dezember 2011 - Geschrieben von Martin - Ein Kommentar

Eben habe ich ein wenig mit der Console.Beep Funktion von C# gespielt und folgendes ist dabei rausgekommen:

Man kann Text ins Feld eingeben, welcher nach einem klick auf „Übersetzten“ in Morse Code übersetzt wird. Alternativ kann über die 3 Knöpfe „Kurz“, „Lang“ und „Pause“ selbst etwas zusammen gemorst werden. Bisher werden nur Buchstaben unterstützt, falls jemand will kann aber gern auch noch Zahlen implementieren.

Hier kann die .exe heruntergeladen werden: MorseBeeper.exe

Aber wie gesagt, nur eine Spielerei von mir, ich übernehme keine Garantie dafür, das der produzierte Morse Code fehlerfrei ist!