LoginSignup
1
0

WindowsTerminal上で「C++,C#,Go言語,Rust」の「Win32のGetAsyncKeyState」機能を使って、入力したKeyを取得する雛形文の比較

Last updated at Posted at 2023-10-23

各言語のプログラム雛形の作成条件

  • Visual studio codeや秀丸でプログラミング。
  • コンパイルはVisual studioとかは使わずにコマンドで手動。
  • 200ミリ秒ごとにループ(繰り返し)する。
  • ループを一周する毎に、変数「t」の値を「1」増やす。
  • 「←」の矢印ボタンを押した時、反応する。
  • GetAsyncKeyStateからの出力は、変数「key37」に格納する。
  • 絵文字を使いたいのでファイルはutf-8で保存する。
     (C++は日本語や絵文字が文字化けした!)

パソコン環境

  • Windows10 : 22H2
  • WindowsTerminal(プレビュー版) : 1.19.2831.0
  • c++のコンパイラ g++ : 10.3.0
  • C#のコンパイラ csc : 4.8.9037.0
  • Go : 1.21.3
  • Rust : 1. 72.0

プログラミング結果

C++

↓13行・249文字

#include <iostream>
#include <windows.h>

int main(){
    long t = 0;
	while(1){
		int key37 = GetAsyncKeyState(37);
        std::cout << "C++ Left-button " << t << " " << key37  << std::endl;
		Sleep(200);
        t++;
	}
	return 0;
}

C++出力結果

image.png

C#

↓15行・515文字

using System;
using System.Threading;
class hello_GetAsyncKeyState {
	[System.Runtime.InteropServices.DllImport("user32.dll")]
	private static extern short GetAsyncKeyState(int vKey);
	public static void Main() {
		Console.OutputEncoding = System.Text.Encoding.GetEncoding("utf-8");//🐓の文字化け対策
 		int t = 0;
		while(true){
			short key37 = GetAsyncKeyState(37);
			Console.WriteLine("C#「← 」キーを押したか?🐓 {0} {1} {2}",t,key37,key37&0x1);
			Thread.Sleep(200);
			t++;
		}
	}
}

C#出力結果

image.png

Go言語

↓22行・421文字

package main

import (
	"fmt"
	"time"
	"golang.org/x/sys/windows"
)

var (
	moduser32            = windows.NewLazyDLL("user32.dll")
	procGetAsyncKeyState = moduser32.NewProc("GetAsyncKeyState")
)

func main() {
	t := 0
	for {
		key37, _, _ := procGetAsyncKeyState.Call(uintptr(37))
		fmt.Println("Go「← 」キーを押したか?🐶 ", t, key37, key37&0x1)
		time.Sleep(200 * time.Millisecond)
		t++
	}
}

Go出力結果
image.png

Rust

↓7行・164文字

Cargo.toml
[package]
name = "file_name"
version = "0.1.0"
edition = "2021"

[dependencies]
windows = { version = "0.51.1", features=["Win32_UI_Input_KeyboardAndMouse"] }

↓15行・約406文字

main.rs
use std::thread;
use std::time::Duration;
use windows::Win32::UI::Input::KeyboardAndMouse::GetAsyncKeyState;
 
fn main() {
    let mut t =0;
    unsafe {
        loop{
            let key37 = GetAsyncKeyState(37);
            println!("Rust 「← 」キーが押したか?🐵 {} {} {}",t,key37,key37&0x1);
            thread::sleep(Duration::from_millis(200));
            t =t+1
        }
    }
}

Rust出力結果

image.png

感想

 三つ並べるとロゼッタストーンみたい。
 以下は「C」「JavaScript」「VBA」「Go」で趣味で遊んだ経験を踏まえての感想(愚痴ばっかり)です。

