?
Solved

Flickering scrollbars

Posted on 2012-08-22
7
Medium Priority
?
1,498 Views
Last Modified: 2016-11-25
I have a simple parent panel stacked with child panels that are the same width as the parent panel (think vertical list. One of these child panels is indicated as the 'selected Item' by reversing its color. The parent panel exposes SelectNext and SelectPrev methods so that the selected item can be changed. There are more child panels than the parent panel can expose, at once so I use VerticalScroll.Value to scroll the chosen panel into view. Scollbars are both disabled.

It works well except when Prev or Next is triggered, quite often both the horizontal and vertical scrollbars flash into view for a split second before disappearing.  I have tried everything I can think of to make it stop;

public class ItemPanel : Panel
    {
        [DllImport("user32.dll")]
        static extern bool ShowScrollBar(IntPtr hWnd, int wBar, bool bShow);

        
        public ItemPanel()
        {
            this.DoubleBuffered = true;
            SetStyle(ControlStyles.OptimizedDoubleBuffer |
                        ControlStyles.UserPaint |
                        ControlStyles.AllPaintingInWmPaint, true);
            this.UpdateStyles();
            this.BackColor = Color.Black;

            ShowScrollBar(this.Handle, 0, false);

            this.AutoScroll = false;
            this.HScroll = false;
            this.VScroll = false;
            this.VerticalScroll.Visible = false;
            this.HorizontalScroll.Visible = false;
        }

Open in new window


Can anyone tell me a way to make those panel scrollbars disappear and stay disappeared?

Thank you for your time,
Dave
0
Comment
Question by:davecove
  • 3
  • 3
7 Comments
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 38320606
"It works well except when Prev or Next is triggered, quite often both the horizontal and vertical scrollbars flash into view for a split second before disappearing."

What kind of code is in those button handlers?...
0
 

Author Comment

by:davecove
ID: 38321043
This kicks things off by deciding which Item should be selected Next

public void SelectNextItem()
        {
            int SelectedItemKey;

            // get the SelectedItem's index in the dictionary, decrement it and take care of wrapping and the case where SelectItem hasn't been set yet 
            try
            {
                SelectedItemKey = MenuItems.Where(m => m.Value == SelectedItem).First().Key;
                SelectedItemKey += 1;
            }
            catch
            {
                SelectedItemKey = 0;
            }

            if (SelectedItemKey >= MenuItems.Count)
                SelectedItemKey = 0;

            //set the new SelectedItem and see if it is visible
            SelectedItem = MenuItems[SelectedItemKey];
            if (!this.ClientRectangle.Contains(SelectedItem.Bounds))
            {
                //if not, scroll so that it is visible
                this.VerticalScroll.Value = (this.ScrollToControl(SelectedItem).Y == 0) ? 1 : Math.Abs(this.ScrollToControl(SelectedItem).Y);
            }
            Redraw();
        }

Open in new window


The parent panel displays some up/down arrow bars above and below this scroll panel if there are any items scrolled off the top or bottom of the panel. The arrow bars come and go depending on if they are needed or not (the scroll panel tells the parent if they are needed), which potentially causes the scroll panel to need to change size.

private void Redraw()
        {
            //figure out if items will all fit in allowed space
            VerticalScroll.Maximum = RequiredViewHeight;
            if (RequiredViewHeight < parentPanel.AvailableViewHeight)
            {
                Rectangle NewBounds = GetNewBounds();
                NewBounds.Height = RequiredViewHeight;
                if (NewBounds != this.Bounds)
                {
                    this.Bounds = NewBounds;
                    parentPanel.FitToItemPanel();
                }
            }
            else
            {  //if they won't fit
                Rectangle NewBounds = GetNewBounds();
                if (NewBounds != this.Bounds)
                {
                    this.MaximumSize = NewBounds.Size;
                    this.Bounds = NewBounds;
                }

                //we might be in the condition where the last item is visible, but not againt the new bottom
                Rectangle LastItemBounds = items.ElementAt(items.Count - 1).Bounds;
                if (this.ClientRectangle.Contains(LastItemBounds))
                {
                    if (Math.Abs(this.AutoScrollPosition.Y) + parentPanel.ItemHeight != this.DisplayRectangle.Height)
                        VerticalScroll.Value = (SelectedItem.Number * parentPanel.ItemHeight);
                }
            }    
        }

Open in new window


All of this works pretty well until the scroll panel gets to the situation where it would normally display scroll bars. That is, let's say the scroll panel had 5 items but was sized so that only 2 were visible. When the panel is first shown, and the first item is selected, all is well. If the next item is selected, all is well. But if the third item is selected, the panel has to scroll to show it. Normally scroll bars magically appear, and they do in this case as well, but only for an instant. Continuing on to items 4 and 5 results in the same quick on/off behavior of the scroll bar. I am trying to stop that flicker.

Thank you for your time,
Dave
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 38321261
Hmm...I think I'd have to play with a pared down version to figure it out.  =\

Is it possible to upload a bare bones project somewhere?
0
Veeam Disaster Recovery in Microsoft Azure

Veeam PN for Microsoft Azure is a FREE solution designed to simplify and automate the setup of a DR site in Microsoft Azure using lightweight software-defined networking. It reduces the complexity of VPN deployments and is designed for businesses of ALL sizes.

 

Author Comment

by:davecove
ID: 38321355
Sure... this is being developed as a control, and I have an 'exerciser' app that goes with it to put it thru its paces outside of the main project.  I'll post a temp dropbox link when I get them up there.

Dave
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 2000 total points
ID: 38322160
This is more of a "band-aid" fix in my opinion, but it works...
    public partial class ScrollPanel : UserControl
    {

        // ... rest of the class code ...

        private const int WM_SETREDRAW = 11; 

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, Int32 msg, Int32 wParam, Int32 lParam);

        public void SelectPrevItem()
        {
            SendMessage(this.Handle, WM_SETREDRAW, Convert.ToInt32(false), 0);  // Turn OFF updates
            itemPanel.SelectPrevItem();
            SendMessage(this.Handle, WM_SETREDRAW, Convert.ToInt32(true), 0); // Turn ON updates
            this.Refresh();
        }

        public void SelectNextItem()
        {
            SendMessage(this.Handle, WM_SETREDRAW, Convert.ToInt32(false), 0);  // Turn OFF updates
            itemPanel.SelectNextItem();
            SendMessage(this.Handle, WM_SETREDRAW, Convert.ToInt32(true), 0); // Turn ON updates
            this.Refresh();
        }

    }

Open in new window


Calling Refresh() is necessary, but it causes flicker on the menu and arrows.  To fix that, also set double buffering on LabelBar and ArrowBar (just like you did with the other classes).
0
 

Author Closing Comment

by:davecove
ID: 38322588
Beautiful!  That's a 5-star solve!

Dave
0
 

Expert Comment

by:Vlad Voiculescu
ID: 41901633
Based on original author snipped code, i slightly modified the code to work for TableLayoutPanel Horizontal Scrolling (without flickering):
   
Public Class ItemTableLayoutPanel
        Inherits TableLayoutPanel
        <DllImport("user32.dll")> _
        Private Shared Function ShowScrollBar(hWnd As IntPtr, wBar As Integer, bShow As Boolean) As Boolean
        End Function


        Public Sub New()
            Me.DoubleBuffered = True
            SetStyle(ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint, True)
            Me.UpdateStyles()
            'Me.BackColor = Color.Black

         
            Me.AutoScroll = True
            Me.HScroll = False
            Me.VScroll = False
            Me.VerticalScroll.Visible = False
            Me.HorizontalScroll.Visible = False
            ShowScrollBar(Me.Handle, 3, False)

        End Sub
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            ShowScrollBar(Me.Handle, CInt(ScrollBarDirection.SB_BOTH), False)
            MyBase.WndProc(m)
        End Sub
    End Class
End Class

Open in new window

0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Simulator games are perfect for generating sample realistic data streams, especially for learning data analysis. It is even useful for demoing offerings such as Azure stream analytics, PowerBI etc.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Suggested Courses

840 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question