- PR -

C# マウスホイールの動作を定義したい

1
投稿者投稿内容
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2006-02-09 12:49
マウス中央にあるホイールによる垂直および水平スクロール動作を一時的に独自の振舞いに定義し、必要がなくなったら、以前の定義に戻したい。

環境 WindowsXP VisualStudio2003 C# Windows.Form Microsoft製Mouse

Q1
マウスにホイール(垂直および水平)が装着されているかを知る方法はありますか?

Q2
ホイールを垂直(あるいは水平)に動かした時に発生するイベントを取得できますか?
(どのようなイベントが発生しますか)

Q3
一時的にイベント発生時の振舞いを変更できますか?
つまり下記の3つをクリアする必要があります。
 ・振舞いを変更する前の定義を記憶する
 ・振舞いを一時変更する
 ・振舞いを記憶させておいた定義にもどす


アプリケーション内で特定のモードになった時に限りホイールに独自の動作をさせ、モードを抜けたらインテリマウスで定義されている通常の振舞いに戻す。例えば通常は画面の垂直および水平スクロールとして働くが、特定のモードでのみ、ホイールを垂直スクロールさせると垂直スクロールバーがスライドし、水平スクロールさせると水平スクロールバーがスライドする、といったことをさせたい。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-09 13:06
部分的にしか答えられませんが、

引用:

ひろしさんの書き込み (2006-02-09 12:49) より:

ホイールを垂直(あるいは水平)に動かした時に発生するイベントを取得できますか?
(どのようなイベントが発生しますか)


MouseWheel イベントが実装されているものは MouseWheel イベントが発生します。
それ以外は WndProc で WM_MOUSEWHEEL を捕えて独自にイベントを実装します。

引用:

一時的にイベント発生時の振舞いを変更できますか?


どのコントロールに実装するかはわかりませんが、
派生クラス側で、切替用のプロパティを実装して、
イベント内で分岐するようにすれば良いのではないでしょうか?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2006-02-09 18:53
イベントが拾えるようになりました。
ホイールが動いた向きと量も取得出来ました。
ありがとうございました。
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2006-02-16 14:45
ホイールによる垂直スクロールは検知きましたが、ホイールによる水平スクロールのほうが検知できません。水平スクロールの検知方法をアドバイス願います。

環境:
WindowsXP SP2 + C#(VS2003)
Microsoft IntelliMouseExplorer + IntelliPoint 5.4

ソースコード

// 垂直スクロールを検知してラベルに表示する
// 水平スクロールも検知できるようにしたい

private void Form1_MouseWheel(object sender, MouseEventArgs e)
{
sender1 = sender.ToString();
delta1 = e.Delta.ToString();
this.label1.Text = msg1+" "+sender1+" "+delta1;

}
private string msg1 = "";
private string sender1;
private string delta1;


protected override void WndProc(ref Message m)
{
const int MOUSEWHEEL = 0x20A;

switch(m.Msg)
{
case MOUSEWHEEL:
msg1 = "WHEEL";
break;
}

base.WndProc (ref m);
}
YAS
ベテラン
会議室デビュー日: 2006/02/15
投稿数: 59
投稿日時: 2006-02-16 22:03
Spy++で水平スクロール時にどんなメッセージがきているか見てみたらどうでしょうか。
(水平スクロール付きのマウスをもっていないので私は確かめられません。)

「チルトホイール WM_MOUSEWHEEL」でGoogle検索すると,どうも直接WM_HSCROLLを送って無理矢理スクロールさせているようですね。もしそうなら検知するのは難しいかもしれません。

[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-16 22:31 ]
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2006-02-17 13:59
下記の通り実験をしてみました。
垂直スクロールと同じ方法では水平スクロールを検知できないようです。
良い解決策は無いでしょうか?宜しくお願いします。


実験
マウスのホイールを垂直スクロールおよび水平スクロールしながら、
スクロールテストプログラムのプロセスに対してメッセージをロギングした。

★spy++によるログ(一部)
<00466> 000903EC R WM_SETCURSOR fHaltProcessing:False [lResult:00000000]
<00467> 000903EC P WM_MOUSEMOVE fwKeys:0000 xPos:300 yPos:18 [wParam:00000000 lParam:0012012C time:3:58:30.015]
<00468> 000A01A2 P WM_MOUSEWHEEL fwKeys:0000 zDelta:120 xPos:400 yPos:184 [wParam:00780000 lParam:00B80190 time:3:58:34.000]
<00469> 000A01A2 S WM_GETTEXTLENGTH wParam:00000000 lParam:00000000
<00470> 000A01A2 R WM_GETTEXTLENGTH cch:5 [lResult:00000005]
<00471> 000A01A2 S WM_GETTEXT cchTextMax:12 lpszText:0012E024 [wParam:0000000C lParam:0012E024]

