AFsoft WebSite(エーエフソフト・ウェブサイト)
 

オペレーティング・システムについて

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
DelphiXE3 [FMX] マウス 2014/06/11
 
前回は、キーボードのキー処理について記述しました。
今回は、マウスの処理について見ていきます。マウス処理については既に、3Dですが [3D-FMX] 3Dアプリケーションテスト(4) にて少し記述しています。
 
フォームや各コントロールには、下記のマウス関連のイベントがあります。以下文章はヘルプより。
OnMouseEnter
※フォームには無し
マウスカーソルが、現在のコントロールの領域に入った際に、発生します。
OnMouseLeave
※フォームには無し
マウスカーソルが、現在のコントロールの領域から外に出た際に、発生します。(※ヘルプ記述無し)
OnMouseDownマウスボタンがコントロール上で押された際に、発生します。
OnMouseMoveマウスカーソルがフォーム領域上で移動した際に発生します。
OnMouseUpフォーム上で押されたマウスボタンが離された際に、発生します。
OnMouseWheel フォームにフォーカスがある間にマウスホイールが動かされた際に発生します。
 
メモ:MacOS X プラットフォーム上では、この関数は、マウスポインタがウィンドウ上にある間にマウスホイールが動いた場合に、呼び出される可能性があります。この場合、ウィンドウにフォーカスがある必要はありません。
 
まずは、OnMouseEnter、OnMouseLeave から見ていきます。
下図のように、ラベル(Label)エディット(Edit)ボタン(Button)を配置します。

各コンポーネントの OnMouseEnter、OnMouseLeave イベントハンドラを下記のようにします。単純に、Label2 にメッセージを表示するだけです。
procedure TForm1.Button1MouseEnter(Sender: TObject);
begin
   Label2.Text := 'Button1 に入りました。';
end;

procedure TForm1.Button1MouseLeave(Sender: TObject);
begin
   Label2.Text := 'Button1 から出ました。';
end;

procedure TForm1.Edit1MouseEnter(Sender: TObject);
begin
   Label2.Text := 'Edit1 に入りました。';
end;

procedure TForm1.Edit1MouseLeave(Sender: TObject);
begin
   Label2.Text := 'Edit1 から出ました。';
end;

procedure TForm1.Label1MouseEnter(Sender: TObject);
begin
   Label2.Text := 'Label1 に入りました。';
end;

procedure TForm1.Label1MouseLeave(Sender: TObject);
begin
   Label2.Text := 'Label1 から出ました。';
end;
保存・コンパイル(ビルド)・実行をしてみます。

ボタン上にマウスを移動すると、メッセージが表示されます


ボタン上から離れると、その旨のメッセージが表示されます
 
操作してみると、Label1 が反応しない事に気がつきます。オブジェクトインスペクタにて、Label1 の HitTest プロパティを確認すると、False になっているのが分かります。ラベルの場合、デフォルトは False なのでしょう。これを True にすることで、Label1 も反応するようになります。
 
 
次に、マウスホイールの OnMouseWheel イベントについて見てみます。
procedure TForm1.Button1MouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; var Handled: Boolean);
begin
   Label2.Text := 'Button1 でマウスホイール('+IntToStr(WheelDelta)+') ';
   ShiftStateCheck(Shift) ;
end;

procedure TForm1.Edit1MouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; var Handled: Boolean);
begin
   Label2.Text := 'Edit1 でマウスホイール('+IntToStr(WheelDelta)+') ';
   ShiftStateCheck(Shift) ;
end;

procedure TForm1.Label1MouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; var Handled: Boolean);
begin
   Label2.Text := 'Label1 でマウスホイール('+IntToStr(WheelDelta)+') ';
   ShiftStateCheck(Shift) ;
end;

procedure TForm1.ShiftStateCheck(Shift: TShiftState) ;
begin
   if (ssShift   in Shift) then Label2.Text := Label2.Text + '[SHIFT] ';
   if (ssAlt     in Shift) then Label2.Text := Label2.Text + '[ALT] ';
   if (ssCtrl    in Shift) then Label2.Text := Label2.Text + '[CTRL] ';
   if (ssLeft    in Shift) then Label2.Text := Label2.Text + '[左] ';
   if (ssRight   in Shift) then Label2.Text := Label2.Text + '[右] ';
   if (ssMiddle  in Shift) then Label2.Text := Label2.Text + '[中] ';
   if (ssDouble  in Shift) then Label2.Text := Label2.Text + '[ダブル] ';
   if (ssTouch   in Shift) then Label2.Text := Label2.Text + '[タッチ] ';
   if (ssPen     in Shift) then Label2.Text := Label2.Text + '[ペン] ';
   if (ssCommand in Shift) then Label2.Text := Label2.Text + '[CMD] ';
end;
自作の手続き ShiftStateCheck() は TForm1クラス定義のところで宣言しておきます。保存・コンパイル・実行します。

マウスホイールを上側(向こう側)に回します
 

マウスホイールを下側(手前側)に回します
 
[Shift]キーを押しながらマウスホイールを回してみると…

 
TShiftState型 の Shift 値は、キーボードの時と同様、下記のSet値です。
意味
ssShiftShift キーが押されています。
ssAltAlt キーが押されています。
ssCtrlCtrl キーが押されています。
ssLeftマウスの左ボタンが押されています。
ssRightマウスの右ボタンが押されています。
ssMiddleマウスのホイール ボタンが押されています。
ssDoubleマウス ボタンがダブルクリックされた。
ssTouchユーザーがタッチ画面に指をあてています。
ssPenペンがタブレット表面に触れています。
ssCommandCMD(Mac 上でのみ)が押されています。
 
