毎度お世話になっております。かなものです。
作業につまってしまい、ご質問させて頂きたいと思います。
またしても長文ですいません。
環境
Windows XP Professional
Delphi 6 Personal
ScrollBoxのスクロールがホイールでは動かないので、
今回、それをホイールでもスクロール出来るように打開策を試みました。
TESTの為に、下記のソースを書きました。
作業内容としては、Form1のOnMouseWheelに、
DOWN・UPにそれぞれScrollBox1.VertScrollBar.Positionの増減をさせいます。
intは、増減をLabel1に表示させているものです。
-----------------------------------------------------------------------------------
procedure TForm1.FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
int := int -1;
ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position -8;
Label1.Caption := IntToStr(int);
end;
procedure TForm1.FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
int := int +1;
ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position +8;
Label1.Caption := IntToStr(int);
end;
-----------------------------------------------------------------------------------
現状では、動くには動くのですが、その動きの幅にバラつきが発生し、
回避できずに行き詰ってしまいました。
まず、Formに、直接ScrollBoxを貼り付けて動作させました。
これは全く問題ありませんでした。
次に、実際の環境に似せてPageControlの中にScrollBoxを貼り付けたら
増減が倍の±16でホイール処理が行われるようになってしまいました。
さらに、実際に実装したいプログラムは、ClientSocketを使っているのですが、
試しに動かしてみたら、ClientSocketを動作させた時点で
5倍の±40でホイール処理が行われるようになってしまいました。
ClientSocketの話は抜きにして、PageControlを調べた所、
このPageControlをFormに張り付けただけで、倍の±16でホイール処理が行われていました。
もう少し突っ込んで調べてみたら、1回ホイールを回しただけで、
OnMouseWheelDOWN・UPが、2回処理が連続で行われていました。
5倍の±40は、5回連続で処理されていた事になります。
ClientSocketを動かしたら5倍に・・・は、全く見当が付かないのですが、
PageControlを張り付けただけで、2回処理される事に関係していると思いました。
GOOGLEで調べてみましたが、これ以上調べる事が出来ませんでした。
結果的に、OnMouseWheelDOWN・UPの多重処理の話になっていますが、
やりたい事は「ScrollBoxのスクロールをホイールで動かす」です。
対処方法、又は他に打開策があれば、ご教授頂けたらと思います。
宜しくお願い致します。
Halbow です。
> ScrollBoxのスクロールがホイールでは動かないので、
そうなんですか。わたしの環境 D5 in Win2000 では一行もコードを書かなくても
ちゃんと動きます。ですから試しようがありません。もういちど確かめてみたら
どうでしょうか。
たまに、マウスドライバが悪さすることもあります。
マウスを(別のメーカーのものに)変えても再現しますか?
私はかなものさんとほぼ同様の環境ですが、再現します。
Handled:= True;
を書き加えれば回避出来ませんか?
ご回答ありがとうございます。
> わたしの環境 D5 in Win2000 では一行もコードを書かなくても・・・
D5がどういう仕組みなのかわかりませんが、
どこかにScrollBoxは未対応という話を聞いた事がありまして・・・。
> たまに、マウスドライバが悪さすることもあります。
> マウスを(別のメーカーのものに)変えても再現しますか?
自宅PC・会社PC(マウス2種類)・ノートPC 全てに同様の現象が発生していまして、
それで悩んでいました。
> 私はかなものさんとほぼ同様の環境ですが、再現します。
> Handled:= True;
> を書き加えれば回避出来ませんか?
帰宅したら早速試してみたいと思います。
結果は追ってご報告致します。
書き忘れです
自宅PC:Win XP Pro
会社PC(マウス2種類):Win XP Pro
ノートPC:Win 2000 Pro
Handled という言葉は知っていましたが、
HELPを読んでも意味が良くわからなかったので、
スルー気味でした・・・。
以上です
Win2000 Pro
Delphi 6 Personal
Win98SE
Delphi 6 Personal
どちらでも、かなものさんと同様の現象が確認されました。
FormMouseWheelDown/upイベントハンドラを書かないと、ホイールではスクロールしません。
また、
Handled := True;
を FormMouseWheelDown/up ハンドラ内に追加しないと正常な±8のスクロールになりませんね。
結果をご報告致します。
OnMouseWheelDOWN・UP に無事に Handled:= True; を加えた所、
無事に現象が回避出来ました。
実際には、Tabを設置してるのですが、
その中の一つに ListView がありまして、
Handled:= True; をそのまま使用すると、上下に動かない事もわかりました。
ですので、このイベントにif文を書いて、これも回避出来ました。
大変助かりました。有難う御座いました。
> FormMouseWheelDown/upイベントハンドラを書かないと、ホイールではスクロールしません。
追加報告有難う御座います。やはりそのままでは動きませんか。
書かれていた事は、私の行った状態と同じだと思います。
知人に協力してもらった所、知人全員がScrollBoxのみではホイールでは動かず、
また、98・ME・2000・XP 全てにおいて上記の現象が発生していました。
今回の処理を行った所、知人全員が正常に動作しているとの亊です。
P.S.
ScrollBoxはホイールに未対応らしいという情報のソースですが、
・・・すいません、見失いました。
昔GOOGLEでホイール処理に関して調べていたら出てきたんですが・・・。
Halbow です。
> 98・ME・2000・XP 全てにおいて上記の現象が発生していました。
そうなんですか。わたしは Win2000 Delphi5 ですが、いま、再び確認しました
が、やはり、コードなしで正常に動作します。Delphi のバージョンの相違が
原因なんですかねぇ。起動したばかりの Form1 の適当なサイズで ScrollBox1
を置いて、その中に Label1 を置いて
procedure TForm1.FormCreate(Sender: TObject);
begin
Label1.Top := 1000;
end;
こんなふうにして、ラベルを下に配置して垂直スクロールバーを表示させて
テストしました。
Halbow です。
直前のレスで
> 起動したばかりの Form1 の適当なサイズで ScrollBox1 を置いて
じゃなくて PageControl1 の TabSheet2 の上に ScrollBox1 を置いて
です。
Delphi4の新規プロジェクトで、Halbowさんと同じように、コンポを配置して試してみました。
結果は、Delphi6 Personalの場合と同様で、イベントハンドラのコードを書かないとホイールでのスクロールは出来ません(‾◇‾)
う〜ん、Delphi5だけが特別ということはないはずなので、一体どうなってるんでしょうね〜(‾〜‾)ゞ
※スクロールBOXのプロパティは、位置とサイズ以外はデフォルトのままですけど…
Halbow です。
> イベントハンドラのコードを書かないとホイールでのスクロールは出来ません(‾◇‾)
およよ、わたしの環境の方が特殊なんですかね。
D4 と D6 が NG で、D5 が OK というのも変ですね。
解決したようですが、
わたしの書き込みのせいで、かえって混乱したようで、申し訳ありませんでした。
Delphi7など、他のバージョンではどうなんでしょう。気になりますねぇ〜
元の質問者はそっちのけで(^^ゞ…
このような違いが出る原因も出来れば知りたいところであります。
もしも本当に達人Halbowさんの環境が特殊だとしたら、どうしたらそのような環境にすることが出来るのかも興味津々です。
Halbow です。
> Halbowさんの環境が特殊だとしたら、どうしたらそのような環境にすることが出来るのかも興味津々です。
わたしの環境はすでに書きましたとおり、Delphi ver5 sp1 in Win2k Pro です。
Delphi のバージョンのせいであれば、わたしの D5 でコンパイルした実行ファイル
は、配布しても正常に動くことが期待できますね。そうではなく、環境が原因だと
すると、他の環境では NG だということになります。逆に、コードを書かないと
スクロールしない場合は、わたしの環境で正常に動くんですかね。
たしかに、かなり深刻な問題ではありますね。
ちなみに、わたしのマウスは USB マウスをアダプタを通して PS/2 端子につないで
います。ドライバは OS 標準のものです。
Halbow です。
わたしの今の環境で、以前にわたしの HP でホイール操作のスクロールメッセージ
について調べた結果を報告してありました。
http://halbow.cool.ne.jp/VCL03.html#VChap3-1
更新履歴を見ると今年の2月ですね。
なんか話が大きくなっていますね。
やり方によってイロイロ変わるんでしょうか?
理解できるかわかりませんが、
私も上記URLの内容を見てみたいと思います。
勝手ながらHalbowさんのページのサンプルをコピペしまして、
Windows XP Professional + Delphi 6 Personal
の環境でコンパイルしたものを、サンプルで置いてみます。
http://kanamono2.hp.infoseek.co.jp/wheel2.zip
よろしかったら動かしてみて頂ければと思います。
なお、ページに書かれていた
> 上記のプログラム実行中にマウスホイールを最小の単位で動かすと、
> 右図のように WM_VSCROLL が送られてきて・・・
・・・の部分がこちらでは再現されませんでした。
参考になれば幸いです。
Halbow です。
> コンパイルしたものを、サンプルで置いてみます。
これを DL して解凍して実行ファイルを起動して試してみました。HP に書いた
とおりに動作します。
ふーむ、これはわたしの環境では WM_MOUSEWHEEL メッセージではなく、
WM_VSCROLL メッセージに置き換わっているみたいですね。ですから、普通に
スクロールするんだと思います。これはドライバレベルでしょうから、
PS/2 接続なのが本質的な原因なのかもしれません。
わたし以外で USB 接続以外のマウスを使っていらっしゃる方が、普通に
ScrollBox を置いた場合にどうなるか興味があるところですね。
とにかく、わたしの環境の方がマイナーであることは確かなようです。
また、上記の推測が正しい場合、コードを書かなくては動作しない場合でも
その実行ファイルはわたしのような環境でも普通に動作するはずですね。
この場合、書いたコードが実行されるのではなく、WM_VSCROLL メッセージ
が処理されるのだと思います。
こういう報告でいいのかわかりませんが(^^;
とりあえずDLして動かしてみました。
マウスのホイールを回してもScrollBoxはスクロールしませんでした。
---
Windows2000Pro(SP2/SP3)
PS/2接続マウス
です
>Halbowさん
HalbowさんのWEBページのサンプル処理関数のままでは、
> 上記のプログラム実行中にマウスホイールを最小の単位で動かすと、
> 右図のように WM_VSCROLL が送られてきて・・・
が起きません。かなものさんと同様ですね。
以下のように WM_MOUSEWHEELの処理を追加しないとホイールでのスクロールは出来ませんです。
もし、Halbowさんの環境で、このようにした場合に何か不具合は起きるでしょうか?
procedure TForm1.SubclassProc(var Msg: TMessage);
begin
OriginalProc(Msg);
case Msg.Msg of
WM_VSCROLL : ScrollBox1VScroll(TWMScroll(Msg));
WM_HSCROLL : ScrollBox1HScroll(TWMScroll(Msg));
WM_MOUSEWHEEL:
begin
case HiWord(Msg.WParam) of
$0078: ScrollBox1.Perform(WM_VSCROLL, MakeWParam(SB_LINEUP,0), 0);
$FF88: ScrollBox1.Perform(WM_VSCROLL, MakeWParam(SB_LINEDOWN,0), 0);
end;
// 一応Messageを確認
Memo1.Lines.Add(Format('Msg = $%4x $%8x $%8x',[Msg.Msg, Msg.WParam, Msg.LParam]));
end;
end;
end;
procedure TForm1.ScrollBox1Click(Sender: TObject);
begin
ScrollBox1.SetFocus;
end;
なお、こちらのマウスドライバは以下の通りで、標準PS/2ポートマウスです。
VMM32.vxd(vmouse.vxd)
MSMOUSE.vxd
MOUSE.drv
出来ましたら、ScrollBox内にLabelを貼り付けただけで Wheelのハンドラを書かない状態で、
Halbowさんの環境でコンパイルした実行ファイルをどこかにUPしてもらえないでしょうか?
それをこちらでDLして実行してみたいのですが...
もし、それでホイールのスクロールが出来れば、Delphiのバージョンに原因がある可能性があり、
ホイールのスクロールが出来なければ、環境(マウス/ドライバ)に原因があると推定出来ますね。
Halbow です。
かなもの さん、通りすがり さん、(‾◇‾) さん、ありがとうございます。
どうも、わたしのせいで混乱させてしまって恐縮です。すみません。
> 以下のように WM_MOUSEWHEELの処理を追加しないとホイールでのスクロールは出来ませんです。
> もし、Halbowさんの環境で、このようにした場合に何か不具合は起きるでしょうか?
不具合は起きません。ホイールを最小単位で下上に動かすと Memo1 には
LINEDOWN : Pos = 0
ENDSCROLL : Pos = 0
LINEDOWN : Pos = 0
ENDSCROLL : Pos = 0
LINEDOWN : Pos = 0
ENDSCROLL : Pos = 0
LINEUP : Pos = 0
ENDSCROLL : Pos = 0
LINEUP : Pos = 0
ENDSCROLL : Pos = 0
LINEUP : Pos = 0
ENDSCROLL : Pos = 0
と表示され、正常に?スクロールされます。わたしのところでは WM_MOUSEWHEEL
メッセージは捕捉できません。うーむ、先の推測が正しそうですね。
> 出来ましたら、ScrollBox内にLabelを貼り付けただけで Wheelのハンドラを書かない状態で、
> Halbowさんの環境でコンパイルした実行ファイルをどこかにUPしてもらえないでしょうか?
> それをこちらでDLして実行してみたいのですが...
承知しました。以下にアップしました。
http://halbow.cool.ne.jp/Download/TestScrollBox.lzh
D5 でコンパイルしたもので
type
TForm1 = class(TForm)
ScrollBox1: TScrollBox;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
Label1.Top := 1000;
end;
これだけがソースです。こちらではホイールでスクロールできます。
よろしくお願い致します。
Halbowさん、DLして実行しました。
昨日と同じですね。
マウスのホイールを回してもScrollBoxはスクロールしませんでした。
---
Windows2000Pro(SP2/SP3)
PS/2接続マウス
です
どうも、話の張本人かなものです。
> 承知しました。以下にアップしました。
DLして動かしてみましたが、こちらではホイールでスクロールされませんでした。
詳しくはわかりませんが、おそらく推測されている内容であっていると思われます。
あと、今はもう壊れて捨ててしまいましたが、
過去に「変な動きをするマウスだなぁ」と思ってたものが一つありました。
今までホイールで動かなかったアプリのスクロールが、
その別のマウスだけは動かす事が出来た記憶があります。
もう数年前なので、メーカーやアプリに関してはもう忘れてしまいましたが、
マウスはPS/2だった事は覚えています。USBではなかったと思います。
今考えると、これもドライバ関係が原因だったのだと思います。
すいません、追加書き込みです。
> わたしのマウスは USB マウスをアダプタを通して PS/2 端子につないで
> います。ドライバは OS 標準のものです。
もしかしたら、過去のマウスはコレだったかもしれません。
うろ覚えで申し訳ないです。
ただ、PS/2端子に繋げていた事は覚えています。
Halbow です。
通りすがりさん、かなものさん、ありがとうございます。
> おそらく推測されている内容であっていると思われます。
そのようですね。
>> わたしのマウスは USB マウスをアダプタを通して PS/2 端子につないで
>> います。ドライバは OS 標準のものです。
> もしかしたら、過去のマウスはコレだったかもしれません。
ふーむ、そうですか。どうもこれが原因のような気がしますね。
わたしのノートパソコンにも USB 端子がありますが、MOが使っていて
物理的にマウスのプラグがささりません。時間ができたらUSB接続に
してみます。
回答ありがとうございました。
>Halbowさん
DLして実行してみました。
やはり、かなものさん、通りすがりさんと同じでホイールでのスクロールは起きませんでした。
結論としては、市販のマウスはホイールの回転で、WM_MOUSEWHEEL、WM_VSCROLL のどちらかのメッセージが送られるということですね。
TMemoもサブクラス化して試してみましたが、TMemoは内部でWM_MOUSEWHEELメッセージを処理してホイールに対応してるようです。
どちらかというとWM_MOUSEWHEELメッセージを送る方が正統派なんでしょうね。
でも、WM_VSCROLLメッセージの方を送れば、ホイールに未対応のコントロールでもホイールに反応してくれるので使う側にとってはとても便利なことです。
マウスドライバーの製作者は気をきかせてそのようなマウスを市販してるのだと思います。
でも、プログラム作成側にとっては思わぬ落とし穴と言えますね〜(‾◇‾)
今回の件は大きな収穫でした。ありがとうございましたm(__)m
Halbow です。
(‾◇‾) さん、ありがとうございます。
> 今回の件は大きな収穫でした。ありがとうございましたm(__)m
いや、そういっていただける方がおられると、心安まります。
わたしの「特殊環境」のせいでここもずいぶんと長いスレッドになり、恐縮しています。
> 時間ができたらUSB接続にしてみます。
これ帰宅してやってみました。みごとに、皆さんと同じように、コードなしでは動作しなく
なりました。上の推測が当たっていたようです。アダプタを介して PS2 接続をすると、
「ホイールに対応していない古い環境なのかも知れない」と気を利かして、WM_MOUSEWHEEL
のかわりに WM_VSCROLL をおくってくれるようですね。気が付きませんでした。
ちかじか、わたしの HP にもここでのやりとりを引用して「追記」しておきます。
スレ主のかなものさんの問題の件とは直接関係ないのに、みなさんからいろいろコメントを
いただいて感激いたしました。それですこし勉強しました。
MSDN の WM_MOUSEWHEEL Notification の項には
The WM_MOUSEWHEEL message is sent to the focus window when the mouse wheel is rotated. The DefWindowProc function propagates the message to the window's parent. There should
be no internal forwarding of the message, since DefWindowProc propagates it up the
parent chain until it finds a window that processes it.
と最初に書かれています。超訳すると
マウスホイールを回転させると WM_MOUSEWHEEL メッセージがフォーカスのあるウィンドウに
送られます。DefWindowProc は、このメッセージを親の連鎖を辿って伝えます。メッセージを
転送するコードを書かなくても、このメッセージを処理して DefWindowProc を呼び出さない
ようにするまで親への伝達は続きます。
VCL では TWinControl の派生クラスに
OnMouseWheel
OnMouseWheelDown
OnMouseWheelUp
のイベントがあり、そのそれぞれに var Handled: Boolean が引数としてあります。これが
さらに親の連鎖へメッセージを転送するかどうか、つまり、DefWindowProc を実行するかどうか
を決めているんですね。ヘルプの
Handled は,コントロールがイベントを処理したかどうかを示します。Handled を False に設定すると,オブジェクトの親がイベントを処理するようにすることができます。
の部分は、逆に読むと Handled を True に設定すると、ここで処理を打ち切ることができる、
という意味ですね。
ありがとうございました。
ツイート | ![]() |