Memulai dengan Input Keyboard pada Win32 dan C++

Keyboard digunakan untuk beberapa jenis input yang berbeda, termasuk:

  • Masukan karakter Teks yang dititikan pengguna ke dalam dokumen atau kotak edit.
  • Tombol pintas. Goresan kunci yang memanggil fungsi aplikasi; misalnya, CTRL + O untuk membuka file.
  • Perintah sistem. Goresan kunci yang memanggil fungsi sistem; misalnya, ALT + TAB untuk beralih jendela.

Ketika memikirkan input keyboard, penting untuk diingat bahwa goresan kunci tidak sama dengan karakter. Misalnya, menekan tombol A dapat mengakibatkan salah satu karakter berikut.

  • sebuah
  • Sebuah
  • á (jika keyboard mendukung penggandaan diakritik)

Selanjutnya, jika tombol ALT ditahan, menekan tombol A menghasilkan ALT+A, yang tidak diperlakukan sistem sebagai karakter sama sekali, melainkan sebagai perintah sistem.

Kode Kunci

Saat Anda menekan tombol, perangkat keras menghasilkan kode pemindaian . Kode pemindaian bervariasi dari satu keyboard ke keyboard berikutnya, dan ada kode pemindaian terpisah untuk peristiwa key-up dan key-down. Anda hampir tidak akan pernah peduli tentang kode pemindaian. Driver keyboard menerjemahkan kode pemindaian menjadi kode tombol virtual . Kode kunci virtual tidak bergantung pada perangkat. Menekan tombol A pada keyboard apa pun menghasilkan kode kunci virtual yang sama.

Secara umum, kode kunci virtual tidak sesuai dengan kode ASCII atau standar pengodean karakter lainnya. Ini jelas jika Anda memikirkannya, karena kunci yang sama dapat menghasilkan karakter yang berbeda (a, A, á), dan beberapa kunci, seperti kunci fungsi, tidak sesuai dengan karakter apa pun.

Namun, kode kunci virtual berikut dipetakan ke dalam setara ASCII:

  • 0 hingga 9 kunci = ASCII '0' – '9' (0x30 – 0x39)
  • Kunci A sampai Z = ASCII 'A' – 'Z' (0x41 – 0x5A)

Dalam beberapa hal, pemetaan ini sangat disayangkan, karena Anda tidak boleh menganggap kode kunci virtual sebagai karakter, karena alasan yang dibahas.

File header WinUser.h mendefinisikan konstanta untuk sebagian besar kode kunci virtual. Misalnya, kode tombol virtual untuk PANAH KIRI adalah VK_LEFT (0x25). Untuk daftar lengkap kode kunci virtual, lihat kode Virtual-Key. Tidak ada konstanta yang didefinisikan untuk kode kunci virtual yang cocok dengan nilai ASCII. Misalnya, kode kunci virtual untuk kunci A adalah 0x41, tetapi tidak ada konstanta bernama VK_A. Sebagai gantinya, cukup gunakan nilai numerik.

Pesan Key-Down dan Key-Up

Saat Anda menekan tombol, jendela yang memiliki fokus keyboard menerima salah satu pesan berikut.

Pesan WM_SYSKEYDOWN menunjukkan kunci sistem , yang merupakan goresan kunci yang memanggil perintah sistem. Ada dua jenis kunci sistem:

  • ALT + kunci apa pun
  • F10

Kunci F10 mengaktifkan bilah menu jendela. Berbagai kombinasi kunci ALT memanggil perintah sistem. Misalnya, ALT + TAB beralih ke jendela baru. Selain itu, jika jendela memiliki menu, kunci ALT dapat digunakan untuk mengaktifkan item menu. Beberapa kombinasi kunci ALT tidak melakukan apa pun.

Semua goresan kunci lainnya dianggap sebagai kunci nonsstem dan menghasilkan pesan WM_KEYDOWN. Ini termasuk kunci fungsi selain F10.

Saat Anda melepaskan tombol, sistem mengirim pesan lepas tombol yang sesuai.

Jika Anda menahan tombol cukup lama untuk memulai fitur pengulangan keyboard, sistem mengirim beberapa pesan penekanan tombol, diikuti dengan satu pesan pelepasan tombol.

Dalam keempat pesan keyboard yang dibahas sejauh ini, parameter wParam berisi kode kunci virtual. Parameter lParam berisi beberapa informasi lain-lain yang dikemas ke dalam 32 bit. Anda biasanya tidak memerlukan informasi dalam lParam. Satu flag yang mungkin berguna adalah bit 30, penanda "status kunci sebelumnya", yang diatur ke 1 untuk pesan penekanan tombol berulang.

