Laden...

MessageFilter - Wert an Formular übergeben

Erstellt von Steve1974 vor 19 Jahren Letzter Beitrag vor 19 Jahren 3.910 Views
Steve1974 Themenstarter:in
13 Beiträge seit 2004
vor 19 Jahren
MessageFilter - Wert an Formular übergeben

Hallo,

ich habe eine IMessageFilter - Klasse, die Tastatureingaben an ein Formular auswertet, um gescannte Barcodes anhand von Präfix/Suffix auszufiltern. Die Klasse soll für mehrere Formulare verwendet werden.

Wie kann ich jetzt die Barcodes an das Formular zurückgeben?

public bool PreFilterMessage(ref Message m) 

...
Formular.HandleBarcode(barcode)
...

HandleBarocde ist keine Methode von Form...

Besten Dank,

Steve.

P
939 Beiträge seit 2003
vor 19 Jahren

Hi Steve,
du sagst ja der Barcode kommt als Tastatureingaben, so wertet man WM_KEYDOWN-Messages aus:

private static int WM_KEYDOWN = 0x0100;

// Barcode-Tastatureingaben ausfiltern.
public bool PreFilterMessage(ref Message m) {
  bool handled = false;

  switch(m.Msg) {
    case WM_KEYDOWN: 
      int keyCode = (int)m.WParam;

      // Wenn der keyCode zum Barcode gehört.
      if(keyCode ...) {
        // ...
        handled = true;
      }
      break;
  }

  return handled;
}

Die zugehörigen WM_KEYUP-Messages müssen auch ausgefiltert werden, höchstwahrscheinlich.

Gruss
Pulpapex

Steve1974 Themenstarter:in
13 Beiträge seit 2004
vor 19 Jahren

Hallo Pulpapex,

danke Dir für die Antwort.

Sorry, ich habe mich etwas missverständlich ausgedrückt. Der Filter funktioniert schon, nur die Daten die rausgefiltert werden, würde ich gerne an eine Methode des Formulars übergeben, um sie dort weiterzubehandeln (z.B. zugehörigen Artikel anzeigen). Also nicht als Tastaturausgabe sonder per Code übergeben.

Im Filter wird der Barcode in eine lokale Variable geschrieben. Wie kann ich jetzt die Variable Barcode an das Formular übergeben?

Besten Dank nochmal,

Steve.

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo Steve1974,

so ganz klar ist es mir immer noch nicht. Erbt denn deine Klasse Formular von Form? Wenn ja, dann kannste da doch gleich tun, was immer du willst. Wenn nicht, dann erstellst du in Deiner Klasse, die von Form erbt, eine neue Methode, die den Code als Parameter erhält und kannst in dieser Methode alles tun, was du willst.

HTH

herbivore

Steve1974 Themenstarter:in
13 Beiträge seit 2004
vor 19 Jahren

Hallo herbivore,

also ich versuche es nochmal:

Es gibt eine Klasse, die von IMessageFilter abgeleitet ist:

public class clsBarcodeMessageFilter : IMessageFilter
{
  string Barcode="";
  Form _fm;
  
  public clsBarcodeMessageFilter(Form fm)
  {
     _fm = fm;
  }

   public bool PreFilterMessage(ref Message m) 
   {
   
     if ((m.Msg == WM_KEYDOWN) || (m.Msg == WM_SYSKEYDOWN))
     {
         ...
        if (SuffixGescannt)
         { 
             // hier ist der Barcode fertig zusammengesetzt, und soll an Formular fm
             // übertragen werden.
  
            // Folgendes funktioniert nicht, da BarcodeScanned keine Methode von Form  ist:
             _fm.BarcodeScanned(Barcode);
            // Da die Klasse von mehreren Formularen verwendet werden soll, steht nicht
            // fest in welche abgeleitete Formularklasse genau konvertiert werden soll.
           }
         ...
      }
   }
}

von herbivore: ... dann erstellst du in Deiner Klasse, die von Form erbt, eine neue Methode, die den Code als Parameter erhält und kannst in dieser Methode alles tun, was du willst.

