Autor Beitrag
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1836
Erhaltene Danke: 333

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 30.11.17 05:51 
Hallo Forum

Problemstellung:
In Pascal kann man sowohl in der WndProc() Methode auf Windows-Messages reagieren:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
type
  TForm1 = class(TForm)
  protected
    procedure WndProc(var Message: TMessage); override;
  end;

// ...

procedure TForm1.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_ACTIVATEAPP then
    if Message.WParam = 1 then
      self.Caption := 'Form aktiv';
  inherited;
end;

als auch in Methoden, die mit der Direktive message deklariert werden:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
type
  TForm1 = class(TForm)
  protected
    //procedure WMActivateApp(var Msg: TMessage); message WM_ACTIVATEAPP;     // Variante 1
    procedure WMActivateApp(var Msg: TWMActivateApp); message WM_ACTIVATEAPP; // Variante 2
  end;

// ...

//procedure TForm1.WMActivateApp(var Msg: TMessage);
//begin
//  if Msg.WParam = 1 then
//    self.Caption := 'Form aktiv';
//end;

procedure TForm1.WMActivateApp(var Msg: TWMActivateApp);
begin
  if Msg.Active then
    self.Caption := 'Form aktiv';
end;

Der Msg-Parameter ist nichts anderes als ein record/struct.
Die Frage ist, ob es in C# etwas Ähnliches gibt, wo man nicht jedes Mal die WndProc() Methode überschreiben muss:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        const int WM_ACTIVATEAPP = 0x001C;

        public Form1()
        {
            InitializeComponent();
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_ACTIVATEAPP)
                if (m.WParam == (IntPtr)1)
                    this.Text = "Form aktiv";
            base.WndProc(ref m);
        }
    }
}

Es geht mir darum, für jene Messages die passenden struct bereitzustellen (wie in Pascal), um mich nicht jedes Mal fragen zu müssen, was der wParam zurück liefert, und ebenso das ständige casten gut sein zu lassen.


Moderiert von user profile iconChristian S.: Topic aus Alle Sprachen - Alle Plattformen verschoben am Do 30.11.2017 um 07:25

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 3608
Erhaltene Danke: 719

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Do 30.11.17 10:10 
Hallo,

ein direktes Äquivalent in C# gibt es dafür nicht, aber unter Does C# have an equivalent of Delphi's message keyword? gibt es Code auf Basis von Attributen und Reflection.

Eine andere unterstützte Möglichkeit ist mittels der IMessageFilter-Schnittstelle, wie in Trapping windows messages (in C#) beschrieben. Wenn man dann noch ein Dictionary<int, Delegate> einführt, in dem sich einzelne Message-Methoden eintragen würden, wäre die PreFilterMessage auch relativ generisch (und wiederverwendbar), à la:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
delegate void MessageDelegate(ref Message);

Dictionary<int, MessageDelegate> MessageMap;

void RegisterMessage(int message, MessageDelegate onMessage)
{
  MessageMap.Add(message, onMessage);
}

public bool PreFilterMessage(ref Message message)
{
  MessageDelegate onMessage;
  if (MessageMap.TryGetValue(message.Msg, out onMessage))
  {
    if (onMessage != null)
    {
      onMessage(ref message);

      return true;
    }
  }

  return false;
}

Man bräuchte dann nur eine Initialisierungsmethode, in der die ganzen Messages registriert werden.

Alternativ kann man diesen Code natürlich auch bei einer WndProc-Methode verwenden.

Für diesen Beitrag haben gedankt: Frühlingsrolle
Frühlingsrolle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1836
Erhaltene Danke: 333

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 30.11.17 16:28 
Hab vielen Dank, Th69!

So komme ich auch ohne die WndProc() Methode aus, bin aber immer noch dazu gezwungen, das Message-struct anwenden zu müssen.
Es soll in dem Sinne auch mit selbstangelegten "Message-structs" funktionieren.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 3608
Erhaltene Danke: 719

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Fr 01.12.17 10:03 
Ich nehme an, dir geht es um folgende Strukturen: Winapi.Messages?

Da in C# die Signatur von WndProc bzw. PreFilterMessage fest vorgegeben ist, also mit dem Parameter ref Message, müßte man mindestens einmal das Casten selber vornehmen. Jedoch gibt es dabei folgende Probleme:
- Strukturen können nicht direkt gecastet werden (außer mittels unsafe per Zeiger zu arbeiten)
- Strukturen können auch nicht vererbt werden (ansonsten könnte man passende Eigenschaften oder Methoden hinzufügen)

Ich habe auch im Internet keine Definitionen der WinApi-Message-Strukturen für C#/.NET gefunden (auch nicht auf P/Invoke.com) - anscheinend greifen alle direkt auf die Message-Member (WParam, LParam) zu.

Das einzige, was mir einfällt, wären explizite Methodenerweiterungen. Hier mal ein Beispiel: Ideone-Code (mit eigener Message-Struktur, da System.Windows.Forms nicht bekannt).

Hier noch mal der relevante Code:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
static class WinExtensions
{
  public static bool WMActivateApp_Active(this Message m)
  {
    return (int)m.WParam != 0;
  }
}

public class Test
{
  public static void Main()
  {
    Message m = new Message();
    
    Console.WriteLine(m.WMActivateApp_Active());
  }
}

Eine andere Möglichkeit sehe ich noch im Marshalling, wie z.B. in C#: Convert struct to another struct beschrieben.

Ich hoffe, eine der Möglichkeiten kannst du für dich umsetzen.

Für diesen Beitrag haben gedankt: Frühlingsrolle
Frühlingsrolle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1836
Erhaltene Danke: 333

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Fr 01.12.17 11:22 
Ja, genau, um die Strukturen geht es mir.
Die verlinkten Beiträge sehen gut aus.Damit sollte ich weiterkommen können. Danke nochmals für die Recherche. :zustimm:

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)