Kunci apa yang saya tekan?

15

Tugasnya adalah menulis kode untuk mengidentifikasi tombol mana yang ditekan pada keyboard. Anda dapat mengasumsikan bahwa hanya satu tombol yang ditekan pada satu waktu dan bahwa ada tata letak keyboard AS standar. Itu adalah tata letak dengan @ lebih dari 2.

Kode Anda harus menampilkan pengidentifikasi unik untuk setiap tombol yang ditekan. Ini termasuk PrtScn, Scroll Lock, Pause, Shift kiri, Shift kanan, Ctrl kiri, Ctrl kanan, Caps Lock, Tab, Enter, Enter pada pad nomor, Num Lock, Insert, Ins pada pad nomor, Backspace, Del, F1 ... F12, Esc, tombol Windows kiri, tombol Windows kanan, Alt, AltGr, kunci aplikasi (menu konteks) dan sebagainya.

Kode Anda harus terus menunggu penekanan tombol dan mengeluarkan identitas mereka sampai terbunuh. Ini harus menampilkan pengidentifikasi segera setelah kunci dirilis. Seharusnya tidak melakukan tindakan lain dari penekanan tombol yang diterimanya dan seharusnya tidak menghasilkan apa pun selain dari pengidentifikasi unik.

Dalam jawaban Anda, tolong tunjukkan apa yang Anda kode output untuk penekanan tombol berikut: Tab, Jeda, Enter, Enter pada pad nomor, kiri tombol Windows, tombol Windows kanan, Masukkan dan Ins pada pad nomor.

Jika Anda memiliki keyboard yang sangat berbeda, tantangannya masih untuk menghasilkan pengidentifikasi yang berbeda untuk setiap tombol pada keyboard Anda.


sumber
1
Di JS (bagaimanapun, browser JS), tidak mungkin untuk memeriksa apakah tombol-tombol tertentu ditekan (mis. Caps Lock, Num Lock, Scroll Lock, PrtScn). Apakah ini berarti bahwa JS tidak dapat menjawab?
ETHproduksi
2
@ ETHproductions Memang. Permintaan maaf kepada pecinta JS di mana-mana.
2
Persyaratan diubah setelah 5 jawaban diberikan (termasuk yang sekarang dihapus). Itu tidak terlalu adil ...
Olivier Grégoire
6
Saya tidak berpikir itu adil / hak untuk meminta output untuk kunci yang tidak ada pada banyak keyboard seperti kunci Windows dll.
Notts90 tidak aktif ke codidact.org
1
@ Notts90 Bukankah itu bagian dari tata letak keyboard AS standar? upload.wikimedia.org/wikipedia/commons/thumb/5/51/...

Jawaban:

22

kode mesin x86, DOS executable, 29 * 28 byte

FAE464D0E873FAE460D0E073F4D41005212192B402CD2188F2CD21EBE3

Ini adalah executable COM untuk MS-DOS , membutuhkan perangkat keras yang kompatibel dengan IBM PC .
Khususnya pengontrol 8042 PS / 2 atau lebih mungkin emulasi melalui SMM .
Singkatnya, itu harus bekerja di luar kotak di PC mainstream.

Kode sumbernya adalah

BITS 16

 ;Disable the interrupts so we don't compete with the IRQ 1 (the 8042 main
 ;device IRQ) handler (the ISR n. 9 by default) for the reading of the codes.
 cli

_wait:

 ;Is 'Output buffer full (OBF)' bit set?

 in al, 64h                ;Read the 8042 status register             
 shr al, 1                 ;Move bit 0 (OBF) into the carry flag

jnc _wait                  ;Keep spinning if CF = OBF not set

 ;Read the scan code S
 in al, 60h

 ;Is S a break code?

 shl al, 1                 ;Bit 7 is set if it is
jnc _wait

 ;PART 2

 ;AL = S mod 10h := y, AH = S / 10h := x
 aam 16
 add ax, 2121h             ;Make both quantities in the printable ASCII range (skip space though)

 ;Print y
 xchg dx, ax
 mov ah, 02h
 int 21h                   ;int 21/ah=02 prints the char in DL

 ;DH is still valid here, it holds x. We print it now
 mov dl, dh
 int 21h

 ;Never terminate
jmp _wait

Saya telah membagi program menjadi dua bagian.

Bagian pertama berkaitan dengan pembacaan scancodes . Scancode adalah nilai numerik yang terkait dengan setiap kunci.
Perhatikan bahwa ini adalah kode perangkat keras, mereka tidak bergantung pada OS atau rangkaian karakter. Mereka seperti pasangan yang disandikan (kolom, baris) dari kunci.
Setiap tombol memiliki kode kunci, bahkan tombol fungsi aneh non-standar yang ditemukan pada beberapa keyboard (misalnya tombol "buka kalk").
Beberapa kunci memiliki scancode multi-byte, mereka memiliki awalan yang dirancang untuk membuat aliran didekodifikasi dengan hanya melihat urutan byte.
Jadi setiap kunci mendapatkan pengenal uniknya, bahkan CTRL, SHIFT, WinKeys dan sebagainya.

