如何在 monoMac 中处理 NSTextField keyDown
How to handle NSTextField keyDown in monoMac
我正在尝试使用 monoMac 和 Xamarin Studio 处理 NSTextField 的 keyDown 事件。
我创建了一个派生的 NSTextFieldDelegate class 并将编辑器委托设置为此 class 的一个实例。但是,我只看到被调用的 Changed 方法,从来没有看到 DoCommandBySelector
class TextPathDelegate : NSTextFieldDelegate {
public override void Changed(NSNotification notification)
{
Console.WriteLine("changed");
}
public override void DidChangeValue(string forKey)
{
Console.WriteLine("didchange = {0}", forKey);
}
public override void WillChangeValue(string forKey)
{
Console.WriteLine("willchange = {0}", forKey);
}
public override bool DoCommandBySelector(NSControl control, NSTextView textView, MonoMac.ObjCRuntime.Selector commandSelector)
{
Console.WriteLine("DoCommandBySelector = {0}", commandSelector.ToString());
return false;
}
}
知道我可能遗漏了什么吗?
编辑 2:
我刚刚注意到,如果我使用箭头键和页面 up/down,就会调用 DoCommandBySelector。仍然无法捕获按键事件
编辑-1:
我尝试用 Xamarin.mac 制作一个小项目,只有 2 个编辑字段,带有派生的编辑控件和委托。
这是代码
class TextPathDelegate : NSTextFieldDelegate {
string Id { get; set; }
public TextPathDelegate(string id) { Id = id; }
public override void Changed(NSNotification notification)
{
Console.WriteLine(Id + "changed");
}
public override bool DoCommandBySelector(NSControl control, NSTextView textView, ObjCRuntime.Selector commandSelector)
{
Console.WriteLine(Id + "DoCommandBySelector = {0}", commandSelector.ToString());
return false;
}
public override void EditingBegan(NSNotification notification)
{
Console.WriteLine(Id + "EditingBegan");
}
public override void EditingEnded(NSNotification notification)
{
Console.WriteLine(Id + "EditingEnded");
}
}
[Register("MyNSTextField")]
class MyNSTextField : NSTextField {
public MyNSTextField(IntPtr handle) : base(handle){}
public override void KeyDown(NSEvent theEvent)
{
Console.WriteLine("KeyDown");
base.KeyDown(theEvent);
}
public override void KeyUp(NSEvent theEvent)
{
Console.WriteLine("KeyUp");
base.KeyUp(theEvent);
}
}
和输出。不调用 keyDown 或 DoCommandBySelector。我一定是遗漏了一些非常基本的东西
1-EditingBegan
1-changed
KeyUp
1-changed
KeyUp
1-changed
KeyUp
1-EditingEnded
2-EditingBegan
2-changed
KeyUp
2-changed
KeyUp
2-changed
KeyUp
谢谢
Cocoa 中的文本编辑与 WPF 真的 不同;-) NSTextField 和类似控件通常不处理实际编辑,因为 NSTextView 字段编辑器是用过……奇怪?取决于你如何看待它,对于 Windows' 样式控件是的,对于 Cocoa 它是标准的:
Field editor is an NSTextView which is maintained by NSWindow. The field editor replaces any NSTextField or NSTextFieldCell in the window for editing purposes.
Semi-required 阅读 material : Text Fields, Text Views, and the Field Editor
NSTextField
不响应 KeyDown
,因为 字段编辑器处理它 及其提供的所有相关功能(单词完成、重音字母弹出窗口等...,从而创建自定义 NSTextField
并覆盖 KeyDown
和 KeyUp
,只有 KeyUp
会被调用:
public override void KeyDown(NSEvent theEvent)
{
throw new Exception("NSTextField KeyDown never gets called");
}
public override void KeyUp(NSEvent theEvent)
{
Console.WriteLine("NSTextField KeyUp");
}
因此 NSTextFieldDelegate
也是如此,你永远不会得到 keydown/keyup 的 commandSelector
...你 将 得到 insertNewline:
、cancelOperation:
、deleteBackward:
、等等……
public override void Changed(NSNotification notification)
{
Console.WriteLine("changed"); // after the field editor is done
}
public override bool DoCommandBySelector(NSControl control, NSTextView textView, Selector commandSelector)
{
Console.WriteLine("DoCommandBySelector = {0}", commandSelector.Name);
return false;
}
怎么办?
首先你真的需要按键吗?改变正常的 Cocoa UIX 不是标准,但如果你真的这样做,一种方法是使用自定义 NSTextView
而不是 NSTextField
并且 KeyDown
覆盖将是叫:
[Register("CustomTextView")]
public class CustomTextView : NSTextView
{
public CustomTextView() : base() {
Console.WriteLine("CustomTextView");
}
public CustomTextView(IntPtr handle) : base(handle) {
Console.WriteLine("CustomTextView IntPtr");
}
[Export("initWithCoder:")]
public CustomTextView(NSCoder coder) : base(coder) {
Console.WriteLine("CustomTextView initWithCoder");
}
public override void KeyDown(NSEvent theEvent) {
Console.WriteLine("CustomTextView KeyDown");
}
public override void KeyUp(NSEvent theEvent) {
Console.WriteLine("CustomTextView KeyUp");
}
}
如果您使用 .xib
进行界面设计,只需在 C# 中创建一个 NSTextView subclass,注册它,.h
将显示在 Xcode 中并使用它用您的 class.
替换 NSTextView
根据您真正需要 keyDown 的目的,编辑 begin/end 可能对您的 NSTextField
:
有用
this.EditingBegan += (object sender, EventArgs e) => {
Console.WriteLine("EditingBegan");
};
this.EditingEnded += (object sender, EventArgs e) => {
Console.WriteLine("EditingEnded");
};
您还可以挂钩 NSWindow 的字段编辑器并监听所有 keyDown:
、过滤控件并仅在它是您感兴趣的控件时做出反应...
我正在尝试使用 monoMac 和 Xamarin Studio 处理 NSTextField 的 keyDown 事件。
我创建了一个派生的 NSTextFieldDelegate class 并将编辑器委托设置为此 class 的一个实例。但是,我只看到被调用的 Changed 方法,从来没有看到 DoCommandBySelector
class TextPathDelegate : NSTextFieldDelegate {
public override void Changed(NSNotification notification)
{
Console.WriteLine("changed");
}
public override void DidChangeValue(string forKey)
{
Console.WriteLine("didchange = {0}", forKey);
}
public override void WillChangeValue(string forKey)
{
Console.WriteLine("willchange = {0}", forKey);
}
public override bool DoCommandBySelector(NSControl control, NSTextView textView, MonoMac.ObjCRuntime.Selector commandSelector)
{
Console.WriteLine("DoCommandBySelector = {0}", commandSelector.ToString());
return false;
}
}
知道我可能遗漏了什么吗?
编辑 2: 我刚刚注意到,如果我使用箭头键和页面 up/down,就会调用 DoCommandBySelector。仍然无法捕获按键事件
编辑-1: 我尝试用 Xamarin.mac 制作一个小项目,只有 2 个编辑字段,带有派生的编辑控件和委托。
这是代码
class TextPathDelegate : NSTextFieldDelegate {
string Id { get; set; }
public TextPathDelegate(string id) { Id = id; }
public override void Changed(NSNotification notification)
{
Console.WriteLine(Id + "changed");
}
public override bool DoCommandBySelector(NSControl control, NSTextView textView, ObjCRuntime.Selector commandSelector)
{
Console.WriteLine(Id + "DoCommandBySelector = {0}", commandSelector.ToString());
return false;
}
public override void EditingBegan(NSNotification notification)
{
Console.WriteLine(Id + "EditingBegan");
}
public override void EditingEnded(NSNotification notification)
{
Console.WriteLine(Id + "EditingEnded");
}
}
[Register("MyNSTextField")]
class MyNSTextField : NSTextField {
public MyNSTextField(IntPtr handle) : base(handle){}
public override void KeyDown(NSEvent theEvent)
{
Console.WriteLine("KeyDown");
base.KeyDown(theEvent);
}
public override void KeyUp(NSEvent theEvent)
{
Console.WriteLine("KeyUp");
base.KeyUp(theEvent);
}
}
和输出。不调用 keyDown 或 DoCommandBySelector。我一定是遗漏了一些非常基本的东西
1-EditingBegan
1-changed
KeyUp
1-changed
KeyUp
1-changed
KeyUp
1-EditingEnded
2-EditingBegan
2-changed
KeyUp
2-changed
KeyUp
2-changed
KeyUp
谢谢
Cocoa 中的文本编辑与 WPF 真的 不同;-) NSTextField 和类似控件通常不处理实际编辑,因为 NSTextView 字段编辑器是用过……奇怪?取决于你如何看待它,对于 Windows' 样式控件是的,对于 Cocoa 它是标准的:
Field editor is an NSTextView which is maintained by NSWindow. The field editor replaces any NSTextField or NSTextFieldCell in the window for editing purposes.
Semi-required 阅读 material : Text Fields, Text Views, and the Field Editor
NSTextField
不响应 KeyDown
,因为 字段编辑器处理它 及其提供的所有相关功能(单词完成、重音字母弹出窗口等...,从而创建自定义 NSTextField
并覆盖 KeyDown
和 KeyUp
,只有 KeyUp
会被调用:
public override void KeyDown(NSEvent theEvent)
{
throw new Exception("NSTextField KeyDown never gets called");
}
public override void KeyUp(NSEvent theEvent)
{
Console.WriteLine("NSTextField KeyUp");
}
因此 NSTextFieldDelegate
也是如此,你永远不会得到 keydown/keyup 的 commandSelector
...你 将 得到 insertNewline:
、cancelOperation:
、deleteBackward:
、等等……
public override void Changed(NSNotification notification)
{
Console.WriteLine("changed"); // after the field editor is done
}
public override bool DoCommandBySelector(NSControl control, NSTextView textView, Selector commandSelector)
{
Console.WriteLine("DoCommandBySelector = {0}", commandSelector.Name);
return false;
}
怎么办?
首先你真的需要按键吗?改变正常的 Cocoa UIX 不是标准,但如果你真的这样做,一种方法是使用自定义 NSTextView
而不是 NSTextField
并且 KeyDown
覆盖将是叫:
[Register("CustomTextView")]
public class CustomTextView : NSTextView
{
public CustomTextView() : base() {
Console.WriteLine("CustomTextView");
}
public CustomTextView(IntPtr handle) : base(handle) {
Console.WriteLine("CustomTextView IntPtr");
}
[Export("initWithCoder:")]
public CustomTextView(NSCoder coder) : base(coder) {
Console.WriteLine("CustomTextView initWithCoder");
}
public override void KeyDown(NSEvent theEvent) {
Console.WriteLine("CustomTextView KeyDown");
}
public override void KeyUp(NSEvent theEvent) {
Console.WriteLine("CustomTextView KeyUp");
}
}
如果您使用 .xib
进行界面设计,只需在 C# 中创建一个 NSTextView subclass,注册它,.h
将显示在 Xcode 中并使用它用您的 class.
根据您真正需要 keyDown 的目的,编辑 begin/end 可能对您的 NSTextField
:
this.EditingBegan += (object sender, EventArgs e) => {
Console.WriteLine("EditingBegan");
};
this.EditingEnded += (object sender, EventArgs e) => {
Console.WriteLine("EditingEnded");
};
您还可以挂钩 NSWindow 的字段编辑器并监听所有 keyDown:
、过滤控件并仅在它是您感兴趣的控件时做出反应...