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);
}

Это внутренний инструмент, и он работает для меня. Решаемые.

Другие вопросы по тегам