🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

SDK

SDK(software development kit)は特定のハードウェアのプラットフォーム、開発環境又はソフトウェアパッケージでソフトウェアをつくるのに必要な開発ツールのセットです。SDKはAPI、IDE又は他の開発ツールとフレームワークを組み合わせたもので構成されていることがあります。

C++

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

DirectX

DirectX(ダイレクトエックス)は、 マイクロソフトが開発したゲーム・マルチメディア処理用のAPIの集合です。

Q&A

1回答

3397閲覧

DirectInput コンソールアプリでSetCooperativeLevelの排他制御設定を行いたい。

Tatsuk

総合スコア11

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

SDK

SDK(software development kit)は特定のハードウェアのプラットフォーム、開発環境又はソフトウェアパッケージでソフトウェアをつくるのに必要な開発ツールのセットです。SDKはAPI、IDE又は他の開発ツールとフレームワークを組み合わせたもので構成されていることがあります。

C++

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

DirectX

DirectX(ダイレクトエックス)は、 マイクロソフトが開発したゲーム・マルチメディア処理用のAPIの集合です。

0グッド

0クリップ

投稿2019/11/17 13:15

編集2019/11/19 17:07

前提・実現したいこと

環境:64bit版windows10,VC++2019,DirectX SDK(June 2010)を利用
コンソールアプリ上でフォースフィードバックを利用したいため、コンソールアプリでの排他制御セット
g_pDIDevice->SetCooperativeLevel(hWlg, DISCL_EXCLUSIVE | DISCL_BACKGROUND)
を行いたいです。

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

下記のコードからDISCL_EXCLUSIVEの部分をDISCL_NONEXCLUSIVEとするか、排他制御設定自体を削除すると問題なくフォースフィードバック機能の有り無しに関わらず動作します。しかし、排他制御設定を行うと ”Acquireに失敗” と表示され、入力の開始が実行できない状態です。実際数値的にも取得できませんでした。 コンソールアプリで排他制御を行う方法を知っていればお手数とは思いますが教えて頂けると幸いです。

c++

