ฉันกดปุ่มอะไร


15

งานคือการเขียนรหัสเพื่อระบุคีย์ที่กดบนแป้นพิมพ์ คุณสามารถสันนิษฐานได้ว่ามีการกดครั้งละหนึ่งแป้นเท่านั้นและมีรูปแบบแป้นพิมพ์มาตรฐานของสหรัฐอเมริกา นั่นคือเลย์เอาต์ที่มีเครื่องหมาย @ เหนือ 2

รหัสของคุณควรแสดงรหัสเฉพาะสำหรับการกดคีย์ใด ๆ ซึ่งรวมถึง PrtScn, Scroll Lock, Pause, Shift ด้านซ้าย, Shift ด้านขวา, Ctrl, ขวา Ctrl, Caps Lock, Tab, Enter, Enter บนแป้นตัวเลข, Num Lock, แทรก, Ins บนแป้นตัวเลข, Backspace, Del, F1 ... F12, Esc, ปุ่ม Windows ซ้าย, ปุ่ม Windows ที่ถูกต้อง, Alt, AltGr, คีย์แอปพลิเคชัน (เมนูบริบท) และอื่น ๆ

รหัสของคุณควรดำเนินการต่อเพื่อรอการกดปุ่มและแสดงตัวตนของพวกเขาจนกว่ามันจะถูกฆ่า มันควรจะส่งออกตัวระบุทันทีที่มีการเปิดตัวกุญแจ ไม่ควรดำเนินการใด ๆ จากการกดปุ่มที่ได้รับและไม่ควรแสดงผลใด ๆ นอกเหนือจากตัวระบุเฉพาะ

ในคำตอบของคุณโปรดแสดงสิ่งที่คุณส่งออกรหัสสำหรับการกดปุ่มต่อไปนี้: Tab, Pause, Enter, Enter บนแป้นตัวเลข, ปุ่ม Windows ซ้าย, ปุ่ม Windows ขวา, ปุ่ม Windows ที่ถูกต้อง, แทรกและ Ins บนแป้นตัวเลข

หากคุณมีแป้นพิมพ์ที่แตกต่างกันมากความท้าทายก็ยังคงแสดงตัวระบุที่แตกต่างกันสำหรับทุก ๆ ปุ่มบนแป้นพิมพ์ของคุณ


1
ใน JS (เบราว์เซอร์ JS อย่างไรก็ตาม) เป็นไปไม่ได้ที่จะตรวจสอบว่ามีการกดปุ่มบางปุ่มหรือไม่ (เช่น Caps Lock, Num Lock, Scroll Lock, PrtScn) นี่หมายความว่า JS ไม่สามารถตอบได้ใช่หรือไม่
ETHproductions

2
@ETHproductions มันทำแน่นอน ขอโทษสำหรับคนรัก JS ทุกที่

2
ข้อกำหนดที่ได้รับการแก้ไขหลังจากมีคำตอบ 5 ข้อ (รวมหนึ่งข้อที่ถูกลบแล้ว) นั่นไม่ยุติธรรมเลยจริงๆ ...
Olivier Grégoire

6
ฉันไม่คิดว่ามันยุติธรรม / ถูกต้องที่จะขอเอาท์พุทสำหรับปุ่มที่ไม่ได้อยู่บนคีย์บอร์ดหลายตัวเช่นปุ่ม Windows เป็นต้น
Notts90 ปิดการใช้งาน codidact.org

1
@ Notts90 พวกเขาไม่ได้เป็นส่วนหนึ่งของรูปแบบแป้นพิมพ์มาตรฐานของสหรัฐอเมริกาหรือไม่ upload.wikimedia.org/wikipedia/commons/thumb/5/51/…

คำตอบ:


22

รหัสเครื่อง x86, ปฏิบัติการ DOS, 29 * 28 ไบต์

FAE464D0E873FAE460D0E073F4D41005212192B402CD2188F2CD21EBE3

