我试图通过使用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。
答案 0 :(得分:3)
您无法替换其他进程拥有的窗口的窗口过程。替换功能的地址仅在您的过程中有效。它会在另一个过程中立即引起炸弹。您必须将DLL注入目标进程以解决此问题。您无法注入以托管语言编写的DLL,CLR未初始化。