Hanya "istirahat kode", dikirim ketika kunci dilepaskan, diproses, "buat kode" diabaikan.
Former memiliki set bit yang lebih tinggi (bit 7 untuk byte), jadi mudah untuk mengenalinya.

Bagian kedua berkaitan dengan pencetakan byte.
Pencetakan selalu panjang dalam perakitan, kami tidak memiliki bawaan.
Untuk membuatnya singkat, dan karena itu diperlukan untuk menulis pengidentifikasi kunci, saya meninggalkan angka desimal atau hex yang mendukung pengodean pribadi.

A byte xy, di mana x adalah nibble yang lebih tinggi dan y yang lebih rendah dicetak sebagai dua karakter berturut-turut c 0 dan c 1 didefinisikan sebagai:

c 0 = 0x21 + y
c 1 = 0x21 + x

Perhatikan bahwa nibble yang lebih rendah dicetak terlebih dahulu (ini memberi saya swap).
Alasannya adalah untuk memetakan masing-masing dari 16 nilai yang mungkin dari menggigit menjadi karakter ASCII berturut-turut dari '!'.
Sederhananya ini adalah angka hex tetapi dengan

  1. Camilan itu bertukar
  2. !"#$%&'()*+,-./01 sebagai digit (als) bukan 0123456789abcdef

Menjalankannya di DOSBox dan menekan beberapa kunci acak (beberapa di antaranya adalah kunci khusus tetapi perhatikan bahwa sebagai proses Windows, DOSBox tidak dapat menangkap semua kunci) menghasilkan

DOSBox menjalankan pengidentifikasi kunci

Perhatikan bahwa program ini tidak pernah berakhir (lebih lanjut, dibutuhkan kontrol penuh dari PC dengan menonaktifkan interupsi) seperti yang saya yakini dimaksudkan oleh pertanyaan (hanya tidak ada pembunuhan proses dalam DOS).


* Mengurangi terima kasih kepada CodyGray .

Margaret Bloom
sumber
Apakah menggunakan INinstruksi berhasil menjadi lebih kecil dalam hal byte daripada memanggil ROM BIOS interupsi (misalnya int 16h, fungsi 10h)?
Cody Grey
@CodyGray Kemungkinan besar tidak, seluruh loop bisa dilewati. Entah bagaimana saya langsung melompat ke ininstruksi. Itu sebenarnya poin yang sangat bagus yang Anda miliki. Jika Anda belum melakukannya, mengapa tidak mempostingnya sebagai jawaban? :)
Margaret Bloom
1
Nah sekarang Anda berbicara gila! Kedengarannya lebih banyak pekerjaan daripada sekadar mengomentari jawaban yang ada. :-p Saya bermain dengan menyatukan sesuatu. Tip yang menyenangkan: ketika bermain golf, xchgdengan akumulator sebagai salah satu register adalah 1 byte, jadi itu lebih baik daripada 2-byte mov.
Cody Grey
1
Oke, masalahnya int 16hadalah bahwa saya tidak mendapatkan kode pindai untuk tombol shift, kunci gulir, atau jeda / istirahat (mungkin orang lain), dan itu diperlukan oleh tantangan. Solusi Anda membaca input langsung dari I / O berfungsi, meskipun sepertinya bagi saya itu mengembalikan nilai yang sama untuk semua kunci di Ins / Del / Home / End / PgUp / PgDown cluster.
Cody Grey
1
@PeterCordes: PAUSE juga memiliki beberapa perilaku aneh, IIUC mengirim kode istirahat bersama dengan kode make pada tombol tekan, dan tidak mengirim apa pun pada rilis kunci. Atau itulah yang saya pahami dari PC Game Programming Encyclopedia.
ninjalj
12

Java 7 atau lebih tinggi, 246 228 byte

import java.awt.event.*;class K{public static void main(String[]a){new java.awt.Frame(){{addKeyListener(new KeyAdapter(){public void keyPressed(KeyEvent e){System.out.println(e);}});show();setFocusTraversalKeysEnabled(0<0);}};}}

Tidak Disatukan:

import java.awt.event.*;
class K{
    static void main(String[]a){
        new java.awt.Frame(){
            {
                addKeyListener(new KeyAdapter(){
                    public void keyPressed(KeyEvent e){
                        System.out.println(e);
                    }
                });
                show();
                setFocusTraversalKeysEnabled(0<0);
            }
        };
    }
}

