“有没有办法从一个地方处理这个问题并影响
每个文本框”
有几种方法。但似乎您不想编辑文本框本身,所以我知道只有一种可靠的方法;附加一个全局键盘挂钩。代码如下:
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
}
要激活,我们添加以下内容:
GlobalKeyboardHook ghk = new GlobalKeyboardHook(Process.GetCurrentProcess());
Type tbType = typeof(TextBox);
ghk.KeyDown += new KeyEventHandler(() => {
if (typeof(this.ActiveControl) == tbType)
RunValidation(this.ActiveControl.Text);
});
一旦有了样板钩子,添加验证就变得非常简单。没有循环意味着您不会浪费处理器时间来迭代超过一千个文本框。
请记住,这将适用于当前进程中所有 TextBox 类型的控件。如果您添加自定义 TextBox 控件或不想检查所有控件 - 在调用 RunValidation() 之前应考虑到这一点。