2 Stimmen

P/Aufruf von SetWindowLong und CallWindowProc in verwaltetem Code (kompakter Rahmen)

Ich versuche, die Fensterprozedur für die Winmobile-Taskleiste zu überschreiben (um gedrückte Tasten zu fangen und zu blockieren), indem ich SetWindowLong verwende. Ich habe eine Klasse mit einer Methode zum Überschreiben und einer zum Wiederherstellen der Fensterprozedur erstellt. Die Methode MessageReceived ist diejenige, mit der ich die Fensterprozedur der Taskleiste ersetzen möchte. Meine Klasse sieht folgendermaßen aus:

class ButtonBlocker
{
  public delegate IntPtr WindowProc(IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam);

  public static WindowProc newWindowDeleg;
  private static IntPtr oldWindowProc;

  [DllImport("coredll.dll")]
  static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

  [DllImport("coredll.dll")]
  static extern int GetWindowLong(IntPtr hWnd, int nIndex);

  [DllImport("coredll.dll")]
  static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

  [DllImport("coredll.dll", EntryPoint = "FindWindow")]
  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

  private static IntPtr MessageReceived(IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam)
  {
      Debug.WriteLine("Message received");
      return CallWindowProc(oldWindowProc, hwnd, uMsg, wParam, lParam);
  }

  public static void OverrideWindowProc()
  {
      newWindowDeleg = MessageReceived;

      IntPtr taskBarHandle = FindWindow("HHTaskBar", null);

      int newWndProc = Marshal.GetFunctionPointerForDelegate(newWindowDeleg).ToInt32();
      int result = SetWindowLong(taskBarHandle, -4, newWndProc);
      oldWindowProc = (IntPtr)result;
      if (result == 0)
      {
          MessageBox.Show("Failed to SetWindowLong");
      }
  }

  public static void RestoreWindowProc()
  {
      IntPtr taskBarHandle = FindWindow("HHTaskBar", null);
      int result = SetWindowLong(taskBarHandle, -4, oldWindowProc.ToInt32());
  }
}

Das Verhalten im mobilen Emulator ist wie folgt - nachdem ich eine Taste gedrückt habe, wird "Message received" in der Debug-Ausgabe angezeigt, aber das Programm stürzt ab und bietet an, einen Absturzbericht an Microsoft zu senden. Der Visual Studio Debugger bleibt hängen und reagiert nicht auf den Stop-Befehl. Er friert erst nach einem Emulator-Reset wieder ein. Das Problem scheint mit dem CallWindowProc am Ende der MessageReceived-Methode zu liegen. Wahrscheinlich gibt es ein Problem mit der alten windowproc-Adresse. Wenn ich versuche, den RestoreWindowProc-Code unmittelbar nach dem OverrideWindowProc-Code auszuführen (ohne dass Nachrichten von meiner Funktion abgefangen werden), wird die Anwendung ordnungsgemäß beendet und der Debugger friert nicht ein. Für jede Idee, wie man dies zum Funktionieren bringen kann, wäre ich dankbar.

Ich verwende Visual Studio 2008 SP1. Das Projekt zielt auf .NET Framework v3.5, Windows Mobile 6 Professional.

3voto

Hans Passant Punkte 894572

Sie können nicht die Fensterprozedur eines Fensters ersetzen, das einem anderen Prozess gehört. Die Adresse der Ersatzfunktion ist nur in Ihrem Prozeß gültig. Sie verursacht eine sofortige Bombe in dem anderen Prozess. Um dieses Problem zu umgehen, müssten Sie eine DLL in den Zielprozess einschleusen. DLLs, die in einer verwalteten Sprache geschrieben sind, können nicht injiziert werden, da die CLR nicht initialisiert ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X