スクリーン上のマウス位置の取得 – プログラミング – Home

スクリーン上のマウス位置の取得
 
通知
すべてクリア

[解決済] スクリーン上のマウス位置の取得

固定ページ 1 / 2

コスモ
 コスモ
(@コスモ)
ゲスト
結合: 20年前
投稿: 18
Topic starter  

環境は、WindowsXP, VC++6.0, SDK です。

作成したウィンドウ上の座標を取得することはできたのですが、
マウスがウィンドウから出てしまうと、値が取得できなくなってしまいます。
ClientToScreen()関数とScreenToClient()関数を試してみたのですが、
何の変化も見られませんでした。
スクリーン上の座標を取得する方法をご存知の方はいらっしゃいますか?

まだ初心者なので、間違っているかもしれませんが
プログラムの一部を記述します。

LRESULT CALLBACK WindowProc (
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {
HDC hdc;
POINT pt;
LRESULT result;
TCHAR str[255];

switch(uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_NCHITTEST:
ClientToScreen(hWnd, &pt);
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
wsprintf(str, TEXT(X = %d,Y = %d), pt.x, pt.y);

hdc = GetDC(hWnd);
TextOut(hdc, 0, 0, str, lstrlen(str));
ReleaseDC(hWnd, hdc);

result = DefWindowProc(hWnd, uMsg, wParam, lParam);
return result == HTCLIENT ? HTCAPTION : result;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}


引用未解決
トピックタグ
SunPac
 SunPac
(@SunPac)
ゲスト
結合: 21年前
投稿: 105
 

GetCursorPos()で画面上のカーソル位置を取得できます。
ScreenToClient()でウィンドウ上の座標に変換します。


返信引用
コスモ
 コスモ
(@コスモ)
ゲスト
結合: 20年前
投稿: 18
Topic starter  

SunPacさん、どうもありがとうございます。

GetCursorPos()ははじめて目にしました。
さっそく調べて試してみたいと思います。


返信引用
瀬戸っぷ
 瀬戸っぷ
(@瀬戸っぷ)
ゲスト
結合: 22年前
投稿: 160
 

> GetCursorPos()ははじめて目にしました。
> さっそく調べて試してみたいと思います。

ちなみに、WM_NCHITTESTメッセージで試すと…
自ウィンドウ以外ではやはり取れないと思います。
マウスカーソルが自ウィンドウ上に無い時にはWM_NCHITTESTが飛んでこないでしょうから…


返信引用
SunPac
 SunPac
(@SunPac)
ゲスト
結合: 21年前
投稿: 105
 

>ちなみに、WM_NCHITTESTメッセージで試すと…
>自ウィンドウ以外ではやはり取れないと思います。
>マウスカーソルが自ウィンドウ上に無い時にはWM_NCHITTESTが飛んでこないでしょうか
>ら…

そうですね。
ウィンドウ外のカーソル位置を取得するならSetCapture()するのでしょうね。


返信引用
コスモ
 コスモ
(@コスモ)
ゲスト
結合: 20年前
投稿: 18
Topic starter  

SetCapture()をつかって試してみたのですが

プログラム事態うまく動きませんでした。

最初に書き込んだプログラムの

ClientToScreen(hWnd, &pt);

部分を

SetCapture(hWnd);にしたのですが。
えらーは起こらなかったのですが、ウィンドウを開いてもカーソルが砂時計になり、制御
不能になってしまいました。

マウスカーソルが画面のどこに行ってもマウス位置を取得することは不可能なのでしょう
か?


返信引用
SunPac
 SunPac
(@SunPac)
ゲスト
結合: 21年前
投稿: 105
 

SetCapture()はマウスメッセージを対象ウィンドウに独占させる物です。
これによりカーソルがウィンドウの外にでてもマウスメッセージが飛んでくるわけです。
もちろんこのままだと他のウィンドウにマウスメッセージが飛ばなくなるので
ある時点でReleaseCapture()しないといけません。
具体的にはWM_LBUTTONDOWNでSetCapture()してWM_LBUTTONUPでReleaseCapture()すると
いいと思います。
SetCapture()している間はマウスカーソルがどこにあろうとWM_MOUSEMOVEが飛んできます
ので、そこで座標を得ればいいわけです。


返信引用
SunPac
 SunPac
(@SunPac)
ゲスト
結合: 21年前
投稿: 105
 

あ、上の具体的の部分はドラッグ処理の場合でした・・・
単にマウスの位置を知りたいだけなら例えばタイマーでGetCursorPos()して
ScreenToClient()するといった手もあります。
繰り返しますがSetCapture()はマウスメッセージを対象ウィンドウに独占させる物です。
これをしないとウィンドウの外にカーソルがあるとメッセージは来ません。
そしてSetCapture()をしたら必ずReleaseCapture()しましょう。


返信引用
コスモ
 コスモ
(@コスモ)
ゲスト
結合: 20年前
投稿: 18
Topic starter  

ありがとうございます。

けっこう複雑ですね。
ぼくに出来るかどうか不安ですが、がんばってみます。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

蛇足ですが、
SetCaptureという関数を紹介された場合は、
その関数の中身を調べて、どんな関数なのかを理解してから
使うようにしたほうが良いです。
今回の場合でいけば、そこからReleaseCaptureという関数に
たどり着けるはずですから。
紹介された関数をそのまま使ってうまく行ったとしても
コスモさん自身の知識になりませんし、
応用が全く利かないと思います。

結果が早くほしいのはわかるんですが、一つ一つ根気強く片付けていかないと
先々で行き詰ってしまうと思いますので、がんばってください。


返信引用
だっち
 だっち
(@だっち)
ゲスト
結合: 23年前
投稿: 12
 

まず、いつカーソルの位置を知りたいのでしょうか?
一番上のコードを見るとWM_NCHITTEST内で行っているようですが・・・

これって現在のカーソルが指定ウィンドウのどこにあるかを調べる物でしょう。
つまり、何らかの必要性で現在カーソルがそのウィンドウのどこにあるかを調べたい時
に、その対象ウィンドウに
SendMessage(hWnd, WM_HCHITTEST, 0, MAKELPARAM(x, y));
というメッセージを送って、その戻り値によって現在の位置をチェックする物なのです。
(xとyはスクリーン上のカーソルの位置です。)
もちろん、これ以外にも使用法はあるかもしれませんが・・・
ですのでこの中で何かを処理するはどうかと思います。
しかも
result = DefWindowProc(hWnd, uMsg, wParam, lParam);
return result == HTCLIENT ? HTCAPTION : result;
という部分は全く意味不明です。

おそらくマウスが動く度にその位置をチェックしたいのでしょう。
だとすると、WM_MOUSEMOVEというメッセージがカーソルを動かす度に飛んできます。
ただしこれはクライアント領域内のみで、SetCapture()すれば位置に関係なく飛んできま
す。この辺はSunPacさんのおっしゃる通りです。

タイマーの件は、おそらくWM_TIMERが飛んできたらその時のカーソルの位置をどこかに
確保しておき、必要に応じて参照すればいい、って事でしょう。
WM_TIMERの間隔を短くすれば実際の位置との誤差も小さいでしょう。
タイマーはSetTimer()で起動できます。

あと、PATIOさんのおっしゃる通り、初めてみるAPIはMSDNで調べるようにしましょう。
関連のあるAPIにリンクが張ってあるので上のような失敗は防げるはずです。
なによりそのAPIの意味を理解しないで使用するのは危険です。
初心者だからこそ、調べるクセをつけましょう。


返信引用
コスモ
 コスモ
(@コスモ)
ゲスト
結合: 20年前
投稿: 18
Topic starter  

MSDNで調べてみたのですが、理解が足りないみたいです。
SetCapture(HWND hWnd)
と書いてあったので、これだけでよいのかと思ってしまいました。

マウス位置を取得したいのは、マウスをクリックしてではなく、常に取得したいと考えて
います。マウスが画面上のどこにあってもです。

result = DefWindowProc(hWnd, uMsg, wParam, lParam);
return result == HTCLIENT ? HTCAPTION : result;
この部分は、マウスがウィンドウ上のどこにあってもタイトルバーの上にあると判断させ
るためのコードです。(これは必要ではありません。)

MSDNの調べ方が足りなくて申し訳ありませんでした。
御迷惑をおかけしました。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

常に取得したいというのは、自アプリがアクティブな間だけですか?
それとも、アクティブでない間も取得したいのですか?
それによって、また変わってきます。

自アプリがアクティブな間だけでよいのであれば、SetCapture がよいでしょう。
この場合、アクティブでなくなるときに ReleaseCapture するのを忘れてはいけませ
ん。

アクティブでない間も取得したいのなら、SetCapture は使えません。
この場合、タイマーで定期的に GetCursorPos するか、あるいはマウスフックが必要に
なるでしょう。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

ちなみに、マウスのボタンを押していない状態でSetCapture() した場合、
自アプリウィンドウの外のイベントは取得できないので、
やはりタイマーかフックを使うしかないと思います。


返信引用
コスモ
 コスモ
(@コスモ)
ゲスト
結合: 20年前
投稿: 18
Topic starter  

自アプリがアクティブでないときも取得をしたいと思っています。

また、自アプリ以外での操作も可能にしたいので
アドバイスを参考にさせていただくとタイマーかマウスブックというものを使うべきであ
ると思いました。

タイマーとマウスブックについて調べてみたいと思います。
親切に教えていただきまして、本当にありがとうございます。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました