GetMeesage関数で、「キーボード入力とマウス入力に関するイベントだけ」を取得するには?

[戻る]
暴君タピオカくん 2015/09/10(木) 14:17:08
GetMeesage関数を使ってマウス操作処理を行うプログラムを作っています。
この処理はループ内で行われ、マウス右クリック押下を検出するまでそのループを抜けま
せん。
今まではマウス入力操作のみ検出すればよかったのですが、機能拡張に伴い、Shiftキー
の押下状態も検出したくなりました。

https://msdn.microsoft.com/ja-jp/library/Cc364699.aspx
上記URLによると、
WM_MOUSEFIRST、WM_MOUSELASTを指定すればマウスイベントのみ検出。
WM_KEYFIRST、WM_KEYLASTを指定すればキーイベントのみ検出。

では、「マウスイベントとキーイベントの両方のみ」を検出するにはどうしたらいいで
しょうか?
逆に言えば、それ以外のイベントは検出したくはありません。
(検出しても問題ないと思うのですが、それによって発生する影響が不安です。この辺の
ところどうなんでしょうか?)

VisualStdio2003です。

仲澤@失業者 2015/09/10(木) 17:07:55
一般のWindowsアプリケーションは全てのメッセージを受領しているので
(ただしほとんどがデフォルト関数に渡されますけど)、
いったい何が不安なのかさっぱりわかりませんが、
どのみちメッセージループ内でやるわけですよね。それなら

1.マウスメッセージの場合WPARAMにSHIFTやCTRLボタンの状態は入っています。
2.それでだめな場合はGetKeyState()で取れます。
3.GetMessage()だと戻ってこないのでPeekMessage()でやってみる。
4.GetMessage()で全てのメッセージを取得したあとswitch()で分けてやる
 (まぁTranslateMessage()に渡さなければコールバックされないですし)。

など、色々とアイデアが浮かびますが、どうでしょう。

タピオカくん 2015/09/11(金) 16:03:43
GetKeyStateを試してみましたが、なぜかうまくいきませんでした…。

不安なのは、今までGetMassage関数に「MK_MOUSEFIRSTとMK_MOUSELAST」を渡していたも
のを、
今回「0と0」を渡すよう変更するわけですが、それによりどんな影響があるかわからな
い、ということです。
漠然とした不安で申し訳ありませんが。。。

たとえば今回の変更により、「本来デフォルトで行われるべき処理が行われなくなる」
なんてことはないものでしょうか?

ちなみに、if文で必要なメッセージしか処理してません。

仲澤@失業者 2015/09/11(金) 16:22:44
まず、確かめたいのは、そのアプリケーションは
何らかの貴重な機器と接続されているのでしょうか。
その場合は、貴重な機器を壊すかもしれませんので安易な事はできませんね。

さて、そうでなければ、なぜやってみないのでしょう。
デバック中のアプリがぶっ飛んだとしても、何も困りませんよね。

いかがでしょう。

ITO 2015/09/11(金) 17:45:01
うーーん、
ウインドウズのアプリケーションを作る限り、メッセージはすべて検出していると思います。

>では、「マウスイベントとキーイベントの両方のみ」を検出するにはどうしたら
>いいでしょうか?
これは無理だと思います。

「検出しても処理しない。」ということはできると思います。
ただ、「何もしない」という意味の何らかのアンサーバックは返すと思います。

何か、メッセージを返すとまずいことがあるのでしょうか?
相手側の機器が送られたメッセージにすべて対応するように作られていて、
今回、マウス入力操作とShiftキーの押下状態のみチェックしたいということですか?
僕も仲澤さんも何がまずいのか、何処までいいのかが分からなく回答が難しい状態
になっています。

タピオカくん 2015/09/14(月) 11:22:40
すみません、質問の仕方がまずかったかな…?
聞きたいのは、「GetMessageって、イベントを検出する『だけ』ですか?」…ってことな
んです。
『だけ』なのであれば、検出されて困るイベントはないです。

Windowsには、「ウィンドゥが閉じられた」「ウィンドゥサイズが変わった」「マウスが
クリックされた」など、様々なイベントがあります。
通常、それらイベントは、システムが適切に処理してくれます。
だけどもし、GetMessageによってそれらイベントを検出したがために、システムにそのイ
ベントが渡されなかったり適切な処理が行われなかったり
…な〜んてことがないかどうか?
ってのを聞きたいのです。

まさかとは思いますが、ありませんよね?

ITO 2015/09/14(月) 13:00:02
これは、大丈夫ですか?
 >ただ、「何もしない」という意味の何らかのアンサーバックは返すと思います。
ソフトの内容により、可能性はあると思います。
あとは、ないと思います。

困ってました 2015/09/18(金) 13:00:59
[[解決]]
ご指摘通り危なっかしいプログラムですが、B_Tojiruを呼んだ後は何もしないし、問題な
く動いているのでこのままとします。
ありがとうございました。

ロマ 2015/09/23(水) 21:13:11
解決済みですが気になることがありますので書き込みます。

メインのメッセージループ以外の場所で GetMessageやPeekMessageを使う場合は
http://blogs.msdn.com/b/oldnewthing/archive/2005/02/22/378018.aspx
の通り、WM_QUITの処理をつけることをお勧めします。

[WM_QUITを処理しない場合の不具合の例]
上記のGetMessageを呼び出しているときに
タスクマネージャー -> アプリケーション -> タスクの終了
で、アプリケーションを終了しようとすると

GetMessageはWM_CLOSEを発生し、WM_CLOSEハンドラはDestroyWindowを呼ぶ。
DestroyWindowはWM_DESTROYを発生し、WM_DESTORYハンドラはPostQuitMessageを呼ぶ。
PostQuitMessageはWM_QUITを発生し、GetMessageはゼロを返し、
たぶん、メインのメッセージループに戻る。
メインのメッセージループのGetMessageは新たなメッセージを待つが、
この時点でウィンドウはないので永久に待ち続ける。

古いスレッドには追加発言できません。