Dockable window with user control is not catching enter key press?

Dockable window with user control is not catching enter key press?

Jef_E
Collaborator Collaborator
3,836 Views
20 Replies
Message 1 of 21

Dockable window with user control is not catching enter key press?

Jef_E
Collaborator
Collaborator

Hi,

 

I made a dockablewindow with a user control added as child control.

 

       ' Set reference to the user interface manager
        Dim oUserInterfaceMgr As UserInterfaceManager _
            = _InvApp.UserInterfaceManager

        ' Create a new dockable window
        _Browser = oUserInterfaceMgr.DockableWindows.Add("SampleClientId", "DDCIntName", "Ellimetal DDC")

        ' Add control to the dockable window
        _Browser.AddChild(Me.Handle)

        ' Dock the window to the right
        _Browser.DockingState = DockingStateEnum.kDockRight

        ' Show the title bar
        _Browser.ShowTitleBar = True

        ' Set the dockable window visible
        _Browser.Visible = True

        ' Set the window width
        _Browser.Width = 220

On this user control there is a textbox that is referenced with a constraint value. I would like to catch a keydown event for this textbox but it is not letting me for the ENTER key only. All other keys work. Is the dockable window catching my Enter keydown ? How can I tell if this is the problem? Can I do something about this?

 

    Private Sub tbOccurrenceElevation_KeyDown(sender As Object, e As KeyEventArgs) Handles tbOccurrenceElevation.KeyDown

        ' Check if the enter key is pressed
        If e.KeyCode = Keys.Return Then
            OccurrenceElevation_Changed()
        End If

    End Sub

 

I asked around on StackOverflow, maybe it was something with my vb.net code but apparently not. See link below

http://stackoverflow.com/questions/43119166/catch-if-user-presses-enter-key-in-textbox?noredirect=1#...

 



Please kudo if this post was helpfull
Please accept as solution if your problem was solved

Inventor 2014 SP2
0 Likes
3,837 Views
20 Replies
Replies (20)
Message 2 of 21

c_hoppen
Advocate
Advocate

 I have a very similar problem. I have a Dockable Window with a TextBox where [Enter] shall commit and [Esc] shall abort. 

But KeyPress, KeyDown and KeyUp behaves the same. The event is fired when pressing a "printable key" but does not when I hit Enter or Esc.

Is there any solution or work around? 

 

Thanks,

Christoph

 

Edit:

Inventor 2018.3, c#, .net 4.6.

It must have worked in past. One of my customers using my tool went from 2016 to 2018 and asked me what happend to the Commit/Abort functionality.

0 Likes
Message 3 of 21

Jef_E
Collaborator
Collaborator

I am using the lost focus event, this event occurs when you leave the textbox by clicking somewhere else or use tab to jump to the next field. 



Please kudo if this post was helpfull
Please accept as solution if your problem was solved

Inventor 2014 SP2
0 Likes
Message 4 of 21

c_hoppen
Advocate
Advocate
Hi Jef_E,

thanks for your reply. Catching the lost focus will not help in my case.
I have several textboxes and I need to catch enter pressed in any of them.

Regards,
Christoph
0 Likes
Message 5 of 21

Jef_E
Collaborator
Collaborator

I hope that someone from Autodesk can elaborate on the matter! For me the lost focus event is also just something to get the job done, but enter key would be better.



Please kudo if this post was helpfull
Please accept as solution if your problem was solved

Inventor 2014 SP2
0 Likes
Message 6 of 21

c_hoppen
Advocate
Advocate

I created a new addin using the template coming with the 2018 SDK - and it worked. So it seems not to be an inventor problem. See the attachment.

Now, I don't know how to make the example not work 😉

(Which magic switch eats the enter key?)

Regards

Christoph

0 Likes
Message 7 of 21

Jef_E
Collaborator
Collaborator

What version did you use earlier? Also 2018?



Please kudo if this post was helpfull
Please accept as solution if your problem was solved

Inventor 2014 SP2
0 Likes
Message 8 of 21

c_hoppen
Advocate
Advocate
The Visual Studio Project that causes the problem came for 2013 and was
migrated once a year (.Net Version and inventor.interop Version).
0 Likes
Message 9 of 21

Jef_E
Collaborator
Collaborator

My version is a 2014 version.. you upgraded the interop to 2018 and it still fails, but a new project form 2018 succeeds am I correct?



Please kudo if this post was helpfull
Please accept as solution if your problem was solved

Inventor 2014 SP2
0 Likes
Message 10 of 21

c_hoppen
Advocate
Advocate
Yes. I upgrade the interop to 2018 and .Net to 4.6. It still fails. The
new project for 2018 succeeds. Strange.
0 Likes
Message 11 of 21

HideoYamada
Advisor
Advisor

Hello,

 

Has anyone solved this problem completely?

 

I've encountered this problem just now and tested some pattern.

 

1) When a UserControl added to the dockable window, a Enter key event could not be captured.

 

2) When a Form added to the dockable window, there was no problem around the Enter key event. But other problem was occurred.

When some other application window laid over the Inventor application window, the dockable window clicked by mouse but the Inventor app window didn't come to forward.

 

It seems that the Form acts as individual window. (So the Enter key can be captured?)

When the Form is having focus, the Navigation bar on the right end is disappeared.

This behavior is same as when another application is having focus.

 

=====
Freeradical
 Hideo Yamada
https://www.freeradical.jp
0 Likes
Message 12 of 21

HideoYamada
Advisor
Advisor

Finally, I found it!

 

using System;

