スクロールバーを使用して、多くの行を含む大きなデータを表示します(背景については、前の質問:MFC:スクロールのOnInitialUpdate()の時間コストを削減する方法を参照してください)。
スクロール機能は、(1)矢印ボタンをクリックする、(2)スクロールシャフトをクリックする、または(3)マウスホイールを回転させる場合に正常に機能します。コンテンツは正しく上下に移動します。しかし、スクロールサムをドラッグすると、距離が非常に小さい場合を除いて、実際には期待どおりに動作しません。
少し前にドラッグすると、後ろにジャンプしたり、最初までジャンプしたりすることがあります。マウスを離しても止まることはなく、親指を最後のレコードまでドラッグすることもできません。
よく見ると、「GetClipBox(...)」は正しいデータを返さないようです。たとえば、最後までドラッグすると、この関数はrect.topがゼロに等しいことを返します。描画するレコードのセットを計算するために戻り値に依存しているため、残りは台無しになっています。
最小限の再現可能な例は、https://138.197.210.223/test/My.tar.gzからアクセスできます。テストするときは、親指を最後までドラッグして効果を高めます。
これは、WM_VSCROLLメッセージの16ビット制限によるものです。実際には、制限は32767であり、ドキュメントに記載されている65535ではありません。かなり前のプロジェクトで同じ問題がありました。
回避策はWM_VSCROLL
、GetScrollInfo()
代わりに関数によって返される32ビット値を使用するようにメッセージ処理を変更することです。オーバーライドOnVScroll()
(クラスビューに移動し、ビューを選択してWM_VSCROLL
メッセージハンドラーを追加します):
void CMyView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// Workaround the 16-bit limitation
if (nSBCode == SB_THUMBPOSITION || nSBCode == SB_THUMBTRACK)
{
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
::GetScrollInfo(m_hWnd, SB_VERT, &si);
// Set nPos to the 32-bit value
nPos = si.nTrackPos;
}
CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
}
これで問題が解決するはずです。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加