Thomas Woelfers Baustatik Blog

Baustatik-Software und was sonst des Weges kommt

Pause

Ich hatte ja eigentlich angenommen, das die Sache mit der Erkältung ein Ende hat (Schleimproduktion eingestellt...) - aber das machte sich dann relativ schnell als Irrtum bemerkbar. Jetzt scheinen die Medikamente aber so langsam zu wirken und ich mache mir ein faules Wochenende.

Schleimproduktion eingestellt

Nachdem ich mich fast die gesamte letzte Woche eigentlich nur mit der Produktion von Schleim befasst habe, bin ich nun so langsam wieder auf dem damm - und wollte von einem "netten" bug berichten, der mich heute einige stunden gekostet hat.

Im Faltwerksprogramm gibt es ein Modell, das es erlaubt, beliebige Eigenschaften von beliebien Objekten zu beliebigen Zeitpunkten zu verändern. Dazu gibt es in jedem Objekt eine Liste von "Clients" - diesen Clients wird mitgeteilt, wenn es eine Änderung an einer Eigenschaft eines Objektes gab. Das kann man dann z.b. benutzen, um die Darstellung des Objektes anzupassen und ähnliches.

Wird ein Objekt gelöscht, dann wird die Liste der Clients geleert. Bis vor kurzen sah der Code dazu wie folgt aus:

while( clients.Count > 0) { clients[0].Disconnect(); }

Im Zuge des Disconnect() trägt sich der Client aus der Liste "clients" aus. Aus Performance-Gründen hatten wir diese Code wie folgt abgeändert:

while( clients.Count > 0) { clients[clients.Count-1].Disconnect(); } Resultat: Sehr merkwürdige Abstürze an unerwarteten Stellen. Was war passiert?

Man sollte meinen, das die vorgenommene Änderung keinerlei Auswirkungen haben kann - eben bis auf den Performance-Gewinn. Doch leider: Diese Änderung verändert tatsächlich die Semantik der ganzen Client/Server beziehung: Plötzlich bekommen die zuletzt erzeugten Clients Ihre "Disconnect()" Nachricht, bevor die ersten Clients die bekommen.

Schon komisch, wie sich eine Menge Arbeit hinter minimalen Änderungen verstecken kann.

Server geht wieder

Klar: Nachdem letzte Woche ein Stück Hardware ausgefallen war, war kurz drauf am Montag abend das nächste dran. Ich habs aber nicht gemerkt, weil ich noch immer mit Grippe im Bett lag. Heute habe ich die Sache aber gerichtet, zumindest für die nächsten paar Tage - und verkrieche mich nun wieder mit meiner Grippe ins Bett. Irgendwann muss es ja besser werden. :-(

Die goldene Regel

Es gibt eine goldene Regel für den Ausfall von Hardware: Der tritt immer ein, wenn es am ungünstigsten ist.

Gestern starb also das Netzteil von www.die.de - und das passiert natürlich nicht um 18.00, wenn man noch schnell ein neues besorgen könnte - sondern natürlich um 21:15. Am Abend vor dem Oster-Wochenende.

Hurra.

Jetzt gehts zwar wieder, aber ich traue der Hardware nicht besonders weit: Es ist schon seit geraumer Zeit "Zeit", den Server auf neue Hardware umzuziehen. Damit fange ich dann jetzt wohl besser mal an. Vorher widme ich mich aber noch ein bisschen meiner Grippe. Scheint ein klasse Wochenende zu werden.

Unterhaltung fürs Wochenende

Nachdem es diesmal ja ein ganz besonders langes Wochenende ist, hier ein Link den ich mir für genau so eine Gelegenheit aufgespart habe: Curveball. Ein Spiel. Um genau zu sein - eine Egoshooter-Variante von Pong. Vorsicht: Leicht suchterzeugend, man kann durchaus einige Stunden vom Wochenende damit verlieren.  :-)

Windows, Office und die Updates

Wer "Windows Update" verwendet, um seinen Rechner auf dem neuesten Stand zu halten, der tut gut daran. Schon allein aus Sicherheitsgründen sollte man die automatischen Updates verwenden, und sich Windows darüm kümmern lassen, das es sich selbst auf dem neuesten Stand hält.