นี่เป็นไฟล์ COM ที่ทำงานได้สำหรับMS-DOSมันต้องใช้ฮาร์ดแวร์ที่รองรับ IBM PC
โดยเฉพาะอย่างยิ่งคอนโทรลเลอร์ 8042 PS / 2หรือมากกว่านั้นการแข่งขันของมันผ่านSMM
เรื่องสั้นสั้นควรทำงานนอกกรอบในพีซีกระแสหลักใด ๆ

รหัสแหล่งที่มาคือ

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

ฉันแบ่งโปรแกรมออกเป็นสองส่วน

ส่วนแรกเกี่ยวกับการอ่านของscancodes Scancodes คือค่าตัวเลขที่เกี่ยวข้องกับทุก ๆ คีย์
โปรดทราบว่าเหล่านี้เป็นรหัสฮาร์ดแวร์พวกเขาไม่ได้ขึ้นอยู่กับระบบปฏิบัติการหรือชุดอักขระ พวกเขาเป็นเหมือนการเข้ารหัสคู่ (คอลัมน์, แถว) ของกุญแจ
ทุกคีย์มี scancode แม้แต่ปุ่มฟังก์ชั่นแปลก ๆ ที่ไม่ได้มาตรฐานที่พบในบางคีย์บอร์ด (เช่นปุ่ม "open calc")
คีย์บางตัวมี scancode แบบหลายไบต์พวกเขามีคำนำหน้าออกแบบมาเพื่อให้สตรีมถอดรหัสได้โดยเพียงแค่ดูลำดับของไบต์
ดังนั้นแต่ละคีย์จะได้รับตัวระบุที่ไม่ซ้ำกันแม้แต่ CTRL, SHIFT, WinKeys และอื่น ๆ

มีการประมวลผลเฉพาะ "รหัสหยุด" ที่ส่งเมื่อปล่อยคีย์เท่านั้นระบบจะไม่ประมวลผล "รหัสทำ"
ตัวสร้างมีชุดบิตสูงกว่า (บิต 7 สำหรับไบต์) ดังนั้นจึงง่ายต่อการจดจำ

ส่วนที่สองเกี่ยวข้องกับการพิมพ์ไบต์
การพิมพ์มีความยาวเสมอในชุดประกอบเราไม่มีตัวเครื่อง
เพื่อให้สั้นและเนื่องจากจำเป็นต้องเขียนตัวระบุของคีย์ฉันจึงละทิ้งเลขฐานสิบหรือเลขฐานสิบหกเพื่อสนับสนุนการเข้ารหัสส่วนบุคคล

ไบต์ที่ xy โดยที่ x คือ nibble ที่สูงกว่าและ y ที่ต่ำกว่าจะถูกพิมพ์เป็นตัวอักษรต่อเนื่องสองตัว c 0และ c 1 ที่กำหนดเป็น

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

หมายเหตุว่าตอดล่างจะมีการพิมพ์ครั้งแรก (นี้ไว้ชีวิตฉันแลกเปลี่ยน)
เหตุผลคือการแมปค่าที่เป็นไปได้ 16 ค่าของการตอดเป็นอักขระ ASCII ต่อเนื่องจาก '!'
เพียงแค่ใส่นี่เป็นเลขฐานสิบหก แต่ด้วย

  1. ไส้ตะเกียงเปลี่ยน
  2. !"#$%&'()*+,-./01 เป็นตัวเลข (als) แทน 0123456789abcdef

ใช้งานในDOSBoxแล้วกดปุ่มสุ่มบางตัว (บางอันเป็นคีย์พิเศษ แต่โปรดทราบว่าเนื่องจากกระบวนการ Windows DOSBox ไม่สามารถจับคีย์ทั้งหมดได้)

DOSBox ใช้งานตัวระบุคีย์

โปรดทราบว่าโปรแกรมนี้ไม่เคยยุติ (ยิ่งไปกว่านั้นมันใช้การควบคุมอย่างสมบูรณ์ของพีซีโดยการปิดการใช้งานอินเตอร์รัปต์) เนื่องจากฉันเชื่อว่าเป็นคำถามที่ตั้งใจไว้


