フォーム上でのマウス動作を監視するには

解決


まる  2004-01-26 21:00:48  No: 6916

Delphi 6 Pro SP2 (Win 98) を使用しています。

フォーム上にボタンやラベルを配置しました。
Form.MouseMoveイベントを使用してマウスポインタの移動を監視すると、
ボタンやラベル上にマウスポインタが移動したときに MouseMoveイベントが
発生しないことが分かりました。

やりたいことは
・フォーム上のマウスポインタの出入りを知りたい
  (ラベルAに Enter/Leave と表示したい)
・マウスポインタの位置を知りたい (フォーム上のみ)
  (ラベルBにマウスポインタの座標を表示したい)
・MouseMoveのようなイベントで、上記を実現したい
  (リアルタイムで表示更新したい)

また、動的にラベルを追加したりしたいので、各コントロールのイベントを
記述するような形は避けたいです。

色々と調べているのですが、どのようにすれば実現できるのか
分からない状態です。
ヒントだけでもいただけませんでしょうか。
すみませんが、よろしくお願いいたします。


にしの  2004-01-26 21:04:54  No: 6917

CM_MOUSEENTERメッセージを使えば出来るかと思います。
この掲示板でも何度か出ているので、CM_MOUSEENTERで検索してみてはどうでしょう。


まる  2004-01-27 01:55:37  No: 6918

にしのさん、ありがとうございます。FAQで申し訳ございません。

早速検索してみたのですが・・・
私のイメージでは、CM_MouseEnter/Leaveは、各コントロールの
イベントハンドラを記述する必要があるように思えてしまうのです。
(共通化する手段がわかりません。(^-^;)
できれば、後でコントロールを追加しても、イベントハンドラを追加しないで
動作するようなものにしたいです。

現状では、
https://www.petitmonte.com/bbs/answers?question_id=1040

を応用させれば実現できそうな気がしています。
これから試してみたいと思います。
ありがとうございました。


にしの  2004-01-27 02:20:32  No: 6919

リアルタイムにマウスポインタの位置を知るというのを読み飛ばしていました。
すみません。

一取得は、TApplicationEventsのOnMessageを使えば、以下のようにして出来ます。

var
  pt: TPoint;
begin
  if Msg.message = WM_MOUSEMOVE then
  begin
    GetCursorPos(pt);
    Label1.Caption := '(' + IntToStr(pt.X) + ',' + IntToStr(pt.Y) + ')';
  end;
end;

OnMessageイベントは、たくさんのメッセージが飛んでくるので、扱いには注意です。


まる  2004-02-03 18:18:31  No: 6920

にしのさん、ありがとうございます。
にしのさんに頂いたアドバイスと過去ログから、以下のように作成しました。

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
var
  AMouse: TMouse;
  APos  : TPoint;
begin
  if Msg.message = WM_MOUSEMOVE then begin
    AMouse := TMouse.Create;
    APos := AMouse.CursorPos;
    APos := ScreenToClient(APos);
    Label1.Caption := IntToStr(APos.X) + ', ' + IntToStr(APos.Y);
  end;
end;

Enter/Leaveは、過去ログにありましたように CM_MouseEnterで
タイマを起動し、PtInRect()を使用して Leaveを判別するようにしました。

これでやりたいことは実現できたのですが、すみません、もう1つだけ
教えて頂けませんでしょうか。

>OnMessageイベントは、たくさんのメッセージが飛んでくるので、
>扱いには注意です。
とのことですが、具体的にどのような点について注意する必要が
あるのでしょうか。
すみませんが、よろしくお願いいたします。


jok  2004-02-03 20:51:14  No: 6921

> AMouse := TMouse.Create;
> APos := AMouse.CursorPos;

TMouse のインスタンスを作成する必要はないよ。Free してないし。
Controls.pas の Mouse オブジェクトを使う。

APos := Mouse.CursorPos;

> 具体的にどのような点について注意する必要があるのでしょうか。

重い処理をしないように、くらい。
上のように  AMouse.Free がないと大変。


まる  2004-02-03 22:48:05  No: 6922

jokさん、ありがとうございます。

Mouseオブジェクトを使用するように変更しました。
Createしたら Freeですね。ありがとうございました。


たかみちえ  URL  2004-02-04 18:15:00  No: 6923

> TMouse.Create
  ヘルプにあるとおり、TMouseを生成してはいけません。どうなるかはわかりませんけど、するべきではなさそうです。

  Mouseオブジェクトは、確か休止状態に入ったり、復帰したりするとき、参照しようとするとエラーが起こるはず。
(GetCursorPosが失敗するので)
  ここではWM_MOUSEMOVEの中なので大丈夫かもしれないですけど、GetCursorPosを使って、得た値がInvalidPointでないときに処理を行うような風にしたほうがいいかも。。

> 具体的にどのような点について注意する必要があるのでしょうか。
  まあ、冗長な処理(ほかでもできるようなことをするとか)はしないほうがいい…でしょうね。グローバルフックとかじゃないので、そこまで気を使う必要もないでしょうけど。
  if文の外で何か処理をしないように、でしょうかね。
OnMessageイベントは、アプリケーション上のメッセージの個数分実行されますから、関係ない処理をすると—わかりますね。


まる  2004-02-04 22:23:40  No: 6924

たかみちえさん、ありがとうございます。

作成したコードも、気がついたら TMouseを宣言しないで
動作していた部分がありました。
ヘルプを見ているうちに Mouse変数というのを見つけ、
Create/Freeする必要ないじゃんってことになりました。

GetCursorPosの前に tryが必要ということでしょうか?
また InvalidPointというのは、負の値などの定数ですか?
もしよろしければご教授下さい。

フックした部分は、できるだけ軽くするようにしたいと思います。
グローバルフックはやったことがありませんが、面白そうですね。
ありがとうございました。


たかみちえ  URL  2004-02-05 02:55:23  No: 6925

> GetCursorPosの前に tryが必要ということでしょうか?
  えー、Win98ではその問題には出会わないかもしれませんけど…。

  Mouseオブジェクトの関数でマウス座標を取得しようとすると、
マウス座標の取得に失敗した場合、エラーメッセージがでてしまいます。
タイマーや今回のメッセージループ内のようなところでつかうと、
エラーが連続して起こり、画面上エラーだらけ…という事態に陥ることがあります。
  try ... except end;  で囲んでも何とかできますけど、
ここはAPIのGetCursorPosを直接呼び出して使った方が早いのではないか?と、おもったわけです。

> InvalidPoint
  まずヘルプを読んでみてください。Delphiの関数なので載っています。(GetCursorPosは、同時にインストールしているはずのWinAPIヘルプや、ネット上のページを参考にしてください)


まる  2004-02-05 18:38:09  No: 6926

たかみちえさん、ありがとうございます。

>えー、Win98ではその問題には出会わないかもしれませんけど…。
細かいことですみませんが、NT系で発生するとかでしょうか?

>Mouseオブジェクトの関数でマウス座標を取得しようとすると、
>マウス座標の取得に失敗した場合、エラーメッセージがでてしまいます。
情報ありがとうございます。
Mouse変数の CursorPosプロパティを取得するときも Mouseオブジェクトの
関数をコールすると考えると、その可能性を感じます。
APIの直接呼び出しの方法は、これから勉強します。

> InvalidPoint
調査が不足しておりました。すみません。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加