Ich versuche, die Fensterprozedur für die Winmobile-Taskleiste zu überschreiben (um gedrückte Tasten zu fangen und zu blockieren), indem ich SetWindowLong verwende. Ich habe eine Klasse mit einer Methode zum Überschreiben und einer zum Wiederherstellen der Fensterprozedur erstellt. Die Methode MessageReceived ist diejenige, mit der ich die Fensterprozedur der Taskleiste ersetzen möchte. Meine Klasse sieht folgendermaßen aus:
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());
}
}
Das Verhalten im mobilen Emulator ist wie folgt - nachdem ich eine Taste gedrückt habe, wird "Message received" in der Debug-Ausgabe angezeigt, aber das Programm stürzt ab und bietet an, einen Absturzbericht an Microsoft zu senden. Der Visual Studio Debugger bleibt hängen und reagiert nicht auf den Stop-Befehl. Er friert erst nach einem Emulator-Reset wieder ein. Das Problem scheint mit dem CallWindowProc am Ende der MessageReceived-Methode zu liegen. Wahrscheinlich gibt es ein Problem mit der alten windowproc-Adresse. Wenn ich versuche, den RestoreWindowProc-Code unmittelbar nach dem OverrideWindowProc-Code auszuführen (ohne dass Nachrichten von meiner Funktion abgefangen werden), wird die Anwendung ordnungsgemäß beendet und der Debugger friert nicht ein. Für jede Idee, wie man dies zum Funktionieren bringen kann, wäre ich dankbar.
Ich verwende Visual Studio 2008 SP1. Das Projekt zielt auf .NET Framework v3.5, Windows Mobile 6 Professional.