BigBasti's Blog About Me & my Digital Lifestyle

10Mrz/100

101 LINQ Beispiele fuer C# Programmierer

Wer Datenbankprogrammierung mit C# betreibt wird früher oder später nicht an LINQ vorbeikommen. Wer sich damit etwas auseinandersetzt wird schnell merken, dass diese Queries schnell recht komplex werden.

Hier bietet Mocrosofts MSDN eine tolle Beispielsammlung an, in der fast alle Anwendungsfälle beschrieben sind. Das ganze findet ihr im MSDN Visual C# Developer Center.

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
7Mrz/100

.NET: Projekte fuer Mobile Geraete koennen auf dem Desktop ausgefuehrt werden

Ich denke, dass viele von euch es schon längst gewusst haben, aber heute habe ich zufällig entdeckt, dass man die Projekte, die für Smartphones mit Windows Mobile programmiert wurden direkt auf dem Desktop ausführen kann.

Dabei bedarf es keinerlei Anpassung oder Modifikation des Codes. Einfach doppelklicken und ab geht's!

mobileApp_thumb
Bild 1: Das selbe Programm auf beiden Plattformen (Bild von Tom Wendel)

Das ist (so weit ich weiß) einzigartig in der Programmierwelt oder? Denn Java Programme können nicht direkt auf den Desktop ausgeführt werden, und genauso iPhone Apps!

Ich bin mal gespannt, wie lange es dauert bis das Ganze auch umgekehrt möglich ist! :)

Wirklich genial!

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
28Feb/100

C#: Alle Sichtbaren Prozesse / Fenster auflisten

Immer öfter benötige ich beim erstellen einer Software Zugriff auf fremde Fenster, doch leider bietet hier die Process-Klasse des .NET Frameworks nur wenig Hilfe. Denn mit ihr kann mann nicht alle Fenster ansprechen!

Problem:

Nehmen wir mal wir möchten alle zur Zeit geöffneten Fenster in einer Liste darstellen, dabei haben wir 3 Windows Explorer Fenster, 2 Mal FireFox und 3 anderen Programme geöffnet.

Wenn wir nun auf die Mittel des .NET Frameworks zurückgreifen, müssten wir das so angehen:


            foreach (Process p in Process.GetProcesses())
            {
                if (p.MainWindowHandle != null){
                    MessageBox.Show(p.MainWindowTitle + " - " + p.MainWindowHandle.ToString());
                }
            }

Der Code ist sehr simpel und leicht verständlich. Wir prüfen, ob ein Fenster sichtbar ist, in dem wir schauen, ob ein Handle dafür hinterlegt ist. Leider kann man das meines Wissens nicht anders lösen.

Aber wie es euch vielleicht schon aufgefallen ist benutzen wir hier die Funktion p.MainWindowHandle() - das Problem hierbei ist das kleine Wörtchen "Main", das in dem Funktionsnamen steckt, denn diese Funktion liefert uns NUR den Titel und das Fensterhandle des Hauptfensters des Programms, oder in anderen Worten, des Fensters eines Programms, das zuletzt aktiv gewesen ist.

Das bedeutet, dass wenn wir 3 Firefox Fenster offen haben wir nur das Handle und den Titel des zuletzt aktiven Fenster bekommen. Schlimmer ist es noch mit den Systemfenstern, da diese immer unter dem Prozess "Explorer" laufen, der unter anderem auch für die Darstellung der Taskleiste verantwortlich ist.

Das bedeutet, dass wir im Normalfall nicht die Windows Explorer Fenster ansprechen können sondern stattdessen das Handle der Taskleiste zurückbekommen, da diese meißt aktiver ist als die Windows Fenster und meistens auch immer im Vordergrund bleibt. (Siehe letzter Artikel)

Lösung:

Doch wie bekommen wir nun alle Fenster? Hier bietet uns das Framework leider keine Hilfe, weswegen wir auf die Win32 API zurückgreifen müssen. Hier finden wir Methoden, die uns viel über die Fenster verraten:


        [DllImport("user32.dll")] //Die Position und Größe eines Fensters bestimmen
        public static extern long GetWindowRect(IntPtr hwnd, ref RECT lpRect);

        [DllImport("user32.dll")] //Prüfen, ob ein Fenster Sichtbar ist
        public static extern bool IsWindowVisible(IntPtr hWnd);

        [DllImport("user32.Dll")] //Alle offenen Fenster abrufen
        public static extern int EnumWindows(ProcessListDemo.Windows.WinCallBack x, int y);

        [DllImport("User32.Dll")] //Titel eines Fensters auslesen
        public static extern void GetWindowText(int h, StringBuilder s, int nMaxCount);

        [DllImport("User32.Dll")] //Die Klasse des Fensters besimmen
        public static extern void GetClassName(int h, StringBuilder s, int nMaxCount);

