Vor kurzem brauchte Ich für die Arbeit ein kleines Programm mit dem man Nachrichten mit C# an andere Programme schicken konnte. Nach großem Googlen durchs Netz bin ich auch fündig geworden und habe eine kleine Applikation zum testen geschrieben.

Da man in C# keine Funktionen für die Übermittlung von Nachrichten zur Verfügung hat, benötigt man Dll-Imports aus der user32.dll was im Quelltext für PostMessage dann so aussieht:

  [DllImport("user32.dll", SetLastError = true)]
  static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);


Die Anwendung verfügt über einen Button mit dem man Notepad starten kann. Ist Notepad gestartet, hat man 5 Sekunden Zeit um einen Dialog mit Eingabefeldern zu starten. Ich habe immer den “Ersetzen”-Dialog genommen. Einen Moment warten und dann erscheint die Nachricht “Message!” in allen Eingabefeldern des Dialogs.

Hier der Programmablauf in Screenshots.

Unser Programm

Unser Programm

Öffnet Notepad

Öffnet Notepad

Schickt eine Message

Schickt eine Message

Den Sourcecode könnt ihr am Ende des Artikels downloaden.

Hier Teilauszüge aus der “btnNotepad_Click”-Funktion

  Process process = new Process();
  process.StartInfo.FileName = "notepad.exe";
  process.Start();

Wir deklarieren einen neuen Prozess. Geben den Dateinamen an und starten diesen.

  pWnd = GetWindow(process.MainWindowHandle, (uint)GetWindow_Cmd.GW_ENABLEDPOPUP);

  // Kein Dialog da, dann Hauptfenster nehmen
  if (pWnd == IntPtr.Zero)
    pWnd = process.MainWindowHandle;

  infoChild = new WindowInfo( pWnd );

  // Alle Edit-Controls des Dialogs als Handle holen
  pControl = FindWindowEx( pWnd, IntPtr.Zero, infoChild.EditFieldName, IntPtr.Zero );
  while (pControl != IntPtr.Zero)
  {
    pControls.Add( pControl );
    pControl = FindWindowEx(pWnd, pControl, infoChild.EditFieldName, IntPtr.Zero);
  }

  Clipboard.SetText("Message!");
  foreach (IntPtr pPost in pControls)
  {
    PostMessage(pPost, (uint)WindowMessage.WM_PASTE, 0, 0);
  }

Zuerst wird versucht ein Child-Window von unserem Process “notepad” vom Typ GW_ENABLEDPOPUP zu finden. Wenn kein Dialog oder ein anderes Fenster gefunden wurde, dann wir einfach das MainWindowHandle vom Process genommen.

Danach wird eine neues Objekt von WindowInfo initialisiert. Diese Klasse habe ich selbst geschrieben und macht im Prinzip nichts anderes als GetClassName aufzurufen und die Informationen in ein String-Array zu speichern. Dies brauchte Ich unbedingt, da ein Edit-Field bei WindowsForms nicht “Edit” heißt, sondern z.B. “WindowsForms10.EDIT.app.0.xxxxx”. Möchte man Nachrichten an ein Control schicken, so muss man nämlich vorher den Namen eines Edit-Fields kennen.

Wir haben nun alle Informationen und können alle Eingabefelder suchen die der Dialog oder unser Hauptfenster besitzt. Danach geht es recht simpel weiter. Wir speichern unsere Nachricht in der Zwischenablage und gehen die Liste jedes gefundenen Eingabefeldes durch und verschicken jeweils ein WM_PASTE.

So schnell geht das :)

Als Tipp empfehle Ich Spy++ mit dem man die Namen und Windowhandles zum testen ermitteln kann.

Download

Links

http://www.thejaeck.net/2008/12/14/postmessage-in-c/trackback/