*ลดขอบคุณCodyGray


การใช้INคำสั่งนั้นมีขนาดเล็กลงในแง่ของไบต์มากกว่าการเรียก ROM ขัดจังหวะ ROM (เช่นint 16h, ฟังก์ชั่น 10 ชม.) หรือไม่?
โคดี้เกรย์

@CodyGray ไม่น่าจะเป็นไปได้ที่การวนซ้ำทั้งหมดอาจถูกข้ามไปได้ อย่างใดฉันก็กระโดดตรงไปที่inคำแนะนำ นั่นเป็นจุดที่ดีมากสำหรับคุณ หากคุณยังไม่ได้ทำทำไมไม่โพสต์มันเป็นคำตอบ? :)
Margaret Bloom

1
ตอนนี้คุณกำลังพูดถึงบ้า! ฟังดูเหมือนจะเป็นอะไรที่มากกว่าการแสดงความคิดเห็นต่อคำตอบที่คุณมีอยู่ :-p ฉันเล่นด้วยการใส่อะไรบางอย่างเข้าด้วยกัน เคล็ดลับความสนุกสนาน แต่เมื่อเล่นกอล์ฟรหัสxchgที่มีสะสมเป็นหนึ่งของการลงทะเบียนเป็น 1 ไบต์เพื่อให้ดีขึ้นกว่า mov2
Cody Gray

1
โอเคปัญหาint 16hคือฉันไม่ได้รับรหัสสแกนสำหรับปุ่ม Shift, ล็อคการเลื่อนหรือหยุด / หยุดพัก (บางทีอาจเป็นอย่างอื่น) และเป็นสิ่งที่ท้าทาย โซลูชันของคุณในการอ่านอินพุตโดยตรงจาก I / O ทำงานได้แม้ว่ามันจะดูเหมือนว่าฉันจะส่งกลับค่าเดียวกันสำหรับคีย์ทั้งหมดในคลัสเตอร์ Ins / Del / Home / End / PgUp / PgDown
Cody Gray

1
@PeterCordes: หยุดชั่วคราวยังมีพฤติกรรมที่แปลกประหลาด IIUC ส่งรหัสการแบ่งพร้อมกับสร้างรหัสในการกดปุ่มและไม่ส่งอะไรในการเปิดตัวปุ่ม หรือนั่นคือสิ่งที่ฉันเข้าใจจาก PC Game Programming Encyclopedia
ninjalj

12

Java 7 หรือสูงกว่า, 246 228 ไบต์

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);}};}}

Ungolfed:

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 ขอบคุณที่ @ OlivierGrégoireสำหรับshow(), 0<0และimport java.awt.event.*;

ซึ่งผลลัพธ์ใน:

ป้อนคำอธิบายรูปภาพที่นี่

แม้จะจัดการกับการกดปุ่ม Shift สำหรับตัวอักษรตัวพิมพ์ใหญ่, ปุ่ม windows, ฝาปิดล็อค, ฯลฯ ... คุณสามารถเห็นมันพิมพ์ 'modifiers' เช่นกัน, ซึ่งเป็น 'ปุ่มกดค้างไว้'

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

ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Dennis

11

HTML (ด้วย Javascript), 46 31 ตัวอักษร, 46 31 ไบต์

การใช้สิ่งนี้เพื่อแยกความแตกต่างระหว่างการป้อนและส่งคืนของนัมแด็ด LControl และ RControl ...ไม่ใช่อีกต่อไปเนื่องจากแอปซิลเลอร์พบวิธีที่จะทำได้ด้วยการเรียกใช้ฟังก์ชัน signle

<body onkeyup=alert(event.code)

ผลลัพธ์เฉพาะ:

ผลลัพธ์ที่ยังคงมีตัวเลขเหล่านั้นฉันไม่สามารถทดสอบบนแล็ปท็อปของฉัน
โปรดรอให้ฉันมีการเข้าถึงคีย์เหล่านั้น