WheelDelta値は、値そのものは何が来るのかは分かりませんが、プラス値かマイナス値かを参照します。
 
 
さて、フォーム Form1 の OnMouseWheel イベントも同じように記述してみます。分かりにくくなると何ですから、もう1つラベルを配置して、そちらに表示するようにします。
procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; var Handled: Boolean);
begin
   Label3.Text := 'Form1 でマウスホイール('+IntToStr(WheelDelta)+') ';
end;
保存・コンパイル・実行をして確認します。

ボタン Button1 上でマウスホイール操作をしてみると・・・

両方のイベントハンドラが動いているのが分かります。
procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; var Handled: Boolean);
begin
   Label3.Text := 'Form1 でマウスホイール('+IntToStr(WheelDelta)+') ';
   Handled := True;
end;
とすれば、フォームの方が優先されて、フォームのイベントハンドラだけが実行され、各コンポーネントのイベントハンドラは実行されません。逆に、各コンポーネントのイベントハンドラ内で「Handled := True;」をしても、フォームのほうが先に実行されますから意味がありません。
 
各コンポーネント領域内にあるときには、その処理を、それ以外のフォーム上の場合は、フォームの処理を、という風にするには、マウスが各コンポーネント領域内に入っている場合には、フラグを立てて、そのフラグが立っている場合には、フォームのイベントハンドラは実行しないよう if文を付けておく、というような感じになりそうです。
 
 
次に、OnMouseDown、OnMouseMove、OnMouseUp イベントについて見ていきます。ラベル Label1 のイベントハンドラを下記のようにしてみます。
procedure TForm1.Label1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
   Label2.Text := 'Label1 でマウスボタンを押しました。';
   ShiftStateCheck(Shift) ;
   Label3.Text := 'X:'+FloatToStr(X)+',Y:'+FloatToStr(Y);
end;

procedure TForm1.Label1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Single);
begin
   Label2.Text := 'Label1 でマウス移動中';
   ShiftStateCheck(Shift) ;
   Label3.Text := 'X:'+FloatToStr(X)+',Y:'+FloatToStr(Y);
end;

procedure TForm1.Label1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
   Label2.Text := 'Label1 でマウスボタンを離しました。';
   ShiftStateCheck(Shift) ;
   Label3.Text := 'X:'+FloatToStr(X)+',Y:'+FloatToStr(Y);
end;
保存・コンパイル・実行をします。

ラベル内でマウス移動中
 

ラベル内でマウスボタンを押しました
 

ラベル内でマウスボタンを離しました
 
TShiftState型の Shift 値の内容で、どのマウスボタンを押したのか分かります。また、TMouseButton型の Button 値の内容でも同じく、どのマウスボタンを押したのか離したのかは分かります。但し、OnMouseMoveイベントに Button 値の引数はありませんし、同時押しの判定も出来ません。
Jw_cad での両ボタンドラッグ操作などは、OnMouseDown イベントで、2つのボタンを同時に押した、という判断をするのは難しいです。左ボタンを押すのと右ボタンを押すのが完全に同時(であると認識される)、というよりも、大抵は、微妙な時間差があるのが普通です。ですから、OnMouseMove時でも、双方のボタンが同時押し状態かどうか、というチェックするのが通例です。
 
勿論、OnMouseDown 時に、両ボタンを完全同時に押した時の処理、というプログラムをしたい場合は、自由に、そのようにすれば良いとは思います。
 
X,Y値は、そのコントロール内でのクライアント領域座標です。
各コントロール内の LocalToAbsolute関数を利用すれば、フォームのクライアント領域内座標が得られるようです。また、スクリーン座標を取得したい場合は、フォームの ClientToScreen 関数を利用すれば取得出来る様子です。また、マウスのスクリーン座標は、「Screen.MousePos」で取得する事も出来る様子です。
 
 
次に、フォームの OnMouseDown、OnMouseMove、OnMouseUp イベントハンドラも記述してみます。新たにもう1つのラベル(Label4) を配置して、
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
   Label4.Text := 'Form1 でマウスボタンを押しました。'
   +' X:'+FloatToStr(X)+',Y:'+FloatToStr(Y);
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Single);
begin
   Label4.Text := 'Form1 でマウス移動中 '
   +' X:'+FloatToStr(X)+',Y:'+FloatToStr(Y);
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
   Label4.Text := 'Form1 でマウスボタンを離しました。'
   +' X:'+FloatToStr(X)+',Y:'+FloatToStr(Y);
end;
のようにすれば、各オブジェクト上では、各オブジェクトでのイベントが発生していて、オブジェクトの無いところ、又は、HitTest プロパティが False のオブジェクト上の場合は、フォームのイベントが発生しているようです。ですので、両方のイベントが同時/時間差に動く、ということは無さそうです。
 
 
バッチファイル
BASIC
C言語のお勉強
拡張子な話
DOSプログラム
Delphi
>Dehi入門編
>Delphi2010
>DelphiXE3
▲2014/06/10
 2014/06/11
▼2014/06/18
 
シェアウェア
Script!World
データベース
 
お問い合わせ 
本サイトはリンクフリーです
リンクバナー
(C)Copyright 1999-2015. By AFsoft All Rights Reserved.