namespace InvAddIn
{
    class MyRichTextBox : System.Windows.Forms.RichTextBox
    {
        private const int WM_GETDLGCODE = 0x0087;
        private const int DLGC_WANTALLKEYS = 0x0004;

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WM_GETDLGCODE:
                    if (m.LParam != null)
                        m.Result = (IntPtr)DLGC_WANTALLKEYS;
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
    }
}

Use this MyRichTextBox instead of normal RichTextBox, and you can input Enter key.

All classes contained in UserControl that are required to capture Enter should be sub-classed as MyRichTextBox.

 

Please try this!

 

=====

Freeradical

 Hideo Yamada

 

=====
Freeradical
 Hideo Yamada
https://www.freeradical.jp
Message 13 of 21

HideoYamada
Advisor
Advisor

The solution I wrote was suitable for RichText, but DataGridView needs another way.

   class MyDataGridView : System.Windows.Forms.DataGridView
    {
        #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;
        private const int WM_KEYDOWN = 0x0100;
        #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 System.IntPtr hwndKeyHook = System.IntPtr.Zero;

        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 && hwndKeyHook == NativeMethods.GetFocus())
                        {
                            NativeMethods.SendMessage(hwndKeyHook, WM_KEYDOWN, wParam, lParam);
                            return 1;
                        }
                        break;
                }
            }
            return NativeMethods.CallNextHookEx(hookObject.hook, nCode, wParam, lParam);
        }
        #endregion
        #region Event
        private static void Controls_GotFocus(object sender, System.EventArgs e)
        {
            if (sender is System.Windows.Forms.Control control)
            {
                hwndKeyHook = control.Handle;
            }
        }

        private static void Controls_LostFocus(object sender, System.EventArgs e)
        {
            hwndKeyHook = System.IntPtr.Zero;
        }

        protected override void OnEditingControlShowing(System.Windows.Forms.DataGridViewEditingControlShowingEventArgs e)
        {
            if (e.Control is System.Windows.Forms.DataGridViewTextBoxEditingControl textBox)
            {
                textBox.GotFocus -= Controls_GotFocus;
                textBox.GotFocus += Controls_GotFocus;
                textBox.LostFocus -= Controls_LostFocus;
                textBox.LostFocus += Controls_LostFocus;
            }
            base.OnEditingControlShowing(e);
        }
        #endregion
    }

When editing of cell is executed, DataGirdView will make a new TextBox for editing.

It's a easy if WndProc of that TextBox can be override, but this method seemed difficult.

So I hook key event of Windows(OS) and rewrite a message.

 

Applying this to UserControl seems like a good one, but it did not work well.

(It was worked fine for DataGridView, but bad for RichText.)

 

In the above codes, I am trying to unhook the event when the add-in's DLL is unloading,

in fact, this mechanism is not working.

(Is Inventor killing the thread dirty?)

As far as I know, there seems to be no problem.

I think Windows(OS) will clear the hooking by terminating add-in's thread.

 

I hope this is useful for you!

 

=====

Freeradical

 Hideo Yamada

 

=====
Freeradical
 Hideo Yamada
https://www.freeradical.jp
Message 14 of 21

c_hoppen
Advocate
Advocate

Thanks for that! Even in Inventor 2020 Autodesk didn't solve the problem. Your solution does...

Cheers

Christoph

0 Likes
Message 15 of 21

C-Hoppen
Advocate
Advocate

Strange(r) Things 😉 The arrow keys stopped working. Sometimes but only sometimes they does. Even when using a normal TextBox instead of the TextBox Hook.

Can anyone confirm this?

I wish you all health and well-being.

 

0 Likes
Message 16 of 21

HideoYamada
Advisor
Advisor

Hi,

 

Doesn't "Enter key" work also when arrow keys are not working?

Does your text box added to the dockable window directly or via WinForm?

 

=====
Freeradical
 Hideo Yamada

 

=====
Freeradical
 Hideo Yamada
https://www.freeradical.jp
0 Likes
Message 17 of 21

C-Hoppen
Advocate
Advocate

Hi,

Enter Key is catched if I use your recommended keyboard hook.

 class TextBoxHook : System.Windows.Forms.TextBox
    {
        private const int WM_GETDLGCODE = 0x0087;
        private const int DLGC_WANTALLKEYS = 0x0004;

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WM_GETDLGCODE:
                    if (m.LParam != null)
                        m.Result = (IntPtr)DLGC_WANTALLKEYS;
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
    }

The arrow keys are never catched, with or without the keyboard hook.

I'm using a winform and add this to my DockableWindow.

0 Likes
Message 18 of 21

HideoYamada
Advisor
Advisor

Hello,

 

As far as I know, no keyboard hook is needed when you add a text box to a Form and the form is added to a dockable window.

 

I will write test code later.

 

=====

Freeradical

 Hideo Yamada

=====
Freeradical
 Hideo Yamada
https://www.freeradical.jp
0 Likes
Message 19 of 21

HideoYamada
Advisor
Advisor

Ahh... latest Inventor 2020 needs key hook even if win form is equipped...

When I tried at here, the way via a form didn't need key hook.

 

Anyway, the project that is attached to this post works fine and a enter and arrow key work also.

Please try it.

 

=====

Freeradical

 Hideo Yamada

 

=====
Freeradical
 Hideo Yamada
https://www.freeradical.jp
0 Likes
Message 20 of 21

LukeDavenport
Collaborator
Collaborator

Hi Hideo,

Would you be able to catch the enter key on a NumericUpDown control (Winforms) that is inside a Dockable window?

Thank you for the help!

Luke

0 Likes