microsoft / WindowsCompositionSamples

The Windows Composition Samples have moved here: https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/SceneGraph
https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/SceneGraph
MIT License
1.12k stars 287 forks source link

The first time I get the visual of a UIElement the size is always 0. #333

Closed groovykool closed 5 months ago

groovykool commented 5 years ago

Issue Type

[x ] Bug Report

Current Behavior

The first time I get the visual of a UIElement the size is always 0. If I get the visual a second time in a separate method call then the size is correct. And then it is correct on any following calls. The enclosing method must finish. Getting the visual twice in the same method doesn't work size is 0.
private void Getvisual() { string logtext = ""; Visual Vis = ElementCompositionPreview.GetElementVisual(pp); logtext += $"[Page pp] Visual Size{Vis.Size.ToString()}" + "\n"; tt.Text = logtext; }

Expected Behavior

I expect the visual size to be correct the first time I get the visual using ElementCompositionPreview.GetElementVisual(xxx)

Steps to Reproduce (for bugs)

Run the above method from an event method. First time size is 0. Second time size is correct. And then always correct?

Your Environment

daneuber commented 5 years ago

@groovykool Thanks for reaching out. It's possible the elements have not fully loaded yet when you're trying to access the size. In your repro steps you mention calling your GetVisual method from an 'event method.' Have you tried calling your it in a page Loaded event to ensure loading has completed?

groovykool commented 5 years ago

Yes I tried calling it from page loaded event. Size is 0. If I then call a second time from another event like a button click, It is correct.

groovykool commented 5 years ago

Here is an example repo. https://github.com/groovykool/UIElementVisual.git

JohnnyWestlake commented 5 years ago

@groovykool the point is it will always be 0 immediately after creation. The point of using loaded isn't too immediately get it's size, but too make sure it's ready when you need it. You could also do the same thing using the Loading event or the XAML constructor for the containing class. Essentially "precaching" the visual.

As to why - probably because the compositor exists outside your application, and hence giving it a command and waiting for it to sync details about the visual between your app and the compositor will not be immediate without introducing delay / holding up your XAML thread.

It's also possible you could use an expression animation to do what you need to with the size - what exactly are you trying to do with it?

groovykool commented 5 years ago

I am using the visual for capturing parts of the screen using GraphicsCaptureItem.CreateFromVisual(Vis);. If the visual size is 0 the screen capture method throws an exception. I can work around problem by getting the visual twice.

robmikh commented 5 years ago

It's true that the frame pool will throw an exception if you try to make the buffers a size of 0x0, but you aren't required to make the buffers the size of your capture item. I'd recommend hooking the Loaded event on the control you want to capture instead of the page or to specify a custom size to the frame pool.

Feel free to take a look at https://github.com/robmikh/VisualCaptureDemo.

groovykool commented 4 years ago

This is still a bug. You can wait forever after the UIElement is loaded, but the size and offset properties of the visual are ALWAYS zero the first time you get them.

Regards, Tony