トップ回答者
WinForms コントロール ListView マウスダウンによる項目直後にスクロールすると選択項目までスクロールが戻る現象

質問
回答
-
スクロールが戻らないようにするだけなら
class ListViewEx : ListView { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool KillTimer(IntPtr hWnd, IntPtr uIDEvent); protected override void WndProc(ref Message m) { const int WM_HSCROLL = 0x114; const int WM_VSCROLL = 0x115; const int WM_TIMER = 0x0113; const int WM_MOUSEWHEEL = 0x020A; switch (m.Msg) { case WM_TIMER: KillTimer(this.Handle, m.WParam); m.Result = IntPtr.Zero; return; } base.WndProc(ref m); } }
のようにWM_TIMERを捨てるといいみたい。
内部でタイマーを描画更新のトリガーに使って選択された項目にスクロールしてるのかな?
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
すべての返信
-
こんにちは。サンプルプロジェクトを作成しました。
環境:Windows 7 Pro 64bit, Visual Studio 2013 Update5, C# または VB, .NET Framework 4.5.2
https://onedrive.live.com/redir?resid=3C3E7130A10633D2!3878&authkey=!ALm-JxWcnYMl38w&ithint=file%2czip
コードによる選択でスクロールが戻る現象はこのプロジェクトでは確認できませんでしたが、マウスダウン→即時にスクロールで選択位置まで戻ってしまう現象は確認できました。
-
すみません、動作に対する詳細がいくつか抜けておりました。
マウスダウンする場所はListViewの選択したい行です。または既に選択されている行でも構いません。
この状態から「マウスホイールによるスクロール」を実行し、少し待つと選択された行までスクロールが戻ります。
追記でWindows8でも試してみましたが、同じ現象が発生してしまいます。あと単純にマウスが壊れているのかと思ったのですが、それとも違うようです。(他アプリケーションでは正常に動作する)
意図しないタイミングでWM_VSCROLLが発生しているのではないかと思ってみてみましたが、そもそもホイールによるスクロールではこのメッセージは発生していないようでした。
-
「ぱちもん」さん、
Windows 8.1 Pro(64-bit)、Visual Studio 2013 でデバッグ実行し、
書いていただいた操作をしてみました。
もう少し細かく書くと・・・
「通常のリストビュー」で、スクロールバーで真ん中あたりまで移動し、行を選択しました。
その状態で、選択行が見えなくなるまで「マウスホイール」で上方または下方にスクロールしました。
そのまま放置しても、見えなくなった選択行が見えるようになる(選択された行にスクロールが戻る)現象は発生しませんでした。
「仮想リストビュー」でも同じ結果でした。
(仮想リストビューというのがどのような機能・テストのためかは分かっていません・・・(^-^;)
Windows 10 Pro(64-bit)とのデュアルブートPCなので、本ポストを投稿してから Win. 10 でも動作を確認してみます。また、Win. 7 マシンでの結果も報告します。
以上。
- 編集済み Ashidacchi 2016年2月3日 9:06
-
結果報告です。
① Windows 8.1 Pro(64-bit)、Visual Studio 2013
② Windows 10 Pro(64-bit)、Visual Studio 2015
③ Windows 7 Ultimate(64-bit)、Visual Studio 2013
以上の環境では再現しませんでした。
原因は、マウス関連(設定とかドライバーとか)にあるように思えます。
よろしければ、PCとマウスの情報(メーカー、モデル名など)をお教えいただけませんか?
ちなみに、私の環境は次のとおりです。
①、②・・・デュアルブート:(Lenovo)ThinkPad E540(ノートPC)
③・・・自作機(タワー型のメインPC)
マウスはどちらも(Microsoft)43U-00037(ワイヤレス、USB トランシーバ使用のスカルプト モバイル マウスという廉価なもの)以上です。
-
スクロールが戻らないようにするだけなら
class ListViewEx : ListView { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool KillTimer(IntPtr hWnd, IntPtr uIDEvent); protected override void WndProc(ref Message m) { const int WM_HSCROLL = 0x114; const int WM_VSCROLL = 0x115; const int WM_TIMER = 0x0113; const int WM_MOUSEWHEEL = 0x020A; switch (m.Msg) { case WM_TIMER: KillTimer(this.Handle, m.WParam); m.Result = IntPtr.Zero; return; } base.WndProc(ref m); } }
のようにWM_TIMERを捨てるといいみたい。
内部でタイマーを描画更新のトリガーに使って選択された項目にスクロールしてるのかな?
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
-
「ぱちもん」さん、
mp4 を拝見しました。
マウスホイールが回されたことは映像では分からないので、操作を理解/再現するのは難しいですが、意図は分かったつもりです。
もし最終的に実現したいことが(自動)スクロール防止なら、gekka さんのコードが参考になるのではないでしょうか?
(gekka さんのお名前は随所で拝見しています・・・<m(__)m>)
もしそうでないなら、最終的に何ができればよいのかをお教えいただければ幸いです。
以上です。
- 編集済み Ashidacchi 2016年2月3日 10:25
-