Die wichtigsten hier sind "EnumWindows" und "IsWindowVisible". Die erste liefert uns eine Liste mit allen Fensterhandles die zur Zeit aktiv sind und mit der Zweiten können wir bestimmen, ob ein Fenster sichtbar ist oder nicht. Die anderen Funktionen lassen wir erstmal ungeachtet.

Wie eben schon erwähnt benutzen wir die EnumWindows-Funktion um uns alle Fensterhandles zu besorgen. Diese Funktion arbeitet hierbei über einen Delegaten Aufruf.


        ///
        /// Beinhaltet alle zur Zeit geöffneten und Minimierten Fenster
        ///
        public LinkedList lstWindows { get; set; }

        ///
        /// Delegate Funktion für EnumWindows (Siehe Declarations)
        /// Gibt die Werte an EnumWindowCallBack weiter
        ///
        public delegate bool WinCallBack(int hwnd, int lParam);

        private void getWindows()
        {
            //Liste mit Fenstern befüllen
            ProcessListDemo.Declarations.EnumWindows(new WinCallBack(EnumWindowCallBack), 0);

        }

        ///
        /// Diese Funktion wird durch die Delegate Funktion WinCallBack aufgerufen
        /// und iteriert durch alle zur Zeit geöffneten Fenster
        private bool EnumWindowCallBack(int hwnd, int lParam)
        {
            IntPtr windowHandle = (IntPtr)hwnd;

            StringBuilder sb = new StringBuilder(1024);
            StringBuilder sbc = new StringBuilder(256);

            ProcessListDemo.Declarations.GetClassName(hwnd, sbc, sbc.Capacity);
            ProcessListDemo.Declarations.GetWindowText((int)windowHandle, sb, sb.Capacity);

            //Nur Prozesse mit einer Beschreibung, also einem Fenster bearbeiten
            if (sb.Length > 0)
            {
                ProcessListDemo.Declarations.RECT r = new ProcessListDemo.Declarations.RECT(); //Fensterposition & Größe bestimmen:
                ProcessListDemo.Declarations.GetWindowRect(windowHandle,ref r);

                Window w = new Window(  sb + "",
                                        windowHandle,
                                        sbc + "",
                                        ProcessListDemo.Declarations.IsWindowVisible(windowHandle),
                                        new ProcessListDemo.Declarations.Point(r.Left, r.Top),
                                        new ProcessListDemo.Declarations.Point(r.Right - r.Left, r.Bottom - r.Top),
                                        Window.WinType.Normal);
                this.lstWindows.AddLast(w);
            }
            return true;
        }

In einfachen Worten erklärt passiert hier folgendes: Wir rufen die EnumWindows Funktion auf und übergeben dieser als Parameter die Referenz auf die Funktion EnumWindowCallBack, dazu benötigen wir die Delegate Funktion WinCallBack. Wichtig hierbei ist, dass alle Funktionen die gleichen Parameterdefinitionen haben. Der zweite Parameter ist bei mir hier aber ungenutzt, dieser ist optional vorhanden, um zB. weitere Referenzen zu übergeben wie zB. eine Listbox worin die Ergebnisse gespeichert werden sollen. Da wir hier aber die Ergebnisse direkt in die Klassen-variable schreiben benötigen wir diese nicht.

Nachdem die EnumWindows Funktion nun aufgerufen wurde macht sie nichts anderes, als die ihr übergebene Funktion (EnumWindowCallBack) aufzurufen. Diese wird dabei für jeden Prozess einmal aufgerufen und bekommt als Parameter das Handle des Fensters.

Im Prinzip nicht kompliziert. Ich habe hier, um das ganze besser zu visualisieren zwei Klassen namens "Window" und "Windows" erstellt. Diese übernehmen die ganze Arbeit für euch und erstellen eine Komplette Übersicht aller Fenster inklusive der Angaben, wie Größe, Position, Handle und Titel. Diese könnt ihr gern in euren eigenen Projekten nutzen.

Bild 1: Die Eigenschaften der Window-Klasse

Wenn ihr euch mal die Ergebnisse der EnumWindows Funktion anschaut werdet ihr feststellen, dass es ziemlich viele Fenster sind die da so im Hintergrund laufen, aber unsichtbar sind! Um diese Fenster zu filtern benutzen wir die Funktion IsWindowVisible und prüfen ob das Fenster Sichtbar ist oder nicht.

Bild 2: Das Demoprogramm in Aktion, zeigt alle Fensterprozesse

