Category Archives: Computer und Internet

Bubble Mouse Move events from child controls up the hierarchy in Windows Forms

Windows Forms (or “WinForms” for short) does not know the concept of event bubbling (also called “event propagation” sometimes). To solve this in terms of command routing, I’ve written some small classes earlier.

To bubble up events from child controls to parent controls (or the form itself), the idea is to hook into the child control creation and hook up for those specific events and manually forward them.

Based on this idea and with the help of a forum answer on MSDN, I’ve written a small class that you can attach to a control and get all child control MouseMove events. The class looks like:

public sealed class MouseEventBubbler
{
    private readonly Control _attachTo;

    public MouseEventBubbler(Control attachTo)
    {
        _attachTo = attachTo;

        _attachTo.MouseMove += _attachTo_MouseMove;

        _attachTo.ControlAdded += _attachTo_ControlAdded;
        _attachTo.ControlRemoved += _attachTo_ControlRemoved;

        foreach (Control control in _attachTo.Controls)
        {
            AttachToControl(control);
        }
    }

    public void _attachTo_MouseMove(object sender, MouseEventArgs e)
    {
        OnMouseMove(e);
    }

    public event MouseEventHandler MouseMove;

    private void _attachTo_ControlAdded(object sender, ControlEventArgs e)
    {
        AttachToControl(e.Control);
    }

    private void _attachTo_ControlRemoved(object sender, ControlEventArgs e)
    {
        DetachFromControl(e.Control);
    }

    private void AttachToControl(Control c)
    {
        c.MouseMove += Child_MouseMove;
        c.ControlAdded += Child_ControlAdded;
        c.ControlRemoved += Child_ControlRemoved;
        AttachToChildren(c);
    }

    private void AttachToChildren(Control parent)
    {
        foreach (Control child in parent.Controls)
        {
            AttachToControl(child);
        }
    }

    private void DetachFromControl(Control c)
    {
        DetachFromChildren(c);
        c.MouseMove -= Child_MouseMove;
        c.ControlAdded -= Child_ControlAdded;
        c.ControlRemoved -= Child_ControlRemoved;
    }

    private void DetachFromChildren(Control parent)
    {
        foreach (Control child in parent.Controls)
        {
            DetachFromControl(child);
        }
    }

    private void Child_ControlAdded(object sender, ControlEventArgs e)
    {
        AttachToControl(e.Control);
    }

    private void Child_ControlRemoved(object sender, ControlEventArgs e)
    {
        DetachFromControl(e.Control);
    }

    private void Child_MouseMove(object sender, MouseEventArgs e)
    {
        var pt = e.Location;
        var child = (Control)sender;
        do
        {
            pt.Offset(child.Left, child.Top);
            child = child.Parent;
        }
        while (child != _attachTo);

        var newArgs = new MouseEventArgs(e.Button, e.Clicks, pt.X, pt.Y, e.Delta);
        OnMouseMove(newArgs);
    }

    private void OnMouseMove(MouseEventArgs newArgs)
    {
        var h = MouseMove;
        if (h != null)
        {
            h(this, newArgs);
        }
    }
}

I’ve also saved it as a PasteBin.

The class can be adjusted to match other events than the MouseMove event, if required.

Dateigrößenangaben in C# menschenlesbar formatieren

Um aus Byte-Angaben (z.B. von Dateigrößen) menschenlesbare Werte (z.B. “12.5GB”) zu machen, sowie den anderen Weg, habe ich mir ein bisschen Code geschrieben bzw. von Stack Overflow zusammen gesucht:

public static class SizeTranslationHelper
{
    /// <summary>
    /// Converts bytes to human-readable, e.g. "12.5GB".
    /// </summary>
    public static string MakeLazy(ulong byteCount)
    {
        string[] suf = { @"B", @"KB", @"MB", @"GB", @"TB", @"PB", @"EB" }; //Longs run out around EB
        if (byteCount == 0)
            return "0" + suf[0];
        var bytes = (ulong)Math.Abs((decimal)byteCount);
        var place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024ul)));
        var num = Math.Round(bytes / Math.Pow(1024ul, place), 1);
        return (Math.Sign((decimal)byteCount) * num).ToString(CultureInfo.InvariantCulture) + suf[place];
    }

    /// <summary>
    /// Converts human-readable, e.g. "12.5GB", to bytes.
    /// </summary>
    public static ulong TranslateLazySize(string sizeLazy)
    {
        sizeLazy = sizeLazy.ToLowerInvariant();

        ulong result = 0;
        if (tryParse(ref result, sizeLazy, @"b", 1ul))
        {
            return result;
        }
        else if (tryParse(ref result, sizeLazy, @"kb", 1024ul))
        {
            return result;
        }
        else if (tryParse(ref result, sizeLazy, @"mb", 1024ul * 1024ul))
        {
            return result;
        }
        else if (tryParse(ref result, sizeLazy, @"gb", 1024ul * 1024ul * 1024ul))
        {
            return result;
        }
        else if (tryParse(ref result, sizeLazy, @"tb", 1024ul * 1024ul * 1024ul * 1024ul))
        {
            return result;
        }
        else if (tryParse(ref result, sizeLazy, @"pb", 1024ul * 1024ul * 1024ul * 1024ul * 1024ul))
        {
            return result;
        }
        else if (tryParse(ref result, sizeLazy, @"eb", 1024ul * 1024ul * 1024ul * 1024ul * 1024ul * 1024ul))
        {
            return result;
        }
        else
        {
            decimal r;
            if (decimal.TryParse(sizeLazy, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out r))
            {
                return (ulong)r;
            }
            else
            {
                throw new Exception(string.Format(@"Cannot parse '{0}' to number.", sizeLazy));
            }
        }
    }

    private static bool tryParse(ref ulong result, string sizeLazy, string suffix, ulong factor)
    {
        decimal r;
        if (
            sizeLazy.EndsWith(suffix) &&
            decimal.TryParse(sizeLazy.Substring(0, sizeLazy.Length - suffix.Length), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out r))
        {
            result = (ulong)(r * factor);
            return true;
        }
        else
        {
            return false;
        }
    }
}

Hier noch der Pastebin-Eintrag dazu.

Zeig mir deine Grill-Hardware, und ich sag dir, wer du bist

Wer hätte gedacht, dass der Sommer wie aus dem Nichts auftaucht? Den Frühling haben wir wohl gekonnt übersprungen, und nun werden die Wiesen in Parks und an Ufern von Grillvölkern bewohnt. Und wenn man da durch die Schlachtfelder der Schaschlik-Spieße schlendert, merkt man schnell: Die verschiedenen Grillvölker definieren sich durch ihre Hardware. Ganz unähnlich sind sie da uns Computer-Aficionados also nicht … Die Inspektion der physischen Bestandteile der konkurrierenden Grills (und wir sprechen hier natürlich von Holzkohlegrills) erfolgt bei den meisten Wiesennomaden aus dem Blickwinkel heraus – man will ja nicht auffallen. Vorlieben werden dabei mit einem wohlwollenden Nicken honoriert, Abneigungen hingegen mit einem spöttischen Lächeln im Mundwinkel quittiert. Holzkohlegrill ist schließlich nicht gleich Holzkohlegrill. So mannigfaltig die Ausführungen des Grills sind, so variabel definieren sie auch den dahinter stehenden Brutzler. Edingershops.de bietet verschiedene Modelle von Weber Grill, die zur Typologie der hier vorgestellten Grillmeister passen.

Bratwurst-pixelio