1#include <iostream> 2 3#define STRICT 4#define DIRECTINPUT_VERSION 0x0800 5 6#include <windows.h> 7#include <crtdbg.h> 8 9#pragma warning( disable : 4996 ) // 警告を一時的に無効にする 10#include <strsafe.h> 11#pragma warning( default : 4996 ) 12 13#include <dinput.h> 14#include <dxerr.h> 15 16 17#define SAFE_RELEASE(x) {if(x){(x)->Release();x=NULL;}} 18 19// 必要なライブラリをリンクする 20#pragma comment( lib, "dinput8.lib" ) 21#pragma comment( lib, "dxerr.lib" ) 22#pragma comment( lib, "dxguid.lib" ) 23 24 25HWND hWlg; 26 27// DirectInputの変数 28LPDIRECTINPUT8 g_pDInput = NULL; 29LPDIRECTINPUTDEVICE8 g_pDIDevice = NULL; // DirectInputデバイス 30LPDIRECTINPUTEFFECT g_pDIEffect = NULL; // エフェクト 31DIDEVCAPS g_diDevCaps; // ジョイスティックの能力 32#define DIDEVICE_BUFFERSIZE 1000 // デバイスに設定するバッファ・サイズ 33 34 35BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); 36BOOL CALLBACK EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef); 37 38int main() 39{ 40 DIJOYSTATE2 dijs; //この構造体にデータを取得する 41 HINSTANCE hInstApp = GetModuleHandle(NULL); //インスタンス・ハンドル 42 HWND hWlg = GetConsoleWindow(); //ウインドウハンドル 43 HRESULT hr; 44 45 // IDirectInput8の作成 46 hr = DirectInput8Create(hInstApp, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&g_pDInput, NULL); 47 // 48 if (FAILED(hr)) 49 { 50 printf("オブジェクト作成に失敗\n"); 51 return -1; 52 } 53 54 // ジョイスティックの列挙 55 hr = g_pDInput->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL,DIEDFL_ATTACHEDONLY); 56 if (FAILED(hr) || g_pDIDevice == NULL) { 57 printf("デバイスオブジェクト作成に失敗\n"); 58 g_pDInput->Release(); 59 return -1; 60 } 61 62 // データ形式を設定 63 hr = g_pDIDevice->SetDataFormat(&c_dfDIJoystick2); 64 if (FAILED(hr)) { 65 printf("入力データ形式のセット失敗\n"); 66 g_pDIDevice->Release(); 67 return -1; 68 } 69 70 //モードを設定(フォアグラウンド&排他モード) 71 hr = g_pDIDevice->SetCooperativeLevel(hWlg, DISCL_EXCLUSIVE | DISCL_BACKGROUND); 72 if (FAILED(hr)) 73 { 74 printf("排他制御のセット失敗\n"); 75 g_pDIDevice->Release(); 76 return -1; 77 } 78 79 //コールバック関数を使って各軸のモードを設定 80 hr = g_pDIDevice->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS); 81 if (FAILED(hr)) 82 { 83 printf("軸モードの設定に失敗\n"); 84 g_pDIDevice->Release(); 85 return -1; 86 } 87 // 軸モードを設定(絶対値モードに設定。デフォルトなので必ずしも設定は必要ない) 88 DIPROPDWORD diprop; 89 diprop.diph.dwSize = sizeof(diprop); 90 diprop.diph.dwHeaderSize = sizeof(diprop.diph); 91 diprop.diph.dwObj = 0; 92 diprop.diph.dwHow = DIPH_DEVICE; 93 diprop.dwData = DIPROPAXISMODE_ABS; 94 hr = g_pDIDevice->SetProperty(DIPROP_AXISMODE, &diprop.diph); 95 if (FAILED(hr)) 96 { 97 printf("軸モードの設定に失敗\n"); 98 g_pDIDevice->Release(); 99 return -1; 100 } 101 // バッファリング・データを取得するため、バッファ・サイズを設定 102 diprop.dwData = DIDEVICE_BUFFERSIZE; 103 hr = g_pDIDevice->SetProperty(DIPROP_BUFFERSIZE, &diprop.diph); 104 if (FAILED(hr)) 105 { 106 printf("バッファ・サイズの設定に失敗\n"); 107 g_pDIDevice->Release(); 108 return -1; 109 } 110 111 112 // 入力制御開始 113 hr = g_pDIDevice->Acquire(); 114 if (FAILED(hr)) 115 { 116 printf("Acquireに失敗\n"); 117 g_pDIDevice->Release(); 118 return -1; 119 } 120 // ポーリング 121 hr = g_pDIDevice->Poll(); 122 if (FAILED(hr)) 123 { 124 printf("pollに失敗\n"); 125 g_pDIDevice->Release(); 126 return -1; 127 128 } 129 130 int i; 131 132 for (i = 0; i <= 10; i++) 133 { 134 135 hr = g_pDIDevice->GetDeviceState(sizeof(DIJOYSTATE2), &dijs); 136 if (SUCCEEDED(hr)) 137 { 138 printf("[X=%d Y=%d Z=%d][Rx=%d Ry=%d Rz=%d][Slider1=%d Slider2=%d]\n", 139 dijs.lX, dijs.lY, dijs.lZ, 140 dijs.lRx, dijs.lRy, dijs.lRz, 141 dijs.rglSlider[0], dijs.rglSlider[1]); 142 143 } 144 else 145 { 146 // 失敗なら再開させてもう一度取得 147 g_pDIDevice->Acquire(); 148 g_pDIDevice->Poll(); 149 g_pDIDevice->GetDeviceState(sizeof(DIJOYSTATE2), &dijs); 150 printf("取得失敗!\n"); 151 } 152 153 Sleep(1000); 154 } 155 156 g_pDIDevice->Unacquire(); 157 if (g_pDIDevice != NULL)g_pDIDevice->Release(); 158 if (g_pDInput != NULL)g_pDInput->Release(); 159 160 printf("正常終了\n"); 161 return 0; 162 163} 164 165BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) 166{ 167 HRESULT hr; 168 169 // 列挙されたジョイスティックへのインターフェイスを取得する。 170 hr = g_pDInput->CreateDevice(pdidInstance->guidInstance, &g_pDIDevice, NULL); 171 if (FAILED(hr)) 172 return DIENUM_CONTINUE; 173 174 // ジョイスティックの能力を調べる 175 g_diDevCaps.dwSize = sizeof(DIDEVCAPS); 176 hr = g_pDIDevice->GetCapabilities(&g_diDevCaps); 177 if (FAILED(hr)) 178 { 179 // ジョイスティック能力の取得に失敗 180 SAFE_RELEASE(g_pDIDevice); 181 return DIENUM_CONTINUE; 182 } 183 184 return DIENUM_STOP; // 1つ見付けたら列挙を止める 185} 186 187// ジョイスティックの軸を列挙する関数 188BOOL CALLBACK EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) 189{ 190 HRESULT hr; 191 192 // 軸の値の範囲を設定(-1000~1000) 193 DIPROPRANGE diprg; 194 ZeroMemory(&diprg, sizeof(diprg)); 195 diprg.diph.dwSize = sizeof(diprg); 196 diprg.diph.dwHeaderSize = sizeof(diprg.diph); 197 diprg.diph.dwObj = lpddoi->dwType; 198 diprg.diph.dwHow = DIPH_BYID; 199 diprg.lMin = -1000; 200 diprg.lMax = +1000; 201 hr = g_pDIDevice->SetProperty(DIPROP_RANGE, &diprg.diph); 202 if (FAILED(hr)) 203 return DIENUM_STOP; 204 205 return DIENUM_CONTINUE; 206} 207

