Currently, WPF applications can have a transparent and borderless window while UWP applications cannot have that. Request is to support the creation of transparent borderless apps using WinUI.
| Capability | Priority |
| :---------- | :------- |
| This proposal will allow developers to accomplish transparent windows | Must |
| This proposal will allow developers to accomplish borderless windows | Must |
This feature could enable designs as shown in this video made by @Niels9001 (source tweet).
This is currently not possible, because:
cc @marb2000 @niels9001
This is a very frequent scenario in Win32, We should consider this scenario at least for WinUI Desktop and WinUI XAML Islands.
Adding a data point, our app (EarTrumpet) requires this functionality.
Anything we can do to get this out of the freezer? https://github.com/microsoft/microsoft-ui-xaml/projects/4#card-25842420
I believe filling in functionality and API gaps should rank much higher. Frankly, I think it's critical to WinUI 3 XAML adoption.
@SavoySchuler @jevansaks ?
Those designs in the tweet look great.
@riverar this is WinUI 2 backlog, and for WinUI 2 is freezer. When WinUI 3 backlog will be active, we will unfreeze it again.
@marb2000 Thanks, it's very confusing how we all talk about WinUI 3 shipping soon yet the repository doesn't reflect WinUI 3 status very well. All we have are the community calls, tags, and word on the street right now.
Can you please give a status update on this?
We'd also like to see transparent borderless windows in WinUI
We want to:
In this picture you can see our product, which is a Windows 10 device with 3 running applications, 2 in yellow and one in red rectangles.
Right now it's achieved via hooking into native and undocumented places of ApplicationFrameHost.dll and Windows.UI.Xaml.dll, but we'd like to avoid that.
This feature is needed for Windows Terminal. microsoft/terminal#603 Having transparent terminal is convenient and expected.
I became really excited once I realized that WinUI could be used in Desktop applications, though I figured I would run into an obstacle that made it impossible. It didn't take long to find the show stopper; this seems to at least one of them and I am sure there are more. @Alikont would you mind sharing the unpublished workaround you are using? Since the day UWP came out in 2012 I have wanted to migrate a boatload of WPF to a more performant XAML flavor. If it requires unpublished trickory I will do whatever it takes.
As simple as this looks, it wasn't as simple to figure out with the information available to us 7/3/2020. I tested this against both 32/64 bit platforms running WinUI Preview 1 with .Net 5.0 preview 6
Disclaimers
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WinUI_InDesktop
{
public static class Interop
{
public static IntPtr SetWindow(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
{
return Environment.Is64BitProcess ?
SetWindowLongPtr(hWnd, nIndex, dwNewLong) :
SetWindowLong(hWnd, nIndex, dwNewLong);
}
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLong")]
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLongPtr")]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
//If you have WPF experience, this is similar to WindowStyle="None"
public static void SetMainWindowBorderless()
{
const int GWL_STYLE = -16;
//WS_VISIBLE | WS_POPUP
var WS_VISIBLE_POPUP = new IntPtr(unchecked((int)0x90000000));
using var process = Process.GetCurrentProcess();
var success = WS_VISIBLE_POPUP != SetWindow(
process.MainWindowHandle,
GWL_STYLE,
WS_VISIBLE_POPUP);
//Helpful when your day goes south
Debug.WriteLineIf(!success, new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message);
}
}
}
@jtbrower Thanks for sharing this piece of code. I was curious about and I tested the SetMainWindowBorderless method. However, It never removes the borders.. Where did you call the method? Even better, can you share a simple repro?
@marb2000 Are there any updates on this topic :)? Would be nice to hear the latest status/plans on this on the next Community Call!
@jtbrower , about the workaround. It's not trivial.
There are 2 places that we hook to achieve our UWP transparency
This information might be relevant to this discussion, because it limits what WinUI can achieve without cooperation from Windows UWP stack, because for UWP applications part of the appearance, including borders and background, is controlled by the OS.
But I don't see technical reason why it can't work in Desktop applications right now. If you set WS_EX_NOREDIRECTIONBITMAP style, Windows will already make a transparent window for you, and you can easily layer Direct Composition visuals there with transparency and effects.
@niels9001 maybe also good to put the question in https://github.com/microsoft/microsoft-ui-xaml/issues/2867
@marb2000 I am heading out the door for an appointment, but will share a solution later today. My solution is an example of a WinUI .Net 5.0 preview 6 desktop application that has a .Net Standard view model library, WinUI custom control library and a native methods library with the Window extension methods.
I also want to show how to change the window size and plan to implement a SizeToContent feature. I have all of the above working except my DragMove needs a little adjustment because my calculations for how much the pointer moved are currently lagging behind reality. I think its related to a DIP unit vs. a screen unit situation. When I went to bed last night, out of nowhere I began seeing a InvalidOperationException: unsupported value type
exception while setting my Page.Window custom dependency property to the Window value. It has to be something stupid I did because it was working fine.
I promise I will share it all today. In the meantime, regarding the example I shared above, that was also done using WinUI desktop with .Net 5.0 preview 6. This can be accomplished by adding a reference to the <PackageReference Include="Microsoft.Windows.CsWinRT" Version="0.1.0-prerelease.200623.5" />
package in your desktop application's csproj. Its given me the opportunity to continue evalutating WinUI while still using .Net5 preview 6.
@marb2000 I apologize for being a couple days later than I said I would be, regarding the example code for the features I mentioned above. I got into a recursive loop of "let me just fix this one last thing".
Edited on 7/30/2020 to match the current Repo Layout and use Permalink Paths
I am going to do my best to document my transition from WPF to WinUI. My focus so far has been primarily on coming up with work-arounds for missing Window features. I created a github repo here.
As for the code that removes the Border/Titlebar it can be achieved using HideWin32NonClientArea(IntPtr windowHandle)
that you will find in this NativeMethods.WindowStyles.cs file.
When you run the sample's solution, you can DragMove the window around your screen by touching anywhere on the window using either mouse or touch. The logic to achieve that can be found in DragMoveBehavior.cs . I also created a behavior that makes it easier to add a DropShadow with rounded corners.
Hopefully, by the time others read this in the future, it will be much further along, but I came back to update the paths to use permalinks because I refactor constantly.
@marb2000 Hate to clog your mentions, buuuuut, any updates on this since preview 2 was released?
Hey @hansmbakker, a suggestion just for your round corners problem
If don't plan to add shadows around the window, you can do the rounded corners easily using CreateRoundedRectRgn and SetWindowRgn or better you can leave it to WPF's Window chrome feature
This implementation was suggested to me by @michalleptuch on Twitter see https://github.com/michalleptuch/RoundedCorners
But if want to add drop shadow around the window, you will experience some problems
https://twitter.com/ShankarBUS/status/1307233994992488450?s=19
But that doesn't stop you. You can add margin & shadow to the content on WPF side and set the rounded region on the xaml islands child window.
I'm trying to implement this in one of my apps I will notify you once I successfully complete my implementation.
Thank you for your suggestion, but I believe those rounded corners of the wpf window are not possible with acrylic.
For acrylic you need UWP, so you need XAML islands to embed it in a WPF window, and that XAML islands part will always be rectangular.
If you give the UWP part rounded corners as well then the XAML islands part still is rectangular with an opaque black background.
That is why I believe this is not possible to be solved today.
First of all I'm sorry for spamming your inboxes 😅
@hansmbakker
Did you even see the repo I specified? I'm 100% sure it worked for me
SetWindowRgn (Which is what WindowChrome in WPF uses to set the CornerRadius) works! It clips not only the WPF Window but also to the "DesktopWindowXamlSource" xaml islands child window!
I know that xaml islands create a child window over the WPF window (this causes the "Air Space" issue)
I saw a post by @michalleptuch about his Ink Workspace app, which had rounded corners and shadow. Out of curiosity I asked him how he did it and I mentioned this issue and the related one in WCT. He then suggested this approach to me. This approach will be really useful if you plan to add no margin or no drop shadow within the UWP xaml. If you are happy with this condition you're good to go!
If you do want to add margin/shadow you will end up with this (I added some margin within the UWP xaml since we need some space to see the shadow)
But I'm planning on another approach. Which is, make the WPF window transparent & borderless and add some margin & shadow to the XamlHost control from WCT within the WPF xaml. Since the UWP xaml is hosted on a child window, we can use FindWindowEx to get its HWND and use CreateRoundedWindowRgn + SetWindowRgn on it.
Hey @marb2000, sorry for the interruption. Since you work on xaml islands, could you verify this?
Ah, I didn't know that the SetWindowRgn
method performs clipping. That would help indeed when no shadow is needed!
As for the shadow, frankly speaking I have no experience with shadows in WPF (would need to look that up), but it is nice that you are working on a workaround!
Most helpful comment
This feature is needed for Windows Terminal. microsoft/terminal#603 Having transparent terminal is convenient and expected.