SendInputにおけるスキャンコードの意味

このQ&Aのポイント
  • SendInputを使用してソフトウェアキーボードのようにキー入力を行いたい場合、KEYBDINPUT構造体のwScanにスキャンコードを設定することで、仮想キーコードに対応する文字を入力できる。
  • スキャンコードを設定するかどうかは、SendInputの動作に影響する。設定しない場合でも仮想キーコードの入力はできるが、設定することでより正確な操作が可能。
  • 常にwScanを設定するかどうかは仕様によるため、具体的な要件に基づいて判断する必要がある。
回答を見る
  • ベストアンサー

SendInputにおけるスキャンコードの意味

お世話になっております。 Win32APIのSendInput関数についてご教授願いたく質問させていただきます。 C#にて、SendInputを使ってソフトウェアキーボードのようにキー入力を行いたいと考えています。 その際にSendInputにKEYBDINPUT構造体をメンバに持つINPUT構造体を渡しています。 private struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } wVkに仮想キーコードを入れてwScanは0で試しているのですが無事に想定した通りに仮想キーコードに対応する文字が入力できています。 ただ、Webで調べたところwScanにきちんとスキャンコード(MapVirtualKeyで取得)も入れているサンプルも多く見つけました。 そこで、スキャンコードを入れて試したところ、前者と同様に適切に入力することができました。 となると、wScanの設定の有無はどのように影響が出るのでしょうか。 問題がなければ常にwScanを入れておけば良いのかも知れませんが、仕様として分からないまま使うのは憚られます。。。 ご存じの方はご教授願えないでしょうか。 宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

私もそれほど詳しくはないのですが、以前仮想キーを送るソフトウェアを作ろうと思った際に以下のHPを見つけました。 http://d.hatena.ne.jp/anon_193/20090504/1241405315 どうやら、DirectInputを介してキーボード入力をフェッチしているソフトウェアの場合はスキャンコードをつけて送らないと無視されてしまうということのようです。

yagugami
質問者

お礼

スキャンコードの方のみを検知している場合があると言うことですね。 今後はスキャンコードも設定しておこうと思います。 大変助かりました、有り難うございました。

