OnDrawItem не учитывает положение горизонтальной прокрутки при вызове из OnPaint
Как видно из названия.
История: чтобы уменьшить мерцание в моем ListBox с DrawMode.OwnerDrawFixed
и пользовательский OnDrawItem(), который я использовал пример подкласса с этой страницы: http://yacsharpblog.blogspot.no/2008/07/listbox-flicker.html который используетSetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
Это работает хорошо, за исключением одной вещи: когда я прокручиваю вбок, чтобы увидеть длинные строки, OnDrawItem(), кажется, не понимает, что он должен рисовать со смещением. Кажется, что горизонтальное смещение прокрутки теряется где-то на пути, и область OnPaint(), вызываемая для заполнения, заполняется моим OnDrawItem(), как если бы ListBox вообще не прокручивался вбок.
Обратите внимание: если я отключу ControlStyles.UserPaint
и пусть системный вызов OnDrawItem() напрямую, он работает нормально, и я могу нормально прокручивать в сторону. Но это мерцает и слишком медленно, чтобы быть полезным. Мне нужен пользовательский OnPaint() и ControlStyles.OptimizedDoubleBuffer
чтобы сделать это гладко.
Может кто-нибудь сказать мне, где / как получить горизонтальную позицию прокрутки, или что нужно сделать, чтобы это произошло автоматически, например, когда система вызывает OnDrawItem?
1 ответ
Я нашел решение здесь: http://www.codeproject.com/Articles/7554/Getting-Scroll-Events-for-a-Listbox
Это своего рода хак, поскольку ListBox просто не предоставляет никаких свойств вокруг полосы прокрутки, но работает. Я использовал упрощенную версию, где я извлекаю данные непосредственно из msg.WParam без вызова какой-либо внешней функции DLL. В любом случае OnPaint будет вызываться сразу же, поэтому нет причин возиться с пересылкой дополнительных событий прокрутки.
private int mHScroll; protected override void WndProc(ref System.Windows.Forms.Message msg) { if (msg.Msg == WM_HSCROLL) { switch ((int)msg.WParam & 0xffff) { case SB_PAGELEFT: mHScroll = Math.Max(0, mHScroll - ClientSize.Width * 2 / 3); //A page is 2/3 the width. break; case SB_PAGERIGHT: mHScroll = Math.Min(HorizontalExtent, mHScroll + ClientSize.Width * 2 / 3); break; case SB_THUMBPOSITION: case SB_THUMBTRACK: mHScroll = ((int)msg.WParam >> 16) & 0xffff; break; } } base.WndProc(ref msg); }
Это внутренний инструмент, и он работает для меня. Решаемые.