Hi, I have a plugin command that consists in a modeless form. It is a radial menu developed in c#.
I want the user be able to activate some menu command with keyboard.
I tried to use KeyboardEvent of the RhinoApp object but I’ve two concerns
For exemple, when I press “Q”, the key code in the event handler is “0” (zéro)
What are the key codes on MacOS platform ?
I want when my plugin command is running (i.e. When the menu is opened) to hook Rhino keyboard events, and prevent pressed key to be added to Rhino command line. Is there a way to achieve this ?
I can “hook” key press event with KeyboardEvent, BUT each char appears in the Rhino command Textbox
I want to disable this behavior while my menu is showing, but I just can’t find a solution. Below what I tried, but without success
“RhinoApp.CommandWindowCaptureEnabled” with no success, it doesn’t disable capture
Flush or write empty string with RhinoApp.CommandLineOut.Flush or RhinoApp.CommandLineOut.Write but it does nothing (I think because the pressed key is sent to the command line after the KeyboardEvent handler)
Love the project! Very excited to see the progress, and very cool it’s open source.
I tried to build your project, but couldn’t seem to. Some instructions for how to do that would be very helpful I think I might be missing some required AppKit dependencies?
Since you have a UI based on an Eto.Forms.Form I’d recommend overriding OnKeyDown for your form and then you can capture the key down and prevent it ending up in the Command Line.
Something like the below
protected override void OnKeyDown(KeyEventArgs e)
{
e.Handled = true;
base.OnKeyDown(e);
// ... Your Code Here
}
Hi @CallumSykes ,
thanks for your quick reply, but I think I wasn’t clear.
I have no problem to capture key press when the Eto.Form has focus. BUT I also want to capture key events when the form has no focus (I can with Rhino KeyboardEvent) but in this case, each keyboard key press is also inputed in the Rhino command line → I don’t want letters to be input in the Rhino command line if my menu is showing
this is to give user hability to trigger plugin menu items with keyboard, something like instant alias in rhino 9 WP
For your problem for compiling the code, you can log an issue on the GitHub repo
The only project dependency is NLog (can be found in Nuget).
I do see this too, I don’t believe these integers correspond to this enum (at least on mac), as you have found.
As I understand it, there is no public way in the C# SDK to prevent keys going to the command line without a UI that has focus (as I showed above).
This API toggle enables the developer to capture text input, but does not affect the functionality of the Command Line. The other items your mentioned work in a similar space.
Damn !
I’ll look into another way to give focus back to the menu, maybe something like press “command” or “control”.
But weird, when I press command, I see that Rhino send the event twice in event handler KeyboardEvent, this does not happen with “normal” keys like A,B etc… Do you know why ?
For the issue on GitHub, I answer. Hope it will help you to compile. So I ask you to give me some dotnet command output to be sure of my answer
Having a hard time repeating an example of this but I’ve also found on Windows that Ctrl key in keyboard events can cause duplicate/twice logic sometimes.
Still trying to figure out why it’s happening and will report back if I do find that.
finally found a hack to capture keyboard event before Rhino and avoid Rhino to add keyboard chars into its command line.
Exemple below in an Eto.Form constructor named “SectorRadialMenuForm”.
The hack consists in changing first and next responder of main Rhino Window to the Eto.Form window.
I know it breaks Rhino behavior, but it works.
Next step is to be able to “relay” the keyboard event to Rhino if the Eto.Form (or plugin) doesn’t want to handle the event.
public SectorRadialMenuForm(PlugIn plugin) : base(plugin)
{
var mainWin = RhinoEtoApp.MainWindow; // Main rhino window
var nswin = (NSWindow)mainWin.ControlObject; // Get native MacoOS Window object
if (nswin != null)
{
var res = nswin.ResignFirstResponder(); // Ask main rhino win to resign his first responder
var formNswin = (NSWindow)this.ControlObject; // Eto form MacOS native NSWindow object
nswin.MakeFirstResponder(formNswin); // Make current « SectorRadialMenuForm » the first responder
nswin.NextResponder = formNswin; // IMPORTANT : Set current etc form window the next responder (without it, it just don’t work)
}
this.KeyDown += (s, e) =>
{
var a = 0; // Here we can respond to keyboard event before Rhino main window. No keyboard char is added to Rhino command
};
this.KeyUp += (s, e) =>
{
var a = 0;// Same as « KeyDown » event but when key is released
};
}
to send the keyboard event to Rhino, it is very simple
Keep a ref to previous “nextResponder”
Set the Eto.Form “nextResponder” to the original Rhino window “nextResponder”
in key down/up event handler in Eto.Form, just update the Handled property of the event. If “true”, the event will NOT be “transferred” to rhino, if “false” the event will be “transferred” to rhino
/!\ I know this is a hack and we should not do this. But there is no rhino API
Exemple code of my previous post
public SectorRadialMenuForm(PlugIn plugin) : base(plugin)
{
var mainWin = RhinoEtoApp.MainWindow;
var nswin = (NSWindow)mainWin.ControlObject;
if (nswin != null)
{
var res = nswin.ResignFirstResponder();
var formNswin = (NSWindow)this.ControlObject;
nswin.MakeFirstResponder(formNswin);
mainRhinoNextResponder = nswin.NextResponder; // Keep ref to rhino main windows next responder
nswin.NextResponder = formNswin;
formNswin.NextResponder = mainRhinoNextResponder; // Set Eto.Form next responder to Rhino window NextResponder so the event can be "transferred" to rhino
}
this.KeyDown += (s, e) =>
{
e.Handled = true; // Rhino will not receive the event
e.Handled = false; // Rhino will receive the event
};
this.KeyUp += (s, e) =>
{
e.Handled = true;
};
}