Seperti namanya, penekanan tombol sistem terutama dimaksudkan untuk digunakan oleh sistem operasi. Jika Anda mencegat pesan WM_SYSKEYDOWN, panggil DefWindowProc setelahnya. Jika tidak, Anda akan memblokir sistem operasi untuk menangani perintah.

Pesan Karakter

Goresan kunci dikonversi menjadi karakter oleh fungsi TranslateMessage , yang pertama kali kita lihat di Modul 1 . Fungsi ini memeriksa pesan penekanan tombol dan menerjemahkannya menjadi karakter. Untuk setiap karakter yang diproduksi, fungsi TranslateMessage menempatkan pesan WM_CHAR atau WM_SYSCHAR pada antrean pesan jendela. Parameter wParam pesan berisi karakter UTF-16.

Seperti yang mungkin Anda duga, pesan WM_CHAR dihasilkan dari pesan WM_KEYDOWN, sementara pesan WM_SYSCHAR dihasilkan dari pesan WM_SYSKEYDOWN. Misalnya, pengguna menekan tombol SHIFT diikuti oleh tombol A. Dengan asumsi tata letak keyboard standar, Anda akan mendapatkan urutan pesan berikut:

WM_KEYDOWN: SHIFT
WM_KEYDOWN: A
WM_CHAR: 'A'

Di sisi lain, kombinasi ALT + P akan menghasilkan:

WM_SYSKEYDOWN: VK_MENU
WM_SYSKEYDOWN: 0x50
WM_SYSCHAR: 'p'
WM_SYSKEYUP: 0x50
WM_KEYUP: VK_MENU

(Kode kunci virtual untuk kunci ALT diberi nama VK_MENU karena alasan historis.)

Pesan WM_SYSCHAR menunjukkan karakter sistem. Seperti halnya WM_SYSKEYDOWN, Anda umumnya harus meneruskan pesan ini langsung ke DefWindowProc. Jika tidak, Anda dapat mengganggu perintah sistem standar. Secara khusus, jangan perlakukan WM_SYSCHAR sebagai teks yang telah di ketik pengguna.

Pesan WM_CHAR adalah apa yang biasanya Anda anggap sebagai input karakter. Jenis data untuk karakter wchar_t, mewakili karakter Unicode UTF-16. Input karakter dapat mencakup karakter di luar rentang ASCII, terutama dengan tata letak keyboard yang umumnya digunakan di luar Amerika Serikat. Anda dapat mencoba tata letak keyboard yang berbeda dengan menginstal keyboard regional lalu menggunakan fitur Keyboard Di Layar.

Pengguna juga dapat menginstal Editor Metode Input (IME) untuk memasukkan skrip kompleks, seperti karakter Jepang, dengan keyboard standar. Misalnya, menggunakan IME Jepang untuk memasukkan karakter katakana カ (ka), Anda mungkin mendapatkan pesan berikut:

WM_KEYDOWN: VK_PROCESSKEY (kunci PROSES IME)
WM_KEYUP: 0x4B
WM_KEYDOWN: VK_PROCESSKEY
WM_KEYUP: 0x41
WM_KEYDOWN: VK_PROCESSKEY
WM_CHAR: カ
WM_KEYUP: VK_RETURN

Beberapa kombinasi tombol CTRL diterjemahkan ke dalam karakter kontrol ASCII. Misalnya, CTRL+A diterjemahkan ke karakter ASCII ctrl-A (SOH) (nilai ASCII 0x01). Untuk input teks, Anda umumnya harus memfilter karakter kontrol. Selain itu, hindari menggunakan WM_CHAR untuk menerapkan pintasan keyboard. Sebagai gantinya, gunakan pesan WM_KEYDOWN; atau bahkan lebih baik, gunakan tabel akselerator. Tabel akselerator dijelaskan dalam topik berikutnya, Tabel Akselerator.

Kode berikut menampilkan pesan keyboard utama di debugger. Coba mainkan dengan kombinasi penekanan tombol yang berbeda dan lihat pesan apa yang dihasilkan.

Nota

