72 lines
2.2 KiB
C#
72 lines
2.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace Speak.Interop
|
|
{
|
|
public class Subclassing : IDisposable
|
|
{
|
|
private const int GWL_WNDPROC = -4;
|
|
|
|
[DllImport("user32", SetLastError = true)]
|
|
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, Win32WndProc newProc);
|
|
[DllImport("user32", SetLastError = true)]
|
|
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr newProc);
|
|
[DllImport("user32")]
|
|
private static extern int CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, int Msg, int wParam, int lParam);
|
|
[DllImport("kernel32.dll")]
|
|
public static extern void SetLastError(uint dwErrCode);
|
|
|
|
private IntPtr wHandle;
|
|
private Win32WndProc wProc;
|
|
private IntPtr oldWndProc = IntPtr.Zero;
|
|
|
|
public Subclassing(IntPtr wHandle)
|
|
{
|
|
this.wHandle = wHandle;
|
|
}
|
|
|
|
public int StartSubclassing(Win32WndProc newWindowProc)
|
|
{
|
|
wProc = newWindowProc;
|
|
SetLastError(0);
|
|
if (oldWndProc != IntPtr.Zero)
|
|
SetWindowLong(wHandle, GWL_WNDPROC, wProc);
|
|
else
|
|
oldWndProc = SetWindowLong(wHandle, GWL_WNDPROC, wProc);
|
|
return Marshal.GetLastWin32Error();
|
|
}
|
|
|
|
public int CallParent(IntPtr hWnd, int Msg, int wParam, int lParam)
|
|
{
|
|
if (Msg == 0x02 || Msg == 0x10)
|
|
{
|
|
StopSubclass();
|
|
}
|
|
return CallWindowProc(oldWndProc, hWnd, Msg, wParam, lParam);
|
|
}
|
|
|
|
public void StopSubclass()
|
|
{
|
|
if (wHandle != IntPtr.Zero && oldWndProc != IntPtr.Zero)
|
|
{
|
|
SetWindowLong(wHandle, GWL_WNDPROC, oldWndProc);
|
|
wHandle = IntPtr.Zero;
|
|
wProc = null;
|
|
}
|
|
}
|
|
|
|
#region Implementation of IDisposable
|
|
|
|
public void Dispose()
|
|
{
|
|
StopSubclass();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public delegate int Win32WndProc(IntPtr hWnd, int Msg, int wParam, int lParam);
|
|
}
|