PrtScn -> PrintScreen
Scroll Lock -> ScrollLock
Pause -> Pause
left Shift -> ShiftLeft
right Shift -> ShiftRight
ซ้าย Ctrl -> ContrlLeft
right Ctrl -> ControlRight
Caps Lock ->
Tab CapsLock -> Tab
Enter -> Enter
ใส่ตัวเลข pad -> NumpadEnter
Num Lock -> NumLock
แทรก -> แทรก
Ins บนแผงตัวเลข -> Numpad0
Backspace -> Backspace
Del -> ลบ
F1 ... F12 -> F1 ถึง F12
Esc -> หนี
คีย์ Windows ซ้าย -> MetaLeft
right ปุ่ม Windows -> รหัส แอพพลิเคชันMetaRight (เมนูบริบท) -> ContextMenu
Alt -> AltLeft
AltGr -> AltRight (ชนิดของบั๊กกี้ตรวจพบ ControlLeft แล้วตามด้วย AltRightแต่มันคือ AltRight)

แก้ไข:
บันทึก 1 ไบต์;หลังจากบันทึกfunc โทร
18 ไบต์ขอบคุณ Lil 'Bits และ ETHproductions พวกเขาสังเกตเห็นว่าฉันลืมย่อชื่อ func และ var ให้สั้นลง
32 ไบต์ได้รับการบันทึกด้วย RogerSpielker เขาได้สังเกตว่าฉันกำลังทำโค๊ดโค้ดโดยไม่มีเหตุผล และอีกครั้ง -2 ไบต์: onkeydown-> onkeyup
1 ไบต์บันทึก: ไม่จำเป็นต้องใช้เครื่องหมายทับสุดท้าย
2 ไบต์บันทึกโดย CraigAyre: with()ฟังก์ชัน
2 ไบต์บันทึกด้วย ASCII-only: keyแทนที่which
4 ไบต์เนื่องจากเรามีข้อความจึงไม่จำเป็นต้องใช้ สำหรับ'-'+(ตัวระบุทุกตัวไม่ซ้ำกันโดยไม่มีสิ่งนี้) บันทึก 1 ไบต์ขอบคุณ ASCII-only (อีกครั้ง): ไม่มีสัญลักษณ์ปิดปิดอีก> 15 ไบต์ขอบคุณ apsillers ดังที่กล่าวไว้ด้านบนของคำตอบของฉัน

<body onkeyup=alert(event.code)


รอ ... ตรวจพบ ... Caps Lock ... อย่างไร ฉันคิดว่ามันเป็นไปไม่ได้ ... PrtScn และ SysRq ไม่ทำงานสำหรับฉัน แต่ฉันอยู่บนแล็ปท็อปที่มีแป้นพิมพ์ขนาดเล็กที่ใช้ Fn + End และ Fn + Home สำหรับปุ่มทั้งสอง
ETHproductions

ฉันชอบคำตอบนี้ แต่ดูเหมือนว่าจะมีปัญหาบางอย่าง แท็บไม่รายงานอะไรสำหรับฉันเมื่อฉันทดสอบที่codepen.io/anon/pen/MoLPQM เช่นเดียวกันกับ F12, PrtScn ไม่ปฏิบัติตามกฎนี้ "มันไม่ควรกระทำการอื่นใดจากการกดปุ่มที่ได้รับและไม่ควรแสดงผลใด ๆ นอกเหนือจากตัวระบุเฉพาะ"

