|
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値です。
値 | 意味 |
ssShift | Shift キーが押されています。 |
ssAlt | Alt キーが押されています。 |
ssCtrl | Ctrl キーが押されています。 |
ssLeft | マウスの左ボタンが押されています。 |
ssRight | マウスの右ボタンが押されています。 |
ssMiddle | マウスのホイール ボタンが押されています。 |
ssDouble | マウス ボタンがダブルクリックされた。 |
ssTouch | ユーザーがタッチ画面に指をあてています。 |
ssPen | ペンがタブレット表面に触れています。 |
ssCommand | CMD(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
データベース
|