[英]How can i write a dll function that uses the C# Keyboard Class
I want to use the following code to access the state of the keyboard at a certain time. 我想使用以下代码在特定时间访问键盘的状态。
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;
}
}
}
This code requires some dlls to compile: WindowsBase.dll and PresentationCore.dll 此代码需要一些dll进行编译:WindowsBase.dll和PresentationCore.dll
Keyboard requires a STA Thread, normally i would write the [STAThread] attribute to the main function and it would work, but this code will be used as a dll, so i can not do that. 键盘需要STA线程,通常我会写的[STAThread]属性的主要功能和它的工作,但是这个代码将被用来作为一个dll,所以我不能做到这一点。 My function ThisIsCalledByAnExternalProgram() would have to run as an STA but it doesnt.
我的功能ThisIsCalledByAnExternalProgram()将不得不为STA运行,但它不。
How do i get this code to work as a dll? 我如何获得此代码以dll的形式工作?
EDIT: What happens when you call ThisIsCalledByAnExternalProgram() within a STAThread flagged method? 编辑:什么,当你调用发生ThisIsCalledByAnExternalProgram()一个STAThread内标记的方法?
When i call the function with my external program i get an exception: System.InvalidOperationException: ...The calling thread must be STA, because many UI components require this. 当我打电话的功能与我的外部程序我得到一个异常:System.InvalidOperationException:...调用线程必须为STA,因为许多UI组件都需要这个。 Stack is:
堆栈为:
System.Windows.Input.InputManager..ctor()
System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
ThisIsCalledByAnExternalProgram()
EDIT#3: I misread the question - ...within a STAThread flagged... i can currently not try this one. EDIT#3:我误解了问题-...在STAThread中标记为......我目前无法尝试此问题。 suppose it passes and works - this would still not solve the problem since i have no control over the calling program.
假设它可以通过并且可以工作-由于我无法控制调用程序,因此这仍然无法解决问题。
EDIT#2: Use a Win32 hook: I want to stay within .net because of portability. 编辑#2:使用Win32挂钩:由于可移植性,我想留在.net内。 All global hook variants are in the end dependent on the machine below the virtual machine, i want to use the prepared Keyboard class of c#.
最终,所有全局钩子变体都取决于虚拟机下方的计算机,我想使用准备好的c#键盘类。
It works in a different context - here is a short demo: 它在不同的上下文中工作-这是一个简短的演示:
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");
}
}
}
}
}
Consider using a hook, instead of using winform classes just for input. 考虑使用钩子,而不是仅将winform类用于输入。 This article is a great explanation of doing that with just C# with some pinvoking;
本文很好地解释了仅使用C#进行一些修改的情况。 it provides a input library (.dll) as well that may suit your needs.
它还提供了一个可能适合您需要的输入库(.dll)。 The article's scope is mainly global hooks but it also discusses using application specific hooks.
本文的范围主要是全局挂钩,但也讨论了使用特定于应用程序的挂钩。
http://www.codeproject.com/KB/cs/globalhook.aspx http://www.codeproject.com/KB/cs/globalhook.aspx
I found a solution to my Problem, but it feels like a Workaround. 我找到了解决问题的方法,但是感觉像是一种解决方法。
A) I have to get around the static property so i can create new Threads. A)我必须避开静态属性,以便创建新的线程。 B) I have to ensure STA before using Keayboard.
B)在使用Keayboard之前,我必须确保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);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.