Как я могу написать функцию DLL, которая использует класс клавиатуры C # - PullRequest
1 голос
/ 27 октября 2011

Я хочу использовать следующий код для доступа к состоянию клавиатуры в определенное время.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Windows.Input;

namespace some.any
{

    public class ANY_CLASS
    {
    [STAThread] //seems to do nothing here
    public static short ThisIsCalledByAnExternalProgram()
    {
        try
        {
            if (Keyboard.IsKeyDown(Key.LeftAlt))
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        catch (Exception e)
        {
                MessageBox.Show(e.ToString());
                return 2;
         }
    }
}

Этот код требует компиляции некоторых библиотек: WindowsBase.dll и PresentationCore.dll

Клавиатура требует STA-потока, обычно я записываю атрибут [STAThread] в основную функцию, и это будет работать, но этот код будет использоваться как DLL, поэтому я не могу этого сделать Моя функция ThisIsCalledByAnExternalProgram () должна работать как STA, но это не так.

Как мне заставить этот код работать как dll?

EDIT: Что происходит, когда вы вызываете ThisIsCalledByAnExternalProgram () внутри помеченного методом STAThread метода?

Когда я вызываю функцию с моей внешней программой, я получаю исключение: System.InvalidOperationException: ... Вызывающий поток должен быть STA, поскольку это требуется для многих компонентов пользовательского интерфейса. Стек это:

System.Windows.Input.InputManager..ctor()
System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
ThisIsCalledByAnExternalProgram()

EDIT # 3: Я неправильно прочитал вопрос - ... внутри помеченного STAThread ... В настоящее время я не могу попробовать этот. предположим, что это проходит и работает - это все равно не решит проблему, так как я не могу контролировать вызывающую программу.

EDIT # 2: Используйте хук Win32: Я хочу остаться в .net из-за портативности. Все глобальные варианты хуков в конце концов зависят от компьютера под виртуальной машиной, я хочу использовать подготовленный класс Keyboard класса c #.

Работает в другом контексте - вот короткая демонстрация:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
//Requires WindowsBase.dll
//Requires PresentationCore.dll


namespace KeyBoardDemo
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            while (true)
            {
                if (Keyboard.IsKeyDown(Key.LeftAlt))
                {
                    Console.WriteLine("LEFT ALT IS PRESSED");
                }
                else
                {
                    Console.WriteLine("LEFT ALT IS NOT PRESSED");
                }
            }
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 03 ноября 2011

Я нашел решение своей проблемы, но это похоже на обходной путь.

A) Мне нужно обойти статическое свойство, чтобы я мог создавать новые потоки.Б) Я должен обеспечить STA перед использованием Keayboard.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Windows.Input;
using System.Threading;

namespace some.any
{

    public class ANY_CLASS
    {
    static STAKeyBoard mSTAKeyBoard = new STAKeyBoard();

    public static short ThisIsCalledByAnExternalProgram()
    {
        try
        {
            if (mSTAKeyBoard.IsKeyDown(Key.LeftAlt))
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        catch (Exception e)
        {
                MessageBox.Show(e.ToString());
                return 2;
         }
    }

    class STAKeyBoard
    {
        private Thread mKeyBoardReadThread = null;
        private Boolean mKeyState = false;
        private Key mKeyOfInterest;
        private string running = "ONLY ONE REQUEST";

        public Boolean IsKeyDown(Key KeyOfInterest)
        {
            lock (running)
            {
                mKeyOfInterest = KeyOfInterest;
                mKeyBoardReadThread = new Thread(new ThreadStart(GetKeyState));
                mKeyBoardReadThread.SetApartmentState(ApartmentState.STA);
                mKeyBoardReadThread.Start();
                mKeyBoardReadThread.Join(1000);
                mKeyBoardReadThread.Abort();
                mKeyBoardReadThread = null;
                return mKeyState;
            }
        }

        private void GetKeyState()
        {
            mKeyState = Keyboard.IsKeyDown(mKeyOfInterest);
        }
    }
}
0 голосов
/ 27 октября 2011

Рассмотрите возможность использования ловушки вместо использования классов winform только для ввода.Эта статья является отличным объяснением того, как сделать это с помощью C # с помощью некоторого пинвокинга;он также предоставляет библиотеку ввода (.dll), которая может удовлетворить ваши потребности.Целью статьи является в основном глобальные хуки, но в ней также обсуждается использование хуков для конкретных приложений.

http://www.codeproject.com/KB/cs/globalhook.aspx

...