-1

As the title says.

History: To reduce flicker in my ListBox with DrawMode.OwnerDrawFixed and a custom OnDrawItem() I used the subclassing example from this page: http://yacsharpblog.blogspot.no/2008/07/listbox-flicker.html which uses SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);

It works well except for one thing: When I scroll sideways to see long strings the OnDrawItem() does not seem to understand that it should draw with an offset. It seems like the horizontal scroll offset is lost somewhere on the way and the area OnPaint() has been called to fill in gets filled in by my OnDrawItem() as if the ListBox was not scrolled sideways at all.

Please note: If I disable ControlStyles.UserPaint and let the system call OnDrawItem() directly, it works fine and I can scroll side-ways normally. But it flickers and is too slow to be useful. I need the custom OnPaint() and the ControlStyles.OptimizedDoubleBuffer to make it smooth.

Can someone tell me where/how to get the horizontal scroll position, or what needs to be done to make this happen automatically, like when the system calls OnDrawItem?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
  • Tinkering with UserPaint for these built-in native Windows controls is a hack that never stops causing trouble. It is also *very* unclear how you even got the scrollbars working at all. There's just no point to this, derive from ListView instead, set View = List and DoubleBuffered to *true* in the constructor. – Hans Passant Jun 19 '15 at 08:43
  • Well, first I have to admit that I'm pretty new to C#.NET. Tthe scroll bars are no problem. The vertical adds itself based on number of items. The horizontal adds itself when I set HorizontalExtent to be wider than the control. – Daniel Westerberg Jun 19 '15 at 12:52
  • I was looking at the ListView at first, but it seemed totally overkill for this purpose. I just need a plain fixed-size-element list with scrollbars and custom draw routine, so I went for the ListBox. – Daniel Westerberg Jun 19 '15 at 13:14
  • Come on! -1 on the *question*?? :-( Give me some useful information instead of being arrogant. @Hans: If you don't know how to set up scrollbars for a ListBox you may not be able to help here at all. ListView.View=List; is completely useless lining up items in columns! I have 20k+ lines that range from 0 to a few kB in length. This tool is for displaying large to huge log files with custom highlight colors. – Daniel Westerberg Jun 22 '15 at 07:36

1 Answers1

0

I found a solution here: http://www.codeproject.com/Articles/7554/Getting-Scroll-Events-for-a-Listbox

That is kind of a hack, since the ListBox simply doesn't expose any properties around the scrollbar, but it works. I used a simplified version where I extract the data directly from msg.WParam without calling any external dll function. OnPaint will be called immediately after anyway, so no reason messing about sending extra scroll events.

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

This is an internal tool, and it works for me. Solved.