結果 spy++には垂直スクロールについてはログに記録されているが、水平スクロールは記録されていなかった。

★スクロールテストプログラムのソースコード

// C# VisualStudio2003

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Text;

namespace WindowsApplication2
{
/// <summary>
/// Form1 の概要の説明です。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Windows フォーム デザイナ サポートに必要です。
//
InitializeComponent();

//
// TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
//
}

/// <summary>
/// 使用されているリソースに後処理を実行します。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
str1 = String.Format("{0:00000} {1:yyyy/MM/dd HH:mm:ss.fff} Log End",counter,DateTime.Now);
sw.WriteLine(str1);
sw.Close();
label1.Text = str1;

if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows フォーム デザイナで生成されたコード
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.BackColor = System.Drawing.SystemColors.Info;
this.label1.Font = new System.Drawing.Font("MS UI Gothic", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(128)));
this.label1.Location = new System.Drawing.Point(8, ;
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(736, 38);
this.label1.TabIndex = 1;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
this.ClientSize = new System.Drawing.Size(760, 54);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseWheel);
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private StreamWriter sw;
private int counter;

private void Form1_Load(object sender, System.EventArgs e)
{
counter = 0;
sw = new StreamWriter(@"c:\data\log.txt",true,Encoding.GetEncoding("Shift_JIS"));
str1 = String.Format("{0:00000} {1:yyyy/MM/dd HH:mm:ss.fff} Log Start",counter,DateTime.Now);
sw.WriteLine(str1);
this.label1.Text = str1;
counter++;
}

private void Form1_MouseWheel(object sender, MouseEventArgs e)
{
time1 = DateTime.Now;
sender1 = sender.ToString();
delta1 = e.Delta;
button1 = e.Button.ToString();
clicks1 = e.Clicks;
x1 = e.X;
y1 = e.Y;
info1 = String.Format("{0:00000} {1:yyyy/MM/dd HH:mm:ss.fff} X={2:0000} Y={3:0000} BUTTON={4} CLICKS={5} DELTA={6} MSG={7}",counter,time1,x1,y1,button1,clicks1,delta1,msg2);
sw.WriteLine(info1);
label1.Text = info1;
counter++;
}
private int msg1;
private string msg2;
private DateTime time1;
private string sender1;
private int delta1;
private string button1;
private int clicks1;
private int x1;
private int y1;
private string info1;
private string str1;



protected override void WndProc(ref Message m)
{
const int WM_HSCROLL = 0x114;
const int WM_VSCROLL = 0x115;
const int MOUSEWHEEL = 0x20A;

msg1 = m.Msg;
msg2 = "";
switch(msg1)
{
case WM_HSCROLL:
msg2 = "HSCROLL";
break;
case WM_VSCROLL:
msg2 = "VSCROLL";
break;
case MOUSEWHEEL:
msg2 = "MOUSEWHEEL";
break;
default:
msg2 = String.Format("OTHER(ID={0})",msg1);
break;

}

base.WndProc (ref m);
}



}
}


★スクロールテストプログラムのログファイル(log.txt)
00000 2006/02/17 13:22:10.593 Log Start
00001 2006/02/17 13:25:44.406 X=0308 Y=0026 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00002 2006/02/17 13:25:44.484 X=0308 Y=0026 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00003 2006/02/17 13:25:44.593 X=0308 Y=0026 BUTTON=None CLICKS=0 DELTA=144 MSG=OTHER(ID=13)
00004 2006/02/17 13:25:46.000 X=0308 Y=0026 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00005 2006/02/17 13:25:46.062 X=0308 Y=0026 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00006 2006/02/17 13:25:46.109 X=0308 Y=0026 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00007 2006/02/17 13:25:46.156 X=0308 Y=0026 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00008 2006/02/17 13:25:46.218 X=0308 Y=0026 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00009 2006/02/17 13:25:56.031 X=0310 Y=0027 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00010 2006/02/17 13:25:56.171 X=0310 Y=0027 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00011 2006/02/17 13:25:56.859 X=0310 Y=0027 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00012 2006/02/17 13:25:56.968 X=0310 Y=0027 BUTTON=None CLICKS=0 DELTA=120 MSG=OTHER(ID=13)
00013 2006/02/17 13:26:03.968 Log End

結果 スクロールテストプログラムでは垂直スクロールは検知できたが、水平スクロールは検知できなかった。
YAS
ベテラン
会議室デビュー日: 2006/02/15
投稿数: 59
投稿日時: 2006-02-17 17:29
メッセージがこないのであれば,あとはマウスの状態をポーリングするくらいしか
私には思いつきません。ごめんなさい。
(水平ホイールの状態を取得できるWin32APIがあればですが。)

あと,DirectInputでできないか調べてみます。

[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-17 23:15 ]
1

スキルアップ/キャリアアップ(JOB@IT)