Замените класс WPF System. Windows .Input.Keyboard (из PresentationCore.dll) для использования с Mono - PullRequest
0 голосов
/ 17 апреля 2020

Я работаю над приложением C#, чтобы сделать его " Mono -совместимым", чтобы иметь возможность использовать его на платформах GNU / Linux. Это приложение использует WinForms и Windows API Presentation Foundation (PresentationCore.dll сборка среди других). Mono и WinForms, кажется, работают . Но API WPF не поддерживаются Mono . Например, следующий пример кода:

using System.Windows.Input;

namespace MyNamespace.Utils
{
    public static class KeyboardUtils
    {
        public static int? GetInputNumber()
        {
            if (Keyboard.IsKeyDown(Key.D1)) return 1;
            // ... test other keys
            return null;
        }
    }
}

не компилируется:

error CS0103: The name 'Keyboard' does not exist in the current context

Нет проблем с Key (доступно в System.Windows.Input, из WindowsBase.dll сборка), поскольку WindowsBase.dll присутствует с Mono.

Напротив, Keyboard не может использоваться, потому что, даже если он расположен в том же пространстве имен System.Windows.Input, он находится в сборке PresentationCore.dll, и он не доступен в Mono, поскольку Mono не поддерживает WPF.

Как преобразовать код такого типа, чтобы сделать его Mono-совместимым?

Edit (1)

Я пытался преобразовать приложение для. NET Core (совместимо с GNU / Linux), но это невозможно из-за некоторых зависимостей.

Edit (2)

Этот метод KeyboardUtils.GetInputNumber иногда используется в методах, где присутствует KeyPressEventArgs, поэтому я мог бы изменить его, чтобы распространить KeyPressEventArgs на эту функцию, используя KeyPreview = true в моем основном Form и добавьте KeyPressEventHandler (void MainForm_KeyPress(object sender, KeyPressEventArgs e)) для перехвата всех вводов с клавиатуры на моем главном Form (благодаря ответу @ Giulio). * 104 5 *

Но большую часть времени эта функция вызывается, например, классами / функциями без KeyPressEventArgs (выбор цвета нажатием цифровой клавиши):

using System.Drawing;

namespace MyNamespace.Utils
{
    public static class ColorUtilities
    {
        public static Color? GetColorForHighlight()
        {
            int? inputNumber = KeyboardUtilities.GetInputNumber();
            switch (inputNumber)
            {
                case 1:
                    return Color.Red;
                // other cases
                default:
                    return null;
            }
        }
    }
}

В этом случае рефакторинг будет стоить слишком много усилий. Есть ли более простое решение, чем распространить KeyPressEventArgs на все функции во всех классах , используя эти KeyboardUtils методы?

1 Ответ

0 голосов
/ 02 мая 2020

Вы также можете добавить обработчик клавиатуры в конструкторе WinForms для Mono:

this.buttonPeriod.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.keyBoardInput);

Затем вы можете перенести код, как это было сделано в примере калькулятора :

/*
 * keyBoardInput - Handles user's input via keyboard.
 */
private void keyBoardInput(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar >= '0' && e.KeyChar <= '9')
    {
        enterNumber(e.KeyChar.ToString());
    }
    else if (e.KeyChar == '.')
    {
        enterNumber(e.KeyChar.ToString());
    }
    else if (e.KeyChar == '\b')
    {
        enterNumber("Backspace");
    }
    else if (e.KeyChar == '=' || e.KeyChar == '+' || e.KeyChar == '-')
    {
        enterOperation(e.KeyChar.ToString());
    }
    else if (e.KeyChar == '/')
    {
        enterOperation("÷");
    }
    else if (e.KeyChar == '*')
    {
        enterOperation("×");
    }
}

Комментарии

Наконец, я увидел, что будет распространяться KeyPressEventArgs повсюду в коде без рефакторинга большого взрыва. Я обновил свой вопрос, не могли бы вы взглянуть?

Что ж, да, вам нужно как-то распространить событие, что в точности зависит от вашего проекта (например, где находится GetColorForHighlight вызывается и так далее), вот пример из репозитория github Никиты Цуканова .

Вы определяете Keyboard stati c class

static class Keyboard
{
    public static readonly HashSet<Key> Keys = new HashSet<Key>();
    public static bool IsKeyDown(Key key) => Keys.Contains(key);

}

и вы реферируете sh события в нем из основной формы

    protected override void OnKeyDown(KeyEventArgs e)
    {
        Keyboard.Keys.Add(e.Key);
        base.OnKeyDown(e);
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        Keyboard.Keys.Remove(e.Key);
        base.OnKeyUp(e);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...