Intercepts WM_KEYDOWN messages
Imports System.Runtime.InteropServices Public Class Form1 Inherits Form ' Constants Private Const GWL_WNDPROC As Integer = -4 Private Const WM_KEYDOWN As Integer = &H100 Private oldWndProc As IntPtr Private newWndProcDelegate As WndProcDelegate Private newWndProcPtr As IntPtr ' Delegate definition Private Delegate Function WndProcDelegate(hWnd As IntPtr, msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr ' Platform check Private Shared ReadOnly is64Bit As Boolean = IntPtr.Size = 8 ' API declarations <DllImport("user32.dll", EntryPoint:="SetWindowLong", SetLastError:=True)> Private Shared Function SetWindowLong32(hWnd As IntPtr, nIndex As Integer, dwNewLong As IntPtr) As IntPtr End Function <DllImport("user32.dll", EntryPoint:="SetWindowLongPtr", SetLastError:=True)> Private Shared Function SetWindowLong64(hWnd As IntPtr, nIndex As Integer, dwNewLong As IntPtr) As IntPtr End Function <DllImport("user32.dll", EntryPoint:="CallWindowProc", SetLastError:=True)> Private Shared Function CallWindowProc32(lpPrevWndFunc As IntPtr, hWnd As IntPtr, msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr End Function ' Cross-platform wrapper Private Shared Function SetWindowProc(hWnd As IntPtr, nIndex As Integer, newProc As IntPtr) As IntPtr If is64Bit Then Return SetWindowLong64(hWnd, nIndex, newProc) Else Return SetWindowLong32(hWnd, nIndex, newProc) End If End Function Private Shared Function CallWindowProcWrapper(prevWndFunc As IntPtr, hWnd As IntPtr, msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr Return CallWindowProc32(prevWndFunc, hWnd, msg, wParam, lParam) End Function ' Setup subclassing Protected Overrides Sub OnHandleCreated(e As EventArgs) MyBase.OnHandleCreated(e) newWndProcDelegate = AddressOf CustomWndProc newWndProcPtr = Marshal.GetFunctionPointerForDelegate(newWndProcDelegate) oldWndProc = SetWindowProc(Me.Handle, GWL_WNDPROC, newWndProcPtr) End Sub Protected Overrides Sub OnHandleDestroyed(e As EventArgs) SetWindowProc(Me.Handle, GWL_WNDPROC, oldWndProc) MyBase.OnHandleDestroyed(e) End Sub ' Custom WndProc Private Function CustomWndProc(hWnd As IntPtr, msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr If msg = WM_KEYDOWN Then Dim keyCode As Integer = wParam.ToInt32() MessageBox.Show($"Key Pressed: {ChrW(keyCode)}", "DWOKSUBCLASS") End If Return CallWindowProcWrapper(oldWndProc, hWnd, msg, wParam, lParam) End Function End Class
Download 'Subclassing a Windows Form':
📥 Download subclassing-a-windows-form.vb