-18 terima kasih kepada @ OlivierGrégoire untuk show(), 0<0danimport java.awt.event.*;

Yang mengakibatkan:

masukkan deskripsi gambar di sini

Bahkan menangani tombol shift untuk karakter huruf besar, tombol windows, kunci topi, dll ... Anda dapat melihatnya mencetak 'pengubah' juga, yang merupakan 'tombol yang ditahan'.

java.awt.event.KeyEvent[KEY_PRESSED,keyCode=27,keyText=Escape,keyChar=Escape,keyLocation=KEY_LOCATION_STANDARD,rawCode=27,primaryLevelUnicode=27,scancode=1,extendedKeyCode=0x1b] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=192,keyText=Back Quote,keyChar='`',keyLocation=KEY_LOCATION_STANDARD,rawCode=192,primaryLevelUnicode=96,scancode=41,extendedKeyCode=0xc0] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=9,keyText=Tab,keyChar=Tab,keyLocation=KEY_LOCATION_STANDARD,rawCode=9,primaryLevelUnicode=9,scancode=15,extendedKeyCode=0x9] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=20,keyText=Caps Lock,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=20,primaryLevelUnicode=0,scancode=58,extendedKeyCode=0x14] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=16,keyText=Shift,keyChar=Undefined keyChar,modifiers=Shift,extModifiers=Shift,keyLocation=KEY_LOCATION_LEFT,rawCode=16,primaryLevelUnicode=0,scancode=42,extendedKeyCode=0x10] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=17,keyText=Ctrl,keyChar=Undefined keyChar,modifiers=Ctrl,extModifiers=Ctrl,keyLocation=KEY_LOCATION_LEFT,rawCode=17,primaryLevelUnicode=0,scancode=29,extendedKeyCode=0x11] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=524,keyText=Windows,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_LEFT,rawCode=91,primaryLevelUnicode=0,scancode=91,extendedKeyCode=0x20c] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=18,keyText=Alt,keyChar=Undefined keyChar,modifiers=Alt,extModifiers=Alt,keyLocation=KEY_LOCATION_LEFT,rawCode=18,primaryLevelUnicode=0,scancode=56,extendedKeyCode=0x12] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=32,keyText=Space,keyChar=' ',keyLocation=KEY_LOCATION_STANDARD,rawCode=32,primaryLevelUnicode=32,scancode=57,extendedKeyCode=0x20] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=18,keyText=Alt,keyChar=Undefined keyChar,modifiers=Alt,extModifiers=Alt,keyLocation=KEY_LOCATION_RIGHT,rawCode=18,primaryLevelUnicode=0,scancode=56,extendedKeyCode=0x12] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=17,keyText=Ctrl,keyChar=Undefined keyChar,modifiers=Ctrl,extModifiers=Ctrl,keyLocation=KEY_LOCATION_RIGHT,rawCode=17,primaryLevelUnicode=0,scancode=29,extendedKeyCode=0x11] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=37,keyText=Left,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=37,primaryLevelUnicode=0,scancode=75,extendedKeyCode=0x25] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=16,keyText=Shift,keyChar=Undefined keyChar,modifiers=Shift,extModifiers=Shift,keyLocation=KEY_LOCATION_RIGHT,rawCode=16,primaryLevelUnicode=0,scancode=42,extendedKeyCode=0x10] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=38,keyText=Up,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=38,primaryLevelUnicode=0,scancode=72,extendedKeyCode=0x26] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=39,keyText=Right,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=39,primaryLevelUnicode=0,scancode=77,extendedKeyCode=0x27] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=96,keyText=NumPad-0,keyChar='0',keyLocation=KEY_LOCATION_NUMPAD,rawCode=96,primaryLevelUnicode=48,scancode=82,extendedKeyCode=0x60] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=110,keyText=NumPad .,keyChar='.',keyLocation=KEY_LOCATION_NUMPAD,rawCode=110,primaryLevelUnicode=46,scancode=83,extendedKeyCode=0x6e] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=10,keyText=Enter,keyChar=Enter,keyLocation=KEY_LOCATION_NUMPAD,rawCode=13,primaryLevelUnicode=13,scancode=28,extendedKeyCode=0xa] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=107,keyText=NumPad +,keyChar='+',keyLocation=KEY_LOCATION_NUMPAD,rawCode=107,primaryLevelUnicode=43,scancode=78,extendedKeyCode=0x6b] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=109,keyText=NumPad -,keyChar='-',keyLocation=KEY_LOCATION_NUMPAD,rawCode=109,primaryLevelUnicode=45,scancode=74,extendedKeyCode=0x6d] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=106,keyText=NumPad *,keyChar='*',keyLocation=KEY_LOCATION_NUMPAD,rawCode=106,primaryLevelUnicode=42,scancode=55,extendedKeyCode=0x6a] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=34,keyText=Page Down,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=34,primaryLevelUnicode=0,scancode=81,extendedKeyCode=0x22] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=33,keyText=Page Up,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=33,primaryLevelUnicode=0,scancode=73,extendedKeyCode=0x21] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=35,keyText=End,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=35,primaryLevelUnicode=0,scancode=79,extendedKeyCode=0x23] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=36,keyText=Home,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=36,primaryLevelUnicode=0,scancode=71,extendedKeyCode=0x24] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=127,keyText=Delete,keyChar=Delete,keyLocation=KEY_LOCATION_STANDARD,rawCode=46,primaryLevelUnicode=0,scancode=83,extendedKeyCode=0x7f] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=155,keyText=Insert,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=45,primaryLevelUnicode=0,scancode=82,extendedKeyCode=0x9b] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=123,keyText=F12,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=123,primaryLevelUnicode=0,scancode=88,extendedKeyCode=0x7b] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=122,keyText=F11,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=122,primaryLevelUnicode=0,scancode=87,extendedKeyCode=0x7a] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=121,keyText=F10,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=121,primaryLevelUnicode=0,scancode=68,extendedKeyCode=0x79] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=120,keyText=F9,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=120,primaryLevelUnicode=0,scancode=67,extendedKeyCode=0x78] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=119,keyText=F8,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=119,primaryLevelUnicode=0,scancode=66,extendedKeyCode=0x77] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=118,keyText=F7,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=118,primaryLevelUnicode=0,scancode=65,extendedKeyCode=0x76] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=117,keyText=F6,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=117,primaryLevelUnicode=0,scancode=64,extendedKeyCode=0x75] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=116,keyText=F5,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=116,primaryLevelUnicode=0,scancode=63,extendedKeyCode=0x74] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=115,keyText=F4,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=115,primaryLevelUnicode=0,scancode=62,extendedKeyCode=0x73] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=114,keyText=F3,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=114,primaryLevelUnicode=0,scancode=61,extendedKeyCode=0x72] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=113,keyText=F2,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=113,primaryLevelUnicode=0,scancode=60,extendedKeyCode=0x71] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=112,keyText=F1,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=112,primaryLevelUnicode=0,scancode=59,extendedKeyCode=0x70] on frame0
Guci Gurita Ajaib
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Dennis
11

