Laden...

WndProc in ClassLib nutzen

Erstellt von moelski vor 11 Jahren Letzter Beitrag vor 11 Jahren 994 Views
M
moelski Themenstarter:in
183 Beiträge seit 2011
vor 11 Jahren
WndProc in ClassLib nutzen

Moin !

Ich schreibe mir gerade eine ClassLib zur Kommunikation mit RS232 und USB HID. Nun würde ich in der ClassLib gerne eine Möglichkeit schaffen USB Geräte (Arrive / Remove) zu erkennen.
Die Lib soll sowohl in einer Consolen- wie auch WinFormanwendung laufen.

Da die Consolen Anwendung keine Messages mitbekommt war meine Idee folgende :

  • in der ClassLib ein Form hinzufügen
  • Form Instanz erzeugen
  • Form hidden setzen
  • mit Show "aufrufen"

Allerdings klappt das nicht in einer Consolen Anwendung. Denn wie ich gelesen habe reicht ein einfaches Show nicht damit das Form auch die Messages mitbekommt. Das geht zwar mit ShowDialog, aber das ist auch nicht die Lösung weil dann die Anwendung steht ...

Auch der DriveDetect von hier:
Detecting USB Drive Removal in a C# Program
hat mir nicht wirklich weiter geholfen. Denn der funktioniert ebenfalls nicht mit Consolen Anwendungen.

Hat jemand evtl. eine Lösung wie ich sowohl in Console als auch WinForms Anwendung die Messages abgreifen kann?

Greetz Dominik

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo moelski,

Das geht zwar mit ShowDialog, aber das ist auch nicht die Lösung weil dann die Anwendung steht ...

ShowDialog ist auch nur ein unschöner und unnötiger Workaround. Wie allgemein bekannt, startet man die Nachrichtenverarbeitung durch Apllication.Run.

Und dann steht die Anwendung natürlich auch nicht, sonst würden Windows-Forms-Programme, die im Main oft nichts anders tun als (ein Form zu erstellen und dann) Application.Run aufzurufen, ebenfalls stehen. Application.Run kehrt lediglich solange nicht zurück, solange die Nachrichtenverarbeitung (laufen soll bzw.) läuft. Und das ist üblicherweise solange die Anwendung läuft. Aktionen hinter dem Apllication.Run werden also in der Tat nicht parallel zum Application.Run, sondern erst nach dessen Ende ausgeführt.

Die Lösung ist aber ganz einfach und auch nicht anders als bei reinen Windows-Forms-Anwendungen: Langlaufende Aktionen müssen in einen anderen Thread ausgelagert werden, siehe [FAQ] Warum blockiert mein GUI?. In einem Konsolenprogramm ist die eigentliche Funktion des Programms die langlaufende Aktion.

Wenn das Application.Run erst in einer Klassenbibliothek genutzt wird, kann es nötig sein, die Threads "umzudrehen", also die eigentliche (langlaufende) Aktion im Main-Threads auszuführen und das Application.Run im extra Thread.

herbivore

M
moelski Themenstarter:in
183 Beiträge seit 2011
vor 11 Jahren

Moin herbivore,

danke für deine Erklärung !

Ich habe jetzt folgendes gemacht:

 Thread t = new Thread(new ThreadStart(StartNewForm));
t.Start();

private void StartNewForm()
{
Application.Run(new TestMessages(DoMessage));
}

private void DoMessage(object sender, MessageReceivedEventArgs eventArgs)
{
HandleDeviceChange(eventArgs.Message);
}

Und der Constructor in meinem Form sieht so aus:

        public delegate void ActiveDeviceRemovedHandler(object sender, MessageReceivedEventArgs e);

        public event ActiveDeviceRemovedHandler DoMessage;

        public TestMessages(ActiveDeviceRemovedHandler DoMessage)
        {
            this.DoMessage += DoMessage;
            InitializeComponent();
        }

Dann kann ich das Formular in einem eigenen Thread starten und über das Event habe ich meinen Hook für die Message Verarbeitung:

        protected override void WndProc(ref Message aMessage)
        {
            if (aMessage.Msg == DsSetupApi.WM_DEVICECHANGE)
            {
                DsLog.Core.LogVerbose(aMessage.ToString());
                if (DoMessage != null)
                {
                    MessageReceivedEventArgs mre = new MessageReceivedEventArgs(aMessage);
                    DoMessage(this, mre);
                }
            }

            base.WndProc(ref aMessage);
        }

Funktioniert soweit ganz gut.

Kannst du mir evtl. noch einen Tip geben wie ich den Thread mit der Form sauber beenden kann?

Greetz Dominik

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo moelski,

mit Application.Exit, aber [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke) beachten.

herbivore

M
moelski Themenstarter:in
183 Beiträge seit 2011
vor 11 Jahren

Moin herbivore,

you made my day 👍 👍

Vielen Dank für deine Hilfe. Funktioniert nun in Console und WinForm Anwendung :evil:

Greetz Dominik

4.221 Beiträge seit 2005
vor 11 Jahren

Nur so als Tipp: Schau Dir auch mal das IMessageFilter - Interface an... da findest Du ein paar interessante Beiträge.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

M
moelski Themenstarter:in
183 Beiträge seit 2011
vor 11 Jahren

Moin !

IMessageFilter ... Meine mich zu entsinnen das man damit nicht alle Messages abfangen kann.

Aber kann ich auc nochmal einen Blick drauf werfen. Danke !

Greetz Dominik