P / Invoking SetWindowLong и CallWindowProc в управляемом коде (компактная структура) - PullRequest
1 голос
/ 20 января 2010

Я пытаюсь переопределить процедуру окна для панели задач winmobile (чтобы поймать и заблокировать нажатые кнопки) с помощью SetWindowLong. Я создал класс с одним методом для переопределения и одним для восстановления оконной процедуры. Метод MessageReceived - это тот, который я использую для замены процедуры окна панели задач. Мой класс выглядит следующим образом:

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());
  }
}

Поведение в мобильном эмуляторе следующее: после нажатия кнопки в сообщении «Отладка» отображается «Сообщение получено», но программа дает сбой и предлагает отправить отчет о сбое Microsoft. Визуальный студийный отладчик зависает и не реагирует на команду остановки. Размораживается только после сброса эмулятора. Кажется, проблема в CallWindowProc в конце метода MessageReceived. Скорее всего, существует некоторая проблема со старым адресом windowproc. Если я попытаюсь выполнить код RestoreWindowProc сразу после кода OverrideWindowProc (без перехвата сообщений моей функцией), приложение завершится нормально, и отладчик не остановится. Будем благодарны за любые идеи о том, как заставить это работать.

Я использую Visual Studio 2008 SP1. Проект нацелен на .NET Framework v3.5, Windows Mobile 6 Professional.

1 Ответ

3 голосов
/ 21 января 2010

Вы не можете заменить оконную процедуру окна, принадлежащего другому процессу. Адрес функции замены действителен только в вашем процессе. Это вызывает немедленную бомбу в другом процессе. Вам нужно будет внедрить DLL в целевой процесс, чтобы обойти эту проблему. Нельзя вводить библиотеки DLL, написанные на управляемом языке, CLR не инициализирован.

...