In dem Demoprogramm zeige ich euch wie ihr die zwei Klassen "Window" und "Windows" sehr einfach dazu benutzen könne, um eine Komplette Übersicht über alle Fenster des Systems zu bekommen.


        private void cmdList_Click(object sender, EventArgs e)
        {
            //Alte Liste Leeren
            lstProcess.Items.Clear();

            //Alle vorhandenen Fenster bestimmen
            Windows windows = new Windows();

            //Alle Fenster durchgehen und in die Lite einsetzen
            foreach (Window w in windows.lstWindows)
            {
                ListViewItem lvi = new ListViewItem(w.winTitle);
                lvi.SubItems.AddRange(new string[] { w.winClass,
                    w.winHandle.ToString(), w.winVisible.ToString() });     

                lstProcess.Items.Add(lvi);
            }
        }

Wie man sieht ist diese Angelegenheit dank der "Windows"-Klassen nun sehr einfach geworden. Zum besseren Verständnis solltet ihr euch das Demoprojekt herunterladen.

Download des Demoprojekts: Download [VS 2008 C#]

Wie hat euch dieser Artikel gefallen? Habt ihr Verbesserungsvorschläge, Kritik oder Lob? Bitte ein Kommentar schreiben!

VN:F [1.8.4_1055]
Rating: 10.0/10 (1 vote cast)
24Feb/100

.NET: Windows Taskleiste verstecken

In den letzten Tagen ist mir durch einen Zufall aufgefallen, dass die Windows Taskleiste (seit Windows Vista) in einem Fenster Prozess des Explorers läuft.

Das interessante/lustige hierbei ist, dass die Taskleiste als Fenster erkannt wird und dementsprechend auch als Fenster behandelt werden kann. Also können wir sämtliche Funktionen für Fenster auch auf die Taskleiste anwenden.

Als Beispiel blende ich hier die Taskleiste mit Hilfe der ShowWindow Funktion aus. Das lustige hierbei, ist dass nicht die Ganze Taskleiste von dieser Aktion betroffen ist. Der "Start"-Knopf von Windows bleibt weiterhin sichtbar und funktioniert, nur das Drumherum ist nun verschwunden.

Der Prozess den wir suchen läuft als "explorer" und sollte der einzige Prozess sein, der ein MainWindowHandle hat aber keinen MainWindowTitle. Wenn man diese zwei Kriterien anwendet, kann man ganz einfach diesen Prozess isolieren:


        [DllImport("user32.dll")]
        public static extern long ShowWindow(IntPtr hWnd, int nCmdShow);

        private IntPtr tbHandle = IntPtr.Zero;
        private void button1_Click(object sender, EventArgs e)
        {
            Process[] pr = Process.GetProcesses();

            foreach (Process p in pr)
            {
                if (p.MainWindowHandle != null && p.MainWindowTitle == ""
                    && p.ProcessName == "explorer")
                {
                    tbHandle = p.MainWindowHandle;
                }
            }

            if (tbHandle != IntPtr.Zero)
            {
                ShowWindow(tbHandle, 0);
            }
            else
            {
                MessageBox.Show(this, "Konnte Prozess nicht finden!",
                "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

Da man nun das MainWindowHandle hat kann man nun mit Hilfe der ShowWindow-Funktion aus der Win32 API das Fenster verstecken.

WICHTIG: Bitte vor dem Verstecken der Taskleiste unbedingt das MainWindowHandle abspeichern, da man diese sonst nicht wieder einblenden kann!

Wenn man die Aktion erfolgreich ausführt sieht man folgendes:

Bild 1: Die Taskleiste ist verschwunden, nur der Start-Knopf ist noch da

Wie man sieht ist nur noch der Start-Knopf da und die gesamte Taskleiste ist verschwunden und ist auch nicht anklickbar!

Wenn man die Option "Taskleiste Automatisch ausblenden" aktiviert hat hat man sogar einen noch schöneren Effekt!

Also wenn ihr nicht wollt, dass euch jemand auf die Taskleiste glotzt oder ihr jemandem einen kleinen Streich spielen wollt könnt ihr das ja mal testen!

Falls ihr eure Taskleiste versteckt habt und aus versehen das Programm beendet könnt ihr die Taskleiste nicht mehr über das Programm wiederherstellen! Die einzige Lösung ist es im Taskmanager ([STRG]+[SHIFT]+[ESC]) den Prozess "explorer.exe" zu beenden und dann über Datei->Neuer Task->"explorer"->[ENTER] den Explorer neu zustarten.

Bild 2: Das Demoprogramm

Ich hoffe diese kleine Spielerei hat euch gefallen, das Demo Projekt (diesmal in C#) gibts hier:

Demoprojekt: Download [VS 2008]

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
17Feb/100

VB.NET: FitzBox IP erneuern ueber uPnP

Die FritzBox ist als Router weit verbreitet und bietet einen Haufen an Konfigurationsmöglichkeiten an. Eins der nützlichsten Features ist uPnP (Universal Plug and Play). Diese Schnittstelle bietet uns eine sehr bequeme Möglichkeit mit dem Gerät zu kommunizieren ohne dass man einen Benutzernamen oder ein Kennwort benötigt!

Wer öfter mal im Internet unterwegs ist, kennst sicherlich mehrere gute Gründe seine IP zu wechseln. Und das ist sehr einfach, denn alles was dafür nötig ist, ist eine erneute Einwahl ins Internet.

Dies kann man sehr einfach über die Benutzeroberfläche der FritzBox machen oder einfach "oldschool"-mäßig das Netzwerkkabel aus der FritzBox ziehen und wieder einstecken. (Letzteres erfordert ebenfalls keinen Benutzernamen und Passwort)

Doch wenn man des öfteren auf diese Funktionalität angewiesen ist, ist es doch relativ nervig und umständlich. Deswegen werden wir hier ein einfaches kleines Programm entwickeln, dass für uns den Router zu einer Neueinwahl ins Internet "zwingt".

Wie oben bereits erwöhnt heißt die Technologie dafür UPnP (Universal Plug and Play). Über diese Technologie lassen sich sehr viele Befehle an die Fritzbox senden, vorausgesetzt, man befindet sich in dem selben Netzwerk.

Von Statusabfragen über Auslastungen und Übertragung, lassen sich sogar Telefonnummern anwählen und Anrufe steuern, im Prinzip kann man alle Funktionen darüber ansteuern. Hier gibts eine nette Übersicht mit vielen Beispielen.

Wie werden die Anfragen eigentlich an die Fritzbox übertragen? Das geschieht sehr einfach über einen POST Aufruf, denn auf der Fritzbox (und auch auf den meisten anderen Routern) läuft ein kleiner Webserver denn man ganz einfach über den Browser erreicht, wenn man die adresse "fritz.box" in die Adresszeile tippt.

Dort ist die Fritzbox genauso aufgebaut wie eine gewöhnliche Webseite. Und diese nimmt auch POST und GET aufrufe entgegen. Genau hier setzen wir an und werden unsere Befehle rüber schicken.


        Dim client As New TcpClient

        client.Connect("fritz.box", 49000)

        Dim stream As NetworkStream = client.GetStream
        Dim bytes As Byte() = New Byte((My.Resources.msg.Length)) {}

        bytes = Encoding.ASCII.GetBytes(My.Resources.msg)

        stream.Write(bytes, 0, bytes.Length)
        bytes = New Byte(1024) {}

        Dim str As String = String.Empty

        Dim count As Integer = stream.Read(bytes, 0, bytes.Length)

        str = Encoding.ASCII.GetString(bytes, 0, count)

        stream.Close()
        client.Close()

Der Code ist sehr simpel, wir erstellen uns einen WebClient und verbinden uns mit der FritzBox. Nach der Verbindung senden wir ein POST Request raus und lesen anschließend die Antwort wieder aus.

Mit dem obigen Code senden wir folgenden Befehl an die Fritzbox:


POST /upnp/control/WANIPConn1 HTTP/1.1
HOST: fritz.box:49000
SOAPACTION: "urn:schemas-upnp-org:service:WANIPConnection:1#ForceTermination"
CONTENT-TYPE: text/xml ; charset="utf-8"
Content-Length: 293

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <u:ForceTermination xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1" />
   </s:Body>
</s:Envelope>

Wie man sieht ist der Befehl ein gewöhnlicher POST Aufruf inkl. Header. Dieser übergibt einen Befehl urn:schemas-"upnp-org:service:WANIPConnection:1#ForceTermination", der der Fritzbox sagt die Verbindung ins Internet neu aufzubauen.

Man muss hierbei sehr aufpassen, besonders die Content-Length Angabe muss genaustens passen, da sonst ein Fehler als Antwort eintrudelt.

Wie immer gibts auch eine kleine Demoanwendung.

Bild 1: Das Demo Programm in action

Download hier: Download [VS 2008 Projekt]

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
25Dez/090

.NET Administratorrechte fuer eigenes Programm einfordern

Wenn man mit .NET entwickelt wird man schnell feststellen, dass man zur Laufzeit bestimmte Ordner nicht öffnen kann, bestimmte Dateien nicht löschen oderbestimmte Systemfunktionen nicht ausführen kann!

Das liegt daran, dass dem Programm die nötigen Rechte fehlen, denn seit Windows Vista werden alle Programme ohne Administratorrechte ausgeführt. Braucht ein Programm dann aber doch diese Rechte sieht man diesen wenig gemochten Dialog von Windows:

Bild 1: Windows Benutzerkontensteuerung in Aktion

Das Angezeigte unterscheidet sich dann natürlich je nach Programm, aber sobald man hier auf Zulassen geklickt hat wird das Programm mit den Vollen Rechten gestartet.

Aber woran kann ich erkennen, dass ich volle Rechte benötige? - Ganz einfach, wenn man Fehlermeldungen erhält, die besagen, dass man keine Rechte besitzt um auf die Dienste zuzugreifen, oder wenn Systemfunktionen (zB. WMI) nicht mehr korrekt ausgeführt werden.

Wie sorge ich nun dafür, dass mein Programm Adminrechte erhält? - Hier gibt es zwei Möglichkeiten. Die erste ist es das Programm mit rechter Maustaste anzuklicken und dann "Als Administrator ausführen" zu wählen:

Bild 2: So kann man jedem Programm Administratorrechte geben

Natürlich kann man die Adminrechte direkt in unserem Programm beantragen, in dem man in den Projekteinstellungen im Tab "Anwendung" auf den Button "Einstellungen für die Benutzerkonstensteuerung anzeigen" klickt. Dazu wird die Datei "app.manifest" im Projektordner generiert, die dann folgende Einstellungen beinhaltet:


        <!-- UAC-Manifestoptionen

             Wenn Sie die Ebene der Benutzerkontensteuerung für Windows ändern

             möchten, ersetzen Sie den Knoten "requestedExecutionLevel" wie folgt:

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />

        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />

        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

         Wenn Sie aus Gründen der Abwärtskompatibilität Datei- und Registrierungsvirtualisierung

         verwenden möchten, löschen Sie den Knoten "requestedExecutionLevel".

        -->

Wie man in dem Grünen Kommentarblock erkennen kann, gibt es drei verschiedene Einstellungsmöglichkeiten, nämlich level="asInvoker" (welcher voreingestellt ist), level="requireAdministrator" und level="highestAvailable".


  requestedExecutionLevel  level="requireAdministrator" uiAccess="false"

Wenn man nun den unter dem Kommentarblock stehenden Eintrag requestedExecutionLevel auf requireAdministrator ändert, wird unser Programm bei jedem Start automatisch Administratorrechte einfordern, und man wird bei jedem Start diesen unschönen Windows Dialog aus Bild 1 zu sehen bekommen.

Wie ihr euch sicher grade denkt ist das sehr unangenehm für den Benutzer, der später mit der Software arbeiten muss. Dieser muss jedes Mal die Ausführung dieses Programms bestätigen. Außerdem sollte man im Hinterkopf behalten, dass Microsoft diesen Dialog nicht zum Spaß eingeführt hat.

So sollte man immer versuchen seine Software so zu gestalten, dass man auch ohne Administratorreche auskommt. Sollte es aber nicht anders gehen, sollte man den Teil, der diese Rechte benötigt stets aus dem Programm auslagern, sodass dieser Spezielle Fall dann gesondert aufgerufen werden kann und man den Benutzer ggf darauf vorbereiten kann, dass gleich eine Meldung von Windows kommt.

Das Hauptprogramm kann und sollte dann auch weiterhin mit dem geminderten Rechten laufen. So verwirrt man den Benutzer nicht und kann Fehlerquellen später besser eingrenzen.

VN:F [1.8.4_1055]
Rating: 10.0/10 (2 votes cast)
11Dez/091

Programmfortschritt in der Windows Taskleiste anzeigen

Wenn ihr Windows 7 bereits verwendet, werden euch sicherlich einige Neuerungen aufgefallen sein. Einige von denen ist die neue Funktion der Taskleiste den Fortschritt eines Programms darzustellen.

Ihr werdet dies beobachten, wenn ihr z.B. eine Datei mit dem Internet Explorer 8 herunterladet oder eine Datei kopiert. Das Programm zeigt den eigenen Fortschritt dann unter dem Eigenen Symbol in der Taskleiste an.

Diese Funktion ist extrem praktisch, so kann man sie benutzen um den Benutzer immer aktuell zu halten, ohne dass er das eigentliche Programm offen hat. Mögliche Anwendungsfälle wären Dateidownloads, Kopiervorgänge, Bildererzeugung und allgemeine Vorgänge, die etwas Zeit in Anspruch nehmen.

Natürlich können auch wir diese Funktionen in unseren Projekten nutzen. Leider werden die Aufrufe an das Betriebssystem unmanaged gestartet, was bedeutet, dass diese Aufrufe umgewandelt (gewrapped) werden müssen. Da das ein sehr komplexer Vorgang ist hat Microsoft uns diesen gespart und schon einige vorgefertigte Klasse angefertigt auf die wir zurückgreifen können.

Diese Librarys finden wir im MSDN in der .NET Interop Sample Library. Diese Beispielsammlung enthällt viele weitere Beispiele. Wir betrachten hier nur das was mit dem Fortschrittsbalken in der Taskleiste zu tun hat.

Deswegen brauchen wir auch nicht alle Klassen, sondern nur diese:

Vista Bridge Sample Library
Windows7.DesktopIntegration
Windows7.DesktopIntegration. Registration.

Windows7.DesktopIntegration enthält hierbei die Klasse WindowsFormsExtensions, welche uns die nötigen "Extensions"-Funktionen zur Verfügung stellt um das Aussehen der Taskleiste ändern zu können.

In unserem (einfachen) Fall werden wir nur die beiden Methoden benötigen:

SetTaskbarProgress(float percent)
SetTaskbarProgressState(ThumbnailProgressState state)

Mit der Ersten Methode können wir den Fortschritt der Progressbar steuern, und mit der zweiten das Aussehen. Für die zweite Funktion müssen wir neben dem Zustands Parameters auch das Handle des Fensters angeben, für das die Aktion ausgeführt wird.

So könnten die Aufrufe folgendermaßen aussehen:


WindowsFormsExtensions.SetTaskbarProgress(Me.ProgressBar1)
WindowsFormsExtensions.SetTaskbarProgressState(Me, _
                         Windows7Taskbar.ThumbnailProgressState.Error)

Garnicht mal so kompliziert oder?

Dabei kann das Taskleistensymbol unseres Programms 5 verschiedene Werte annehmen:

progresstaskbarBild 1: Cool oder?

Wenn wir nun also ein neues Windows Forms Projekt erstellen müssen wir ersteinmal die drei oben erwähnten Class Librarys importieren. Das machen wir in dem wir über Datei->Hinzufügen->Vorhandenes Projekt wählen

progresstaskbar3Bild 2: Projekte hinzufügen

Auf diese Weise fügen wir alle drei oben erwähnten Projekte dem unseren hinzu. Wenn das geschafft ist müssen wir noch die nötigen Verweise hinzufügen. Dazu wählen wir Projekt->Verweis hinzufügen... und dann den Tab "Projekte"

progresstaskbar4Bild 3: Verweise hinzufügen

Hier wählen wir alle drei Projekte aus und klicken auf "OK"!

Wie ihr nun im Projektmappen Explorer erkennen werdet ist das Projekt gleich mal um einiges gewachsen! Ihr könnt dieses Vorgehen auch umgehen, indem ihr die importierten Class Librarys als DLL kompiliert und direkt in das Projekt einbindet. Das schafft vielleicht mehr Übersicht.

Nun haben wir schon das größte Hindernis schon überwunden! Nun gehts ans Programmieren, wofür ihr die oben vorgestellten Funktionen benutzen könnt um eurem Programm den nötigen Windows 7 Look zu verpassen!

Ich habe dazu wie immer eine kleine Demo angefertigt. Meine sieht so aus:

progresstaskbar2Bild 4: Das Demoprojekt in Aktion

Das Demoprojekt könnt ihr hier laden: Download [VS 2008]

VN:F [1.8.4_1055]
Rating: 8.2/10 (5 votes cast)
9Dez/090

VB.NET: Saubere Klassen erstellen mit Properties

Heutzutage wird fast nurnoch Objektorientiert programmiert. Das bedeutet, dass ein größeres Projekt schnell mal auf eine Klassenanzahl von 100 und mehr wächst.

Damit man den Überblick behält und den Code, den man schon geschrieben hat möglichst wiederverwenden kann, sollte man ein paar grundlegende Regeln beachten.

In diesem Artikel möchte ich ein Beispiel zeigen, wie man eine Klasse in ein Projekt integriert und dank der benutzten Standardmethoden an ein Datagrid bindet.

Warum schreibe ich diesen Artikel überhaupt? Erst gestern habe wurde in einem Forum die Frage gestellt, warum man eine Liste (Of T) nicht als DataSource für ein DataGridView benutzen kann. Dabei ist das sehr wohl möglich, der User hat seine Klasse aber "unschön" gestaltet, weswegen sich die anderen Steuerelemente auch quer gestellt haben.

Hier ein Beispiel einer solchen "Unschönen" Klasse:


Public Class Auto
    Public marke As String
    Public motor As String
    Public geschw As Integer
End Class

        Dim al As New List(Of Auto)
        al.Add(New Auto With {.marke = "VW", .motor = "Diesel", .geschw = 0})

        al(0).geschw += 10

Wie man sieht sind hier alle Klassenvariablen öffentlich zugänglich, und die Klasse hat keinerlei Kontrolle darüber, wie sie befüllt werden. Ein weiterer Nachteil ist auch die Inkompabilität zu anderen Steuerelementen, da diese einen Standardkonformen Aufbau der Klasse erwarten. Finden sie bestimmte Elemente in der Klasse nicht so verweigern diese die Funktionalität!

Wie müsste diese Klasse also umgebaut werden, damit diese kompatibel zu anderen Objekten wird?


Public Class Auto
    Private geschw As Integer

    Public Sub New(ByVal marke As String, ByVal motor As String)
        Me._marke = marke
        Me._motor = motor
    End Sub

    Private _marke As String
    Public Property Marke() As String
        Get
            Return _marke
        End Get
        Set(ByVal value As String)
            _marke = value
        End Set
    End Property

    Private _motor As String
    Public Property Motor() As String
        Get
            Return _motor
        End Get
        Set(ByVal value As String)
            _motor = value
        End Set
    End Property

    Public Sub beschleunigen(ByVal a As String)
        geschw += a
    End Sub

    Public Sub bremsen(ByVal a As String)
        geschw -= a
    End Sub
End Class

Wie man sieht ist die Klasse nun natürlich um einiges länger geworden. Leider kann man das zur zeit noch nicht anders machen. Aber Abhilfe kommt in der neuen VB.NET Version, wo man die properties so wie in C# 3.0 erstellen kann.

Die Zugriffe auf die Klassenvariablen werden nun über properties gesteuert, die nun auch zB. überprüfen könnten, ob der übergebene Wert überhaupt passt und gegebenenfalls noch Änderungen daran vornehmen.

Aber was bringt uns nun dieser längere Aufbau der Klasse? Nun, wenn wir unser Objekt, das aus dieser Klasse entsteht an andere Objekte übergeben, erwarten diese, dass sie properties vorfinden, mit denen sie arbeiten können.

Hat die Klasse keine Properties so können wir auch bestimmte Funktionen auch nicht benutzen. Ich möchte das mal an einem DataGridView demonstrieren, da dieses Element von den properties sehr schön Gebrauch macht!

Fügt man folgenden Code einem Form mit einer DataGridView hinzu:


    Private Sub Form1_Load() Handles MyBase.Load
        Dim autos As New List(Of Auto)

        autos.Add(New Auto("VW", "Diesel"))
        autos.Add(New Auto("Audi", "Benziner"))
        autos.Add(New Auto("Mercedes", "Diesel"))
        autos.Add(New Auto("Renault", "Diesel"))
        autos.Add(New Auto("BMW", "Beziner"))

        Dim bs As New BindingSource
        bs.DataSource = autos

        Me.DataGridView1.DataSource = bs
    End Sub

erhält man folgendes Bild:

datagridviewBild 1: Die Datagridview stellt alle Informationen angenehm dar

Wie man sieht konnte man mit nur 3 Zeilen Code (Abgesehen vom Erzeugen der Werte) alle Daten der Liste visualisieren. Man beachte desweiteren, dass sogar die Namen der Properties (Marke und Motor) ausgelesen werden und der richtigen Tabelle zugeordnet werden!

Dies könnte man natürlich auch ohne Properties hinbekommen, doch würde man viel mehr Aufwand betreiben müssen und man denke an die Zukunft, in der unser Modell sehr einfach zu warten wäre.

Hier gibts ein kleines Demoprojekt: Download [VS 2008]

VN:F [1.8.4_1055]
Rating: 8.0/10 (4 votes cast)
9Dez/090

ASP.NET: Erzeugen eines MD5 Hashs

Wer sich schon mal mit PHP auseinander gesetzt hat, wird wissen wie einfach es ist dort einen MD5 Hash zu einem Wert zu berechnen. Dies geht dort sehr simpel mit der Funktion "MD5($wert);".

Leider oder zum Glück ist es in in ASP.NET etwas komplexer aufgebaut. Somuss man hier erst Instanzen von Kryptographie Klassen erstellen, bevor man endlich den gewünschten MD5 String bekommt.

So sieht der Code dafür aus:


using System.Security.Cryptography;
using System.Text;
        public String MD5(String wert)
        {
            byte[] bWert = Encoding.UTF8.GetBytes(wert);
            MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] hash = md5.ComputeHash(bWert);
            string md5Wert = BitConverter.ToString(hash).Replace("-", "").ToLower();

            return md5Wert;
        }

Mit dieser Funktion bekommt man einen sauberen MD5 Hash in Kleinbuchstaben. Diese Funktion lässt sich nun so benutzen wie unter PHP um bequem MD5 hashes zu berechnen.

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
8Dez/093

Windows Aero Glas in eigenen Projekten nurzen Teil 3

Es ist etwas Zeit seit dem zweiten Teil vergangen, und wie ich in den Kommentaren sehe, sind da noch ein paar Fragen offen!

Das Hauptproblem mit den Glasoberflächen unter Windows sind die GDI und GDI+ Komponenten, diese unterstützen keine Transparenz. Das macht es so schwierig diese auf Glas ordentlich zu rendern.

Wenn ihr meine persönliche Meinung hören wollt, lasst es ganz bleiben! Denn seit knapp 4 Jahren stellt Microsoft uns ein sehr mächtiges grafisches Werkzeug zur Verfügung, nämlich WPF.

WPF soll die neue Präsentationsschicht unter Windows werden. Das heißt WPF regelt wie die UI-Elemente, die wir sehen, zb. Knöpfe und Fenster aussehen und sich verhalten!

Aber ich will nicht weiter auf den Aufbau von WPF eingehen, für uns ist wichtig zu wissen, dass in WPF alle Elemente die Transparenz beherrschen. Das macht sie für uns perfekt um sie auf Glas einzusetzen!

aerowpfBild 1: Ein in WPF gerendertes Fenster mit Steuerelementen

Wie man auf dem Bild 1 gut erkennen kann, sieht man keine verpixelten Texte mehr und der Hintergrund ist wunderbar Transparent, auch bei dem Button!

Alle WPF Steuerelemente beherrschen viel mehr Optische Funktionen, so sind die beiden ProgressBars im Bild 1 ebenfalls Transparent. Das geht nicht mit GDI+!

Für alle die jetzt denken, oh nein, ich will nicht schon wieder eine neue Sprache erlernen, kann ich für Entwarnung sorgen. Auch unter WPF wird mit VB.NET und C# programmiert. Ihr könnt euren Code in 80% der Fälle komplett übernehmen!

Wie gesagt liegt der Schwerpunkt von WPF auf der Präsentation, deswegen werdet ihr die alten Grafik-Klassen nicht mehr wiederfinden. Desweiteren gibts auch keine Windows.Forms mehr, sondern nurnoch Windows (Fenster). Dies sind ein paar der Stolperfallen, durch die man sich kämpfen muss und an die man sich gewöhnen muss.

Wie ihr an dem folgenden Beispielcode sehen werdet, werdet ihr viel wiedererkennen:


Imports System.Runtime.InteropServices
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows.Media
Imports System.Windows
Imports System.Windows.Interop

Public Class GlassForm
 _
        Private Shared Sub DwmExtendFrameIntoClientArea _
                (ByVal hwnd As IntPtr, ByRef margin As MARGINS)
    End Sub
 _
    Public Shared Function DwmIsCompositionEnabled() As Boolean
    End Function

    Public Shared Function ExtendGlassFrame(ByVal window As Window, _
                            ByVal margin As MARGINS) As Boolean
        If Not DwmIsCompositionEnabled() Then
            Return False
        End If

        Dim hwnd As IntPtr = New WindowInteropHelper(window).Handle

        ' Hintergrundfarbe auf Tranzparent setzen, für WPF und die Win32 Ansicht
        window.Background = Brushes.Transparent
        HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = _
                                        Colors.Transparent

        Dim margins As New MARGINS(margin.left, margin.right, _
                                   margin.top, margin.bottom)
        DwmExtendFrameIntoClientArea(hwnd, margins)
        Return True
    End Function
End Class

Public Structure MARGINS
    Public left As Integer
    Public right As Integer
    Public top As Integer
    Public bottom As Integer

    Public Sub New(ByVal l As Integer, ByVal r As Integer, _
                   ByVal t As Integer, ByVal b As Integer)
        left = l
        right = r
        top = t
        bottom = b
    End Sub
End Structure

Wie man sieht ähnelt der Code sogar sehr dem aus Teil 2. Nur die entsprechenden (in WPF nicht mehr vorhandenen)  Elemente wurden angepasst.

Das tolle hierran ist, dass wir nun alle Steuerelemente benutzen können die wir wollen, ohne uns Sorgen machen zu müssen wie diese gerendert werden!

Das Demoprojekt gibts es hier: Download [VS 2008]

Hier gehts zum zweiten Teil des Tutorials.

Eventuell schiebe ich noch einen vierten Teil nach, warten wir ersteinmal eure Reaktionen ab :)

VN:F [1.8.4_1055]
Rating: 10.0/10 (1 vote cast)
Get Adobe Flash playerPlugin by wpburn.com wordpress themes