1

次のコードを使用して、特定の時間のキーボードの状態にアクセスしたいと考えています。

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;
         }
    }
}

このコードをコンパイルするには、いくつかの dll が必要です: WindowsBase.dll および PresentationCore.dll

キーボードには STA スレッドが必要です。通常、[STAThread] 属性をメイン関数に書き込むと機能しますが、このコードは dll として使用されるため、それを行うことはできません。私の関数 ThisIsCalledByAnExternalProgram() は STA として実行する必要がありますが、そうではありません。

このコードを dll として動作させるにはどうすればよいですか?

編集: STAThread フラグ付きメソッド内で ThisIsCalledByAnExternalProgram() を呼び出すとどうなりますか?

外部プログラムで関数を呼び出すと、例外が発生します: System.InvalidOperationException: ...多くの UI コンポーネントがこれを必要とするため、呼び出しスレッドは STA でなければなりません。スタックは次のとおりです。

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

編集#3:私は質問を読み違えました-...フラグが立てられたSTAThread内...私は現在これを試すことができません。それが成功して機能すると仮定します-呼び出し元のプログラムを制御できないため、これでも問題は解決しません。

編集#2:Win32フックを使用します:移植性のために.net内に留まりたいです。すべてのグローバル フック バリアントは、最終的に仮想マシンの下のマシンに依存します。準備された 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");
                }
            }
        }
    }
}
4

2 に答える 2

0

問題の解決策を見つけましたが、回避策のように感じます。

A) 新しいスレッドを作成できるように、静的プロパティを回避する必要があります。B) Keyboard を使用する前に STA を確認する必要があります。

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);
        }
    }
}
于 2011-11-03T10:56:23.390 に答える
0

入力のためだけに winform クラスを使用する代わりに、フックを使用することを検討してください。この記事は、ピンボークを使用して C# だけでそれを行うことの優れた説明です。必要に応じて入力ライブラリ (.dll) も提供します。この記事の範囲は主にグローバル フックですが、アプリケーション固有のフックの使用についても説明します。

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

于 2011-10-27T12:26:23.747 に答える