Seit einiger Zeit gibt es aber eine deutlich bessere Alternative: Microsoft Update. Auch das kann automatisch betrieben werden und sich selbst darum kümmern, das das System immer auf dem neuesten Stand ist. Im Gegensatz zum normalen Windows Update kümmert sich Microsoft Update aber noch zusätzlich um Updates für die Office-Programme wie Outlook und Word, sowie um weitere Software wie zum Beispiel SQL Server. Ich kann den Umstieg nur empfehlen.

Forms dynamisch erweitern

Unter MFC (von der reinen Win32 API brauchen wir erst gar nicht reden) war es immer ein wenig aufwendig, Dialoge dynamisch zu erweitern. Mit dem Support für Tabs auf Dialogen ging das dann irgendwann deutlich besser - war aber immer noch "komisch".

Mit Windows.Forms ist die Sache hingegen extrem einfach. Angenommen, man hat einen Dialog mit einem TabControl, und der Dialog soll zur Laufzeit um neue TabPages erweitert werden. Diese Pages, einschliesslich aller Eventhandler, legt man einfach mit dem Forms-Editor auf einer anderen Form an: Man tut also einfach so, als wäre die 2. Form die "richtige" Form. Spezialcode für die Tatsache, das die TabPages zur Laufzeit auf einer anderen Form liegen braucht man nicht.

Jetzt geht es nur noch darum, die Pages von der einen auf die andere Form zu transportieren. Unter der Vorraussetzung das die Form mit den zusätzlichen Pages in Form der Klasse Option1 vorliegt, und das TabControl auf dieser Form den Namen "tabControl1" hat, geht das wie folgt:

private void GetExternalPages()
{
   Option1 o = new Option1();
   Control[] controls = o.Controls.Find("tabControl1", false);
   if (controls.Length != 1) throw new InvalidOperationException("Quellform ist nicht richtig aufgebaut. Vermutlich fehlt das TabControl.");

   TabControl source = controls[0] as TabControl;

   while( source.TabPages.Count > 0)
   {
      TabPage page = source.TabPages[0];
      source.TabPages.Remove(page);
      this.tabControl1.TabPages.Add(page);
   }
}

Warum ist der Cursor in Word plötzlich so klein?

Heute hatte ich ein interessantes Phänomen: Der Cursor in Word (die "Einfügemarke", also das Ding, das blinkt) war plötzlich nur noch etwa halb so hoch wie die Zeile die ich bearbeiten wollte. In den Optionen habe ich nichts gefunden, das das Ding wieder auch die "richtige" Größe bringen konnte. Und der "kleine" Cursor ist schlecht - man kann dann tatsächlich deutlich schlechter lesen, was man gerade tippt.

Grund und Lösung: Offenbar ein Bug in der "Zoom" Funktion von Word. Wenn man die Einstellungen für Zoom einmal ändert und dann wieder auf den eigentlich gewünschten Wert stellt, ist der Cursor wieder richtig.

Der TypeDescriptor und ICustomTypeDescriptor

Wenn man den TypeDescriptor verwendet, um zum Beispiel an die Properties eines Objektes zu gelangen, dann gibt es da zwei Methode: Die eine bekommt ein Objekt, die anderen einen Typ. (Die gibt es dann mit mehreren Geschmacksrichtungen wie zum Beispiel Filter...)

Auf den ersten Blick ist nicht ersichtlich warum es überhaupt zwei davon gibt: Wenn man ein Objekt hat, kann man per GetType() schliesslich einfach an den Typ kommen - es würde also eine Methode in TypeDescriptor reichen. Die Dokumentation sagt auch nicht viel dazu aus, und wen man ein kleines Testprogramm mit ein paar Properties schreibt, dann bekommt man auch in beiden Fällen das gleiche.

Allerdings nicht immer - und zwar dann nicht, wenn der Typ "ICustomTypeDescriptor" implementiert. Tut er das, dann bekommt man mit TypeDescriptor.GetProperties( Type ) die "Original" Properties, und mit GetProperties( object) die "CustomProperties".

Das ist auch sinnvoll: Irgendwie muss die Implementierung von ICustomTypeDescriptor ja an die "Original" Properties drankommen - und das geht dann eben über GetProperties( Type).