Laden...

Klasse soll ein Formular verstecken und anzeigen

Erstellt von WolleWtal vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.168 Views
W
WolleWtal Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren
Klasse soll ein Formular verstecken und anzeigen

Hallo zusammen,

Ich habe eine Klasse die durch die Main aufgerufen wird und diese erstellt in einem Thread einen TCP Listener, der mir auf Telnet Kommandos reagiert.

Wenn der listener den das Telnet Kommando HIDE erhällt soll er mir mein Formular verstecken, wenn er SHOW erhält soll das Formular angezeigt werden.

Der Listener läuft gut und macht was er soll.

Ich schaffe es einfach nicht, abhängig vom empfangenen Wert das Formular aus dem Listener heraus zu Steuern.

Habe mir hier und auch woanders schon die Form1 Form 2 Sachen angeschaut aber irgendwie komme ich damit nicht weiter.

Ist jemand so gut, und öffnet mir die Augen, ich habe nicht die leiseste Ahnung.

Grüße.

2.207 Beiträge seit 2011
vor 6 Jahren

Hallo WolleWtal,

hilf uns ein wenig dir zu helfen

meinst du mit

Habe mir hier und auch woanders schon die Form1 Form 2 Sachen angeschaut

zum Beispiel [FAQ] Warum blockiert mein GUI? ?

Was genau meinst du mit

irgendwie komme ich damit nicht weiter

Was hast du probiert? Wo hakt es? Hast du Code?

Gruss

Coffeebean

W
WolleWtal Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Hierhin übergibt meine Klasse den empfangenen Befehl:

 
public static void Befehl(String Befehl)
        {
            Worker(Befehl);
        }

Leider kann ich in der static anscheinend nicht den Befehl Show(); oder Hide(); nutzen.

Deswegen habe ich versucht den Befehl hierhin zu übergeben, was aber leider auch nicht funktioniert, weil dann anscheinend ein Objektverweis fehlt.



        private void Worker(String DoIt)
        {
            switch (DoIt)
            {
                case "SHOW":
                    Show();
                    break;
                case "HIDE":
                    Hide();
                    break;
                default:

                    break;
            }
        }

Ohne Hilfe bekomme ich das nicht hin.

Bin doch schon im Betreffenden Formular mit meinem Befehl, warum klappt dass denn dann nicht, ich verstehe es nicht.

Hier noch der gesamte Code des Formulars zur Vollständigkeit.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace nspHSBrowser
{
    /// <summary>
    /// 
    /// </summary>
    public partial class Browser : Form
    {
        /// <summary>
        /// 
        /// </summary>
        public Browser()
        {
            InitializeComponent();
            this.ShowInTaskbar = false;
            WB_01.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WB_01_DocumentCompleted);
            WB_01.Navigate("http://192.168.111.171:3777/");
        }

        private void HSWLaNOnOffico_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
        }
        private void WB_01_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            ((WebBrowser)sender).Document.Window.Error += new HtmlElementErrorEventHandler(Window_Error);
        }
        private void Window_Error(object sender, HtmlElementErrorEventArgs e)
        {
            e.Handled = true;

        }
        public static void Befehl(String Befehl)
        {
            Worker(Befehl);
        }
        private void Worker(String DoIt)
        {
            switch (DoIt)
            {
                case "SHOW":
                    Show();
                    break;
                case "HIDE":
                    Hide();
                    break;
                default:

                    break;
            }
        }
    }
}


Gruß, Wolle

16.806 Beiträge seit 2008
vor 6 Jahren

a) und warum ist die Methode static? Eine statische Methode kann eben keine Instanz-Methode aufrufen. Basics OOP. static entfernen und es geht.
b) Aktionen über Strings zu übergeben ist "der falschester" von allen möglichen Wegen. Wenn überhaupt in diesem Sinne, dann mit Enums.

Was das am Ende werden soll erschließt sich mir nicht wirklich.
Willst nicht mal beschreiben, was das eigentlich werden soll? Nur ein Remote-Kommando abwarten oder soll das mehr werden? Ein Bot?

W
WolleWtal Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Das fertige Programm nimmt über die TCPListener.cs Befehle von einem Smarthome Server über Telnet entgegen und soll je nach erhaltenem Befehl mein Form Anzeigen oder halt wieder ausblenden.

Die Form stellt nur einen Webserver ohne Rahmen zur Verfügung den ich halt über eine Visualisierung im Smarthome einblenden kann, sodass es aussieht, dass der Browser zur Visualisierung gehört.

