We have a advanced software written by using c# ( windows forms ). In their we have 1000 or more textboxes. I need to validate user input on all these textboxes to stop entering
"Is there any way to handle this from a single place and affect for every textboxes"
There's a few ways. But it seems you don't want to edit the textbox itself, so there's only one reliable way I'm aware of; attaching a global keyboard hook. Code follows:
class GlobalKeyboardHook
{
#region DLL Imports
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int hookEventId, keyboardProc callback, IntPtr handleInstance, uint threadId);
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr handleInstance);
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr ignoredParameter, int hookCode, int wParam, ref KeyboardHookStruct lParam);
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string libFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion DLL Imports
#region Class Declarations
private delegate int keyboardProc(int code, int wParam, ref KeyboardHookStruct lParam);
private keyboardProc kbdProc;
public struct KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int extraInfo;
}
private static class KeyboardMessages
{
public const int WH_KEYBOARD_LL = 13;
public const int WM_KEYDOWN = 0x100;
public const int WM_KEYUP = 0x101;
public const int WM_SYSKEYDOWN = 0x104;
public const int WM_SYSKEYUP = 0x105;
}
IntPtr HookPointer = IntPtr.Zero;
IntPtr ModuleInstance = IntPtr.Zero;
public event KeyEventHandler KeyDown;
public event KeyEventHandler KeyUp;
#endregion Class Declarations
#region Class Functions
public GlobalKeyboardHook() {
EnableHook(true, null);
}
public GlobalKeyboardHook(Process P) {
EnableHook(true, P);
}
~GlobalKeyboardHook() {
EnableHook(false, null);
}
public void EnableHook(bool Enabled)
{
EnableHook(Enabled, null);
}
public void EnableHook(bool Enabled, Process P) {
if (Enabled)
{
HookPointer = SetWindowsHookEx(KeyboardMessages.WH_KEYBOARD_LL, kbdProc = HookCallback, ModuleInstance = P == null ? LoadLibrary("User32") : GetModuleHandle(P.MainModule.ModuleName), 0);
}
else
{
UnhookWindowsHookEx(HookPointer);
HookPointer = IntPtr.Zero;
ModuleInstance = IntPtr.Zero;
kbdProc = null;
}
}
public int HookCallback(int code, int wParam, ref KeyboardHookStruct lParam) {
if (code >= 0) {
KeyEventArgs key = new KeyEventArgs((Keys)lParam.vkCode);
if ((wParam == KeyboardMessages.WM_KEYDOWN || wParam == KeyboardMessages.WM_SYSKEYDOWN) && (KeyDown != null)) {
KeyDown(this, key) ;
} else if ((wParam == KeyboardMessages.WM_KEYUP || wParam == KeyboardMessages.WM_SYSKEYUP) && (KeyUp != null)) {
KeyUp(this, key);
}
if (key.Handled)
return 1;
}
return CallNextHookEx(HookPointer, code, wParam, ref lParam);
}
#endregion Class Functions
}
To activate we add the following:
GlobalKeyboardHook ghk = new GlobalKeyboardHook(Process.GetCurrentProcess());
Type tbType = typeof(TextBox);
ghk.KeyDown += new KeyEventHandler(() => {
if (typeof(this.ActiveControl) == tbType)
RunValidation(this.ActiveControl.Text);
});
Once you have the boilerplate hook, adding validation becomes pretty simple. No loops means you're not wasting processor time iterating over a thousand text boxes.
Just remember this will apply to ALL controls of type TextBox within the current process. If you add a custom TextBox control or don't want to check all of them - that should be accounted for prior to calling RunValidation().