@Lembik ใช้ html ไม่สามารถป้องกันระบบจากการใช้รหัส คุณจำเป็นต้องบังคับให้ไม่จดจำอินพุตคีย์ด้วยภาษาที่มีประสิทธิภาพของเครื่อง (หรือระบบ) (เช่น C อาจ) และสำหรับแท็บฉันไม่ทราบว่ามีเงื่อนไขอะไรบ้างสำหรับการทำงาน (ฉันหมายความว่ามันใช้งานได้บางครั้งและบางครั้งก็ไม่ได้ฉันไม่รู้ว่าคำตอบของฉันใช้คีย์ที่สำรวจได้อย่างไร
V. Courtois

@Lembik หากคุณดูรหัสในรูปแบบสแตนด์อโลน (ไม่ใช่ตัวอย่างหรือซอหรือคล้ายกัน) หน้าเต็มหน้าจอ (เช่นด้วย F11) มันจะจับแท็บ; ความจริงที่ว่ามันไม่ได้จับแท็บเป็นฟังก์ชั่นของสภาพแวดล้อมของเบราว์เซอร์ที่มีขนาดใหญ่ไม่ใช่รหัสที่กำลังเรียกใช้บนหน้าเว็บ สำหรับการป้องกันพฤติกรรมเริ่มต้น<body onkeydown=return!!alert(event.code)>ควรทำเคล็ดลับโดยกลับfalseไปที่keydown
apsillers

8

Tcl / Tk, 22 ตัวอักษร

bind . <Key> {puts %K}

วิ่งตัวอย่าง:

คีย์ที่ระบุโดย Tcl / Tk

หมายเหตุ:

  • ไม่มีปุ่ม Windows ที่ถูกต้องบนแป้นพิมพ์ของฉัน ☹ ( นักออกแบบที่ชาญฉลาดวางสวิตช์แบ็คไลท์ไว้ที่นั้น)
  • ส่วนแทรกของแผ่นตัวเลขจะสร้างรหัสที่แตกต่างกันตามสถานะของ NumLock
  • ปุ่มปรับระดับเสียงสร้างรหัสเฉพาะของ X.org ส่วนอื่น ๆ ทั้งหมดเป็นเพียงกุญแจหลักปกติ

6

Bash กับ X.org ขนาด 21 ไบต์

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

น่าเสียดายที่ฉันไม่สามารถทดสอบได้ตั้งแต่ฉันใช้ MacBook บน Linux - ไม่มี PrntScr ไม่มีแป้นตัวเลขและทั้งหมด

xevX.orgเป็นเครื่องมือที่เอาท์พุทเมาส์และแป้นพิมพ์ภายใต้เหตุการณ์ที่เกิดขึ้น ฉันไปป์ที่ awk ตัวกรองคู่บรรทัด (เนื่องจากทุกปุ่มถูกแสดงเมื่อกดแป้นและจากนั้นเมื่อปล่อย) และเลือกเฉพาะที่มี(k- สตริงนี้อยู่ในทุกบรรทัดที่อธิบายถึงปุ่มกด


คุณสามารถเพิ่มตัวอย่างผลลัพธ์ที่แสดงในคำถามได้ไหม

1
@Lembik เอาต์พุตทั้งหมดปรากฏขึ้นหลังจากออก
enedil

อา. นั่นไม่ใช่สิ่งที่สเป็คขอ ฉันจะล้างมันตอนนี้

สิ่งนี้ทำให้เกิดข้อผิดพลาดทางไวยากรณ์ทันที

3
โปรดทราบว่า Linux ไม่ได้หมายถึง X11 เช่นนี้จะไม่ทำงานบนคอนโซลข้อความ (ใช้ที่showkey -sนั่น: P) หรือบนเดสก์ท็อป Wayland GUI อย่างแท้จริง นี่เป็นคำตอบ bash + Xorg จริงๆ
Peter Cordes

5

C และ Win32, 240 224 216 205 202 194 191 ไบต์

#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);}

เอาท์พุท

TAB: F0008C00F0008

PAUSE: 450012C0450012

ENTER: 1C000CC01C000C

NUMPAD-ENTER: 11C000CC11C000C

WINDOWS-LEFT: 15B005AC15B005A

WINDOWS-RIGHT: 15C005DC15C005D

INSERT: 152002CC152002C

NUMPAD-INSERT: 52002CC052002C

คำอธิบาย

#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);
}

การแก้ไข

-16 ขอบคุณ @ugoren

-8: เปลี่ยนWNDCLASSเป็นintอาร์เรย์เนื่องจากสมาชิกทั้งหมด 10 คนมีขนาด 4 ไบต์

-11: การเริ่มต้นบางส่วนของอาร์เรย์ข้อมูล wndclass ลดลงถึง 9 องค์ประกอบ

-3: ใช้intการประกาศ impl สำหรับ wndclass-data

-8: ลบ newline ออกจากรูปแบบเอาต์พุต (ไม่จำเป็นใน spec และ printf flushes ทันทีโดยไม่มี) ย้ายRegisterClassไปCreateWindowหาเรื่องโดยใช้กลับATOM; ตั้งชื่อ wndclass mที่ต้องการเพียงแค่ศูนย์ไบต์ในนั้นจะเป็นสตริงที่ถูกต้อง

-3: ใช้wvar ซ้ำสำหรับMSGข้อมูล


การทำสิ่งเดียวกันกับ C ++ โดยใช้coutจะไม่สั้นลงหรือไม่?
onurcanbektas

@Leth No. <iostream>+ std::cout<<a^b<<"\n"อีกต่อไป นอกจากนี้ฉันคิดว่าคุณจะต้องเพิ่มประเภทผลตอบแทนให้กับฟังก์ชั่นการประกาศและmไม่สามารถเป็นนัยintได้
MooseBoys

ประหยัดถ่านด้วยfor(;GetMessage(&m,0,16,0);)DispatchMessage(&m);
ugoren

นอกจากนี้p(x,y,a,b)และ(void*)pควรบันทึกบางส่วน
ugoren

3

Java (OpenJDK 8) , 369 ไบต์

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);}}

