2016-07-31 10 views
-2

キーストロークを1つの汎用ウィンドウに送信するC++コンソールアプリケーションがあります。 メッセージキュー(入力用)をすべて開いて、EnumWindows()そして、私のコールバックストアに関するいくつかの情報、それはGetWindowText()GetWindowThreadProcessId()PostThreadMessage()を持っている(メッセージキューを持っている場合WM_NULLメッセージで、チェックするため)ともそのHWND hWnd ... [以下のコード]SendInputを使用してキーストロークを送信する

ヒント:はこれです正しいか使用する必要がありますEnumChildWindows() ?これを行うための最善の方法である:

は、私は窓の1 ...

ヒントになどの例ALT+F4またはCTRL+Tのためにキーストロークを送りたい...

を続けます? SendInput()またはPostThreadMessage()

[HALF自動返信]:で、私は現在、たとえば​​ため、myVKey = MapVirtualKeyEx(..., MAPVK_VSC_TO_VK, ...)でVirtualKeyでスキャンコードの変換を使用してINPUTのグループを送信し、SendInput()をしようとしているとF456あると62intなどのタイプHEX383E ...入力をdwFlags = 0で行い、その後は逆順でdwFlags = KEYEVENTF_KEYUP と入力します(コマンドグループのみを処理する必要があります。 (?右)

私はVKEYハードウェアスキャンコードよりも優れていると思う

3番目の質問:SendInput()を使用する前に、どのように私は窓を持っていけばいいですか? ましょう...私は、ウィンドウに関するすべての情報を持っている

私が使用しなければならない何と順にSetFocus()SetActiveWindow()および/またはSetForegroundWindow()を想定? 【全てがコメントされている]

コードのビット:

bool _res = false; 
_res = AttachThreadInput(GetCurrentThreadId(), targetThreadID, TRUE); 
if (!_res) { 
    cout << "Error: " << GetLastError() << endl; 
} 
else { 
    //SetFocus(focusHandler); 
    //SetActiveWindow(focusHandler); 
    //SetForegroundWindow(focusHandler); 
enter code here 
    if (!prevH) { 
     cout << "Error: " << GetLastError() << endl; 
    } 
    else { 
    UINT res = SendInput(nTotVKey, numInputVect, sizeof(INPUT)); 
    if (res != nTotVKey) { 
     cout << "Error: " << GetLastError() << endl; 
    } 
    else { 
     _res = AttachThreadInput(GetCurrentThreadId(), targetThreadID, FALSE); 
     if (!_res) { 
      cout << "Error: " << GetLastError() << endl; 
     } 
    } 
} 

任意の助けが理解されるであろう。おかげで..

EDIT:REAL SCENARIOは、クライアントが「私が選択したウィンドウにCTRL + Wをやる」と言うているC/Sアプリケーションであり、サーバ「CTRL + Wに送るC#クライアントを想像してみて"サーバーがスレッド入力キューに送信する必要があるGoogle Chromeのメッセージ(例)..." CTRL + W "の入力を送信するためにforegound" Google Chrome "を配置する必要があります..どんな競争も心配しないでください条件などを入力します。必要に応じて、クライアントは再度コマンドを送信します。

+0

1つにつき1つの質問をお願いします! –

+0

あなたは正しいですが、最初の2つは最終的な質問に関連しています。 –

+0

メッセージキューを持つスレッドがウィンドウを所有しているかどうかを調べるために、 'PostMessage'を調べる必要はありません。ウィンドウを所有するスレッドにはメッセージキューがあります。実際、USER32 APIを呼び出したスレッドにはメッセージキューがあります。特定のウィンドウに入力を送信する場合、唯一信頼性が高くサポートされている方法は[UI Automation](https://msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx)です。他のすべてのもの( 'AttachThreadInput'であなたのハックを含む)は、いずれかの方法で失敗します。 – IInspectable

答えて

0

ありがとうございます。私はStackOverflowの過去の質問について私の答えを見つけました。

1:これは正しいですか?またEnumChildWindows()も使用しますか?

回答:いいえほとんどの子供が親からの入力を受け取るため、私はそれを必要としません。

2:これを行う最も良い方法はどれですか? SendInput()またはPostThreadMessage()

A:SendInput()と仮想キー。

3:何と私は(のSetFocusを使用しなければならないためこれで)、SetActiveWindow()および/またはSetForegroundWindow()

A:十分ですSetFocus()です。

0

最初に、なぜあなたにEnumChildWindows()が必要かわかりません。 EnumWindows()が機能しない理由について、より明確な情報を提供する必要があります。

第2に、PostMessage()はおそらく、別のウィンドウにメッセージを送信するための最も穏やかなアプローチです。ただし、各アプリケーションが独自の入力をどのように処理するかに応じて、メッセージは無視されるかフィルタされる可能性があります。可能な場合は、ターゲットとするアプリケーションとメッセージへの応答方法を知っていれば、PostThreadMessage()を使用しました。

キーボードフォーカスのあるウィンドウのみがSendInput()で送信されたキーメッセージを表示します。さらに、変更されたシーケンスを含むキーメッセージを送信する場合は、ctrl、alt、shiftのようなキーを使用します。次のようなシーケンスを送信する必要があります:make ctrl, make T, break T, break ctrl

私のアドバイス:およそスキャンコードを心配しないで、あなただけの仮想キーに対処する必要があります。スキャンコードは従来のものです。 USBキーボードハードウェアはそれらを生成しません(Windowsはそうです)。

第3に、必要なのはSetForgroundWindow()です。

+1

'PostThreadMessage()'は特定のHWNDをターゲットにすることはできませんが、代わりに 'PostMessage()'を使用する必要がありますが、[PostMessageでキーボード入力をシミュレートすることはできません](https://blogs.msdn.microsoft.com/oldnewthing/ 20050530-11 /?p = 35513)。 'SendInput()'の競合条件に関しては、 'SendInput()'への複数の呼び出しで複数のキーストロークを送信しないでください。代わりに複数の 'INPUT'を使って* once *を呼び出してください。提供された配列をユーザーの入力でインターリーブするのを防ぎます。これは[文書化された動作](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310.aspx)です。 –

+1

'SetForegroundWindow()'には多くの制限がありますが、競合状態はもちろんですが(これも文書化されています)(https://msdn.microsoft.com/en-us/library/windows/desktop/ms633539.aspx)ユーザーはいつでもフォアグラウンドウィンドウを変更することができます。 –

+0

あなたの返信ありがとうございます。私はアプリケーションの実際のシナリオを使って投稿を編集しました。競合状態やそれに類することは関係ありません...クライアントが「選択したウィンドウにCTRL + Wを実行する」と言っているC/Sアプリケーションで、サーバーに「CTRL +サーバーのスレッド入力キューに送信する必要があるGoogle Chrome(たとえば)の "W"メッセージ... "CTRL + W"入力を送信するためにforegound "Google Chrome"を挿入する必要があります –

0

あなたのWindows 8またはWindows 10があなたをブロックしています。

Windows 8セキュリティモデルでは、アプリケーションにはUIオートメーションクライアントに必要な特権がありません。しかし、アプリケーションをターゲットとしてオートメーションクライアントとして機能するデスクトップアプリケーションを作成することができます。これを行うには、デスクトップオートメーションクライアントアプリケーションをUIAccess権限で構築する必要があります。

マニフェストをUIAccess = "true"に変更し、管理者権限を取得し、証明書を作成し、その証明書でアプリケーションに署名し、Program Filesの下の場所に配置して実行します。ここ

https://msdn.microsoft.com/en-us/library/windows/desktop/dd979761.aspx?f=255&MSPPError=-2147217396

、ここ

https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/4b6dbc43-a026-4957-9178-91d2001e2d0d/windows-8-block-alttab-simulation#291eb5b4-f6d2-49b6-83db-658bd832f2c9

プラスこの

https://msdn.microsoft.com/en-us/library/ms742884.aspx?f=255&MSPPError=-2147217396

この

を説明したように

+0

返信いただきありがとうございます。私はまったく読んでいますが、SendSAS()は不明です(Windows.hは既にsas.hに含まれています) –

関連する問題