Pastikan untuk menyertakan wchar.h, jika tidak, swprintf_s akan tidak terdefinisi.

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    wchar_t msg[32];
    switch (uMsg)
    {
    case WM_SYSKEYDOWN:
        swprintf_s(msg, L"WM_SYSKEYDOWN: 0x%x\n", wParam);
        OutputDebugString(msg);
        break;

    case WM_SYSCHAR:
        swprintf_s(msg, L"WM_SYSCHAR: %c\n", (wchar_t)wParam);
        OutputDebugString(msg);
        break;

    case WM_SYSKEYUP:
        swprintf_s(msg, L"WM_SYSKEYUP: 0x%x\n", wParam);
        OutputDebugString(msg);
        break;

    case WM_KEYDOWN:
        swprintf_s(msg, L"WM_KEYDOWN: 0x%x\n", wParam);
        OutputDebugString(msg);
        break;

    case WM_KEYUP:
        swprintf_s(msg, L"WM_KEYUP: 0x%x\n", wParam);
        OutputDebugString(msg);
        break;

    case WM_CHAR:
        swprintf_s(msg, L"WM_CHAR: %c\n", (wchar_t)wParam);
        OutputDebugString(msg);
        break;

    /* Handle other messages (not shown) */

    }
    return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}

Pesan Keyboard Beragam

Beberapa pesan keyboard lainnya dapat diabaikan dengan aman oleh sebagian besar aplikasi.

  • Pesan WM_DEADCHAR dikirim untuk kunci penggabungan, seperti pada kasus penggunaan tanda diakritik. Misalnya, pada keyboard bahasa Spanyol, aksen pengetikan (') diikuti oleh E menghasilkan karakter é. WM_DEADCHAR dikirim untuk karakter aksen.
  • Pesan WM_UNICHAR usang. Ini memungkinkan program ANSI untuk menerima input karakter Unicode.
  • Karakter WM_IME_CHAR dikirim ketika IME menerjemahkan urutan penekanan tombol ke dalam karakter. Ini dikirim selain pesan WM_CHAR biasa.

Keadaan Keyboard

Pesan keyboard digerakkan oleh peristiwa. Artinya, Anda mendapatkan pesan ketika sesuatu yang menarik terjadi, seperti tekan tombol, dan pesan memberi tahu Anda apa yang baru saja terjadi. Tetapi Anda juga dapat menguji status kunci kapan saja, dengan memanggil fungsiGetKeyState.

Misalnya, pertimbangkan bagaimana Anda akan mendeteksi kombinasi klik mouse kiri + tombol ALT. Anda dapat melacak status tombol ALT dengan mendengarkan pesan penekanan tombol dan menyimpan penanda, tetapi GetKeyState menghemat kerepotan. Saat Anda menerima pesan WM_LBUTTONDOWN, cukup panggil GetKeyState sebagai berikut:

if (GetKeyState(VK_MENU) & 0x8000)
{
    // ALT key is down.
}

Pesan GetKeyState mengambil kode kunci virtual sebagai input dan mengembalikan sekumpulan bendera bit (sebenarnya hanya dua bendera). Nilai 0x8000 berisi bendera bit yang menguji apakah tombol saat ini ditekan.

Sebagian besar keyboard memiliki dua tombol ALT, kiri dan kanan. Contoh sebelumnya menguji apakah salah satu dari mereka ditekan. Anda juga dapat menggunakanGetKeyStateuntuk membedakan antara instans kiri dan kanan tombol ALT, SHIFT, atau CTRL. Misalnya, kode berikut menguji apakah tombol ALT kanan ditekan.

if (GetKeyState(VK_RMENU) & 0x8000)
{
    // Right ALT key is down.
}

Fungsi GetKeyState menarik karena melaporkan status virtual keyboard. Status virtual ini didasarkan pada konten antrean pesan Anda, dan diperbarui saat Anda menghapus pesan dari antrean. Saat program Anda memproses pesan jendela, GetKeyState memberi Anda rekam jepret keyboard pada saat setiap pesan diantrekan. Misalnya, jika pesan terakhir pada antrean adalah WM_LBUTTONDOWN, GetKeyState melaporkan status keyboard pada saat pengguna mengklik tombol mouse.

Karena GetKeyState didasarkan pada antrean pesan Anda, ini juga mengabaikan input keyboard yang dikirim ke program lain. Jika pengguna beralih ke program lain, setiap tombol menekan yang dikirim ke program tersebut diabaikan oleh GetKeyState. Jika Anda benar-benar ingin mengetahui status fisik keyboard langsung, ada fungsi untuk itu: GetAsyncKeyState. Namun, untuk sebagian besar kode UI, fungsi yang benar adalah GetKeyState.

Berikutnya

Tabel Akselerator