質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1526閲覧

仮想の物理入力のようなものを作りたいです...

void_390duke

総合スコア7

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2020/08/04 12:42

前提

とあるゲーム(ぷよぷよ™テトリス®のSteam版)で, プログラムにプレイさせるようなことをしたいのですが, そもそもキー入力がうまくできません. 下で詳しく説明します.

発生している問題・エラーメッセージ

私はkeybd_event()関数でこれを実現できると思い, これをバックグラウンドで0.1秒に一回fとjのキーボードを入力するとしたコードを書きました. 確かにプログラムは動いているようで, GoogleChromeのほうでは期待した反応を見せた一方, ゲームのほうでは動きませんでした.
カレントの時間([msec])をウィンドウに表示させるようにしており, ゲームプレイ(ウィンドウモードで)中でもその表示が常に動いていることを確認したので, バックグラウンドで動作はしているのは確かだと思います.

該当のソースコード

C++

1#include<windows.h> 2#include<mmsystem.h> 3#include <string> 4#include<thread> 5#include <mutex> 6 7#pragma(lib, "WinMM.Lib") 8 9std::mutex mtx_; 10 11LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { 12 switch (msg) { 13 case WM_DESTROY: 14 PostQuitMessage(0); 15 return 0; 16 case WM_CLOSE: 17 int close=MessageBoxW(hWnd, L"Are you sure to close this window?", L"about to be closed", MB_YESNO); 18 if (close == IDNO) { 19 return 0; 20 } 21 else { 22 DestroyWindow(hWnd); 23 PostQuitMessage(0); 24 return 0; 25 } 26 } 27 return DefWindowProc(hWnd, msg, wp, lp); 28} 29 30namespace myGlobalVars { 31 HWND hWnd; 32 MSG msg; 33 WNDCLASSEX wcex; 34 bool isErr = false; 35 HINSTANCE hI; 36 HINSTANCE hP; 37 PSTR lp; 38 int nC; 39}; 40 41using namespace myGlobalVars; 42 43void ThreadA() { 44 45 std::lock_guard<std::mutex> lock(mtx_); 46 47 ZeroMemory(&wcex, sizeof(WNDCLASSEX)); 48 49 wcex.cbSize = sizeof(WNDCLASSEX); 50 wcex.style = CS_HREDRAW | CS_VREDRAW; 51 wcex.lpfnWndProc = WndProc; 52 wcex.hInstance = hI; 53 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 54 wcex.lpszMenuName = NULL; 55 wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 56 wcex.lpszClassName = L"mWnd"; 57 58 if (!RegisterClassEx(&wcex)) { 59 isErr = true; 60 return; 61 } 62 63 hWnd = CreateWindowEx( 64 NULL, 65 L"mWnd", 66 L"aa", 67 WS_OVERLAPPEDWINDOW, 68 300, 300, 69 800, 600, 70 NULL, 71 NULL, 72 hI, 73 NULL 74 ); 75 76 if (hWnd == NULL) { 77 isErr = true; 78 return; 79 } 80 81 ShowWindow(hWnd, nC); 82 83 bool isQuit = false; 84 85 timeBeginPeriod(1); 86 DWORD timeMarker = timeGetTime(); 87 88 while (1) { 89 while (1) 90 { 91 DWORD curTime = timeGetTime(); 92 93 std::wstring str = std::to_wstring(curTime) + L" " + std::to_wstring(timeMarker); 94 95 HDC hdc = GetDC(hWnd); 96 TextOutW(hdc, 50, 50, str.c_str(), lstrlen(str.c_str())); 97 ReleaseDC(hWnd, hdc); 98 99 if (msg.message == WM_QUIT) { 100 isQuit++; 101 break; 102 } 103 PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); 104 TranslateMessage(&msg); 105 DispatchMessage(&msg); 106 107 if (timeMarker < curTime - 100) { 108 timeMarker = curTime; 109 keybd_event(0x46, 0x00, KEYEVENTF_EXTENDEDKEY | 0, 0); 110 keybd_event(0x46, 0x00, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 111 112 keybd_event(0x4a, 0x00, KEYEVENTF_EXTENDEDKEY | 0, 0); 113 keybd_event(0x4a, 0x00, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 114 } 115 } 116 if (isQuit) { 117 break; 118 } 119 } 120 121 return; 122} 123 124int WINAPI WinMain( 125 HINSTANCE hInstance, 126 HINSTANCE hPrevInstance, 127 PSTR lpCmdLine, 128 int nCmdShow 129) { 130 131 hI=hInstance; 132 hP=hPrevInstance; 133 lp=lpCmdLine; 134 nC=nCmdShow; 135 136 std::thread th_a(ThreadA); 137 th_a.join(); 138 139 140 if (isErr) { 141 return 0; 142 } 143 144 return msg.wParam; 145}

実現したいこと

言語はC++のままで, 仮想のキーボードを作るようなことができればよいなと考えております. ゲームパッドの入力でも問題ありません. Win32は今勉強中なので使ってみたいという気持ちから使っていますが, もしWin32でできないようでしたらほかの方法でも結構なので, 教えていただけるとありがたいです. マルチスレッドは特に使わない予定なので, 無視してもらって大丈夫です. (先ほど別の問題の原因だと思って導入したものです. 濡れ衣でしたが...)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

keybd_event(0x46, 0x00, KEYEVENTF_EXTENDEDKEY | 0, 0);
keybd_event(0x46, 0x00, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);

keybd_event(0x4a, 0x00, KEYEVENTF_EXTENDEDKEY | 0, 0);
keybd_event(0x4a, 0x00, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);

気になるのは第2引数bScanが0で固定されている事です。
スキャンコードは適当に設定しても動くこともある一方で
きちんと設定しないと読み取ってくれないアプリやそもそもkeybd_eventでは入力できないアプリもあったような気がします。

投稿2020/08/04 23:53

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

void_390duke

2020/08/05 09:06

ご回答ありがとうございます! keybd_eventでは厳しいアプリなのかもしれませんね... 他にもゲームのウィンドウにキーボード関連のメッセージを送ってみたり, 仮想のゲームパッドを作ってみるなどしてみましたが, うまくいきませんでした(ゲームパッドはそもそもできていない可能性もあるため何とも言い難いです). 私の使っているRAZER SYNAPSEにキーバインドをずらして設定するとゲームでも反応するので何か方法はありそうに感じてしまいます... keybd_event()類似の関数はありますでしょうか.
asm

2020/08/05 09:34

最悪、カーネルモードドライバを使うことになりますね・・・ https://github.com/oblitum/Interception マクロ対策としてアンチハックされてる事もあるのが面倒なのですが・・・
void_390duke

2020/08/05 10:01

カーネルに手を出すのはちょっと気が引けますね(笑)最終手段としては良さそうですね!ありがとうございます. 方針をバーチャルゲームパッドにして再度質問を投稿してみたいと思いますので, こちらの質問ではBAにさせていただきます. ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問