Der tragbare Kugelgrill, zum Beispiel, hat eine äußerst niedrige Höhe. Er ist der perfekte Begleiter für den entspannten Zeitgenossen, der die Sonnenseite des Lebens liebt. Und das nicht nur sprichwörtlich. Wohin auch immer die Sonne wandert, der gechillte Grillmeister geht mit ihr mit. Er wird niemals im Schatten stehen. Oder besser: sitzen. Denn der tragbare Grill ist vor allem ein Allrounder für hippieeske Wiesen-Sit-Ins. Am Grill vegetarische Würstchen wendend herumstehen, während alles anderen liegend entspannen? Nö. Zu anstrengend.

Einen Grill von der Tankstelle guckt der professionelle Premiumgriller nur mit verzogener Miene an. Er ist jeden Sommer in seiner Grill-Montur (Schürze mit einem kecken Sprücheklopfer-Aufdruck und hitzeresistente Ofenhandschuhe) und mit seiner „Software“ (zwei verschiedene Grill-Roste, Spezial Briketts) vor Ort, um allen zu demonstrieren, wer der Grill-König ist. Wie viel PS sein unverwüstlicher Edelstahl-Grill hat, stellt er gern zu Schau: Komfortable Stehhöhe, Lenkrollen und Räder an den Stehfüßen, eine Ablagefläche für das argentinische Rindersteak, und ein Deckelthermometer. Durch neidische Blicke fühlt er sich in seiner Überlegenheit bestätigt. Doch Achtung: Niemand sonst darf seinen Premiumgrill befeuern, also Finger weg!

Der Durchschnittsbrutzler hingegen hat es leicht. Er bleibt im Kampf der Grillvölker schweizerisch neutral und ist nur des Grillens wegen ein Wiesenbewohner. Er macht seinen Grillabend weder zu einem Happening noch zu einem Exklusiv-Event und betrachtet seinen Grill als Arbeitstier, das genau das machen soll, wozu es gedacht ist: Lebensmittel lecker machen. Im Vorhinein eine Grillkunde zu studieren, würde ihm nicht mal im Traum einfallen, und so brät er seine Würstchen nach einem Rezept aus Bauchgefühl und Erfahrung auf einem Grill, den er schon seit Jahren besitzt und liebevoll pflegt.

Also nichts wie raus auf die Wiesen der Republik mit Bier und Grillgut im Gepäck. Welchen Grill auch immer ihr besitzt: Viel Vergnügen und guten Appetit!

Bildquelle: Katharina Wieland Müller / pixelio.de

“Staatsbürgerkunde” – Podcast über DDR-Geschichte(n)

Ein herzallerliebster Podcast:

Staatsbürgerkunde

staatsbuergerkunde-podcast

Darin geht es um verschiedene Aspekte der DDR-Geschichte, und zwar zum größten Teil selbst erlebter Geschichte.

Der “Protagonist” das Podcasts lädt regelmäßig seine Eltern oder andere Besucher zu Gesprächen ein und erzählt dann jeweils zu einem Thema, z.B. Eisenbahn oder NVA oder die eigene Auswanderung noch zu DDR-Zeiten.

Mich berührt das jedes mal wieder und unterhält mich prächtig. Dank dem Niedergang der DDR habe ich eine tolle Frau und einen wunderbaren Sohn. Deshalb habe ich, zumindest indirekt, eine Affinität zur ehemaligen “Zone”.

Der Podcast erscheint so ca. alle 3 Wochen. Ich kann ihn Euch nur wärmstens ans Herz legen!

Fehlermeldung “System.MethodAccessException” bei .NET-4-Programmen beheben

