2010-01-20 67 views
1

我想通过使用SetWindowLong覆盖winmobile任务栏的窗口过程(以捕获和阻止按下的按钮)。我创建了一个类,其中一个方法用于覆盖,另一个用于恢复窗口过程。 MessageReceived方法是我用来替换任务栏窗口过程的方法。我的类看起来方式如下:P /在托管代码(紧凑框架)中调用SetWindowLong和CallWindowProc

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

在移动仿真器的行为是下面的 - 之后我按下一个按钮,“收到消息”显示在调试输出,但该程序崩溃,并提供送向微软提交崩溃报告。 visual studio调试器挂起并且不会对停止命令做出反应。只有在仿真器复位后才会解冻。 问题似乎是在MessageReceived方法结束时的CallWindowProc。很可能,旧的windowproc地址存在一些问题。 如果我试图在OverrideWindowProc代码之后立即执行RestoreWindowProc代码(没有消息被我的函数拦截),那么应用程序退出并且调试器不会冻结。 任何想法如何让这个工作,将不胜感激。

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

回答

3

您不能替换另一个进程拥有的窗口的窗口过程。替换函数的地址仅在您的过程中有效。它会在另一个过程中造成直接的炸弹。您将不得不将DLL注入到目标进程中以解决此问题。您不能注入以托管语言编写的DLL,CLR未初始化。

+0

事实上,如果我使用我的应用程序窗口句柄而不是任务栏,代码将很好地工作。唯一让我无法理解的是,为什么GreenButton应用程序能够工作,因为它不注入dll,并且实际上在它自己的exe文件中定义了两个函数。它是用本地代码编写的,但根据你的解释,这不应该起作用。有什么想法吗? 这里是网站:http://www.supware.net/GreenButton/ 这里是链接到源代码: http://www.supware.net/GreenButton/GreenButton-source.zip The有趣的部分是在GreenButton.cpp文件中。 – Yakimych 2010-01-21 10:17:23