Hello,
I'm sorry for the time it took to reply.
The following code is working, but I believe there is a better way to resolve this issue...
This code runs properly only when MyNumericUpDown is used in one WinForm.
If you want to use this in multiple dockable window, the class must be created for the each window.
(e.g. class MyNumericUpDown1, class MyNumericUpDown2, ...)
class MyNumericUpDown : System.Windows.Forms.NumericUpDown
{
#region Win32 API declare
private static class NativeMethods
{
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
internal static extern System.IntPtr SetWindowsHookEx(int hookType, HookObject.HookHandler hookDelegate, System.IntPtr module, uint threadId);
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
internal static extern bool UnhookWindowsHookEx(System.IntPtr hook);
[System.Runtime.InteropServices.DllImport("user32.dll")]
internal static extern int CallNextHookEx(System.IntPtr hook, int code, System.IntPtr wParam, System.IntPtr lParam);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
internal static extern uint GetCurrentThreadId();
[System.Runtime.InteropServices.DllImport("user32.dll")]
internal static extern System.IntPtr GetFocus();
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
internal static extern System.IntPtr SendMessage(System.IntPtr hWnd, int Msg, System.IntPtr wParam, System.IntPtr lParam);
}
private const int WH_KEYBOARD = 2;
private const int VK_CANCEL = 0x03;
private const int VK_RETURN = 0x0d;
private const int VK_ESCAPE = 0x1b;
#endregion
#region Key Hook
private class HookObject
{
public delegate int HookHandler(int code, System.IntPtr wParam, System.IntPtr lParam);
public HookHandler hookDelegate;
public System.IntPtr hook;
public void SetHook(HookHandler onHook)
{
// Check this cotrol is in Visual Studio.
bool inDesignMode;
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
inDesignMode = true;
}
else
{
using (var p = System.Diagnostics.Process.GetCurrentProcess())
{
inDesignMode = (
p.ProcessName.Equals("DEVENV", System.StringComparison.OrdinalIgnoreCase) ||
p.ProcessName.Equals("XDesProc", System.StringComparison.OrdinalIgnoreCase)
);
}
}
// Exexute only outside of Visual Studio.
if (!inDesignMode)
{
if (hook == System.IntPtr.Zero)
{
hookDelegate = new HookHandler(onHook);
hook = NativeMethods.SetWindowsHookEx(WH_KEYBOARD, hookDelegate, System.IntPtr.Zero, NativeMethods.GetCurrentThreadId());
if (hook == System.IntPtr.Zero)
{
int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(errorCode);
}
}
}
}
public void Unhook()
{
if (hook != System.IntPtr.Zero)
{
NativeMethods.UnhookWindowsHookEx(hook);
}
}
public HookObject(HookHandler onHook)
{
SetHook(onHook);
}
~HookObject()
{
Unhook();
}
}
private static readonly HookObject hookObject = new HookObject(OnHookKey);
private static MyNumericUpDown focusedControl;
private static int OnHookKey(int nCode, System.IntPtr wParam, System.IntPtr lParam)
{
if (-1 < nCode)
{
int vKey = (int)wParam;
ulong keyFlag = (ulong)lParam;
switch (vKey)
{
case VK_RETURN:
case VK_CANCEL:
case VK_ESCAPE:
if ((keyFlag & 0xc0000000) == 0 && focusedControl != null)
{
focusedControl.ValidateEditText();
// If you want to fire other events, write the code here.
return 1;
}
break;
}
}
return NativeMethods.CallNextHookEx(hookObject.hook, nCode, wParam, lParam);
}
#endregion
#region Event
protected override void OnEnter(System.EventArgs e)
{
base.OnEnter(e);
focusedControl = this;
}
protected override void OnLeave(System.EventArgs e)
{
base.OnLeave(e);
focusedControl = null;
}
#endregion
}
=====
Freeradical
Hideo Yamada