How to force background to redraw properly when visual glitching occurs
When i use the UI Ribbon with a project where the form is sizable and controls are sized/moved, visual glitching occurs.
Nothing I've tried fixes this.
I've tried AutoRedraw True/False, .Refresh with both.
I've tried RedrawWindow/UpdateWindow during the size event, suclassing with
Code:
Case WM_SIZE
Dim rc As RECT
GetClientRect hWnd, rc
InvalidateRect hWnd, rc, CTRUE
explicitly sending WM_ERASEBKRND, explicitly sending it then handling it with
Code:
Dim rcWin As RECT
GetClientRect hWnd, rcWin
FillRect wParam, rcWin, hbrWhite
'Exit Sub ' doesnt matter
and even the nuclear option,
Code:
Case WM_PAINT
Dim ps As PAINTSTRUCT
Dim hDC As LongPtr
hDC = BeginPaint(hWnd, ps)
Dim rcWin As RECT
GetClientRect hWnd, rcWin
FillRect hDC, rcWin, hbrWhite
EndPaint hWnd, ps
Exit Function
None of these gets rid of the trail of control glitch.
I'm really at a loss here and this effectively makes the ribbon not an option for any sizable form.
Attached is the VB6 UI demo with the sizable border and moving list to illustrate the problem. this is also a problem in twinBASIC; a version full of debug testing stuff for the new project can be found here.
Last edited by fafalone; Feb 7th, 2025 at 08:15 PM.
Re: How to force background to redraw properly when visual glitching occurs
In the tB version at least, setting AutoRedraw = False and HasDC = False seems to refresh OK....that's not a great solution (esp. if you need a DC), I was just mucking about and noticed that worked in case it provides any clues.
Re: How to force background to redraw properly when visual glitching occurs
Personally, I haven't found a way to open it in VB6 at all. Requires dependency As UIRibbonFramework, which is unclear where to get it from and how to connect it to VB6.
Re: How to force background to redraw properly when visual glitching occurs
Jon Johnson, Let me quote your own words: "This project was developed exclusively in twinBASIC; there's no VB6 version". And now I completely don't understand how you made it work in VB6. After all, your example is a VB6 project...
Re: How to force background to redraw properly when visual glitching occurs
Originally Posted by HackerVlad
Jon Johnson, Let me quote your own words: "This project was developed exclusively in twinBASIC; there's no VB6 version". And now I completely don't understand how you made it work in VB6. After all, your example is a VB6 project...
It requires oleexp.tlb as a reference. Nothing else besides that, except that to run from the IDE you must compile first, but a message box tells you that if you don't.
The zip attached to this thread is a VB6 project. It's a modified version of the original VB6 project.
It was originally developed in twinBASIC but to quote my own words:
This is a backport of the most basic Ribbon demo from my now 3-part series on using the Ribbon in twinBASIC. The code is virtually unchanged; just some minor syntax differences where I had taken advantage of some new language features, using oleexp.tlb for the interfaces and some APIs instead of tbShellLib, and locally defining some APIs. The resources are unchanged, and indeed I just used the .res file from that project. I wanted to at least bring the proof of concept basic one to VB6, but won't be backporting the others; tB is the future.
What only exists in twinBASIC are two other demos with much more sophisticated ribbons.
Last edited by fafalone; Feb 7th, 2025 at 04:54 PM.
Re: How to force background to redraw properly when visual glitching occurs
Oh, how difficult it is! Well, why didn't you immediately say that dependency As UIRibbonFramework is oleexp.tlb? I couldn't figure it out for half an hour...
Re: How to force background to redraw properly when visual glitching occurs
Now, after I connected the oleexp.tlb library, I managed to compile the project. However, the EXE file refused to run at startup due to an automatic runtime error.
Re: How to force background to redraw properly when visual glitching occurs
It does work in the IDE, you just have to compile it first because the only way to load a ribbon is to pass a module handle containing it as a resource. When you run from the IDE for API-based resource loads like that, App.hInstance or GetModuleHandle(0) gives you the handle of VB6.exe, which doesn't contain your project's .res file.
I added code that detects if you're running from the IDE and if so, instead passes the module handle for the compiled exe where the ribbon resources are.
Not sure why you'd get an error with the exe unless you're not on Windows 7 or higher.
Re: How to force background to redraw properly when visual glitching occurs
Originally Posted by fafalone
It does work in the IDE, you just have to compile it first because the only way to load a ribbon is to pass a module handle containing it as a resource. When you run from the IDE for API-based resource loads like that, App.hInstance or GetModuleHandle(0) gives you the handle of VB6.exe, which doesn't contain your project's .res file.
I added code that detects if you're running from the IDE and if so, instead passes the module handle for the compiled exe where the ribbon resources are.
Not sure why you'd get an error with the exe unless you're not on Windows 7 or higher.
Okay, thanks for the explanation, now I understand that the project should run in the IDE if there is an executable EXE file. So I press F5 in VB6 and was able to identify the location of the automation error (-2147467259).
Re: How to force background to redraw properly when visual glitching occurs
Originally Posted by HackerVlad
Okay, thanks for the explanation, now I understand that the project should run in the IDE if there is an executable EXE file. So I press F5 in VB6 and was able to identify the location of the automation error (-2147467259).
Re: How to force background to redraw properly when visual glitching occurs
At least two people have already reported the problem, on different systems... I suspect that you need to download an older version of the oleexp.tlb library to make it work, but I'm not sure.
Re: How to force background to redraw properly when visual glitching occurs
Sorry looks like I got things mixed up between different folders and old VBPs/res file.
Updated the zip should be ok now.
Also jpbro from tB Discord discovered that the glitching doesn't occur if the Form's HasDC property is changed to False... that's a big help as many apps don't need it and the much more complex ribbon demos work too still with it. But still would really like to solve it for the regular setting.
Last edited by fafalone; Feb 7th, 2025 at 08:21 PM.
Re: How to force background to redraw properly when visual glitching occurs
Be more careful next time, because I've spent a lot of time not understanding what the problem is. However, now, as I said in another topic, a new problem arises: hanging in an endless loop (but the automation error has disappeared), hanging occurs on the same line of code.
I suspect a problem with resources. Do you have SP6? I remember that VB6 SP5 has a bug related to resources.
Re: How to force background to redraw properly when visual glitching occurs
Can't reproduce a problem this time with a fresh download/extract/open. Yes I have SP6.
I tested running the exe on Windows 7 and it worked fine. Interestingly, no visual glitching, once again proving Windows 7 is superior to 10, still sad my new hardware won't let me run it outside a VM.
Re: How to force background to redraw properly when visual glitching occurs
Of course Windows 7 is much better, that's why I don't want to upgrade to 10. So if I had managed to launch your project, I would not have noticed any problems? But alas, it doesn't start for me. Probably because I have SP5.
Re: How to force background to redraw properly when visual glitching occurs
I ran Portable Microsoft Visual Basic 6.0 SP6 and compiled the project. Now it works in the EXE, but it doesn't work in the IDE. Error 445 in line code:
Code:
Private Sub IUIApplication_OnViewChanged(ByVal viewId As Long, ByVal typeID As UI_VIEWTYPE, ByVal view As IUnknown, ByVal verb As UI_VIEWVERB, ByVal uReasonCode As Long) 'Implements IUIApplication.OnViewChanged
Err.Raise E_NOTIMPL
End Sub
If there's resource file related bugs in VB6 SP5 and thats what you're using, very likely the problem. But yes there's no glitching on 7 apparently.
Yes, as we thought, this is a problem in SP5. Now I am convinced of this. You should probably make a note for this project that only works from version SP6. Or write a script, as I've always done before, which cuts off extra bytes for resources via CopyMemory. I used to be too lazy to upgrade to SP6, and I've known for a long time about this bug with loading resources to SP5, that SP5 inserts extra bytes, so I manually cut off these bytes via CopyMemory...
Although it will be impossible to compile an EXE in SP5 unless you manually change the resource file in a certain way...
Re: How to force background to redraw properly when visual glitching occurs
After I was able to compile the EXE in version SP6, after that, in version SP5, the IDE also worked. The most important thing was to compile the EXE correctly on SP6. It is very important. After that, the IDE SP5 also worked.
However, error 445 appears in the portable VB6 version. It turns out that it's enough to simply disable this line of code Err.Raise E_NOTIMPL and everything works.
Re: How to force background to redraw properly when visual glitching occurs
It's best to even completely remove this code altogether so that it works for sure in all VB6 builds. Thus, it will also work in the portable version now.
Code:
Private Sub IUIApplication_OnViewChanged(ByVal viewId As Long, ByVal typeID As UI_VIEWTYPE, ByVal view As IUnknown, ByVal verb As UI_VIEWVERB, ByVal uReasonCode As Long) 'Implements IUIApplication.OnViewChanged
Err.Raise E_NOTIMPL
End Sub
Re: How to force background to redraw properly when visual glitching occurs
To avoid continual redrawing issues occurring when resizing a form, instead I subclassed it and looked for WM_EXITSIZEMOVE message. Resizing the form only then when the drag is finally complete. It saved CPU usage as my resize event resizes/places all controls in a new position dynamically according to form size, so the resize event caused a lot of graphical glitches during the drag.
Resizing and repainting only when the form resize is complete is a departure from normal VB6 standards but it is an option and it doesn't happen often, so I don't worry about it. In your case I think it would remove your glitching as the resize of the combo box would only happen once.
Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.
By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.
Re: How to force background to redraw properly when visual glitching occurs
Wayne found an alternate solution to HasDC = False.
All the ribbon samples don't use the CS_OWNDC window class style while VB/tB does if HasDC=True so that's the trigger; Wayne identified that actual cause as for some reason the clipping region being changed.
Adding this to the end of Form_Load eliminates the glitching without requiring HasDC to be False:
Code:
Dim rgn As LongPtr
rgn = CreateRectRgn(0, 0, 8000, 8000)
Call SelectClipRgn(Me.hDC, rgn)
though there may be issues if AutoRedraw=True then...but progress.
Re: How to force background to redraw properly when visual glitching occurs
So, I have some important news regarding your initial topic that the graphics are buggy. Yes, I also have buggy graphics even in Windows 7, but only if Windows Aero is enabled. If we disable the desktop composition at startup, then the graphics are no longer buggy.
Re: How to force background to redraw properly when visual glitching occurs
Originally Posted by fafalone
Wayne found an alternate solution to HasDC = False.
All the ribbon samples don't use the CS_OWNDC window class style while VB/tB does if HasDC=True so that's the trigger; Wayne identified that actual cause as for some reason the clipping region being changed.
Adding this to the end of Form_Load eliminates the glitching without requiring HasDC to be False:
Code:
Dim rgn As LongPtr
rgn = CreateRectRgn(0, 0, 8000, 8000)
Call SelectClipRgn(Me.hDC, rgn)
though there may be issues if AutoRedraw=True then...but progress.
And adding these lines of code solves the problem only by half, there are fewer glitches, but there are still some. It solves the problem 100% only if you check disable Windows desktop composition in the properties of the EXE file.
Re: How to force background to redraw properly when visual glitching occurs
Think for yourself, because the graphics in the VB6 form designer are also buggy when we pull buttons on the form, if we are in the properties vb6.exe we will not check the box "Disable Windows desktop composition".
Re: How to force background to redraw properly when visual glitching occurs
Originally Posted by HackerVlad
And adding these lines of code solves the problem only by half, there are fewer glitches, but there are still some. It solves the problem 100% only if you check disable Windows desktop composition in the properties of the EXE file.
I see... couldn't test that since VirtualBox has **** graphics support and Aero can't be used in Win7. Before you tested using that code, you changed HasDC back to True right?
Does the HasDC=False option (used without the additional code in #24) completely fix it?
Re: How to force background to redraw properly when visual glitching occurs
I just didn't even know about the existence of such a property as HasDC. In fact, no additional code is needed, no matter what properties you set for HasDC or for AutoRedraw, if you disable Windows Aero, it will always work without glitches in Windows 7.
Re: How to force background to redraw properly when visual glitching occurs
Originally Posted by HackerVlad
I just didn't even know about the existence of such a property as HasDC. In fact, no additional code is needed, no matter what properties you set for HasDC or for AutoRedraw, if you disable Windows Aero, it will always work without glitches in Windows 7.
Yes but getting to use Aero is one of the nicest things about sticking with 7, so I'd want it to work there.
Re: How to force background to redraw properly when visual glitching occurs
Personally, I think that the whole problem is in Windows Aero, but it's also worth noting that standard Windows applications such as MSPaint and WordPad work quite well even with Windows Aero, you just need to look at their source codes, if they are somewhere, to find out how they managed to do it. it wasn't buggy.
Re: How to force background to redraw properly when visual glitching occurs
Okay, it turned out to be much simpler:
Code:
Private Sub Form_Resize()
List1.Top = ((Form1.Height / Screen.TwipsPerPixelY) + GetRibbonHeight(pFramework)) - List1.Height - 100
List1.Refresh ' Get rid of the redrawing glitch
End Sub
In this case, it is advisable to set the ListBox Appearance property to Flat.
Re: How to force background to redraw properly when visual glitching occurs
I just noticed another glitch, my method turned out to be not very good, if there is a scrollbar in the listbox, then it will be buggy. It turns out that you additionally need to find the scrollbar window inside the listbox (if there is one) and manually redraw the scrollbar in the same way.
Re: How to force background to redraw properly when visual glitching occurs
Originally Posted by HackerVlad
I just noticed another glitch, my method turned out to be not very good, if there is a scrollbar in the listbox, then it will be buggy. It turns out that you additionally need to find the scrollbar window inside the listbox (if there is one) and manually redraw the scrollbar in the same way.
Just using .Refresh doesn't fix the glitching on Windows 10; one of the first things I tried.
Could you tell me if changing the Form's HasDC property to False (and leaving AutoRedraw = False, and without the SelectClipRgn code or .Refresh) fixes the glitching on Windows 7 w/ Aero enabled? That's really shaping up to be the best solution; that's how MSPaint and WordPad are configured (the HasDC option controls whether the CS_OWNDC style is set on the window class). As far as I can tell from Raymond Chen's explanation, changing that property would only cause problems if a) You're doing a bunch of manual API drawing directly to the Form DC (so PictureBoxes and UserControls aren't affected), and also b) Make an assumption that things you select into the DC will still be there after you release it and then do more drawing.
Re: How to force background to redraw properly when visual glitching occurs
Originally Posted by fafalone
Could you tell me if changing the Form's HasDC property to False (and leaving AutoRedraw = False, and without the SelectClipRgn code or .Refresh) fixes the glitching on Windows 7 w/ Aero enabled?
Yes, this will fix the problem. But not to the end. The listbox won't be so buggy anymore, the listbox graphics won't be buggy when the ribbon disappears from above! List1.Refresh must also be added to completely solve the problem when Windows Aero is enabled.