如何编写一个使用c#键盘类的dll函数?
本文关键字:键盘 dll 函数 何编写 一个 | 更新日期: 2023-09-27 18:12:28
我想用下面的代码访问键盘在某一时刻的状态。
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]属性到main函数,它会工作,但这段代码将被用作一个dll,所以我不能这样做。我的函数ThisIsCalledByAnExternalProgram()必须作为STA运行,但它没有。
我如何得到这个代码作为一个dll工作?
编辑:当你在statthread标记的方法中调用ThisIsCalledByAnExternalProgram()时会发生什么?
当我用外部程序调用函数时,我得到一个异常:系统。InvalidOperationException:…调用线程必须是STA,因为许多UI组件都需要它。堆栈是:
System.Windows.Input.InputManager..ctor()
System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
ThisIsCalledByAnExternalProgram()
编辑# 3:我误解了你的问题……在一个STAThread标记…我现在不能尝试这个。假设它通过并工作——这仍然不能解决问题,因为我无法控制调用程序。
编辑# 2:使用Win32钩子:我想留在。net是因为它的可移植性。所有全局钩子变量最终都依赖于虚拟机下面的机器,我想使用c#中准备好的Keyboard类。
它在不同的上下文中工作-这里有一个简短的演示:
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");
}
}
}
}
}
考虑使用钩子,而不是仅为输入使用winform类。这篇文章很好地解释了如何使用c#和一些调用来实现这一点;它还提供了一个输入库(.dll),可以满足您的需要。本文的范围主要是全局钩子,但也讨论了使用特定于应用程序的钩子。
http://www.codeproject.com/KB/cs/globalhook.aspx我找到了一个解决问题的方法,但感觉像是一个变通方法。
A)我必须绕过静态属性,这样我就可以创建新的线程。B)我必须在使用键盘前确保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);
}
}
}