Custom caret for the whole application

rahul kumar 605 Reputation points
2023-06-30T11:27:44.8466667+00:00

HI , I have created a custom caret class which is working fine in my textboxes . Now i am looking for a way by which i can use that caret across all the textboxes , datagridview's on all the Form's of my project . What should i have to do . Please suggest the way to use it particularly inside datagridview if there is no way to use it across all textboes and datagridview's at once .

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,921 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,285 questions
{count} votes

Accepted answer
  1. Castorix31 86,971 Reputation points
    2023-07-02T04:54:44.8366667+00:00

    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;
                }
            }
    
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. kdavenport313 5 Reputation points
    2023-07-14T15:36:21.45+00:00

    The most important part of this article is that it contains all relevant information and links

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.