DirectInputのマウス関連についての質問です。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
t_white

DirectInputのマウス関連についての質問です。

#1

投稿記事 by t_white » 16年前

どうもこんばんはです。

DirectInputを用いて入力関連を扱うクラスを作っているのですが、
通常のマウスカーソルと同じ座標を取得するにはどうしたら良いのでしょうか。
協調レベルがDISCL_NONEXCLUSIVE(非排他的アクセス)で表示される通常のマウスカーソルが指している座標を取得したいのです。

軸モードが相対値のまま、
//	毎ループ呼ばれる状態更新用の関数です。
HRESULT CInputMouse::UpdateState()
{
	HRESULT rc;

	//	添え字の切り替え(0⇔1)(ボタンを押した直後判定用に状態を現在と一つ前の二つ取得してます)(lXとか座標の状態まで二重に取得する必要は無いのでボタン用に配列つくって分けちゃったほうがよかったかも・・・)
	m_NowBufNo=1-m_NowBufNo;

	//	アクセス権を取得する前に初期化
	ZeroMemory(&m_MouseState[m_NowBufNo], sizeof(DIMOUSESTATE2));

	//	マウスのアクセス権を取得
	rc = m_pMouseDevice->Acquire();
	if(FAILED(rc))
	{
		return rc;
	}

	//	マウスの状態を取得
	rc = m_pMouseDevice->GetDeviceState(sizeof(DIMOUSESTATE2),&m_MouseState[m_NowBufNo]);
	if(FAILED(rc))
	{
		return rc;
	}

	if(m_MouseState[m_NowBufNo].lX)
		m_AbsPosition.x += m_MouseState[m_NowBufNo].lX;
	if(m_MouseState[m_NowBufNo].lY)
		m_AbsPosition.y += m_MouseState[m_NowBufNo].lY;
	if(m_MouseState[m_NowBufNo].lZ)
		m_AbsPosition.z += m_MouseState[m_NowBufNo].lZ;

	return S_OK;
}
以上のように実装しても、マウスの動き自体は合わせられるのですが、
始点が違っていてずれていたり、ウィンドウの端に行ってからもマウスを外側へ動かしていくと、
標準のマウスカーソルは端でとまったままなのにm_AbsPosition.x、yの値は端より外へ進み続けてしまいます。

絶対値モードにして実装すれば標準のマウスカーソルの座標と合わせる事は可能でしょうか?
それとも相対地モードで実装する方法はあるのでしょうか。
WindowsAPIの関数を使わなければならないのでしょうか。(出来る限り使用を控えたいです)
(ゲームのウィンドウの外から内へ入った時のみ、その最初の座標を取得するような使い方ならいいです)

毎度毎度文章の構成が下手ですみません。;
必要な情報が欠けていたら書きますので言ってくださいです。

どうかご教示して頂けたらありがたいです。よろしくお願いします。

t_white

Re:DirectInputのマウス関連についての質問です。

#2

投稿記事 by t_white » 16年前

取り合えずWindowAPIを毎更新使う方法では、
RECT rect;
	GetWindowRect(hWnd,&rect);
	POINT MousePos;
	// スクリーン上での位置を取得
	// ツールバー、タイトルバーなどは未考慮
	GetCursorPos( &MousePos );
	m_AbsPosition.x = MousePos.x-rect.left;
	m_AbsPosition.y = MousePos.y-rect.top;
という方法で実装できました。
よく考えたら、標準のマウスカーソルはWindowsが管理しているわけだから、
WindowsAPIを使わなきゃ座標取得できるわけないですよね・・・。
担任の教員に「DirectInputのほうが断然処理速度はやいからそっち使えるならWindowsAPIなんか使うなよー」と言われたことがあったので拘りすぎていたかもです…。
FPSなどのマウスを排他的アクセス、相対値座標で使うゲームならDirectInputで、
ノベルゲーやシュミレーションなどの非排他的アクセス、絶対値座標で作ったほうが快適なゲームではWindowsAPIで実装すればよいのでしょうか。

この見解に間違いがあったら思いっきり突っ込んでいただけるとありがたいです。
引き続きDirectInputを使った実装についてのご教示もお願いしますです。

Justy

Re:DirectInputのマウス関連についての質問です。

#3

投稿記事 by Justy » 16年前


>m_AbsPosition.x、yの値は端より外へ進み続けてしまいます

 DirectInputはそういうものです。
 ドライバと通信するので細かい制御はできますが、
Windoswのウインドウとは関係なく動くので、DirectInputだけでは
画面上の絶対座標は取得できません

 絶対値モードを使っても、結局どこかを原点とした座標になってしまいます。



>WindowsAPIの関数を使わなければならないのでしょうか

 ウインドウに関連付いた使い方をするなら、使うのを避けられないです。

 結局のところ併用するのがいいと思います。
 5ボタンなどの押下情報は WinAPIではとれないですし、DirectInputを使った
情報取得の方が速いですし。

t_white

Re:DirectInputのマウス関連についての質問です。

#4

投稿記事 by t_white » 16年前

>>Justy様
>ウインドウに関連付いた使い方をするなら、使うのを避けられないです。
やはりそうですか。;
それではこれからWindowsAPIを使ってウィンドウの枠なども考慮したコードを考えて行きたいと思います~。
横の枠によるずれは直せたのですが、縦のタイトルバーなどによるずれは難しいですね。
回答ありがとうございました。^

Justy

Re:DirectInputのマウス関連についての質問です。

#5

投稿記事 by Justy » 16年前


>横の枠によるずれは直せたのですが、縦のタイトルバーなどによるずれは難しいですね

 ?
 横が直せたのなら、同じような手法で縦も直せるはずです。

 縦はタイトルバーの高さ(SM_CYCAPTION)とフレーム枠(SM_CYDLGFRAME)の大きさを
横と同じく GetSystemMetrics()で求めて足せばYオフセットになりますよ。

t_white

Re:DirectInputのマウス関連についての質問です。

#6

投稿記事 by t_white » 16年前

返信遅くなってすみません。

> 縦はタイトルバーの高さ(SM_CYCAPTION)とフレーム枠(SM_CYDLGFRAME)の大きさを
>横と同じく GetSystemMetrics()で求めて足せばYオフセットになりますよ。
なるほど、そういう方法もあったのですね。勉強になります。ありがとうございました!

現在知っていたGetClientRect()とGetWindowRectを組み合わせて差異を求めるというような事をやっていたのでタイトルバーを考慮するのが難しかったのです…。WinAPIも勉強しよう・・・。

あのあとScreenToClient()という、
GetCursorPos()で取得した座標を直接クライアントの座標に直してくれる便利な関数を見つけたので
それを使用していたりします。(もしこの関数が処理が重くて有名とか問題があったら教えて下さい=)
色々便利だなぁ。

閉鎖

“C言語何でも質問掲示板” へ戻る