C# 如何在Windows 7下记录非标准密钥中的密钥事件

C# 如何在Windows 7下记录非标准密钥中的密钥事件,c#,c++,c,windows,windows-7,C#,C++,C,Windows,Windows 7,我有一个双重问题,我对这两个分支都不熟悉 背景: 我从MSI买了一台新的笔记本电脑。作为我以前从未见过的功能,CD驱动器上没有安装机械弹出按钮。相反,数字弹出按钮是功能键上方“智能条”的一部分。不幸的是,智能酒吧的底层软件非常糟糕。即使在被动模式下,它也会占用屏幕空间和任务栏上的空间。*我已取消安装此软件 项目: 我想写一个程序,在启动时运行,并隐藏在后台。该程序的唯一功能是使弹出按钮弹出CD驱动器 第一步:我想知道当我按下那个按钮时会发生什么。我怀疑我不需要编写任何代码,只需要使用一个实用程序

我有一个双重问题,我对这两个分支都不熟悉

背景: 我从MSI买了一台新的笔记本电脑。作为我以前从未见过的功能,CD驱动器上没有安装机械弹出按钮。相反,数字弹出按钮是功能键上方“智能条”的一部分。不幸的是,智能酒吧的底层软件非常糟糕。即使在被动模式下,它也会占用屏幕空间和任务栏上的空间。*我已取消安装此软件

项目: 我想写一个程序,在启动时运行,并隐藏在后台。该程序的唯一功能是使弹出按钮弹出CD驱动器

第一步:我想知道当我按下那个按钮时会发生什么。我怀疑我不需要编写任何代码,只需要使用一个实用程序——我的一位同事提到了一个“事件记录器”,但谷歌没有提供任何有用的东西

第二步:我想编写上述程序,这意味着我需要与WIN32或.net framework交互,以执行windows在“我的电脑”下右键单击CD驱动器并单击“弹出”时使用的相同功能调用

问题: 第一个问题:你知道一个实用程序会告诉我当按下按钮时会发生什么吗

第二个问题:您知道在该事件中需要调用什么函数才能弹出驱动器吗

第三个问题:我是否忽略了其他明显的路径

从“我也有同样的问题,这是我所写的解决方案的源代码”到“我想本教程可能会对你有所帮助”,我愿意接受任何答案

我更愿意在C/C++/C中工作,但我愿意接受其他建议。正如标题所述,我在Windows7下工作

*出于好奇,该软件是MSI S-Bar,出于某种原因,它被吹捧为这一系列笔记本电脑的“功能”。

请点击此处:

c:

c#:


您必须使用
mciSendString
API。看这里,如果你想用编程的方式来做的话。

你可以编写一个简单的程序,在按下弹出键的同时轮询键盘。使用并检查以查看按下了什么。或者,您可以在按下弹出键时处理消息并检查键代码


你试过查看控制面板吗?转到控制面板>监视器>按键设置-从那里您可以重新分配键盘上的按键。

热键

如果它们是键盘的一部分(只是因为它们看起来像,并不意味着它们真的是),它们将有一个扫描码。可用于找出扫描码并对其作出反应-以下代码应有帮助:

class Program
{
    static void Main(string[] args)
    {
        var myClass = new MyClass();
        myClass.Install();
        Application.Run(new Form()); // You need a form, not sure why.
        myClass.Uninstall();
    }
}

