As I said in comments, probably not the best method but it seems to works for me (tested on Windows 10 22H2) :
private SUBCLASSPROC SubClassDelegate;
static List<IntPtr> EditWindows = new List<IntPtr>();
static IntPtr hHook = IntPtr.Zero;
HookProc CBTHookProcedure;
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private void InstallHook()
{
if (hHook == IntPtr.Zero)
{
CBTHookProcedure = new HookProc(CBTHookProc);
hHook = SetWindowsHookEx(WH_CBT, CBTHookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId());
if (hHook == IntPtr.Zero)
{
int nErrorCode = Marshal.GetLastWin32Error();
// ...
}
}
}
public Form1()
{
InitializeComponent();
SubClassDelegate = new SUBCLASSPROC(WindowSubClass);
InstallHook();
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
}
public IntPtr CBTHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
else
{
//if (nCode == HCBT_CREATEWND)
if (nCode == HCBT_SETFOCUS)
{
if (lParam != IntPtr.Zero)
{
StringBuilder sClass = new StringBuilder(260);
GetClassName(wParam, sClass, (int)(sClass.Capacity));
if (sClass.ToString().Contains("EDIT"))
{
//Console.WriteLine("Class : {0}", sClass);
if (!EditWindows.Contains(wParam))
{
EditWindows.Add(wParam);
bool bRet = SetWindowSubclass(wParam, SubClassDelegate, 0, 0);
}
}
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
}
private int WindowSubClass(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam, IntPtr uIdSubclass, uint dwRefData)
{
switch (uMsg)
{
case WM_SETFOCUS:
{
DefSubclassProc(hWnd, uMsg, wParam, lParam);
RECT rect = new RECT();
GetClientRect(hWnd, out rect);
// Test 10 pixels width Caret
CreateCaret(hWnd, IntPtr.Zero, 10, rect.bottom - rect.top);
SetCaretPos(0, 1);
ShowCaret(hWnd);
return 0;
}
break;
case WM_KILLFOCUS:
{
DestroyCaret();
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
foreach (IntPtr hWndEdit in EditWindows)
{
RemoveWindowSubclass(hWndEdit, SubClassDelegate, 0);
}
}
Declarations :
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool ShowCaret(IntPtr hWnd);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool SetCaretPos(int X, int Y);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool DestroyCaret();
public const int WM_SETFOCUS = 0x0007;
public const int WM_KILLFOCUS = 0x0008;
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
public const int HCBT_MOVESIZE = 0;
public const int HCBT_MINMAX = 1;
public const int HCBT_QS = 2;
public const int HCBT_CREATEWND = 3;
public const int HCBT_DESTROYWND = 4;
public const int HCBT_ACTIVATE = 5;
public const int HCBT_CLICKSKIPPED = 6;
public const int HCBT_KEYSKIPPED = 7;
public const int HCBT_SYSCOMMAND = 8;
public const int HCBT_SETFOCUS = 9;
public const int WH_CBT = 5;
public delegate int SUBCLASSPROC(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam, IntPtr uIdSubclass, uint dwRefData);
[DllImport("Comctl32.dll", SetLastError = true)]
public static extern bool SetWindowSubclass(IntPtr hWnd, SUBCLASSPROC pfnSubclass, uint uIdSubclass, uint dwRefData);
[DllImport("Comctl32.dll", SetLastError = true)]
public static extern int DefSubclassProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
[DllImport("Comctl32.dll", SetLastError = true)]
public static extern bool RemoveWindowSubclass(IntPtr hWnd, SUBCLASSPROC pfnSubclass, uint uIdSubclass);
[DllImport("User32.dll", SetLastError = true)]
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public RECT(int Left, int Top, int Right, int Bottom)
{
left = Left;
top = Top;
right = Right;
bottom = Bottom;
}
}