「C++」

  • 最もシンプルに書ける。
  • 「Sleep(200);」と書くだけで0.2秒待ってくれるのは、すごくない?
  • 「while(1)」の「1」や「return 0;」の「0」の意味がわからん。
  • 「std::cout」もなんだこれ?という感想。
  • 最もシンプルに書けるので、C++を使いたいが以下より私には無理だった。
    • utf-8や絵文字が絶望的に出力できない。
    • メモリの扱いにプロ技術が必要。

「C#」

  • C#の内部はutf-16なので、utf-8が直接使えなく、絵文字を表現できないのが致命傷。
  • utf-8を使う為には以下の一文が必要になる
  • 「Console.OutputEncoding = System.Text.Encoding.GetEncoding("utf-8");」
  • C#ってなんで「class」から始めんとあかんのだ。
  • 「private」「pubclic」「static」「void」も非常に鬱陶しい。プログラムが横に長くなる。
  • とボヤキつつ、C#の最大最強の魅力はコンパイラ「csc」が標準でWindowsにインストールされている事。
  • 機械系エンジニアには2023年の昨今、もはや管理者権限ない。
     会社のパソコンは、2020年頃から管理者権限は剥奪され、ソフトを自由にインストールできない。出来ても限定されたソフトとなる。追加でインストールしたい時には、管理者権限の一時申請やら上司の許可が必要になる。
     私は会社内で中堅になったので、今は比較的、会社内の手続きや説明も楽になったけど、理解のない会社や上司だったら無理だろうなと思う。「Visual Studio」とかも「何それ?」となって、インストールなんで夢のまた夢。なので、Visual Studioを使わない素の「csc」と「メモ帳」での野良プログラムは今後も静かな需要があると思う。

「Go」

  • いつもはシンプルなGo言語なのに、今回はシンプルにあらず。
  • 今回の方法をWebから探し出すのが苦労した。
  • 「NewLazyDLL」や「NewProc」ってなんやねん。一見さんお断り的な。
    • 予備知識として「DLLファイル=Dynamic Load Library」の存在を知らなきゃならない。
    • 「DLLファイル」内部に「GetAsyncKeyState」が入っていることはVBA作成した際に知っているが、なかなか知らんな。
    • DLLファイルは「C言語」で書かれている。
  • 「Call」もしっくりこない。
  • 「uintptr」も難しい。やめてよって感じ。出てこないで欲しい。ポインター恐怖症。
  • 要するに普段使わない用語を使うという事で。

「Rust」

  • Webで「Rust GetAsyncKeyState」で検索すると「GetAsyncKeyState」を使う方法は複数あり(winapiとかのライブラリもある)迷った。
  • 迷った結果、マイクロソフトの「win32metadata」プロジェクトでの「Windowsのwin32クレート」を使ってます。
  • マイクロソフトがRustでwin32を使えるようにする「win32metadata」プロジェクトはネットニュースで知っていたが、「Rust GetAsyncKeyState」でgoogle検索しても一番上に検索候補が挙がってこなかった。
    -「Cargo.toml」の[dependencies] (=依存関係) の記述も注意しなくちゃならない。事前準備が必要。
  • Rust本文は短めだが、tomlと合計すると記述量はやや多めとなる。
  • toml内の「Win32_UI_Input_KeyboardAndMouse」で、途中にアンダーバー「_」で繋ぐのは正直、反則だと思う。「::」や「.」で良いだろう。

補足説明

「Win32」って何?

↓ウィキペディアの説明ページ

  • Microsoft社のWindowsは、C言語やC++言語で制作されている。
  • 結果的にCやC++をコンパイルすれば、そのままOSと同一の機械語に変換できる。
  • Win32の「32」は、32ビットパソコン時代に作られた為。64ビットCPUの昨今は「Win64」となるが、慣習的にWin32と言えばWin64も含んでいる。

参考にしたサイト

simple windows keylogger using GetAsyncKeyState

windows::Win32::UI::Input::KeyboardAndMouse::GetAsyncKeyState

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0