Thomas Wölfers Baustatik-Blog

Thomas Wölfers Baustatik Blog

Die TreeView und die Bitmaps


Die Windows.Forms TreeView hat eine ImageList - und in dieser ImageList kann man die Bitmaps unterbringen, die für die einzelnen Nodes im Tree verwendet werden. Leider zeigt sich hier auch bei .Net das etwas merkwürdige Erbe von Win32: Die TreeView - beziehungsweise deren Nodes - haben nämlich zwei Felder, mit denen Bitmaps gesetzt werden können. Das eine ist der ImageIndex, das andere der SelectedImageIndex.

Der ImageIndex enthält den Index des Bildes aus der ImageList, das verwendet werden soll, wenn sich die Node im 'Normalen' Zustand befindet. Der 'SelectedImageIndex' ist der Index des Bildes für den ausgewählten Zustand einer Node. Ich kenne zwar kein Programm das im Baum ein anderes Icon für ausgewählte Nodes verwendet als für Nodes im Normalzustand - aber sei's drum, ist ja schon wenn man die Möglichkeit hat.

Nun würde man erwarten das es außerdem auch einen Index für den 'aufgeklappten' Zustand einer Node gibt: Im Baum ist das schließlich deutlich wichtiger als der 'ausgewählte' Zustand - darum verwendet man schließlich einen Baum.

