Closed gileli121 closed 2 years ago
COOL !! I did it! My mistake was here:
It should be:
ComInterfaceType.InterfaceIsIInspectable
I found it by looking on windows.graphics.capture.h
Now it works perfect!
This will disable the border!!
Add:
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIInspectable)]
[Guid("f2cdd966-22ae-5ea1-9596-3a289344c3be")]
public interface IGraphicsCaptureSession3
{
bool IsBorderRequired { get; set; }
}
Add the following code after you have session
object and before the call to session.StartCapture();
:
var pUnk = Marshal.GetIUnknownForObject(session);
var session3 = Marshal.GetObjectForIUnknown(pUnk) as IGraphicsCaptureSession3;
session3.IsBorderRequired = false;
I'm going to close this as you seem to have it figured out. To recap, all WinRT interfaces inherit from IInspectable, so keep that in mind when crafting those interface definitions by hand. I would recommend looking at the CsWinRT project to have them generated from metadata instead.
Second, a comment on the usage of the IsBorderRequired property. Before accessing this property, you should call GraphicsCaptureAccess.RequestAccessAsync and request access to the border. This doesn't make a huge difference for unpackaged Win32 applications, but is critical for packaged applications. Even if you are writing an unpackaged application, I still suggest calling it as it is the documented requirement.
EDIT: One more thing, it's safe to modify the IsBorderRequired property even if RequestAccessAsync says you don't have access. That just means the user preference or the system policy is currently set so that the border will always show up. But if it changes, the system will reevaluate using the value you placed in IsBorderRequired.
I'm going to close this as you seem to have it figured out. To recap, all WinRT interfaces inherit from IInspectable, so keep that in mind when crafting those interface definitions by hand. I would recommend looking at the CsWinRT project to have them generated from metadata instead.
Second, a comment on the usage of the IsBorderRequired property. Before accessing this property, you should call GraphicsCaptureAccess.RequestAccessAsync and request access to the border. This doesn't make a huge difference for unpackaged Win32 applications, but is critical for packaged applications. Even if you are writing an unpackaged application, I still suggest calling it as it is the documented requirement.
EDIT: One more thing, it's safe to modify the IsBorderRequired property even if RequestAccessAsync says you don't have access. That just means the user preference or the system policy is currently set so that the border will always show up. But if it changes, the system will reevaluate using the value you placed in IsBorderRequired.
You wrote:
but is critical for packaged applications.
My project is Win32 app / WPF app that packaged as Microsoft Store app using this method: https://docs.microsoft.com/en-us/windows/msix/desktop/desktop-to-uwp-packaging-dot-net I tested it also while it is installed as "UWP" app and it worked fine without GraphicsCaptureAccess.RequestAccessAsync
So I don't understand why it is matters at all anyway.
Please just follow the documentation. Otherwise, your app may break in the future, even if it appears to not do anything today.
@robmikh
So you saying that the fact that it works for a packaged app is a bug? My app is declared with capability runFullTrust
so I don't think that it is a bug.
This is the part about capabilities in my packaged app:
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="WindowTop"
Description="UWP_PackagingProject"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png"/>
<uap:SplashScreen Image="Images\SplashScreen.png" />
<uap:InitialRotationPreference>
<uap:Rotation Preference="landscape"/></uap:InitialRotationPreference>
</uap:VisualElements>
<Extensions>
<desktop:Extension
Category="windows.startupTask"
Executable="WindowTop\WindowTop.exe"
EntryPoint="Windows.FullTrustApplication">
<desktop:StartupTask
TaskId="WindowTopStartupTask"
Enabled="false"
DisplayName="Start WindowTop with Windows" />
</desktop:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
If I will call to GraphicsCaptureAccess.RequestAccessAsync, it will open dialog for the user (assuming that I added graphicsCaptureWithoutBorder
capability) and the user will need to accept it?
If you're running full trust, that would explain not seeing anything from RequestAccessAsync (although, again, you should still call it).
In the event that you would get a prompt, it would be a one time prompt to the user. All other times it would return the user's selected preference. This is similar to the way GPS or camera capabilities work.
If you're running full trust, that would explain not seeing anything from RequestAccessAsync (although, again, you should still call it).
OK, the current behavior considered as bug?
And anyway, I should not get a prompt after RequestAccessAsync
in case of full trust package?
Not a bug, and yes I wouldn't expect the prompt to show up.
If that changes in the future, it would only be a prompt the user sees once for the duration that your application is installed.
Thank you @robmikh
So if it is not bug, I am not going to use GraphicsCaptureAccess.RequestAccessAsync
even if it suggested because if it work, don't break it
.
And another question: How I can check if this property IsBorderRequired
is available in the system?
I can try to warp it in try-catch block but maybe there is better way
That's a bad idea.
Use ApiInformation:
Hello, For some reason,
IGraphicsCaptureSession2
andIGraphicsCaptureSession3
are not available in C# but it is available in the docs here https://docs.microsoft.com/en-us/uwp/api/windows.graphics.capture.graphicscapturesession.iscursorcaptureenabled?view=winrt-22000I was able to manually import this part myself -
I found this part in
windows.graphics.capture.h
So took the example here: https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/tree/master/dotnet/WPF/ScreenCapture And under
CaptureSampleCore
I created this class:Next, in file: https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/blob/master/dotnet/WPF/ScreenCapture/CaptureSampleCore/BasicCapture.cs#L94
I added the following code:
I did debug and found that it actually try to work because it was able to get
session2
object and the debugger shows 2 properties that aretrue
. It means that something until this point worked fine - it was able to cast it toIGraphicsCaptureSession2
and also read these properties:It even show extra property called
IsBorderRequired
. It is documented in the docs and I want to use it also.. but not for now. I don't know how it printed it becauseIGraphicsCaptureSession2
should not have it..IGraphicsCaptureSession3
have it..The program will crash when it will execute this line that it tries to set the value of
IsCursorCaptureEnabled
tofalse
:Any idea what I am doing wrong here?
Thanks