c # - Sådan logger du på vigtige begivenheder fra ikke-standardtaster under Windows 7

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et todelt problem, og jeg er ikke bekendt med hverken gren af ​​det.


Baggrund:
Jeg har købt en ny bærbar computer fra MSI. Som en funktion, jeg aldrig har set før, har cd-drevet ikke en mekanisk udløserknap, der er monteret på drevet. I stedet er en digital udstødningsknap en del af 'smart-bar' over funktionstasterne. Desværre er den software, der ligger til grund for smart-baren, frygtelig. Selv i passiv tilstand tager det op på fast ejendom og det tager plads på proceslinjen. * Jeg har uninstalleret denne software.


Projekt:
Jeg vil skrive et program, der kører ved opstart og ligger diskret i baggrunden. Programmets eneste funktion er at gøre, at udløserknappen skubber cd-drevet ud.


Trin 1: Jeg vil gerne finde ud af, hvad der sker, når jeg trykker på knappen. Jeg formoder, at jeg ikke behøver at kode noget, men kan bruge et værktøj - en af ​​mine kolleger nævnte en 'event logger', men google giver intet til brug.


Trin to: Jeg vil skrive det nævnte program, hvilket betyder, at jeg skal interagere med enten WIN32 eller muligvis .net-rammen til at udføre de samme funktionsopkaldsvinduer, når jeg højreklikker på cd-drevet under 'Min computer' og klik på ' Udstøde.'


Spørgsmål:
Første spørgsmål: Kender du et værktøj, der fortæller mig, hvad der sker, når knappen trykkes?


Andet spørgsmål: Ved du, hvilken funktion jeg har brug for at kalde på den begivenhed for at skubbe drevet ud?


Tersiært spørgsmål: Overvejer jeg nogle indlysende anden vej?


Jeg er åben for eventuelle svar fra 'Jeg havde det samme problem, her er kildekoden til løsningen jeg skrev' til 'Jeg tror måske, at denne vejledning hjælper dig?'


Jeg foretrækker at arbejde i C/C ++/C # men jeg er åben for andre forslag. Som titlen siger, arbejder jeg under Windows 7.


* For nysgerrige er softwaren MSI S-Bar, som af en eller anden grund er blevet præsenteret som en 'funktion' af denne serie af bærbare computere.

Bedste reference


Jeg stødte på det samme problem mig selv. Jeg ved ikke, om du er bekendt med autohotkeys, men brugte den til at skrive et script til at erstatte s-bar.


AutoHotKey (AHK) er et open source makroskabende og scripting sprog til Windows med masser af funktionalitet. Du kan køre scripts gennem selve programmet eller kompilere dem i eksekverbare filer, der kan køres på enhver computer.


Du kan gøre eject cd-drevet arbejde med blot et par linjer kode:


;CD eject button
SC142::
Drive, Eject
return


SC142 er nøglekoden. Det kan ikke være det samme på hver MSI-bærbar computer, men hvis du sætter linjen '#InstallKeybdHook' øverst på dit script. Du kan se alle tastaturhændelserne AHK ser gennem en GUI.


Jeg kunne kortlægge de fleste knapper til forskellige funktioner på min MSI laptop, selv om AHK ikke ville fange tastaturhændelser fra en af ​​dem.


For eksempel:


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

;CinemaPro Key
SC13B::
Run, "C:Program FilesMedia Player Classicmpc-hc64.exe"
return

Andre referencer 1


genvejstaster


Hvis de er en del af tastaturet (bare fordi de ser ud som de er, betyder de ikke, at de virkelig er), vil de have en scanningskode. SetWindowsHookEx kan bruges til at finde ud af scancoden og reagere på den - følgende kode bør hjælpe: [6]


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


En human interface enhed vil være meget sværere at interagere med. Forhåbentlig The Code Project kan hjælpe. [7]

Andre referencer 2


Udstødning af cd-drevet. Behøver ikke administratorrettigheder.


#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
", 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
", GetLastError());
    MessageBox(NULL, msg, "ejectcd", MB\_OK);
    return 1;
  }

  return 0;
}

Andre referencer 3


tjek her:


c:


CDR [8]


c #:


OpenCD [9]

Andre referencer 4


Du skal bruge mciSendString API. se her så link til dette, hvis du vil gøre det programmatisk.

Andre referencer 5


Du kan skrive et simpelt program, der blot afstemmer tastaturet, mens du trykker på udløserknappen. Brug GetKeyboardState () og kontroller for at se, hvad der er presset. Eller du kunne håndtere WM\_KEYDOWN-beskeden og inspicere nøglekoderne, når du rammer udkaststasten. [11] [12]


Har du forsøgt at kigge i kontrolpanelet? Gå til Kontrolpanel> Monitor> Nøgleindstillinger - derfra kan du omfordele nøglerne på tastaturet.