locked
Panel control is repeating to paint RRS feed

  • Question

  • I'm using a Panel control to draw graphs.

    The Panel is called using 

    1:      Panel1.Refresh()
    

    from 

       Sub Add_plots()
    

    It works fine in most of the computers with Win 7 or Win 10 OS. But in one Win 7 PC, it keeps repeating within Sub Panel_Paint(...). When I debug it line-by-line, I found that after End Sub line, it goes to Sub Panel_Paint(...) again.

    Does anyone know the reason? How should I avoid it?

     Thank you very much!

       Private Sub Panel_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
    
       End Sub
    

       Private Sub Panel_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
            If Fig_Title Is Nothing Or m_PaintNumber = 0 Or m_PaintXP = m_PaintNumber Then
                Exit Sub
            End If
    
            On Error Resume Next
            Dim s As String = IIf(m_PageNumber > Max_Pages, "p", "s")
    
            If m_PaintNumber > Max_Pages Then m_PaintNumber = Max_Pages
            Call Paint_Size()
            Dim Plt As String = IIf(m_PaintNumber > 0, Plots(m_PaintNumber - 1), Nothing)
    
            PaintRec(0)
            Select Case PltsType(m_PaintNumber)
                Case "SA"
                    DrawSA(RctL, RctR, Plt, e, s)
     
            End Select
            If ED_ver Then AddEDmsg(0, 0, e)
            If Not Registered Then Text_Path(PaintRegn, e)
            If Val(myOS.MajorVersion & myOS.MinorVersion) < 61 Then m_PaintXP = m_PaintNumber
            '        m_PaintXP = m_PaintNumber
        End Sub
    
       Sub Add_plots()
            If m_PaintNumber = 0 Then ResetPanelBG()
    
            If PlotExistOrNot() Then GoTo 1
    
            Max_Pages += 1
            ReDim Preserve Fig_Title(Max_Pages), PltsType(Max_Pages)
            ReDim Preserve Encl(Max_Pages)
    
            Fig_Title(Max_Pages) = PrjInfo.PlotTitle
            PltsType(Max_Pages) = PlotType
            Encl(Max_Pages) = IIf(Encl_prefix = "" And Encl_No = -1, " ", Encl_prefix & (Max_Pages + Encl_No).ToString)
            ReDim Preserve Plots(Max_Pages - 1)
            Plots(Max_Pages - 1) = Max_Pages.ToString & "|" & PrjInfo.PlotTitle & "|" & _
                                   Encl(Max_Pages) & "|" & ThisFigChannel & "|" & _
                                   Page_Orintation & "|" & PlotType & "|" & CorLgd
            m_PaintNumber = Max_Pages
    
    1:      Panel1.Refresh()
        End Sub
    


    Wednesday, June 1, 2016 7:01 PM

Answers

  • Good one Reed.

    Yes remove all error handling so you have a better change to see where the error is.

    Make sure you have Visual Studio project set to break on errors. ie VS 2015 menu - DEBUG - WINDOWS - EXCEPTIONS be sure Common Language Runtime Exceptions has all the items checked so VS will stop on those errors.

    Wednesday, June 1, 2016 7:38 PM