สิ่งนี้ไม่สามารถรันด้วย TIO ได้เนื่องจากใช้ส่วนต่อประสานแบบกราฟิก แต่ทำงานบนคอมพิวเตอร์ของฉัน

หยุดชั่วคราว: 153
ป้อน: 81
ใส่ NumPad: 84
ปุ่ม Super ซ้าย: 193 (หลังจากปิดใช้งานทางลัดเมนูสำหรับเดสก์ท็อปของฉัน)
ปุ่ม Super Right: 201
แทรก: 241
ใส่ใน Numpad: 522948 (ฉันไม่มีเลย แต่นั่นคือสิ่งที่คุณจะได้รับเมื่อคุณกด 5 ด้วย Num lock off เมื่อเปิด Num lock คุณจะได้รับ 812)

Ungolfed / คำอธิบาย:

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
    }
}

ดูเหมือนว่าจะใช้งานไม่ได้กับคีย์แท็บใช่หรือไม่
Poke

setFocusTraversalKeysEnabled(false);ในคำตอบของคุณจะแก้ไขปัญหานี้
Magic Octopus Urn

@MagicOctopusUrn ฉันไม่รู้ว่ามันทำอะไรและฉันไม่คิดว่าฉันต้องการ: P
musicman523

มันทำให้คำตอบของคุณทำงานสำหรับคีย์ TAB เนื่องจากคำตอบของคุณนั้นไม่ถูกต้องหากไม่มี
Magic Octopus Urn

Ohhhhh ฉันเห็นแล้ว - Tab คือ "กุญแจโฟกัสการสำรวจเส้นทาง"
musicman523

3

สกาล่า 2.10+, 279 ตัวอักษร, 279 ไบต์

ตอนนี้เป็นการตอบสนองแบบสกาล่า :) ถึงแม้ว่าฉันจะรู้สึกว่าฉันทำ Java อย่างไรก็ตามเราไม่สามารถทดสอบกับ 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){}})}}

เป็นเรื่องน่าเศร้าที่เราต้องประกาศวิธีการสืบทอดทั้งหมดแม้ว่าเราจะไม่ได้ใช้มัน: ฉันสามารถลบมันออกจากการนับไบต์เนื่องจากธงคอมไพเลอร์บางตัวสามารถอนุญาตให้ประกาศไม่ได้?

