Laden...

[gelöst] Alle Form-Objekte/Instanzen einer Anwendung behandeln

Erstellt von JuyJuka vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.356 Views
JuyJuka Themenstarter:in
2.187 Beiträge seit 2005
vor 13 Jahren
[gelöst] Alle Form-Objekte/Instanzen einer Anwendung behandeln

Hallo @All,

Ich möchte alle Form-Objekte in meiner Anwendung mit einem neuen Icon versehen.
Das ganze klappt auch schon mit dem nachfolgenden Code, nur bin ich mir nicht sicher ob es da nicht noch bessere Wege gibt.

Ziele:

Danke erst mal für's Lesen.

Gruß
Juy Juka

Der Code:

public void Ausfuehren(string parameter)
    {
      Application.AddMessageFilter(this);
    }

    public static System.Windows.Forms.Form GetForm(System.IntPtr handle)
    {
      return handle == System.IntPtr.Zero ? null : System.Windows.Forms.Control.FromHandle(handle) as System.Windows.Forms.Form;
    }

    private static System.EventHandler shown;

    bool IMessageFilter.PreFilterMessage(ref Message m)
    {
      System.Windows.Forms.Form f;
      if (m != null)
      {
        if((f = GetForm(m.HWnd)) != null)
        {
         f.Shown += shown ?? (shown = new System.EventHandler(f_Shown));
        }
      }
      return false;
    }

    private static System.Drawing.Icon icon;
    private void f_Shown(object sender, System.EventArgs e)
    {
      Form f = sender as Form;
      if (f != null)
      {
        f.Icon = icon ?? (icon = System.Drawing.Icon.FromHandle(Properties.Resources.NeuesIcon.GetHicon()));
      }
    }
R
103 Beiträge seit 2009
vor 13 Jahren

Also ich habe bei mir alle Forms in der Anwendung von einer eigenen abstrakten Klasse Baseform abgeleitet, die wieder von form erbt.

Damit bin ich bis jetzt gut gefahren (mit Standardfunktionen wie drucken, (de)serialisieren etc. in der Baseform, die dann überladen werden können) .
solche Änderungen wie das Icon lassen sich damit dann auch recht einfach ändern, da sie nur in der baseform erfolgen müssten.

Du musst dann natülich einmal heftigst refactoren um das umzusetzen, dafür hast Dus in zukunft aber einfacher...

5.299 Beiträge seit 2008
vor 13 Jahren
  • Allgemein Bessere Performance (Da der MessageFilter unglaublich oft ausgeführt wird, ist hier jede Optimierung natürlich Goldwert).

Du wertest die Message gar nicht aus. Ich täte denken, in der API ist ein Wert für Form_Shown (oder vergleichbares) hinterlegt, auf den man lauschen könnte.

Edit: guck: int WM_SHOWWINDOW = 24, guckma, ob das kommt.

Der frühe Apfel fängt den Wurm.

1.130 Beiträge seit 2007
vor 13 Jahren

Vielleicht hilf folgende Eigenschaft der Application-Klasse

public static FormCollection OpenForms
{
    [UIPermission(SecurityAction.Demand, Window=UIPermissionWindow.AllWindows)]
    get
    {
        return OpenFormsInternal;
    }
}
 

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

JuyJuka Themenstarter:in
2.187 Beiträge seit 2005
vor 13 Jahren

Hallo @All,

@rasepretrep: Basis-Form vor allem abstrakt geht mal garnicht, dieses Desaster hatten wir in der letzten Version der Software. Ein Framework für die Forms (wie du es vorschlägst) ist aber schon ein angestrebtes Ziel, jedoch im nachhinein ist das aus Zeitlichen gründen nicht drin (alls ich die Form's das letzte mal gezählt habe waren es weit über 200 und das ist auch schon wieder 4 Jahre her).

@ErfinderDesRades: Vielen Danke. Wenn man normalerweise nicht so weit in die Windows-Api-Welt eintaucht (ich finde IMessageFilter ist mit dem Kopf vorran drin), sucht man sich nach solchen Konstanten dumm und dämlich.

@Floste: Wenn es jetzt noch ein Ereigniss gibt, das ausgelöst wird, wenn eine neue Form erzeugt wird, muss ich mal zum Augenarzt. 😃 😃

Danke an alle die gepostet haben und danke für eure Zeit und Hilfe.

Gruß
Juy Juka

1.130 Beiträge seit 2007
vor 13 Jahren

@Floste: Wenn es jetzt noch ein Ereigniss gibt, das ausgelöst wird, wenn eine neue Form erzeugt wird, muss ich mal zum Augenarzt. 😃 😃

Gibts nicht, lässt sich aber basteln, mit etwas reflection:

Gehen tut das ganz einfach:


class MyArrayList:ArrayList
{
    public MyArrayList(ICollection values):base(values)
    {
    }

    public override int Add(object obj)
    {

        EventFeuern((Form)obj);

        return base.Add(obj);
    }
}

void EventRegistrieren()
{
    MyArrayList newList=new MyArrayList(Application.OpenForms);
    typeof(FormCollection).InvokeMember("list", NonPublic|Instance|SetField, null, Application.OpenForms, new object[1]{newList});
}

Jetzt fehlt nurnoch EventFeuern zu implementieren! Ist nicht getestet, sollte aber klappen!

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

5.299 Beiträge seit 2008
vor 13 Jahren

genial! 👍

Das einzige, was nicht funzt ist die Typ-Angabe, da muß ReadonlyCollectionBase angegeben werden, die BasisBasisKlasse von FormCollection.

Der frühe Apfel fängt den Wurm.

1.130 Beiträge seit 2007
vor 13 Jahren

Komisch, ich bin mir 110% sicher, dass man mit dieser funktion auch auf geerbte Felder zugreifen kann! (zumindest in manchen situationen)

[EDIT] Woran ich gedacht habe waren keine wirklich privaten felder

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Floste,

hm, klingt nach Zugriff per Reflection auf vererbte private Felder.

herbivore

JuyJuka Themenstarter:in
2.187 Beiträge seit 2005
vor 13 Jahren

Hallo @All,

Danke für eure Zeit und mühe.

Besonderen Dank an Floste, da ich mich für seiner/ihrer Methode entschidene habe und es sauber und flüssig funktioniert.

Gruß
Juy Juka