関連するQ&A

  • C#でウィンドウのアイコン取得する方法

    タスクマネージャのアプリケーションタブに 起動しているアプリケーション名とアイコンが一覧で表示されている部分のように 小さいアイコンを取得したいんですがなかなかうまくいきません。 ファイルに紐付くアイコンと解釈していただいても構いません。 とりあえず、下記のWin32 APIの処理を利用してみましたが SHGetFileInfoだけしかうまくいきませんでした。 しかし、SHGetFileInfoも、アイコンは取得できますがこれはファイルに紐付くアイコンではなく 実行体(EXE)に紐付くアイコンで表示されてしまいました。 開いているウィンドウ情報からだと実行プロセスのEXEのパスしか分からないからです。 ★質問★: ファイルに紐付く小さいアイコンの取得方法を教えてください!できればサンプルソース込みだと助かります。 #region 小さいアイコンを取得するためのWin32 API(ファイルパスから) // SHGetFileInfo関数 [DllImport("shell32.dll")] private static extern IntPtr SHGetFileInfo( string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); // SHGetFileInfo関数で使用するフラグ private const uint SHGFI_ICON = 0x100; // アイコン・リソースの取得 private const uint SHGFI_LARGEICON = 0x0; // 大きいアイコン private const uint SHGFI_SMALLICON = 0x1; // 小さいアイコン private const uint SHGFI_TYPENAME = 0x400;//ファイルの種類 // SHGetFileInfo関数で使用する構造体 private struct SHFILEINFO { public IntPtr hIcon; public IntPtr iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその1) [DllImport("user32.dll", EntryPoint = "GetClassLong")] public static extern IntPtr GetClassLongPtr32(IntPtr hWnd, int nIndex); [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")] public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex); const int GCL_HICON = (-14); const int GCL_HICONSM = (-34); #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその2) [DllImport("User32.dll", EntryPoint = "SendMessage")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); public const int WM_GETICON = 0x7F; public const int WM_SETICON = 0x80; public const int ICON_SMALL = 0; public const int ICON_BIG = 1; #endregion

  • VB6で他のアプリへ左右のCTRLキーを送る方法

    先に「Excel VBA で CTRLキーを送る方法」と題して質問したものです。 VB6でSendInputを使うアドバイスを頂きCTRLを送ることが出来たので解決したと思っていましたが、左右のキーの判断が出来ていないようです。 下記のコードを実行形式にしてたとき、引数の如何にかかわらず、受け取る側(YourAppli.ws)では右のCTRLを受け取った動作をします。左のCTRL(Zキーに近い方)を受け取った動作をしてくれません。 アプリケーションに左右のCTRLを認識させる方法をご教示お願いします。 コードの作成は http://mt-soft.sakura.ne.jp/web_dl/vb-parts/key_sendinput/​を参考に致しました。 Option Explicit Private Type KEYBDINPUT wVk As Integer wScan As Integer dwFlags As Long time As Long dwExtraInfo As Long no_use1 As Long no_use2 As Long End Type Private Type INPUT_TYPE dwType As Long xi As KEYBDINPUT End Type '仮想キーコード Private Const KEYEVENTF_KEYUP = &H2 'キーアップ Private Const KEYEVENTF_EXTENDEDKEY = &H1 'スキャンコードは拡張コード Private Const INPUT_KEYBOARD = 1 '入力タイプ:キーボード Private Const VK_CTRL = &H11 'Contorol Private Const VK_LCONTROL = &HA2 'Left_Contorol Private Const VK_RCONTROL = &HA3 'Right_Contorol Private Const VK_RETURN = &HD 'Right_Contorol Private Const KEY_DOWN = 0 'キー押し下げ Private Const KEY_UP = 1 'キーアップ '仮想キーコード・ASCII値・スキャンコード間でコードを変換する Private Declare Function MapVirtualKey Lib "user32" _ Alias "MapVirtualKeyA" (ByVal wCode As Long, _ ByVal wMapType As Long) As Long 'キーストローク、マウスの動作、ボタンのクリックをシミュレートする Private Declare Function SendInput Lib "user32.dll" _ (ByVal nInputs As Long, pInputs As INPUT_TYPE, _ ByVal cbsize As Long) As Long ' 指定時間Wait(ミリ秒) Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Sub Main() Const AppID = "YourAppli.ws" Dim i As Integer AppActivate AppID Select Case Command Case "L", "l" Send_LCtrl Case "R", "r" Send_RCtrl Case "" Send_Ctrl Case Else MsgBox ("Error") End Select Sleep 50 End Sub Private Sub Send_LCtrl() Call KeyEvent(VK_LCONTROL, KEY_DOWN) Call KeyEvent(VK_LCONTROL, KEY_UP) End Sub Private Sub Send_RCtrl() Call KeyEvent(VK_RCONTROL, KEY_DOWN) Call KeyEvent(VK_RCONTROL, KEY_UP) End Sub Private Sub Send_Ctrl() Call KeyEvent(VK_CTRL, KEY_DOWN) Call KeyEvent(VK_CTRL, KEY_UP) End Sub Sub KeyEvent(VkKey As Integer, UpDown As Integer) ' VkKey:仮想キーコード ' UpDown:動作(KEY_DOWN/KEY_UP) ' Dim inputevents As INPUT_TYPE With inputevents .dwType = INPUT_KEYBOARD With .xi .wVk = VkKey '操作キーコード .wScan = MapVirtualKey(VkKey, 0) 'スキャンコード If UpDown = KEY_DOWN Then 'キーDown .dwFlags = KEYEVENTF_EXTENDEDKEY Or 0 Else 'キーUP .dwFlags = KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP End If .time = 0 .dwExtraInfo = 0 End With End With Call SendInput(1, inputevents, Len(inputevents)) End Sub

  • 仮想キーコード、スキャンコードの拾い方

    Cで、ファンクションキーを含む、キーボードのオン・ オフした際の、仮想キーコード、及び、スキャンコード を拾いたいんです。 画面で何を押したか確認できるような簡単なAPを業務の 必要にせまられて作りたいのですが、サンプルコード とかどこかに落ちていないでしょうか。 仕様 例えば、vf3, vf4, vf5の各キ-を押したとき、以下の スキャンコ-ドと仮想キ-コ-ドを発生する。 vf3 : 0x45+E0, VK_NUMLOCK vf4 : 0x46, VK_OEM_SCROLL vf5 : 0x29, VK_DBE_SBCSCHAR/VK_DBE_DBCSCHAR 雑誌の付録にあったよ、とか以前こんなの作ったこと あるよ、とかどんな小さな情報でも結構です。 ご存知の方がいましたらなにとぞよろしくお願いします。 m(__)m m(__)m m(__)m

  • 文字コードでの比較

    getch()で、1文字入力したときに、「Alt」キーを押したら終了するといったプログラムを作りたいのですが、「Alt」キーには文字コードがないそうで、仮想キーコードっていうのがあるみたいなのですが、これを使って「Alt」キーが押された判定って出来ないのですか?

  • 構造体の初期化の時にポインタを入れるにはどうしたらいいですか?

    構造体の初期化の時にポインタを入れるにはどうしたらいいですか? 例えば、このような構造体で↓ struct PACKET { uint16_t size; // データの長さ uint16_t *data; // データバイト列 }; 初期化の時にsizeとdataを入れるにはどうしたらいいのでしょうか? dataがuint16_t*じゃなくてchar*なら struct PACKET { uint16_t size; // データの長さ char *data; // データバイト列 }; struct PACKET p = { 5, "12345" }; というようにできるのですが・・・

  • 未割り当てのローカル変数

    未割り当てのローカル変数 '' が使用されました。と出てコンパイルできません・・。 以下ソースです。 [DllImport("kernel32.dll")] public static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe); public struct PROCESSENTRY32 { public uint dwSize; public uint cntUsage; public uint th32ProcessID; public uint th32DefaultHeapID; public uint th32ModuleID; public uint cntThreads; public uint th32ParentProcessID; public int pcPriClassBase; public uint dwFlags; public string szExeFile; } PROCESSENTRY32 pe; pe.dwSize = 0; pe.cntThreads = 0; pe.th32ProcessID = 0; pe.th32DefaultHeapID = 0; pe.th32ModuleID = 0; pe.cntThreads = 0; pe.th32ParentProcessID = 0; pe.pcPriClassBase = 0; pe.dwFlags = 0; pe.szExeFile = "aa"; bool bResult = Process32First(hSnap, ref pe); ~~~ こんな風に全部0で代入して初期化?してもエラーが出ます。 回答よろしくお願いします・・。

  • C++/C#間での構造体の引き渡し方法に関して

    現在、C++で作成したクラスを、 C#から呼び出し実行しようとしております。 引数として、構造体を利用したいので、 C++側、C#側でそれぞれ下記のように 構造体を定義しました。 【C++】 typedef struct _Msg { ULONG Code; ULONG sessionId; }Msg; 【C#】 [StructLayout(LayoutKind.Sequential)] public struct Msg { public uint Code; public uint sessionId; } そして、下記のようにC++側で定義したクラスを C#側で呼び出そうとしたのですが、 「Msg*から_Msg*に変換できません」という コンパイルエラーが発生してしまいました。 構造体の定義は同じものになっていると思うのですが、 この原因は何だと考えられるでしょうか。 よろしくお願いいたします。 【C++】 ULONG Wrap::API( Msg* sample_Msg ) { return 1; } 【C#】 Msg sample_msg; Wrap.API(&sample_msg);

  • 配列を含んだ構造体への値設定について教えて下さい。

    配列を含んだ構造体への値設定について教えて下さい。 下記のような構造体の定義があります。 typedef struct A_T { UINT64 a1; UINT32 a2; } A_t; typedef struct B_T { UINT32 b1; A_t b[8]; } B_t; 構造体B_tを関数の引数で渡し、A_tのa1とa2に値を設定したいのですが、プログラミング初心者の為、どのように作ればよいのかわかりません。 どうぞ教えて下さい。

  • VC#からdll関数を使う

    c#(vs2003)から、c++で書かれたdllの中に含まれる関数を読み込む部分を書いています。この関数は以下のように定義 され、構造体のポインタを返り値として返します。 SENSOR* GetSensor(); SENSOR構造体はdllの中では以下のように定義されています。 typedef struct{   int type; unsigned short param; char name[64]; DWORD con_pos; } SENSOR; これをc#のコードの中で読み込むため、c#のクラスの中で、以下のように再定義しました。 [StructLayout(LayoutKind.Sequential)] public struct SENSOR {   public int type;   public ushort param;   public string name;   public uint con_pos; } 後にc#のコードの中に、dllの中の関数を呼び出す定義を以下のように書きました。 [DllImport("sensor.dll"); public static extern SENSOR* GetSensor(); ここで SENSOR* sensor = GetSensor(); といった感じでdllをの関数を使って値を取得するようにしたのですが、実行すると 「return value をマーシャル できません : ポインタはマーシャルされた構造体を参照できません。」 といったエラーが出ます。いろいろと調べたのですが解決方法がわかりません。アドバイスをいただけたら幸いです。

  • C#で構造体の配列を持った構造体を使いたいのですが

    C#で構造体の配列を持った構造体を使いたいのですが Cならば struct xyz { struct abc _abc[32]; int index; }; struct abc { int a; int b; int c; }; struct xyz _xyz[8]; xyz[0]._abc[3].b = 1; のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません うまくやる方法をどなたかご存知ないでしょうか Visual Studio 2005行った場合 コンパイルで 構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するには、次元指定子を変数の識別子の前に指定します。固定サイズ バッファ フィールドを宣言するには、フィールド型の前に fixed キーワードを使用します となり fixed をつけると 固定サイズ バッファの型は次のうちの 1 つでなければなりません: bool、byte、short、int、long、char、sbyte、ushort、uint、ulong、float または double となってしまいます