ปุ่มนี้จะพิมพ์ (สำหรับการตอบสนอง html-js ของฉัน) ปุ่มกด "-" แล้วตามด้วย "ตำแหน่ง"

ตัวอย่างเช่น

PrtScn -> ไม่สามารถตรวจสอบได้
Scroll Lock -> 145-1
Pause -> 19-1
Shift ซ้าย -> 16-2
Shift ขวา -> 16-3 Left
Ctrl -> 17-2
Ctrl ขวา -> 17-3
Caps Lock ->
แท็บ20-1 -> ตรวจสอบไม่ได้
Enter -> 10-1
ป้อนบนแป้นตัวเลข -> 10-4
Num Lock -> 144-4
แทรก -> 96-1
Ins บนแป้นตัวเลข -> 96-4
Backspace -> 8-1
Del -> 127-1
F1 ... F12 -> 112-1 ถึง 123-1
Esc -> 27-1
คีย์ Windows ซ้าย -> 524-2
คีย์ Windows ขวา -> 524-3
Alt -> 18- 2
AltGr -> 18-3 (ชนิดบั๊กกี้มันตรวจจับ 17-2 และ 18-3 แล้วแต่มันเป็น 18-3)
แอปพลิเคชันคีย์ (เมนูบริบท) -> 525-1

แม้ว่าฉันคิดว่ามันขึ้นอยู่กับคอมพิวเตอร์: / ตอนนี้ฉันใช้แล็ปท็อปที่มีความสามารถสูง


หากคุณไม่ต้องการนับการประกาศที่ไม่จำเป็นคุณอาจต้องรวมความยาวของแฟล็กคอมไพเลอร์ที่ไม่ได้มาตรฐาน หากไม่มีคอมไพเลอร์เก่าที่ใช้ในการตั้งค่าเริ่มต้นนั้น คำตอบ C มักจะต้องรวบรวมด้วย-std=c89ตั้งแต่คอมไพเลอร์สมัยใหม่เริ่มต้นที่ c99 หรือ c11 แต่ไม่จำเป็นต้องนับ ดังนั้นฉันไม่แน่ใจว่าการพิจารณาคดีจะมาจาก meta-golf
Peter Cordes

3

TI-BASIC, 19 ไบต์

PROGRAM: S

If Ans
Disp Ans
getKey
prgmS
  • ใส่: 105,
  • ปุ่มซ้าย: 24,
  • ปุ่มขวา: 26,
  • Ins [ert] แตกต่างกันเล็กน้อยเพราะปกติแล้วจะใช้การกดปุ่มสองครั้งเพื่อไปถึง แต่สิ่งเหล่านั้นจะเป็น 21 ตามด้วย 23

นี่คือภาพประกอบของกุญแจที่เหลืออยู่:

ป้อนคำอธิบายรูปภาพที่นี่

คำอธิบาย:

โปรแกรม: S ตัวแก้ไขแสดงชื่อที่ด้านบนนอกเหนือจากรหัส ชื่อคือ "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

น่าเสียดายที่ไม่สามารถทำได้ใน Arnold C ดังนั้นฉันต้องติดกับ TI-BASIC


1
ใช้ได้กับทุกคีย์ในภาพนั้นหรือไม่ หากไม่ใช่คีย์ใดที่ล้มเหลว

2
ใช่มันใช้ได้กับทุกปุ่มยกเว้นปุ่มเปิดซึ่งสงวนไว้สำหรับการฆ่าโปรแกรมโดยไม่ทำให้แบตเตอรี่หมดลงในเครื่องคิดเลข
bearacuda13

@ bearacuda13: ฉันมีเครื่องคิดเลขที่เท่ากันซึ่งฉันซื้อเมื่อ 18 ปีก่อนและไม่ทราบรายละเอียดคีย์ ON เป็นเวลาหลายปี ฉันใช้มันตั้งแต่ตอนจบมหาวิทยาลัย (11 ปีที่แล้ว) แต่ใครจะรู้ ...
sergiol

