self.ScreenshotWindowMBS returns nil

I’ve been trying to reduce windows flicker.
One option I am exploring is to set the window backdrop to be a screenshot of the window at key points, such as on deactivate or when changing view styles and the like.

(I’ve had to revert to Xojo 2015 again after a disasterous attempt to use a Direct2D Xojo)

My code can use two methods:
Either an API call

        Dim screenCap As Picture = New Picture(self.Width, self.Height,32)
        Dim HWND As Integer 
        hwnd = self.handle
        Dim SourceDC As Integer = GetDC(HWND)
        Dim DestDC As Integer = screenCap.Graphics.Handle(screenCap.Graphics.HandleTypeHDC)
        Call BitBlt(DestDC, 0, 0, self.Width, self.Height, SourceDC, 0,0, SRCCOPY Or CAPTUREBLT)
        Call ReleaseDC(HWND, SourceDC)

or

self.ScreenshotWindowMBS

The API call actually causes the screen to flash while it happens.
I had high hopes of the MBS call, but it always gives me nil
I’ve tried a few sets of plugin versions, the current set I use is dated 2020

Before I spend hours changing the plugins and hoping that those don’t introduce unexpected side effects:

Does self.ScreenshotWindowMBS work for anyone else?

Sorry, but ScreenshotWindowMBS is macOS only.

ScreenshotRectMBS seems to work, but needs coordinates in Pixel:

dim scale as Double = screen(0).ScaleFactor

dim p as Picture = ScreenshotRectMBS(self.left * scale, self.top * scale, self.Width * scale, self.Height * scale)

p.VerticalResolution = scale * 72
p.HorizontalResolution = scale * 72

canvas1.Backdrop = p

Thanks Christian… I just discovered ScreenshotRectMBS myself.
Sadly, .scalefactor is absent in Xojo 2015, so I get an image that contains (probably) 1/4 of the picture I really want, at the size that I do.

WindowsDisplayMBS class may have this information.

And of course we would appreciate if you could update MBS Plugins to a current one.
If I look right, your license is good for current release, which should work for Xojo 2015 on Windows.

I’ll investigate that, thank you.
My license is good for current - but I’m always wary of changing something that I know works…:wink:
(I use the current set for my iOS work)

Sadly, I was hoping that there would be a distinction between LogPixelsX and WidthDPI
but WidthDPI and HeightDPI don’t return anything useful.
I know that asking for something the ‘same size’ as my window, gets me the right number of pixels, but not the entire window. It must be scale factor/retina, something.
If I could work out by how much (reliably, not just on my machine), I could swing it.

LogPixelsX is what you look for, so 96 dpi.

I’ll fix the HeightDPI, which is a division by zero error as the computer doesn’t know the physical size of the screen!

2 Likes

If this is GDI+ Xojo flicker can you tell me where you get it and I can possibly give you some pointers on how to reduce it.

Any time the screen is activated, or restored from minimised, the whole window goes briefly white, then my controls appear
They are all set to EraseBackground = false, and shouldn’t do that.

The white is ‘empty window’, and one solution would be setting a backdrop from a screenshot.
(But oddly, taking a screenshot with the API solution, itself, causes a brief flash like taking a photo.
So pointless)

Flicker when restoring a window is sort of expected but I don’t think i’ve seen it when an application has been activated.

Do you capture and process any of the windows messages such as WM_ERASEBACKGROUND?

Hi.
No, nothing like that. I catch MOUSEMOVE and END_SESSION

Can you create a small sample project that shows the issues?

If it were a small project, I probably wouldn’t have the problem.
The main screen is pretty much covered edge to edge with a variety of controls… listboxes, various scrollbars, several (non overlapping) canvases…

I guess I will just buckle down and live with it. After all, I have reluctantly done so for many years.

It sounds like Windows is erasing the window background before redrawing.

You could try consuming the WM_ERASEBACKGROUND windows message.

1 Like

Interesting.
If I do that, the bits of window that aren’t covered with controls show as black… LOL

You’re currently looking for the MBS solution, with ScreenshotRectMBS. Hope it’s not equivalent as the API solution and will flicker the same!

That is correct as you have prevented all background painting from occurring by consuming the event. In one of our windows we just fill the relevant areas.

Another technique is to use the Win32 SetWindowLong API to enable WS_CLIPCHILDREN on the parent (window). This excludes the areas occupied by controls when a redraw is triggered. However, you are then responsible for triggering a redraw of the controls yourself via the Xojo Paint event on the window.