Arc*_*ght 2 c# interop keyboard-shortcuts
这是一个程序,我已经使用了旧的xp日的许多变化它是一个cmd行程序,它将改变媒体应用程序(Spotify,vlc,mediaPlayer)中的轨道,就像具有下一个/上一个轨道按钮的键盘一样.
目前我正在使用Microsoft自然键盘,它没有那些按钮,但具有执行此编程的可编程键.
当Visual Studio 2012/2013具有焦点(Windows 7)(尚未尝试其他版本)时,这一切都有效,并且它可以在Sql管理工作室中使用.
using System;
using System.Runtime.InteropServices;
namespace NxtTrack
{
class Program
{
[DllImport("user32.dll")]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern void keybd_event(byte vkCode, byte scanCode, int flags, IntPtr extraInfo);
enum TrackMove
{
Previous,Next
}
static void Main(string[] args)
{
TrackMove trackMove;
try
{
if(args[0].ToLower().Contains("previous"))
trackMove = TrackMove.Previous;
else if(args[0].ToLower().Contains("next"))
trackMove = TrackMove.Next;
else
{
throw new Exception("wrong param");
}
}
catch
{
Console.WriteLine("Params needed: Next or Previous");
return;
}
TrackKeys(trackMove);
}
private static void TrackKeys(TrackMove trackMove)
{
//http://msdn.microsoft.com/en-us/library/dd375731%28v=VS.85%29.aspx
byte msg = trackMove == TrackMove.Previous ? (byte)0xB1 : (byte)0xB0;
keybd_event(msg, 0x45, 0, IntPtr.Zero);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这些是VK_MEDIA_NEXT_TRACK和VK_MEDIA_PREV_TRACK虚拟键.对它们的处理非常复杂:
这里的解决方案是不发送击键,而是向上移动先前列出的处理链.如果可以直接调用shell钩子但是没有公开该功能,那将是很好的.下一步是发送WM_APPCOMMAND消息.
这需要选择一个窗口来发送消息.由于UAC这一天很困难,一个名为UIPI(用户界面权限隔离)的功能可以防止非提升程序向高架程序发送消息.所以你不能只使用前台的窗口,它可能是一个以管理员权限运行的应用程序.与Visual Studio一样,PostMessage和keybd_event()在尝试时失败的可能原因.
诀窍是将它发送到您拥有的窗口.你做的很难,你正在使用一个控制台模式项目.这可以解决.Project + Add Reference,选择System.Windows.Forms.在项目中添加一个新类并粘贴下面显示的代码.用,例如,替换你的keybd_event()调用
AppCommand.Send(AppCommands.MediaNext);
Run Code Online (Sandbox Code Playgroud)
我把你可以发送的所有命令放在整个套件中.我提供了一个Cleanup()方法来释放资源,没有必要调用它.该代码与.NET 2.0到4.5.1兼容
using System;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public enum AppCommands {
BrowserBack = 1,
BrowserForward = 2,
BrowserRefresh = 3,
BrowserStop = 4,
BrowserSearch = 5,
BrowserFavorite = 6,
BrowserHome = 7,
VolumeMute = 8,
VolumeDown = 9,
VolumeUp = 10,
MediaNext = 11,
MediaPrevious = 12,
MediaStop = 13,
MediaPlayPause = 14,
LaunchMail = 15,
LaunchMediaSelect = 16,
LaunchApp1 = 17,
LaunchApp2 = 18,
BassDown = 19,
BassBoost = 20,
BassUp = 21,
TrebleUp = 22,
TrebleDown = 23,
MicrophoneMute = 24,
MicrophoneVolumeUp = 25,
MicrophoneVolumeDown = 26,
Help = 27,
Find = 28,
New = 29,
Open = 30,
Close = 31,
Save = 32,
Print = 33,
Undo = 34,
Redo = 35,
Copy = 36,
Cut = 37,
Paste = 38,
ReplyToMail = 39,
ForwardMail = 40,
SendMail = 41,
SpellCheck = 42,
Dictate = 43,
MicrophoneOnOff = 44,
CorrectionList = 45,
MediaPlay = 46,
MediaPause = 47,
MediaRecord = 48,
MediaFastForward = 49,
MediaRewind = 50,
MediaChannelUp = 51,
MediaChannelDown = 52,
Delete = 53,
Flip3D = 54
}
public static class AppCommand {
public static void Send(AppCommands cmd) {
if (frm == null) Initialize();
frm.Invoke(new MethodInvoker(() => SendMessage(frm.Handle, WM_APPCOMMAND, frm.Handle, (IntPtr)((int)cmd << 16))));
}
private static void Initialize() {
// Run the message loop on another thread so we're compatible with a console mode app
var t = new Thread(() => {
frm = new Form();
var dummy = frm.Handle;
frm.BeginInvoke(new MethodInvoker(() => mre.Set()));
Application.Run();
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
mre.WaitOne();
}
public static void Cleanup() {
if (frm != null) {
frm.BeginInvoke(new MethodInvoker(() => {
frm.Close();
Application.ExitThread();
mre.Set();
}));
mre.WaitOne();
frm = null;
}
}
private static ManualResetEvent mre = new ManualResetEvent(false);
private static Form frm;
// Pinvoke
private const int WM_APPCOMMAND = 0x319;
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1108 次 |
| 最近记录: |