Resize komplexer Visualisierungen Teil 1: Windows Forms

Bewertung:  / 1

So ziemlich alle moderneren GUI Toolkits bieten heute die Möglichkeit die einzelnen Komponenten eines Bildschirmes bei Vergrößerung oder Verkleinerung der Auflösung entsprechend anzupassen. Dies passiert jedoch meist über Distanzblöcke, Anchors, oder Grids. Dies ist zwar bei Standard GUIs meist ausreichend, stößt aber spätestens dann an die Grenzen, wenn bei einem komplexen SCADA System alle dargestellten Elemente zueinander verschobe bzw vergrößert werden müssen und die Relationen der Elemente zueinander erhalten bleiben sollen. Es sieht ja auch blöd aus, wenn bei einem Piping Diagramm auf einmal die Rohre nicht mehr aneinander stoßen sondern Lücken dazwischen sind.

Bei dem Versuch diese Probleme mit den normalen Positionierungs-Mitteln eines GUI Frameworks zu lösen wird man kläglich scheitern.

Ebenfalls gibt es das Problem, dass vielleicht die Elemente zueinander in Relation bleiben, allerdings gibt es keine Lösung, den Font entsprechend auch noch anzupassen. Was nutzt es wenn bei Wechsel von einem 640 x 480 Schirm auf Full HD zwar die Element angepasst werden, aber die Fonts in Ihrer Größe nicht mit vergrößert werden. Man wird dann zwangsläufig auf dem HD Display zur Lupe Greifen müssen. Oder besser zum Fernglas, denn meist geht mit der Erhöhung der Bilddiagonale und Auflösung auch eine Erhöhung der Distanz zwischen Betrachter und Display einher.  

Hier beschreiben wir eine Klasse für Windows Forms, die dieses Problem löst.

Die Solution für VS2012 finden Sie im zip Format im Anhang zu diesem Artikel.

Zunächsten Leiten wir uns eine Klasse von UserControl ab, die wir bspw. ResizeControl nennen. Diese abgeleitete Klasse wird nun um ein paar Funktionen erweitert.

1.

Zunächst wird eine neue Struktur angelegt. Hier werden zu jedem Control das auf dem Container liegt die ursprünglichen Daten gespeichert

struct myControl

        {

            public string Name;      // Control Name

            public Point Location;   // Control Location

            public int Width;        // Control Breite

            public int Height;       // Control Höhe

            public float CharSize;   // Control Zeichengröße

        }

2.

Es wird ein Dictionary deklariert, dass für alle Controls die zugehörigen Daten der Struktur myControl speichert.

Dictionary<string, myControl> myControls = newDictionary<string, myControl>();

3.

Für das Container Control werden dann einige original Daten gespeichert.

       public float factorWidth, factorHeight;

    public float OrigWidth, OrigHeight;

4.

Als erste neue Funktion wird das Speichern der vorhandenen Controls auf dem Container realisiert. Die Funktion ist rekursiv und betrachtet alle Controls, auch die, die in Sub-Controls liegen. Controls, die selber resizable sind, werden nicht berücksichtigt. 

publicvoid FillControls(ControlCollection concol)
{
    try
    {
       for (int i = 0; i < concol.Count; i++)
       {
          // Don't resize children of resizable controls, because they resize themself
          if (!(concol[i] isResizableControl) && concol[i].HasChildren)
          {
              ControlCollection newcol = concol[i].Controls;
              FillControls(newcol);
          }
          myControl c = newmyControl();
          c.Name = concol[i].Name;
          c.Location = concol[i].Location;
          c.Width = concol[i].Width;
          c.Height = concol[i].Height;
          c.CharSize = concol[i].Font.Size;
        
          if (c.Name != "" && !myControls.ContainsKey(c.Name))
          {
              myControls.Add(c.Name, c);
          }
       }
    }
    catch (Exception E)
    {
        Console.WriteLine("");
    }
}

5.

Für das eigentliche resize der Controls wird nun eine Funktion erstellt die durch alle Controls geht und diese in Position und Größe anpasst. Auch rekursive für alle Sub-Controls.

publicvoid resizeControls(ControlCollection concol)
{
    try
    {
        for (int i = 0; i < concol.Count; i++)
        {
            // Resize also all children of the container
            // Don't do it for resizable controls because they resize themself
            if (!(concol[i] is ResizableControl) && concol[i].HasChildren)
            {
                ControlCollection newcol = concol[i].Controls;
                resizeControls(newcol);
            }

            if (myControls.ContainsKey(concol[i].Name))
            {
                myControl mc = myControls[concol[i].Name];
                concol[i].Location = new Point((int)((float)mc.Location.X * factorWidth), (int) ((float)mc.Location.Y * factorHeight));
                concol[i].Width = (int)((float)mc.Width * factorWidth);
                concol[i].Height = (int)((float)mc.Height * factorHeight);

                float newFontSize = mc.CharSize * factorHeight;
                Font myFont = new Font(concol[i].Font.FontFamily, newFontSize, concol[i].Font.Style);
                concol[i].Font = myFont;
            }
        }
    }
    catch (Exception E)
    {
        Console.WriteLine("");
    }
}

Attachments:
Download this file (ResizableControl.zip)Resizable Control in Windows Forms[Ein abgeleitetes UserControl mit automatischer resize Funktion]121 kB

TwinSAFE KL6904 an BK1120

Bewertung:  / 1

Vor kurzem wurde ich zu einem Serviceeinsatz bei einem unserer Kunden gerufen. Der Kunde plante eine Maschine umzubauen und dazu mussten einige Änderungen an der Steuerung und an dem Notaus System durchgeführt werden. Insbesondere wurden Lichtgitter und verschiedene Sicherheitssensoren entfernt.

Die Steuerung basiert auf TwinCAT und die externen Module sind über EtherCAT angebunden. 

Bei dem Versuch die geänderte Logik des TwinSAFE Programms über den Verifier auf die KL6904 zu laden meldete der Verifier dann jedes mal "Der Host meldet Fehler, Klemme nicht erreichbar".

Zunächst vermutete ich ein Problem beim BK1120, da dieser auch sporadisch in den SAFEOP Modus schaltete. Ein Austausch des BK1120 ergab zwar, dass der neue BK1120 nun nicht mehr in den SAFOP Modus schaltete, aber die KL6904 war immer noch nicht erreichbar. Nach mehrfachen Versuchen, bis zu dem Punkt, da wir nur noch den BK1120 mit der KL6904 am Bus hatten war das Problem nicht zu lösen.

Letztendlich habe ich mich mit meinem Laptop an den Bus gehangen, und damit funktionierte es dann. Was war also das Problem?

Mein lokal laufendes TwinCAT war im Konfig Modus und im Free Run. Damit kam ich nun auf die Klemme. Das gleiche mit dem Steuerungs PC probiert funktionierte auch. Mir war aber nicht bekannt, dass man TwinCAT in den Konfig Modus schalten muss um Änderungen an dem TwinSAFE Programm auf die Klemme zu laden.

Nach Rücksprache mit der Firma Beckhoff kamen wir dann zu folgendem Ergebnis:

Der BK1120 war über eine Task mit 1 ms in der SPS synchronisiert. Dadurch entsteht so viel Traffic auf dem K-Bus, dass die KL6904 mit Ihrem Protokollen nicht mehr durchkommt und somit nicht beschrieben werden kann. 

Also, für alle die eine KL6904 mit BK1120 verwenden, synchronisieren Sie auf eine langsamere Task in der SPS oder aber schalten Sie TwinCAT in Konfig wenn das Programm über den Verifier geladen werden soll.

Zusätzliche Informationen