HTML (dengan Javascript), 46 31 karakter, 46 31 byte

Menggunakan ini untuk membedakan numpad masuk dan kembali, LControl dan RControl ... Tidak lagi sejak apsillers menemukan cara untuk melakukannya dengan panggilan fungsi signle.

<body onkeyup=alert(event.code)

Output spesifik:

OUTPUT YANG MASIH DENGAN ANGKA ADALAH MEREKA SAYA TIDAK BISA MENGUJI LAPTOP SAYA
TUNGGU AKU AKAN MEMILIKI AKSES KE KUNCI MEREKA

PrtScn -> PrintScreen
Scroll Lock -> ScrollLock
Jeda -> Pause
Shift kiri -> ShiftLeft
Shift kanan -> ShiftRight
Ctrl kiri -> ContrlLeft
Ctrl kanan -> ControlRight
Caps Lock -> CapsLock
Tab -> Tab
Enter -> Enter
Enter pada nomor pad -> NumpadEnter
Num Lock -> NumLock
Sisipkan -> Masukkan
Ins pada pad nomor -> Numpad0
Backspace -> Backspace
Del -> Hapus
F1 ... F12 -> F1 ke F12
Esc -> Melarikan diri dari
tombol Windows kiri -> MetaLeft
kanan Kunci Windows -> MetaRight
Alt -> AltLeft
AltGr -> AltRight (jenis kereta, ia mendeteksi ControlLeft dan kemudian AltRight,tapi itu memang AltRight)
kunci aplikasi (menu konteks) -> ContextMenu

EDIT:
1 byte disimpan pada ;setelah panggilan fungsi
18 byte disimpan berkat Lil 'Bits dan ETHproductions, mereka melihat saya lupa untuk mempersingkat nama func dan var.
32 byte disimpan berkat RogerSpielker, dia perhatikan saya melakukan kode sparated tanpa alasan; dan lagi -2 byte: onkeydown-> onkeyup
1 byte disimpan: tidak perlu slash akhir
2 byte disimpan berkat CraigAyre: with()fungsi
2 byte disimpan berkat ASCII-only: keysebagai pengganti which
4 byte yang disimpan, karena kita memiliki teks, tidak perlu untuk '-'+(setiap pengidentifikasi adalah unik tanpa ini) 1 byte disimpan berkat ASCII-only (lagi): tidak ada lagi simbol penutup > 15 byte yang disimpan berkat apsillers, seperti yang dikatakan di atas jawaban saya.