Wie ruft man dann die Methode auf?
(vgl. Kommentar im Code oben)
Form hat die Methode nicht. Man müßte vermutlich eine Typkonvertierung in die abgeleitete Formklasse (FrmDatenerfassung) machen, und dann die Methode aufrufen. Jetzt soll die Klasse clsBarcodeMessageFilter aber von mehreren verschiedenen Formularklassen verwendet werden. D.h. die Klasse in die man konvertieren müßte steht erst zur Laufzeit fest.

Das Formular sieht übrigens so aus:

public class FrmDatenerfassung : System.Windows.Forms.Form
{
...
  public FrmDatenerfassung()
  {
    InitializeComponent();
    clsBarcodeMessageFilter msgflt = new clsBarcodeMessageFilter(this);
    Application.AddMessageFilter(msgflt);
  }

  public void BarcodeScanned(string barcode)
  {
     // Behandlung des gescannten Barcodes; soll von clsBarcodeMessageFilter auferufen werden
   }

...
}

Hoffe es ist verständlich was ich meine, wenn nicht bitte nochmal nachfragen.

Danke für die Antworten,

Steve.

D
279 Beiträge seit 2004
vor 19 Jahren

Hallo,

du könntest eine Basisklasse erstellen, die von Form erbt und in der du BarcodeScanned implementierst. Dann leitest du deine anderen Form Klassen von dieser Klasse ab und erstellst in clsBarcodeMessageFilter eine Variablen des Typs der Basisklasse.

Wenn die Implementierung von BarcodeScanned allerdings in jeder Klasse anders sein soll, verwendest du Interfaces:


public interface IMyFrm
	{
		void BarcodeScanned(string barcode);
	}

	public class FrmDatenerfassung : Form, IMyFrm
	{
		// Form...
		public void BarcodeScanned(string barcode)
		{
			//Deine Implementierung
		}
	}
	
	public class clsBarcodeMessageFilter : IMessageFilter
	{
		IMyFrm _fm;

		public bool PreFilterMessage(ref Message m)
		{
			//...
			_fm.BarcodeScanned("test");
			//...
		}
	}

Ich weiß ja nicht, was du genau machen willst. Gegenbenfalls würde es auch einfach reichen die Methode einfach irgendwo statisch zu deklarieren und einfach die aktuelle Form mit zu übergeben. Dann könntest du die Methode aber ja auch direkt in der selben Klasse deklarieren...

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo Steve1974,

ich denke auch, dass die Lösung darin liegt, eine zusätzliche (Ober-)Klasse einzuführen, die die benötigte Methode deklariert. Die verschiedenen Forumlare müssen dann von dieser erben statt von Form. Der Name FormWithBarcodeScannedMethod ist natürlich verbesserungsfähig.


public abstract class FormWithBarcodeScannedMethod : Form
{
   public virtual void BarcodeScanned (string barcode)
   {
   }
   //...
}

public class clsBarcodeMessageFilter : IMessageFilter
{
  string Barcode="";
  FormWithBarcodeScannedMethod _fm;
  
  public clsBarcodeMessageFilter(FormWithBarcodeScannedMethod fm)
  {
     _fm = fm;
  }
  //...
}

HTH

herbivore

P
939 Beiträge seit 2003
vor 19 Jahren

Ich würde den Interface-Ansatz bevorzugen. Dann ist man nicht auf Form-Klassen beschränkt, sondern kann den Barcode z.B. auch in Modell-Klassen hinterlegen.

Steve1974 Themenstarter:in
13 Beiträge seit 2004
vor 19 Jahren

Die Interface Variante funktioniert perfekt! 👍

... aber jetzt bekomme ich die globale Fehlerbehandlung nicht mehr hin. 😦

Wenn in der Funktion BarcodeScanned (s. Post von Denny) eine Exception ausgelöst wird (throw...), löst ThreadException nicht aus, sondern es kommt der Dialog "Eine nicht behandelte Ausnahme ... ist aufgetreten", und danach wird erst AppDomain.CurrentDomain.UnhandledException ausgelöst. Wenn die Anwendung außerhalb von VS geöffnet wurde, wird sie einfach geschlossen. Wie kann man diese Ausnahmen jetzt (global) so behandeln, dass nicht gleich die ganze Anwendung geschlossen wird?

Würde mich freuen, wenn mir jemand sagen kann was hier zu tun ist...

Danke für die Hilfe,

Steve.