Key logging can be used for naughty things, and manipulating Caps Lock seems rather strange, but since the information is already available to the public and you know your user stories better than me, I posted a solution.
Here is an example based on a piece of code sent from a keylogger code in C # on the MSDN forum.
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows.Forms; class Program { private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private static LowLevelKeyboardProc _proc = HookCallback; private static IntPtr _hookID = IntPtr.Zero; private static bool lastKeyWasLetter = false; [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("user32.dll")] static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); [STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); _hookID = SetHook(_proc); Application.Run(); UnhookWindowsHookEx(_hookID); } private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private static void ToggleCapsLock() { const int KEYEVENTF_EXTENDEDKEY = 0x1; const int KEYEVENTF_KEYUP = 0x2; UnhookWindowsHookEx(_hookID); keybd_event(0x14, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0); keybd_event(0x14, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0); _hookID = SetHook(_proc); } private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { if (lastKeyWasLetter) { if (Control.IsKeyLocked(System.Windows.Forms.Keys.CapsLock)) { ToggleCapsLock(); } lastKeyWasLetter = false; } Keys key = (Keys)Marshal.ReadInt32(lParam); if (key == Keys.Space) { if (!Control.IsKeyLocked(System.Windows.Forms.Keys.CapsLock)) { ToggleCapsLock(); } } else if (key >= Keys.A && key <= Keys.Z) { lastKeyWasLetter = true; } } return CallNextHookEx(_hookID, nCode, wParam, lParam); } }
Paste this into the new Windows Program.cs application in Visual Studio to try it out.
If you intercept an event with a key to enable and disable Caps Lock, then the event will be intercepted before the application processes it. This means that turning Caps Lock on when you press the letter key will cause the application you enter to receive the letter in lower case, even immediately after a space.
I suggested that you try to force the capital letters of the first letter in each word (and if so, you may have to handle other keys, such as Return), so my fragment will disable Caps Lock on the next key press after pressing the letter. Please note that you cannot just try to grab the key, because with fast typing, you can hold the initial key until you press the next key.