###試したこと
原因は
HRESULT IDirectInputDevice8::SetCooperativeLevel(
HWND hwnd
DWORD dwFlags
);
の最初の引数として必要なHWNDの部分に対応可能なハンドルをGetConsoleWindow()では取得できないせいではないかと考えています。
HWND hWlg = GetForegroundWindow();
HWND hWlg = GetDesktopWindow();
また今回opencvと組み合わせるので
HWND hWlg = (HWND)cvGetWindowHandle(windowName);
も試してみましたが、こちらも入力制御ができませんでした。

補足情報(FW/ツールのバージョンなど)

参考にしたもの
http://www.kohgakusha.co.jp/support/sdx9xpv7/index.html
のサンプルプログラム4
利用したジョイスティック・ゲームパッド
Cyborg Evo Force Joystick(フォースフィードバック機能あり)
BSGP1204BK(フォースフィードバック機能なし)

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

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

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

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

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

guest

回答1

0

IDirectInputDevice8::SetCooperativeLevel で排他制御が必要な場合、同一プロセス内のトップレベルウィンドウのハンドルを渡す必要があります。

同一プロセスのウィンドウではないので、以下はすべて使用できません。

C++

1HWND hWlg = GetConsoleWindow(); 2HWND hWlg = GetForegroundWindow(); 3HWND hWlg = GetDesktopWindow();

OpenCV のウィンドウは同一プロセス内になると思うのですが、トップレベルウィンドウを満たしていないかプロジェクトの種類をコンソールアプリケーションにしていると、そもそもできない制限があるかもしれません。

サンプルが示す通り素直に自分でウィンドウを作成されるのが良いと思います。

投稿2019/11/30 12:42

編集2019/11/30 12:44
atata0319

総合スコア881

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

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

Tatsuk

2019/12/01 09:03 編集

atata0319様、回答ありがとうございます。 やはり、WIN32APIと組み合わせてウィンドウを作成するのが一番良いみたいですね。一応WIN32APIの勉強も進めているのですが、opencvとの組み合わせが私の知識不足故に中々上手くいっていないので、もう少しコンソールアプリ上での排他制御についての回答を待ちたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問