Я пытаюсь переопределить процедуру окна для панели задач 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.