P /在托管代码中调用SetWindowLong和CallWindowProc(紧凑框架)

时间:2010-01-20 20:23:14

标签: c# windows-mobile compact-framework

我试图通过使用SetWindowLong覆盖winmobile任务栏的窗口过程(以捕获和阻止按下的按钮)。我创建了一个类,其中一个方法用于覆盖,另一个用于恢复窗口过程。 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发送崩溃报告。 visual studio调试器挂起并且不对stop命令作出反应。它仅在模拟器复位后解冻。 问题似乎是MessageReceived方法结束时的CallWindowProc。最有可能的是,旧的windowproc地址存在一些问题。 如果我尝试在OverrideWindowProc代码之后立即执行RestoreWindowProc代码(我的函数没有拦截任何消息),应用程序退出正常,调试器不会冻结。 任何有关如何使其工作的想法将不胜感激。

我正在使用Visual Studio 2008 SP1。该项目面向.NET framework v3.5,Windows Mobile 6 Professional。

1 个答案:

答案 0 :(得分:3)

您无法替换其他进程拥有的窗口的窗口过程。替换功能的地址仅在您的过程中有效。它会在另一个过程中立即引起炸弹。您必须将DLL注入目标进程以解决此问题。您无法注入以托管语言编写的DLL,CLR未初始化。