<body onkeyup=alert(event.code)

V. Courtois
sumber
Tunggu ... bagaimana ... Caps Lock ... terdeteksi? Saya pikir itu tidak mungkin ... Hah, oh well. PrtScn dan SysRq tidak berfungsi untuk saya, tetapi saya menggunakan laptop dengan keyboard kecil yang menggunakan Fn + End dan Fn + Home untuk dua tombol tersebut.
ETHproduksi
Saya suka jawaban ini tetapi sepertinya ada beberapa masalah. Tab tidak melaporkan apa pun untuk saya ketika saya mengujinya di codepen.io/anon/pen/MoLPQM . Juga F12, PrtScn tidak mengikuti aturan ini "Seharusnya tidak melakukan tindakan lain dari penekanan tombol yang diterimanya dan seharusnya tidak menghasilkan apa pun selain dari pengidentifikasi unik."
@Lembik menggunakan html, tidak mungkin untuk mencegah sistem menggunakan kunci. Anda harus memaksanya tidak mengenali input kunci dengan bahasa yang efektif (atau sistem) mesin (seperti C mungkin). Dan untuk tab, saya tidak tahu kondisi apa untuk bekerja (maksud saya, kadang-kadang berfungsi dan kadang tidak, saya tidak tahu bagaimana jawaban saya memperlakukan kunci yang dapat dilewati.
V. Courtois
@Lembik Jika Anda melihat kode dalam standalone (bukan cuplikan atau biola atau serupa), halaman layar penuh (misalnya, dengan F11) maka ia menangkap Tab; fakta bahwa itu tidak menangkap tab adalah fungsi dari keadaan lingkungan browser yang lebih besar, bukan kode yang dijalankan pada halaman. Sedangkan untuk mencegah perilaku default, <body onkeydown=return!!alert(event.code)>harus melakukan trik dengan kembali falsepadakeydown
apsillers
8

Tcl / Tk, 22 karakter

bind . <Key> {puts %K}

Contoh dijalankan:

kunci yang diidentifikasi oleh Tcl / Tk

Catatan:

  • Tidak ada tombol Windows yang tepat pada keyboard saya ☹ ( perancang yang pintar meletakkan lampu latar di tempatnya)
  • Sisip numeric pad menghasilkan kode yang berbeda berdasarkan status NumLock
  • Kenop volume menghasilkan kode spesifik X.org, semua yang lain hanya keyyms biasa
manatwork
sumber
6

Bash dengan X.org, 21 byte

xev|awk 'NR%2&&/\(k/'

Sayangnya, saya tidak dapat mengujinya karena saya menggunakan MacBook di Linux - tanpa PrntScr, tanpa keyboard numerik & semua.

xevadalah alat yang menampilkan acara mouse dan keyboard di bawah X.org. Saya menyalurkannya ke awk, memfilter garis rata (karena setiap tombol ditampilkan saat tombol ditekan, lalu saat dilepaskan), dan pilih hanya yang berisi (k- string ini ada di setiap baris yang menjelaskan tombol yang ditekan.

enedil
sumber
Bisakah Anda menambahkan contoh output yang tercantum dalam pertanyaan.
1
@Lembik semua output muncul setelah keluar.
enedil
Ah. Bukan itu yang diminta oleh spec. Saya akan menghapusnya sekarang.
Ini memberikan kesalahan sintaks sekarang.
3
Perhatikan bahwa Linux tidak menyiratkan X11. misalnya ini tidak akan berfungsi pada konsol teks (gunakan di showkey -ssana: P), atau pada desktop GUI Wayland murni. Ini benar-benar jawaban bash + Xorg.
Peter Cordes
5

C dan Win32, 240 224 216 205 202 194 191 byte

#include<d3d.h>
#include<stdio.h>
w[9];p(x,y,a,b){printf("%X",a^b);}main(){w[1]=p;w[9]=p;CreateWindow(RegisterClass(w),0,1<<28,0,0,0,0,0,0,0,0);for(;GetMessage(w,0,16,0);)DispatchMessage(w);}

Keluaran

TAB: F0008C00F0008

PAUSE: 450012C0450012

ENTER: 1C000CC01C000C

NUMPAD-ENTER: 11C000CC11C000C

WINDOWS-LEFT: 15B005AC15B005A

WINDOWS-RIGHT: 15C005DC15C005D

INSERT: 152002CC152002C

NUMPAD-INSERT: 52002CC052002C

Penjelasan

#include <d3d.h> // shortest built-in header that includes windows.h
#include <stdio.h> // for printf

w[9]; // space for wndclass-data array

// function castable to the signature of WNDPROC
p(x,y,a,b)
{
    // key and state are encoded in the last two 4-byte arguments to wndproc
    printf("%X",a^b);
}

main(m)
{
    // set minimal window class equivalent data pointing to wndproc above
    w[1]=p;w[9]=p;

    // create the window using the class, with WS_VISIBLE flag
    CreateWindow(RegisterClass(w),0,1<<28,0,0,0,0,0,0,0,0)
    for(;GetMessage(w,0,16,0);) // filter messages 15 and lower, which fire without input
        DispatchMessage(w);
}

Suntingan

-16 Terima kasih kepada @ugoren

-8: diubah WNDCLASSmenjadi intarray karena semua 10 anggota adalah 4 byte

-11: inisialisasi parsial array wndclass-data, dikurangi menjadi 9 elemen

-3: gunakan intmendeklarasikan implisit untuk wndclass-data array

-8: hapus baris baru dari format keluaran (tidak diharuskan dalam spesifikasi dan printf segera dihapus tanpa itu); pindah RegisterClasske CreateWindowarg, menggunakan kembali ATOM; atur nama wndclass myang hanya membutuhkan nol-byte di dalamnya sebagai string yang valid.

-3: menggunakan kembali wvar untuk MSGdata

MooseBoys
sumber
Melakukan hal yang sama dengan C ++ dengan menggunakan cout tidak akan jauh lebih pendek?
onurcanbektas
@Leth No. <iostream>+ std::cout<<a^b<<"\n"lebih panjang. Plus, saya pikir Anda perlu menambahkan tipe kembali ke decl fungsi, dan mtidak bisa menjadi implisit int.
MooseBoys
Simpan char denganfor(;GetMessage(&m,0,16,0);)DispatchMessage(&m);
ugoren
Juga, p(x,y,a,b)dan (void*)pharus menyimpan beberapa.
ugoren
3

Java (OpenJDK 8) , 369 byte

import java.awt.event.*;import javax.swing.*;class F{public static void main(String[] a){JFrame f=new JFrame();f.addKeyListener(new KeyListener(){public void keyPressed(KeyEvent e){System.out.print(e.getKeyCode()*8+e.getKeyLocation());}public void keyTyped(KeyEvent e){}public void keyReleased(KeyEvent e){}});f.setVisible(true);f.setFocusTraversalKeysEnabled(false);}}

Ini tidak dapat dijalankan dengan TIO karena menggunakan antarmuka grafis, tetapi berfungsi di komputer saya.

Jeda: 153
Masukkan: 81
Masukkan pada NumPad: 84
Tombol Kiri Super: 193 (Setelah menonaktifkan pintasan Menu untuk desktop saya)
Kunci Super kanan: 201
Masukkan: 241
Masukkan Numpad: 522948 (saya tidak punya, tapi itu yang Anda dapatkan ketika Anda menekan 5 dengan Num lock off. Ketika Num lock aktif, Anda mendapatkan 812.)

Tidak Disatukan / Penjelasan:

import java.awt.event.*; // KeyListener, KeyEvent
import javax.swing.*; // JFrame

class F implements KeyListener {

    public static void main(String[] a) {
        JFrame f=new JFrame(); // creates a new GUI frame
        f.addKeyListener(new KeyListener() {  // puts a KeyListener in the frame with the following properties:

            // Method that runs whenever a key is pressed
            public void keyPressed(KeyEvent e) {
                // getKeyCode returns an integer that uniquely identifies the key,
                // but not the location (e.g. LShift and RShift have the same key code)
                // To fix this, I scale up the key code by 8 and add the location,
                // which is always 0-4 (Standard, Left, Right, NumPad, or Unknown)
                // I could have scaled by 5 instead but I wasn't really thinking
                System.out.print(e.getKeyCode() * 8 + e.getKeyLocation());
                // If you want nicer-looking output, just change "print" to "println"
            }

            // Method that runs whenever a printable character is typed (does nothing)
            public void keyTyped(KeyEvent e){}

            // Method that runs whenever a keyboard key is released (does nothing)
            public void keyReleased(KeyEvent e){}
        });

        f.setVisible(true); // the frame will only except key presses if it is visible
        f.setFocusTraversalKeysEnabled(false); // disables "focus traversal" keys (such as Tab) from actually traversing focus
    }
}
musicman523
sumber
Tidak terlihat seperti itu berfungsi untuk tombol tab?
Poke
setFocusTraversalKeysEnabled(false);dalam jawaban Anda akan memperbaikinya.
Magic Gurita Guci
@MagicOctopusUrn Saya tidak tahu apa yang dilakukannya dan saya rasa saya tidak mau: P
musicman523
Itu membuat jawaban Anda berfungsi untuk kunci TAB, karena jawaban Anda tidak valid tanpanya.
Guci Gurita Ajaib
Ohhhhh saya melihat - Tab adalah "kunci traversal fokus"
musicman523
3

Scala 2.10+, 279 karakter, 279 byte

Sekarang ini adalah respon scala :) meskipun rasanya seperti saya melakukan Java. Lagi pula kami tidak dapat mengujinya di TIO.

import scala.swing._
import java.awt.event._
object M extends SimpleSwingApplication{def top=new MainFrame{this.peer.addKeyListener(new KeyListener(){def keyPressed(e:KeyEvent){print(e.getKeyCode+"-"+e.getKeyLocation)}
def keyReleased(e:KeyEvent){}
def keyTyped(e:KeyEvent){}})}}

Sangat menyedihkan kita perlu mendeklarasikan semua metode yang diwariskan walaupun kita tidak menggunakannya: apakah saya dapat menghapusnya dari jumlah byte, karena beberapa flag compiler dapat mengizinkan tidak mendeklarasikannya?

Ini mencetak (seperti untuk respons html-js saya) tombol yang ditekan, "-" dan kemudian "lokasinya".

Contohnya :

PrtScn -> tidak dapat diverifikasi
Scroll Lock -> 145-1
Jeda -> 19-1
Shift kiri -> 16-2
Shift kanan -> 16-3
Ctrl kiri -> 17-2
Ctrl kanan -> 17-3
Caps Lock -> 20-1
Tab -> tidak dapat diverifikasi
Enter -> 10-1
Masukkan pada pad nomor -> 10-4
Num Lock -> 144-4
Masukkan -> 96-1
Ins pada pad nomor -> 96-4
Backspace -> 8-1
Del -> 127-1
F1 ... F12 -> 112-1 hingga 123-1
Esc -> 27-1
tombol Windows kiri -> 524-2
tombol Windows kanan -> 524-3
Alt -> 18- 2
AltGr -> 18-3 (jenis kereta, ia mendeteksi 17-2 dan kemudian 18-3,tetapi memang 18-3)
kunci aplikasi (menu konteks) -> 525-1

Meskipun saya pikir itu tergantung pada komputer: / Saya pada laptop azerty sekarang.

V. Courtois
sumber
Jika Anda ingin tidak menghitung deklarasi yang tidak dibutuhkan, Anda mungkin harus memasukkan panjang flag kompiler non-standar. Kecuali jika kompiler lama digunakan secara default untuk itu? Jawaban C biasanya perlu dikompilasi -std=c89karena kompiler modern default ke c99 atau c11, tetapi tidak perlu menghitungnya. Jadi saya tidak yakin apa putusannya dari meta kode-golf.
Peter Cordes
3

TI-BASIC, 19 byte

PROGRAM: S

If Ans
Disp Ans
getKey
prgmS
  • Masukkan: 105,
  • Tombol kiri: 24,
  • Kunci kanan: 26,
  • Ins [ert] sedikit berbeda karena biasanya diperlukan dua penekanan tombol untuk sampai ke, tetapi mereka akan 21 diikuti oleh 23.

Berikut ini ilustrasi dari sisa tombol:

masukkan deskripsi gambar di sini

Penjelasan:

PROGRAM: S Editor menampilkan nama di bagian atas terlepas dari kode; namanya "S"

If Ans    // If the last input isn't zero
Disp Ans  // Display the last input
getKey    // Input a key press
prgmS     // Call the same program in a recursive fashion

Sayangnya, ini tidak mungkin dilakukan di Arnold C, jadi saya harus tetap menggunakan TI-BASIC.

bearacuda13
sumber
1
Apakah itu berfungsi untuk setiap kunci di gambar itu? Jika bukan kunci mana yang gagal?
2
Ya, itu berfungsi untuk setiap tombol kecuali tombol on, yang disediakan untuk mematikan program tanpa mengeluarkan baterai dari kalkulator.
bearacuda13
@ bearacuda13: Saya memiliki kalkulator yang sama dengan yang saya beli 18 tahun yang lalu dan tidak tahu detail kunci ON selama bertahun-tahun. Saya telah menggunakannya sejak akhir universitas (11 tahun yang lalu), tetapi siapa tahu ...
sergiol
1

C #, 144 + 601 = 745 byte

Terdiri dari dua kelas, saya tidak bisa berhasil menggabungkan mereka ke dalam satu kelas.

Kelas utama:

namespace System.Windows.Forms{class P:Form{static void Main(){Application.Run(new P());}P(){new Reflection.M().U+=k=>Console.Write(k.f+k.v);}}}

Kelas kait:

namespace System.Reflection{using Runtime.InteropServices;public class M{public delegate void d(s s);event d u;public event d U{add{if(h<1){j=m;h=SetWindowsHookEx(13,j,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);}u+=value;}remove{u-=value;}}public struct s{public int v;public int c;public int f;}[DllImport("user32.dll")]static extern int SetWindowsHookEx(int idHook,p lpfn,IntPtr hMod,int dwThreadId);delegate int p(int c,int w,IntPtr l);p j;int h;int m(int c,int w,IntPtr l){if(c>=0&u!=null&(w==257|w==261))u.Invoke((s)Marshal.PtrToStructure(l,typeof(s)));return -1;}}}

Output:

  • Tab: 137
  • Jeda: 147
  • Memasukkan: 141
  • NumPad Enter: 142
  • Windows kiri: 220
  • Windows Kanan: 221
  • Memasukkan: 174
  • Masukkan NumPad: 224
TheLethalCoder
sumber
Saya bisa mendapatkan byte turun sedikit dengan mengubah ||ke |dan golfs lain yang sejenis tapi otak saya butuh istirahat setelah melakukan itu!
TheLethalCoder
Di kelas Hook, saya pikir public int v;public int c;public int f;bisa disingkat menjadipublic int v,c,f;
Tanda Tanya
@QuestionMarks Ide bagus akan bermain golf ketika saya kembali ke komputer
TheLethalCoder
1

AutoHotkey , 26 Bytes

loop{
input,x,L1M
send %x%
}

Tidak dapat menguji (hanya untuk menang), tetapi Mopsi mengatakan

M: Keyboard yang dimodifikasi seperti Control-A hingga Control-Z dikenali dan ditranskripsi jika sesuai dengan karakter ASCII asli.

Jadi itu seharusnya baik-baik saja.

phil294
sumber
1

WinApi C ( gcc ), 156 byte

#include <d3d.h>
#define b GetStdHandle(-10)
BYTE i[20];main(){SetConsoleMode(b,0);a:ReadConsoleInput(b,i,1,i+5);*i^1||*(i+4)||printf("%X\n",i[10]);goto a;}

Program ini mencetak Kode Virtual-Key Windows yang dikaitkan dengan setiap tombol keyboard input. The \ndalam printfformat string opsional (tapi membuat keluaran ramah-manusia) dan dapat turun untuk skor total 154 byte . Cara mudah untuk mematikan program (tanpa taskmgr) adalah dengan CTRL + PAUSE. Jika Anda memiliki keyboard dengan tombol Fn, program ini tidak dapat mengambilnya karena bahkan tidak diperhatikan oleh Windows.

  • Kredit untuk jawaban MooseBoys untuk #include <d3d.h>trik dan inspirasi untuk BYTEarray.

Program dengan variabel lokal, keterbacaan, dan tanpa peringatan kompiler terlihat seperti ini:

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

int main(void)
{
    HANDLE conIn = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD ir;
    DWORD useless;

    SetConsoleMode(conIn, 0);

    for(;;)
    {
        ReadConsoleInput(conIn, &ir, 1, &useless);

        if(ir.EventType == KEY_EVENT && !ir.Event.KeyEvent.bKeyDown)
            printf("%X\n", ir.Event.KeyEvent.wVirtualKeyCode);
    }

    return 0;
}
Pak Acak
sumber
1

C (gcc) + Win32, 94 95 98 105 107 110 byte

#import"d3d.h"
j;f(){for(;;)for(j=191;j--;)GetAsyncKeyState(j)&(j<16||j>18)?printf("%d",j):0;}

Kode menangkap kunci bahkan setelah fokus hilang.

Tangkapan layar berikut direkam dengan menambahkan spasi di antara keluaran ( printf("%d ",j);+1 byte) untuk kemudahan penayangan yang lebih baik:

tangkapan layar kunci

Left-ctrl Left-win Left-alt Space Right-alt Right-win Right-menu Right-ctrl Left-shift Z X C Right-shift Left-shift 1 2 3 Num 1 Num 2 Num 3 Left-shift +/= (on the main part) Num + Left-alt PrtScn

Kode digunakan GetAsyncKeyStateuntuk menanyakan status kunci tanpa memeriksa antrian pesan, biasanya lebih real-time daripada pendekatan mode pengguna lainnya (kecuali DirectInput). Pendekatan ini banyak digunakan dalam keyloggers.

(j<16||j>18)menyaring Ctrl / Alt / Shift biasa. 16/17/18 dipicu setiap kali kiri atau kanan ditekan, bersama dengan nilai vkey yang ditentukan lokasi.

Keyu Gan
sumber
1

PowerShell, 34 byte

$Host.UI.RawUI.ReadKey().Character

Keluaran pada baris yang sama dengan input, yang dapat sedikit membingungkan.

Gabriel Mills
sumber