public class MyClass : CriticalFinalizerObject
{
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(HookType idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId); 
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk); 
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); 
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
    [DllImport("winmm.dll")]
    static extern Int32 mciSendString(String command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);

    private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

    private enum HookType : int
    {
        WH_KEYBOARD = 2,
        WH_KEYBOARD_LL = 13
    }
    private enum WindowsMessage : int
    {
        WM_KEYUP = 0x101
    }

    private HookProc _myCallbackDelegate;
    private IntPtr _hook;

    public MyClass()
    {
        _myCallbackDelegate = MyCallbackFunction;
    }

    public void Install()
    {
        Uninstall();

        using (Process process = Process.GetCurrentProcess())
        using (ProcessModule module = process.MainModule)
        {
            _hook = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, _myCallbackDelegate, GetModuleHandle(module.ModuleName), 0);
        }
    }

    public void Uninstall()
    {
        var ptr = Interlocked.Exchange(ref _hook, IntPtr.Zero);
        if (ptr != IntPtr.Zero)
            UnhookWindowsHookEx(ptr);
    }

    private IntPtr MyCallbackFunction(int code, IntPtr wParam, IntPtr lParam)
    {
        if (code >= 0 && wParam == (IntPtr)WindowsMessage.WM_KEYUP)
        {
            var sk = Marshal.ReadInt32(lParam);
            // This can be used to find the scancode.
            // Press the key and watch the console to find out the scancode.
            Console.WriteLine("ScanCode: 0x{0:x4}", sk);

            if (sk == 0x0041) // 0x0041 is A
            {
                // We can't hold up the hook for too long; start the
                // tray open on another thread.
                new Action(OpenTray).BeginInvoke(null, null);
            }
        }
        return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
    }

    private void OpenTray()
    {
        mciSendString("set CDAudio door open", null, 0, IntPtr.Zero);
    }

    ~MyClass()
    {
        Uninstall();
    }
}
HID


人机界面设备将更难与之交互。希望能有所帮助。

弹出CD驱动器。不需要管理员权限

#include <windows.h>
#include <vfw.h>
#include <stdio.h>

#pragma comment(lib, "Vfw32.lib")

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 
{
  char msg[512];
  HANDLE h;
  DWORD bytesreturned;

  h = CreateFile("\\\\.\\cdrom0", MAXIMUM_ALLOWED, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

  if (h == INVALID_HANDLE_VALUE) 
  {
    sprintf(msg, "CreateFile: %u\n", GetLastError());
    MessageBox(NULL, msg, "ejectcd", MB_OK);
    return 1;
  }

  if (!DeviceIoControl(h, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &bytesreturned, NULL)) 
  {
    sprintf(msg, "DeviceIoControl: %u\n", GetLastError());
    MessageBox(NULL, msg, "ejectcd", MB_OK);
    return 1;
  }

  return 0;
}
#包括
#包括
#包括
#pragma注释(lib,“Vfw32.lib”)
int-WINAPI WinMain(HINSTANCE-HINSTANCE、HINSTANCE-hPrevInstance、LPSTR-lpCmdLine、int-nShowCmd)
{
char-msg[512];
手柄h;
德沃德·拜特兹回来了;
h=CreateFile(“\\.\\cdrom0”,允许的最大值,文件共享读取;文件共享写入,NULL,打开现有,0,NULL);
if(h==无效的\u句柄\u值)
{
sprintf(msg,“CreateFile:%u\n”,GetLastError());
消息框(空,消息,“弹出CD”,MB_OK);
返回1;
}
if(!DeviceIoControl(h,IOCTL\u存储\u弹出\u媒体,NULL,0,NULL,0,&字节返回,NULL))
{
sprintf(msg,“DeviceIoControl:%u\n”,GetLastError());
消息框(空,消息,“弹出CD”,MB_OK);
返回1;
}
返回0;
}

我自己也遇到了同样的问题。我不知道您是否熟悉自动热键,但使用它编写了一个脚本来替换s-bar

AutoHotKey(AHK)是一种针对Windows的开源宏创建和脚本语言,具有大量功能。您可以通过程序本身运行脚本,也可以将脚本编译成可在任何计算机上运行的可执行文件

只需几行代码即可使弹出式CD驱动器正常工作:

;CD eject button
SC142::
Drive, Eject
return
SC142是关键代码。在每台MSI笔记本电脑上可能都不一样,但如果您在脚本顶部添加“#InstallKeybdHook”。您可以通过GUI查看AHK看到的所有键盘事件

虽然AHK无法从其中一个按钮捕获键盘事件,但我能够将大多数按钮映射到MSI笔记本电脑上的各种功能

例如:

;Star key (AHK only receives KeyUp event)
SC139 UP::
Run, Control
return

;CinemaPro Key
SC13B::
Run, "C:\Program Files\Media Player Classic\mpc-hc64.exe"
return

我有一些弹出CD的现有代码。我星期一回到办公室后会把答案贴出来。