Unnötig zu sagen: Das gibts natürlich nicht. Wenn man so etwa 'ungewöhnliches' machen will wie einen Baum bei dem man andere Icons im aufgeklappten und geschlossenen Zustand verwendet, dann muss man das von Hand machen. :-(

Dazu implementiert man einen Handler für AfterExpand() und AfterCollapse() - und darin setzt man dann in Abhängigkeit von der Node die Image-Indizes. Dabei wirds dann noch nerviger: Man muß nämlich sowohl den 'ImageIndex' als auch den SelectedImageIndex setzen - auch wenn man sich für den 'SelectedImageIndex' eigentlich gar nicht interessiert.


Bitmaps in VS.Net Projekten laden


Die Verarbeitung von Resourcen wie zum Beispiel Bitmaps zur Laufzeit von Programmen die Sie mit dem Visual Studio erstellen ist ein wenig merkwürdig - unverständlich sogar, würde ich sagen. Das ganze Modell erscheint ein unausgegoren... Trotzdem kann man natürlich Bitmaps laden.

So gehts:

Angenommen Sie haben ein Projekt in dem sich das Bitmap 'Bitmap1.bmp' befindet. Dieses Bitmap soll nun im Code geladen werden. Das geht im Prinzip so:

Bitmap bmp = new Bitmap( GetType(), "Bitmap1.bmp");

Der Type spezifiziert dabei die Assembly in der sich das Bitmap befindet. Mit anderen Worten: Man legt damit fest, das sich die Bitmap-Resource in der gleichen Assembly befindet wie 'Type'. Der String gibt einfach den Namen der Resource an.

Wenn man diesen Code übersetzt und ausführt bekommt man aber eine Exception... :(

Grund: Es reicht nicht die Bitmap ins Projekt aufzunehmen. Man muss auch (manuell, und zwar jedes mal wenn man ein neues Bitmap anlegt !) festlegen das das Bitmap tatsächlich mit ins Binary soll. Dazu muss man in den Properties der Bitmap die Eigenschaft 'BuildAction' von 'Content' auf 'Embedded Resource' stellen. Dann gehts.

Aber auch nur so lange sich der abgebildete Code in einer Klasse befindet, die sich selbst direkt im Default-Namespace des Projektes befindet. Ist außerdem noch ein Namenspace namens 'Test' vorhanden - liegt der Code also in der Klasse 'Form1' in 'DefaultNamespace.Test' - bekommt man wieder eine Exception.

Grund: Der zugrunde liegende Resource-Manager baut den Namen der gesuchten Resource aus der Assembly von 'Type' und aus dem Namespace von Type zusammen. Es wird dann also das Bitmap 'DefaultNamespace.Test.Bitmap1.bmp' gesucht - und das gibts nicht.

Lösung: Man muss das Bitmap im Projekt umbennen - und zwar in Test.Bitmap1.bmp.

Einfache aber beknackte Regel: Das Bitmap muss im Projekt mit einem Namen vorliegen, der den kompletten Pfad im Namespace des 'Types' bis aufs erste Element enthält.

Wer immer sich das ausgedacht hat sollte dafür bestraft werden. Ist natürlich nur meine Meinung...


Die ausführliche Statistik der Statiksoftware


Gestern habe ich die 'kurze' Statistik-Funktion des TimeServers beschriebén. Den TimeServer haben Sie dann (in Form eines kleinen roten D in der Taskleiste) auf dem Rechner laufen, wenn Sie unsere Baustatik-Programme im Work&Cash Verfahren nutzen.

Der TimeServer hat auch eine Befehl zum anzeigen einer ausführlichen Statistik. Nicht sonderlich überraschenderweise hat dieser Befehl den Namen 'Ausführliche Statistik anzeigen'.

Der Befehl öffnet einen Dialog mit zwei Listen. In der Liste 'Beteiligte Computer' erhalten Sie eine Aufschlüsselung wieviel Zeit die einzelnen mit dem TimeServer auf Ihrem Computer verbundenen anderen Computer verbraucht haben. Dabei werden Aenderungen bei Computernamen nicht mitgeführt: Wenn ein Rechner unter dem Namen 'Pauls Rechner' Zeit verbraucht hat und dann in 'Müllers Rechner' umbenannt wird, dann taucht er zweimal in der Liste auf.

In der Liste 'Verbrauchte Zeit' erhalten Sie eine Übersicht, wieviel Zeit an welchen Tagen verbraucht wurde: Damit können Sie sich einen Eindruck darüber verschaffen, wie hoch Ihr Zeitverbrauch eigentlich ist. (Kleiner Tipp: Die Kosten werden meist deutlich unterhalb der Telefongebühren liegen - es lohnt sich nicht wirklich, viel Zeit auf Analyse der Statistik zu verschwenden...)


Work&Cash Timeserver: Das bedeutet die Statistik


Wenn Sie unsere Statikprogramme mit einem Work&Cash Vertrag benutzen, dann läuft auf Ihrem Rechner das Timeserver Programm. Diese Programm besorgt die Buchhaltung für Ihren Work&Cash Vertrag. Wenn Sie mit der rechten Maustaste auf das rote 'D' Symbol in der Taskleiste klicken, dann erhalten Sie das TimeServer Objektmenü - die folgenden Blog-Einträge werden die dort zu findenden Befehle ein wenig erläutern. Heute gehts um den Befehl 'Aktuelle Statistik anzeigen'.

Der Befehl öffnet eine Dialogbox die in zwei Teile aufgeteilt ist. Der obere Teil ist grau hinterlegt, der untere weiss. Im oberen Bereich finden Sie die folgenden Angaben:

Zeitpunkt der Statistik: Das gibt den Zeitpunkt auf Ihrem Rechner an, an dem die angezeigten Daten Gültigkeit hatten.

Momentan verwendete Zeitblöcke: Ihre Arbeitszeit wird in 'Blöcken' verwaltet, wobei ein Block jeweils eine gewisse Menge an Arbeitszeit enthalten kann. Die 'Mege' an Zeit pro Block ist beliebig, und Blöcke können auch in kleinere Blöcke unterteilt werden. Diese Angabe hier sagt, wie viele Zeitblöcke momentan auf Ihrem Rechner verwendet werden.

Momentan zur Verfügung stehende Zeit: Die Anzeige gibt an, wieviel Arbeitszeit momentan auf Ihrem Rechner verfügbar ist. Die Angabe erfolgt sowohl in Studen als auch in Sekunden. Notgedrungen ist die Stunden-Angabe dabei gerundet.

Berechnete Zeit seit dem letzten Start: Gibt an, wieviel Arbeitszeit Sie seit dem letzten Start des TimeServers verbraucht haben. Zeit wird nur dann verbraucht, wenn auch ein Statikprogramm betrieben wird.

An der Berechnung beteiligte Computer: Gibt an, wieviele Computer (aus Ihrem LAN) Zeit von den Blöcken auf Ihrem Computer verbraucht haben. Wenn Ihr Rechner als Server für andere Rechner dient, dann steht hier eine Zahl größer als 1 - sonst eine 1.

An der Berechnung beteiligte Prozesse: Gibt an, wie viele unterschiedliche Sitzungen mit den einzelnen Statikprogrammen gezählt wurden. (Wenn Sie zum Beispiel das Tragwerksprogramm zweimal und das Plattenprogramm einmal starten, dann wird hier eine '3' angegeben.)

Anzahl momentan betrachteter Computer: Gibt an, wieviele Computer zum aktuellen Zeitpunkt mit dem TimeServer verbunden sind. Wenn Ihr System nicht als Server fungiert, dann steht hier immer eine '1'.

Im weissen Bereich erfolgt eine Auflistung aller Zeitblöcke die sich auf Ihrem System befinden: Blöcke deren Haltbarkeit abgelaufen ist, werden als 'abgelaufen/verschoben/leer' bezeichnet. Für jeden Block der noch gültige Arbeitszeit enthält, enthält die Liste eine Zeile mit der Angabe der im Block verfügbaren Stunden (und Sekunden).


Wie baut man ein Attribut in C#?


In .Net kann man Metadaten an Klassen und Methoden hängen um diese mit zusätzlichen Informationen auszustatten. Die Zuordnung dieser Metadaten zu einer Methode (oder Klasse...) erfolgt dabei über 'Attribute'.

Dabei gibt es eine ganze Menge von mitgelieferten Attributen mit denen man zum Beispiel erklärende Texte an Property-Accessors zuweisen kann: Diese Texte werden dann vom Property-Grid im 'Hilfe'-Bereich angezeigt. Man kann Attribute aber auch selbermachen - das ist sogar ganz einfach.

Angenommen man hat einen get/set Accessor mit dem man einen double-Wert einstellen kann:

double Groesse
{
   get{ return this.groesse; }
   set{ this.groesse = value; }
}

Nun will man den Accessor mit einem zulässigen Maximalwert ausstatten. Dafür gibt es kein mitgeliefertes Attribut, man möchte aber das die Sache hinterher ungefähr wie folgt aussieht:

[ MaximumValue( 400.0)]  // 400 soll der maximalwert sein
double Groesse
{
// ... 

Damit kann man nun an anderer Stelle im Quellcode (zum Beispiel auf der Dialogbox in der der Anwender den Wert angeben kann) nach einem MaximumValue Attribute suchen ( Type.Attributes ), und anhand dessen Wert überprüfen ob die angegebene Zahl OK ist. Stellt sich die Frage aus welchem Himmel das MaximumValue Attribut dann fällt....

Attribute selbermachen: So gehts

Eigentlich ist die Sache ganz einfach: Ein Attribut ist einfach eine Klasse die von System.Attribute abgeleitet wird. Die Klasse kann verschiedene Konstruktoren haben, und durch das attributieren in den eckigen Klammern wird dann der jeweils passende Konstruktor aufgerufen. Das Grundgerüst von MaxValue sieht also einfach so aus:

public class MaxValueAttribute : System.Attribute
{
   private double maxValue;
   public MaxValueAttribute( double maxValue)
   {
      this.maxValue = maxValue;
   }
   double Size
   {
      get
      {
          return this.maxValue;
      }
   }
}


Korrektur: Doch Änderung für SP2


Kleine Korrektur zum Posting von gestern bezüglich des Service Pack2 und unserer Statiksoftware. Heute ( war ja klar das das so kommen musste ...) haben wir dann doch ein Problem entdeckt das beseitigt werden muss. Wir werden uns also nochmals auf die Suche nach weiteren Problemen machen - und dann irgendwann im Laufe der nächsten Tage ein Update für alle Programme veröffentlichen in dem das Problem mit dem SP2 beseitigt sein wird.


Windows XP SP2: Änderungen bei Work&Cash


Ab Montag dem 16. August beginnt Microsoft damit das Service Pack 2 für Windows XP auch an 'Normale' Anwender auszuliefern. Wenn Sie die Funktion fürs automatische Update von Windows verwenden, dann wird ihr Windows im Laufe der nächsten Tage automatisch aufs SP2 umgestellt.

Das SP2 ist im wesentlichen ein Sicherheitsupdate. Warum Sie das SP2 auf jeden Fall einsetzen sollten habe ich bereits hier geschrieben.

Auswirkungen des SP2 auf unsere Statikprogramme

Wir haben in den letzten Monate sowohl am öffentlichen wie auch am nichtöffentlichen Betatest des SP2 teilgenommen und konnten in dessen Verlauf keinerlei Auswirkungen des SP2 auf unsere Programme feststellen.

Sie müssen nach der Installation des SP2 allerdings einmalig tätig werden um die Statiksoftware normal weiter nutzen zu können - und zwar dann, wenn Sie unsere Programme im Rahmen eines Work&Cash Vertrages nutzen.

Der Grund dafür ist der, das das SP2 mit einer eingebauten und von Haus aus eingeschalteten Firewall ausgestattet ist. Das ist eine gute Sache, und Sie sollten diese Firewall auf jeden Fall nutzen - zumindest dann, wenn Sie über keine andere aktuelle Firewall verfügen.

Diese Firewall blockiert Netzwerkverbindungen: Wenn auf Ihrem System ein Programm läuft das solche Verbindungen annimmt - wenn es also als Server fungiert - dann wird dies von der ins SP2 eingebauten Firewall zunächst unterbunden. Startet ein solches Programm, dann zeigt die Firewall eine Meldung an um darauf hinzuweisen, das ein Server-Programm entdeckt wurde.

Der 'TimeWise' Server der zu Ihrer Work&Cash Lizenz gehört ist ein solches Programm. Beim TimeWise Server handelt es sich um die Software die Ihre Zeiteinheiten verwaltet, und von der die einzelnen Programme Zeitblöcke fürs arbeiten abholen können. Der TimeWise Server läuft lokal auf Ihrer Workstation (oder einer in Ihrem LAN). Ob der TimeWise Server läuft oder nicht, können Sie an einem kleinen roten 'D' in der Taskleiste neben der Uhr erkennen.

Wenn der TimeWise Server nach der Installation des SP2 zum ersten Mal gestartet wird, dann erhalten Sie die folgende Meldung der Windows Firewall:

Damit Ihre Statikprogramme mit dem Server kommunizieren können müssen Sie diese Kommunikation freigeben. Das tun Sie, indem Sie auf diesem Dialog den Button 'Nicht mehr blocken' drücken. Danach startet der TimeServer und damit auch die Statikprogramme ohne Probleme.

Wenn Sie dann über die Systemsteuerung in die Einstellungen der Windows-Firewall gehen, dann finden Sie dort folgenden Dialog vor:

Der TimeWise-Server ist in dieser Abbildung das Programm ganz unten in der Liste der Programme. (XTimeWise Server-Part for local and LAN setups). Das Häkchen neben dem Programm besagt, das für dieses Programm die Blockierung durch die Firewall aufgehoben ist.

Die Blockierung wird dabei von Haus aus völlig aufgehoben - das ist aber deutlich freier als notwendig: Der TimeServer muss nämlich nur vom eigenen Rechner oder von Rechnern in Ihrem LAN (Subnetz) erreichbar sein. Das können Sie mit dem Button 'Bearbeiten' einstellen: Wenn Sie hir die Option für 'Subnetze' wählen, dann ist ihr TimeWise Server nur noch aus dem eigenen LAN erreichbar - genau so sollte das auch sein.