掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
SendInputで指定したウィンドウに仮想キーを送るには? (ID:55622)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
最近、フリーセルが流行っているじゃない。 それでね、フリーセルのステージデータを 読み取ってプログラムで解を求めてやろうと思ったわけですよ。 フリーセルの内部を解析するのはリバースエンジニアリングなんで、 この手は使いません。 表に見えている、画面をキャプチャしてカードの並びを読み取る ようにしたのですが、カードの重なっている部分にAがあると 色の区別はつくけどクローバとスペード、ハートとダイヤの 区別がつかないのです。で、あなたのようにフリーセルにメッセージ を(この場合WM_RBUTTONDOWN/UP) 送って不明なカードだけめくって キャプチャして、全配置を読み取っています。 指定番号のステージを読み取れるように、 メニューを開いて、番号入力まで、メッセージを送って実行できるように してみました。 キー押下に関しては WM_KEYDOWN/UP だけでなく WM_CHAR も送らなければ ならない場合がありました。 そのプログラムから抜粋しますね。 Win2K/VC++6.0/MFC 相手側アプリ(ここではフリーセル)の挙動はSpy++で調べました。 Win2K/Xpでは問題なく動作しています。 Win98 ではある程度繰り返すとフリーセル側がフリーズしてしまいます。 メッセージの受け取り方が違うと思われますが、原因は未確認です。 Win98 側でも Spy++ で調べなおさなければならないですね。 まあ、「やっつけ」程度で作成したプログラムで、 お作法なんて、どっかへ飛んでる部分もありますが、 参考まで。 // WM_CHAR で使用する。lParam のコレクション(wParam=VK_0..VK9用)。 const DWORD g_dwNumKeyCodes[10] = { 0x00520001,0x004F0001,0x00500001,0x00510001,0x004B0001, 0x004C0001,0x004D0001,0x00470001,0x00480001,0x00490001, }; BOOL CCaptureDib::FreeCellSelectStage(int nID) { BOOL bDone = FALSE; int wx,wy,nCurID; CWnd * pAppWnd,* pDlg,* pCtl; char szID[16]; sprintf( szID, "%d", nID ); // オリジナルアプリを検索。 if(( pAppWnd = FindFreeCellWindow( nCurID )) == NULL ) { // ここでオリジナルアプリを起動してもよい。 return( FALSE ); } if( nCurID == nID ) return( TRUE ); CheckIconic( pAppWnd, TRUE ); CheckTargetSize( pAppWnd, wx, wy ); // [ゲーム(G)][選択(S)] で発生するコマンドを送出。 TRACE("MESSAGE SEND=[ゲーム(G)][選択(S)]\n"); pAppWnd->PostMessage( WM_COMMAND, 0x00010067, 0x00000000 ); // 確認ダイアログが立ち上がるまで待つ。 Sleep(100); // 確認ダイアログを検索。 if(( pDlg = FindFreeCellDialog( "フリーセル\tはい(&Y)\tいいえ(&N)\tこのゲームを終了しますか?" )) == NULL ) { TRACE("フリーセル確認ダイアログが見つからない.\n"); return( FALSE ); } // 確認ダイアログに IDYES コマンドを送出。 TRACE("MESSAGE SEND=WM_COMMAND/IDYES\n"); pDlg->PostMessage( WM_COMMAND, 0x00000006, 0x002002EB ); // ゲーム番号の指定ダイアログが立ち上がるまで待つ。 Sleep(100); // ゲーム番号の指定ダイアログを検索。 if(( pDlg = FindFreeCellDialog( "ゲーム番号の指定\tゲーム番号を選んでください。\t(1 から 32000 まで)\tOK" )) == NULL ) { TRACE("ゲーム番号の指定ダイアログが見つからない.\n"); return( FALSE ); } // ダイアログのエディットコントロールを取得する。 // 0x00CB は Spy++ を用いて調査した。 if(( pCtl = pDlg->GetDlgItem( 0x00CB )) == NULL ) { TRACE("ゲーム番号の指定ダイアログにエディットコントロールがない。\n"); return( FALSE ); } // エディットコントロールに数字を入力 char * p; for( p = szID; *p; p ++ ) { pCtl->PostMessage( WM_CHAR, 0x00000000+p[0], g_dwNumKeyCodes[p[0]-0x30] ); Sleep(10); } // ゲーム番号の指定ダイアログに<ENTER押下>を送出。 TRACE("MESSAGE SEND=WM_KEYDOWN/VK_RETURN\n"); pDlg->PostMessage( WM_KEYDOWN, VK_RETURN, 0xC11C0001 ); // ダイアログが閉じられるのを待つ。 Sleep(100); // ステージが変更されたことを確認する。 CWnd * pWndCheck; if(( pWndCheck = FindFreeCellWindow( nCurID )) == NULL ) { TRACE( "FreeCell が落ちた?\n"); return( FALSE ); } // 指定ステージになっていることを確認。 if( nCurID == nID ) { bDone = TRUE; } // m_pWnd->SetActiveWindow(); // 自アプリへ戻す。 CheckIconic( pAppWnd, FALSE ); return( bDone ); } // 所定のコントロールを所有したダイアログを検索。 // CWnd * CCaptureDib::FindFreeCellDialog( CString cs ) { CWnd * pDlg; if( pDlg = m_pWnd->GetDesktopWindow()) { CString csT,csW; int pos = cs.Find( 0x09 ); if( pos < 0 ) { csT = cs; cs = ""; } else { csT = cs.Left( pos ); cs.Delete( 0,pos ); } TRACE("対象: %s\n", csT ); for( pDlg = pDlg->GetTopWindow(); pDlg; pDlg = pDlg->GetNextWindow( GW_HWNDNEXT )) { pDlg->GetWindowText( csW ); TRACE("Window: %s\n", csW ); if( csW == csT ) { TRACE("Window: %s - コントロールを検索\n", csW ); CWnd * pCtl; for( pCtl = pDlg->GetTopWindow(); pCtl; pCtl = pCtl->GetNextWindow( GW_HWNDNEXT )) { pCtl->GetWindowText( csW ); TRACE("Window-Control: %s\n", csW ); if(( pos = cs.Find( csW )) > 0 ) { cs.Delete( pos,csW.GetLength()); } } cs.Replace( "\t","" ); TRACE("見つからなかった項目: %s\n", cs ); if( cs == "" ) { return( pDlg ); } } } } return( NULL ); }
←解決時は質問者本人がここをチェックしてください。
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.