我正在尝试使用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。