1

C #, 144 + 601 = 745 ไบต์

ประกอบด้วยสองคลาสฉันไม่สามารถจัดการเพื่อรวมเข้าเป็นหนึ่งคลาสได้สำเร็จ

ชั้นหลัก:

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);}}}

ชั้นเบ็ด:

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;}}}

ขาออก:

  • แท็บ: 137
  • หยุด: 147
  • Enter: 141
  • NumPad ป้อน: 142
  • Windows ซ้าย: 220
  • Windows ขวา: 221
  • แทรก: 174
  • แทรก NumPad: 224

ฉันสามารถลดจำนวนไบต์ลงได้โดยการเปลี่ยน||ไป|เล่นกอล์ฟอื่นที่คล้ายคลึงกัน แต่สมองของฉันต้องการพักผ่อนหลังจากทำเช่นนั้น!
TheLethalCoder

ในชั้นเรียน Hook ฉันคิดว่าpublic int v;public int c;public int f;อาจถูกตัดให้สั้นลงpublic int v,c,f;
เครื่องหมายคำถาม

@QuestionMarks ความคิดที่ดีจะเล่นกอล์ฟเมื่อฉันกลับไปที่คอมพิวเตอร์
TheLethalCoder

1

AutoHotkeyขนาด 26 ไบต์

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

ไม่สามารถทดสอบ (win-only) แต่Mตัวเลือกบอกว่า

M: การกดแป้นที่ถูกปรับเปลี่ยนเช่น Control-A ผ่าน Control-Z จะถูกจดจำและถอดความหากตรงกับอักขระ ASCII จริง

ดังนั้นควรทำดี


1

WinApi C ( gcc ), 156 ไบต์

#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;}

โปรแกรมนี้พิมพ์รหัส Windows Virtual-Key ที่คลาดเคลื่อนไปกับแต่ละแป้นพิมพ์ของอินพุต \nในprintfรูปแบบสตริงเป็นตัวเลือก ( แต่ทำให้ผลผลิตเป็นมิตรกับมนุษย์) และสามารถลดลงสำหรับคะแนนรวมของ154 ไบต์ วิธีง่ายๆในการฆ่าโปรแกรม (โดยไม่ Taskmgr) CTRL + PAUSEอยู่กับ หากคุณมีแป้นพิมพ์ที่มีปุ่ม Fn โปรแกรมนี้จะไม่สามารถรับได้เนื่องจาก Windows ไม่ได้สังเกตเห็น

  • ให้เครดิตกับคำตอบของ MooseBoys สำหรับ#include <d3d.h>เคล็ดลับและแรงบันดาลใจสำหรับBYTEอาร์เรย์

โปรแกรมที่มีตัวแปรโลคอลความสามารถในการอ่านและไม่มีคำเตือนคอมไพเลอร์มีลักษณะดังนี้:

#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;
}

1

C (gcc) + Win32, 94 95 98 105 107 110 ไบต์

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

รหัสจับคีย์แม้หลังจากโฟกัสหายไป

ภาพหน้าจอต่อไปนี้มีการบันทึกการเพิ่มช่องว่างระหว่างเอาต์พุต ( printf("%d ",j);+1 ไบต์) เพื่อให้อ่านง่ายขึ้น:

ภาพหน้าจอที่สำคัญ

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

รหัสใช้GetAsyncKeyStateเพื่อสอบถามสถานะคีย์โดยไม่ตรวจสอบคิวข้อความโดยทั่วไปจะเป็นแบบเรียลไทม์มากกว่าวิธีอื่น ๆ ในโหมดผู้ใช้ (ยกเว้น DirectInput) วิธีการนี้ใช้กันอย่างแพร่หลายในคีย์ล็อกเกอร์

(j<16||j>18)กรอง Ctrl / Alt / Shift ปกติ 16/17/18 จะถูกเรียกเมื่อกดปุ่มซ้ายหรือขวาพร้อมกับค่า vkey ที่ระบุตำแหน่ง


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.