Eigentlich ist das schon alles was passieren soll.
Das soll die Basis des Programmes werden, alles weitere steht noch nicht fest.

a) und warum ist die Methode static? Eine statische Methode kann eben keine Instanz-Methode aufrufen. Basics OOP. static entfernen und es geht.

Wenn ich Static entferne kann mein TCP-Listener nicht mehr auf


public void Befehl(String Befehl)
        {
            Worker(Befehl);
        } 

zugreifen.

Was muss ich machen, dass ich aus TCPListener.cs die Form Anzeigen, bzw. Ausblenden kann.

b) Aktionen über Strings zu übergeben ist "der falschester" von allen möglichen Wegen. Wenn überhaupt in diesem Sinne, dann mit Enums.

Die Ausgabe von TCPListener ist halt ein String der das enthält, was man per Telnet an den Listener übergeben hat.

Das ganze wollte ich halt mit switch auswerten, aber wie nun das Ergebnis aus TCPListener an die Form übergeben wird, ist mir egal, Hauptsache am Ende macht meine Form halt Show(); oder Hide();

Ich bekomme halt die Übergabe aus TCPListener nicht so hin, dass ich Show(); oder Hide(); im Formular ausführen kann.

Gruß, Wolle

16.806 Beiträge seit 2008
vor 6 Jahren

Also zu aller erst fehlen Dir wohl die absoluten Basics, was die objektorientierte Programmierung angeht. Daher ein freundlicher Hinweis auf [FAQ] Wie finde ich den Einstieg in C#?
Zudem programmierst Du in die falsche Richtung: die Business Logik sollte die UI nicht kennen, sondern umgekehrt.

Die UI sollte einen Event von TcpListener abonnieren, sodass die UI auf Aktionen reagieren kann.
Du versuchst es umgekehrt: das kann nicht klappen.

Bau also entsprechend Dein Code um, dann klappt es auch und ist dann prinzipiell auch Regelkonform.
Siehe auch [Artikel] Drei-Schichten-Architektur für das grundlegende Verständnis von Software.
(was Du machst ist der "verbotene Zugriff" ganz rechts im Bild des Einleitungsposts!)

W
WolleWtal Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Die UI sollte einen Event von TcpListener abonnieren, sodass die UI auf Aktionen reagieren kann.
Du versuchst es umgekehrt: das kann nicht klappen.

Kannst Du mir nicht mal ein Einfaches Beispiel dafür geben, wie man das richtig machen müsste?
Ich meine, anhand einer Klasse und einer Form.

Form Aboniert Event von Klasse und reagiert auf event.

Gruß

16.806 Beiträge seit 2008
vor 6 Jahren

Sorry, aber bitte hab Verständnis, dass ich Dir jetzt nicht den Code dazu schreiben werde; ich hab auch noch andere Dinge zutun. Sonst wäre ich Sonntags bei Sonnenschein auch nicht im Büro.
Das Forum ist halt auch kein kostenloser Code-Generator, weil man sich die Basics oder Doku nicht antun will 😃

Du brauchst:

  • eine Klasse (zB "Server"), die den TcpListener wrappt, da Du ja sicherlich auf die Clients hören willst.
  • Diese Klasse hat einen Event für "ClientConnected", sowie für "ClientDataReceived", denn Du willst ja auf die Daten hören, wenn ein Client was schickt.

Diesen Event musst Du dann in die UI abonnieren und darauf reagieren.

W
WolleWtal Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Das Du mir meinen kompletten Code schreibst, erwarte ich auch garnicht, aber ein wenig mehr Hilfe hätte ich mir schon erhofft.

Aber sei es drum.

Wenn ich dich richtig verstehe müsste TCPListener in meinem Beispiel von meiner Form erzeugt und auf ein Event, was vorher abonniert wurde, in TCPListener reagieren.

Richtig?

16.806 Beiträge seit 2008
vor 6 Jahren

Du musst Dir unbedingt die Basics aneignen, sonst fährt jeder Deiner Software-Versuche gegen die Wand.
Vom Code kopieren lernt man nichts - und ich fürchte einige Teile dieses Codes verstehst nicht ganz...

Und Du solltest unbedingt die Texte durchlesen, die man Dir schreibt 😉

Du brauchst:

  • eine Klasse (zB "Server"), die den TcpListener wrappt, da Du ja sicherlich auf die Clients hören willst.
  • Diese Klasse hat einen Event für "ClientConnected", sowie für "ClientDataReceived", denn Du willst ja auf die Daten hören, wenn ein Client was schickt.