All replies

  • Well, the problem may not be as it seems... when you are debugging, switching to the IDE window during a Break causes windows to change focused application.  When you switch focus back to the program (exit debugging) that brings the program window back to the foreground and causes it to repaint.  So the "double painting" may just be a side effect of the debugging session.

    I would suggest that you get rid of the line of code:

    On Error Resume Next

    This is bad in .Net.  It really only exists for backward compatibility with VB6 programs being migrated to .Net.  A new .Net program should always use a Try-Catch block to handle errors.  The problem is that there may be some other error occurring in your paint routine and the On Error Resume Next is hiding it from you.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Wednesday, June 1, 2016 7:23 PM
  • "When I debug it line-by-line, I found that after End Sub line, it goes to Sub Panel_Paint(...) again."

    When you are debugging by stopping execution at a break point VS will often keep calling the paint event. But when running from .exe it wont behave the same.

    How do you know that "But in one Win 7 PC, it keeps repeating within Sub Panel_Paint(...). "

    is happening?

    Is there a counter or something? How do you know its only on one pc etc?

    What does this do:

        Call Paint_Size()
        PaintRec(0)
        DrawSA(RctL, RctR, Plt, e, s)

    Does any of that resize the panel or form? Trigger a control event that then repaints?


    Wednesday, June 1, 2016 7:23 PM
  • PS stop execution of the code in the panel paint event one line at a time and then see where the problem starts or stops.

    ie comment out the code or put EXIT SUB at the first line, run, see if problem is gone. If its gone then move the EXIT SUB down the code one line at a time until it starts. If you still have the problem with no code in the sub then it is something else.

    Wednesday, June 1, 2016 7:30 PM
  • Thank you for your response.

    The program runs fine on other PCs. Yesterday, my guy installed the program in a Win 7 PC and found a dialog (called after refresh Panel) does not disappear. I then installed VB 2010 Express into that PC and debugged the source code and found it's repeating inside the Panel sub.    

    Wednesday, June 1, 2016 7:37 PM
  • Good one Reed.

    Yes remove all error handling so you have a better change to see where the error is.

    Make sure you have Visual Studio project set to break on errors. ie VS 2015 menu - DEBUG - WINDOWS - EXCEPTIONS be sure Common Language Runtime Exceptions has all the items checked so VS will stop on those errors.

    Wednesday, June 1, 2016 7:38 PM
  • Thank you for your suggestion. I'll remove        On Error Resume Next and use  Try-Catch block to check it.
    Wednesday, June 1, 2016 7:38 PM
  • Thank you for your suggestion. I'll remove        On Error Resume Next and use  Try-Catch block to check it.

    Don't put in try catch until you find the error. Then fix the error. Then add the error handling, if its needed for some reason.
    Wednesday, June 1, 2016 7:40 PM
  • Thank you.

    I use Try-Catch to check the same data on my PC. There is no error. I'll check on that problem PC.

    Wednesday, June 1, 2016 7:52 PM
  • GoTo uncessary in current day programming really. Kind of a bad habit once it becomes a habit. Perhaps you can change the Sub Add_plots to something like below (see line "If PlotExistOrNot() Then Panel1.Refresh : Exit Sub") and remove the GoTo and the line number "1:".

    I don't know the issue though. The IfPlotExistOrNot, which I guess is a function, code I don't see though or understand in the code you display.

    Also is the Win7 machine that faults the same as the other Win7 machines? Same OS? All x86 or x64? All have same .Net Frameworks installed on them? All up to date with updates? All have same .Dlls used by your app?

       Sub Add_plots()
            If m_PaintNumber = 0 Then ResetPanelBG()
    
            If PlotExistOrNot() Then Panel1.Refresh : Exit Sub
    
            Max_Pages += 1
            ReDim Preserve Fig_Title(Max_Pages), PltsType(Max_Pages)
            ReDim Preserve Encl(Max_Pages)
    
            Fig_Title(Max_Pages) = PrjInfo.PlotTitle
            PltsType(Max_Pages) = PlotType
            Encl(Max_Pages) = IIf(Encl_prefix = "" And Encl_No = -1, " ", Encl_prefix & (Max_Pages + Encl_No).ToString)
            ReDim Preserve Plots(Max_Pages - 1)
            Plots(Max_Pages - 1) = Max_Pages.ToString & "|" & PrjInfo.PlotTitle & "|" & _
                                   Encl(Max_Pages) & "|" & ThisFigChannel & "|" & _
                                   Page_Orintation & "|" & PlotType & "|" & CorLgd
            m_PaintNumber = Max_Pages
            Panel1.Refresh()
        End Sub


    La vida loca

    Wednesday, June 1, 2016 10:32 PM
  • Thank you for your suggestion, Mr. Monkeyboy<abbr class="affil" style="border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;margin:0px;outline:0px;padding:0px;display:inline-block;vertical-align:top;color:#000000;"></abbr> .

    I'll make changes as you suggested.

    My PC (used to develop this program) is with 64 bit Win 7 Pro, SP1 and .NET Framework 4, 4.5, 4.5.1, 4.5.2, 4.6 & 4.6.1 installed. The problem PC is of the same OS but only .NET Framework 4 & 4.6.1 installed.

    The program reference .NET Framework 4.0.0.0

    Wednesday, June 1, 2016 11:10 PM
  • Thank you for your suggestion, Mr. Monkeyboy<abbr class="affil" style="border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;margin:0px;outline:0px;padding:0px;display:inline-block;vertical-align:top;color:#000000;"></abbr> .

    I'll make changes as you suggested.

    My PC (used to develop this program) is with 64 bit Win 7 Pro, SP1 and .NET Framework 4, 4.5, 4.5.1, 4.5.2, 4.6 & 4.6.1 installed. The problem PC is of the same OS but only .NET Framework 4 & 4.6.1 installed.

    The program reference .NET Framework 4.0.0.0


    Well I would check the other Win7 PC's too. Same OS isn't specific to whether the OS is x86 or x64. You should verify if the OS is 32 bit x86 or 64bit x64. And perhaps which CPU it has compared to other systems. Also what .Net Framework is your app compiled to? I figure that 4.6.1 may be a .Net Framework that is a multi targeting pack perhaps.

    La vida loca

    Thursday, June 2, 2016 2:00 AM
  • Paint events fire many more times than you may realise. For example, the form repaints 4 times on start up. Everytime you move something, or change focus, or make a change on some control, there is another paint event. Same with Panels.

    Suggest you use a bitmap to plot drawings upon. sequenced by some sort of timer. Then simply have this bitmap cast in a paint event. That way it does not matter if there a 100 paint events fired in one second - or only 10, whatever state your bitmap is in - it will be shown as thus.

    You still need to call Refresh() or Invalidate() when you make sequenced changes to the bitmap. Normally, sequenced animation should be called with Invalidate(), whereas mouse driven or scrollbar driven repaints should be called with Refresh().


    BumperSticker: Amateurs built the Ark, Professionals built the Titanic

    Thursday, June 2, 2016 5:05 AM