Habe vorhin ein .NET-2-Programm (Windows Forms) nach .NET 4.5 geändert (also in der Projektkonfiguration in Visual Studio .NET 2012 das Ziel-Framework geändert.

Bei diesem Aufruf hat es dann gekracht:

AppDomain.CurrentDomain.UnhandledException += currentDomain_UnhandledException;

Dort kam dann eine Fehlermeldung:

System.MethodAccessException was unhandled HResult=-2146233072 Message=Fehler beim Versuch der SecurityTransparent-Methode “ZetaHelpdesk.Main.Code.AppHost.Host.Main()”, auf die sicherheitskritische Methode “System.AppDomain.add_UnhandledException(System.UnhandledExceptionEventHandler)” zuzugreifen.

Die Assembly “zeta-helpdesk, Version=2.1.0.1, Culture=neutral, PublicKeyToken=1dbe5f735b90e083″ ist mit “AllowPartiallyTrustedCallersAttribute” markiert und verwendet das Sicherheitstransparenzmodell der Stufe 2. Bei Festlegung der Transparenz auf Stufe 2 werden alle Methoden in AllowPartiallyTrustedCallers-Assemblys standardmäßig sicherheitstransparent, was die Ursache der Ausnahme sein kann.

Source=zeta-helpdesk

StackTrace: bei ZetaHelpdesk.Main.Code.AppHost.Host.Main() in c:\P\Zeta Helpdesk\Source\Core\Main\Code\AppHost\Host.cs:Zeile 100. bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() bei System.Threading.ThreadHelper.ThreadStart_Context(Object state) bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) bei System.Threading.ThreadHelper.ThreadStart() InnerException:

Wer die Fehlermeldung aufmerksam liest, findet auch schon die Ursache. Da steht nämlich, dass ein Assembly-Attribut hier unpassend ist. Und tatsächlich habe ich folgendes in der Datei “AssemblyInfo.cs” stehen:

[assembly: AllowPartiallyTrustedCallers]

Ich hatte seinerzeit aus diesem Grund das Attribut eingefügt.

Als ich das Attribut dann entfernt habe, lief alles wie gewünscht. Neu kompilieren natürlich auch noch ;-)

Fernbedienung bei elektrischem Garagentorantrieb funktioniert nicht mehr – Lösung

Vor kurzem war mein Garagentor “defekt” im Sinne, dass es nicht mehr richtig hoch/runter fuhr:

Ursache war, dass der Endpunkt sich wohl irgendwie verstellt hatte. Das habe ich dann mithilfe des Handbuchs zum Antrieb entsprechend korrigieren können.

Da das Handbuch die Platine und Schalter irgendwie anders als mein Modell skizziert hatte, habe ich wohl auch irrtümlich dabei die Funkfernbedienung deaktiviert.

Heute habe ich dann mit Try-and-Error tatsächlich die Fernbedienung wieder zum Laufen gebracht:

BAS-Tortechnik-AMS120-Fernbedienung

Die Lösung war dann:

  • Knopf in obigem Bild (“PROG/RESET”) 3 Sekunden drücken, bis Ton ertönt.
  • Dann auf Fernbedienung drücken. Es ist ein Piepsen zu hören.
  • Dann nochmals den “PROG/RESET”-Knopf (“Schalter”, jaja) für 3 Sekunden drücken.
  • Und dann nochmals auf der Fernbedinung.

Danach fuhr es bei mir wieder korrekt runter als auch hoch.

Ggf. habe ich auch öfters auf die Fernbedienung gedrückt. Auf jeden Fall läuft es jetzt :-) Und der Anschlag oben/unten stimmt auch noch.

Unter Windows 8, Bilder mit der Desktop-Bildanzeige öffnen

Unter Windows 8 startet beim Anklicken von Bildern im Explorer im Desktop-Modus leider die Vollbild-Kachel-Anwendung “Foto”.

Das stört mich sehr. Zum Glück gibt es einen Weg, wieder die unter Windows 7 bekannte Bildanzeige mit all ihren Vorteilen anzuzeigen:

  1. From the desktop, load the Control Panel. Right-click the screen’s bottom-left corner and choose Control Panel from the pop-up menu.
  2. When the Control Panel opens, click the Programs category. Click Default Programs and then click Set Your Default Programs. The Set Default Programs window appears.
  3. From the left pane, click Windows Photo Viewer. Then select Set This Program As Default and click OK. That tells Windows Photo Viewer to open all of your photos, bypassing the Start screen’s Photos app.

Danach geht’s wieder sauber.