Wenn ich dich richtig verstehe müsste TCPListener in meinem Beispiel von meiner Form erzeugt und auf ein Event, was vorher abonniert wurde, in TCPListener reagieren.

Client


    class Program
    {
        static void Main(string[] args)
        {
            var ipAddress = Dns.GetHostEntry("localhost").AddressList.First(a => a.AddressFamily == AddressFamily.InterNetwork);
            Thread.Sleep(5000); // wait for server start

            Console.WriteLine("Client: Connecting to server");

            // Create multiple clients with multiple textx
            foreach (var c in Enumerable.Range(0, 5))
            {
                TcpClient client = new TcpClient();
                client.Connect(ipAddress, 17597);

                Console.WriteLine($"Client #{c}: Connected to server");

                using (var clientWriteStream = new StreamWriter(client.GetStream()))
                {
                    foreach (var i in Enumerable.Range(0, 10))
                    {
                        clientWriteStream.WriteLine($"Hejsan #{i} from client #{c}");
                        clientWriteStream.Flush();

                    }
                }
            }

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();

        }
    }

Server


   class Program
    {
        static void Main(string[] startParameters)
        {
            Console.WriteLine("Server init.");

            var ipAddress = Dns.GetHostEntry("localhost").AddressList.First(a => a.AddressFamily == AddressFamily.InterNetwork);
            MyServer server = new MyServer(ipAddress, 17597);

            server.OnClientConnected += (sender, client) => Console.WriteLine($"[SERVER]: Client '{client.Client.RemoteEndPoint}' connected.");
            server.OnClientMessage += (sender, args) => Console.WriteLine($"[SERVER]: Message from client '{args.Client.Client.RemoteEndPoint}': '{args.Message}'");

            Console.WriteLine("Server start.");

            Task runningServer = server.RunServerAsync();

            Console.WriteLine("Server is running. Press any key to exit.");
            Console.ReadKey();

            try
            {
                server.Cancel(TimeSpan.FromSeconds(30));
                Console.WriteLine("Soft Cancel done.");
            }
            catch (Exception)
            {
                Console.WriteLine("Hard Cancel done.");
            }

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }



    public class MyServer
    {
        private TcpListener _listener;
        private List<TcpClient> _clients = new List<TcpClient>();
        private CancellationTokenSource _cts = new CancellationTokenSource();

        private Task _runningServerTask = null;
        private List<Task> _connectedClientTasks = new List<Task>();

        public MyServer(IPAddress address, int port)
        {
            _listener = new TcpListener(address, port);
        }

        // Events
        protected virtual void FireClientConnected(TcpClient client) => OnClientConnected?.Invoke(this, client);
        public event EventHandler<TcpClient> OnClientConnected;
        protected virtual void FireClientMessage(ClientMessageEventArgs args) => OnClientMessage?.Invoke(this, args);
        public event EventHandler<ClientMessageEventArgs> OnClientMessage;

        public Task RunServerAsync()
        {
            if (_runningServerTask == null)
            {
                try
                {
                    _runningServerTask = Task.Run(async () =>
                    {
                        _listener.Start();

                        while (true)
                        {
                            // warten bis jemand connected
                            TcpClient client = await _listener.AcceptTcpClientAsync();
                            _clients.Add(client);

                            _connectedClientTasks.Add(Task.Run(async () => { await ListenToClientAsync(client); }, _cts.Token));

                        }
                    }, _cts.Token);
                }
                catch (Exception ex) when (_cts.Token.IsCancellationRequested)
                {
                    // Es wurde ein Cancel angefragt
                }
                finally
                {
                    _listener.Stop();
                }
            }

            return _runningServerTask;
        }

        private async Task ListenToClientAsync(TcpClient client)
        {
            using (var stream = new StreamReader(client.GetStream()))
            {
                string data;
                while ((data = await stream.ReadLineAsync()) != null)
                {
                    FireClientMessage(new ClientMessageEventArgs(client, data));
                }
            }
        }


        public void Cancel(TimeSpan maxCancelWaitTime)
        {
            _cts.Cancel(maxCancelWaitTime);

            // Warten auf das Beenden aller Clients
            Task.WhenAll(_connectedClientTasks);

            // warten bis der Server beendet ist
            Task.WhenAll(_runningServerTask);
        }
    }

    public class ClientMessageEventArgs : EventArgs
    {
        public TcpClient Client { get; }
        public string Message { get; }

        public ClientMessageEventArgs(TcpClient client, string message)
        {
            Client = client;
            Message = message;
        }
    }

Die Konsolenanwendung ist hier die Präsentationsschicht.