Open hansmbakker opened 5 years ago
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!
Has there been any progress on this yet @marb2000?
Is there any progress on the transparency issue.
from the patch is clearly visible that
Background="Transparent"
was supported a long time andOpacity
too.
You may have missed that we had to use a private API to get this working. Everything looks easy through that lens.
Without us using that API, XAML enforces the presence of a black background under all controls as an "emergency" measure to explicitly prevent transparency.
Originally posted by @DHowett in https://github.com/microsoft/terminal/issues/603#issuecomment-923125091
If it was UWP I could have used some private API like this: IWindowPrivate, but when it comes to WinUI, I am not familiar and why did they need to enforce the presence of a black background to prevent transparency when people need transparency, at least it must be optional. Windows.UI.Composition can render on transparent window, so i believe Microsoft.UI.Composition can also do same, if the root visual is intentionally painted with black color, I don't think adding a dependency property to enable transparency requires years of work.
If it was UWP I could have used some private API like this: IWindowPrivate, but when it comes to WinUI, I am not familiar and why did they need to enforce the presence of a black background to prevent transparency when people need transparency, at least it must be optional. Windows.UI.Composition can render on transparent window, so i believe Microsoft.UI.Composition can also do same, if the root visual is intentionally painted with black color, I don't think adding a dependency property to enable transparency requires years of work.
Thankfully they managed to sort it (no release yet but transparency is merged onto main in microsoft/terminal now) and that issue is closed, but I don't think there is any way for individual developers to use their method for other apps
do you have any links or docs
PR: microsoft/terminal#11180 Doc PR: MicrosoftDocs/terminal#416
Thankyou
Is there any progress? 😉
April 2022 not fixed and no update in almost 2 years..?
SetLayeredWindowAttributes works
A test with a completely transparent window, with just a visible Button :
SetLayeredWindowAttributes works
A test with a completely transparent window, with just a visible Button :
Does this block input from what is behind the Transparent window?
@castorix Could you share source code?
Does this block input from what is behind the Transparent window?
Yes, while the ex. style has not WS_EX_TRANSPARENT (but this style "kills" the UI and it needs more code to manage it...)
@castorix Could you share source code?
It depends on which exact behaviour is wanted I used OverlappedPresenter.SetBorderAndTitleBar to remove title bar/borders, added WS_EX_LAYERED ex. style then SetLayeredWindowAttributes, but without title bar, code must be added to move the window for example (like WM_NCHITTEST)
Or maybe it can be better with a Border if the title bar is removed. I tested with PointerMoved, PointerPressed, PointerReleased to move the window but not sure if it is the simplest method...
SetLayeredWindowAttributes works A test with a completely transparent window, with just a visible Button :
Can you share your source code?
FWIW this did the job. I don't really understand why interop and multiple libraries were required to obtain a class that has the properties of what the baseline WPF window xaml was capable of, but I'm very appreciative of you sharing this!
@marb2000 / @ranjeshj We might be able to close this out now since this is seemingly supported in WASDK 1.0.
@castorix Could you share source code?
It depends on which exact behaviour is wanted I used OverlappedPresenter.SetBorderAndTitleBar to remove title bar/borders, added WS_EX_LAYERED ex. style then SetLayeredWindowAttributes, but without title bar, code must be added to move the window for example (like WM_NCHITTEST)
@castorix Sorry, I don't get it 😞 Do I need to set WS_EX_LAYERED style on parent or content window? How to exactly set SetLayeredWindowAttributes and when? I just want to remove window background like this https://github.com/microsoft/microsoft-ui-xaml/issues/1247#issuecomment-1092858148
@marb2000 / @ranjeshj We might be able to close this out now since this is seemingly supported in WASDK 1.0.
I strongly disagree, the fact still stands that you can't just set the window to be transparent easily like wpf.
@castorix Sorry, I don't get it 😞 Do I need to set WS_EX_LAYERED style on parent or content window? How to exactly set SetLayeredWindowAttributes and when? I just want to remove window background like this #1247 (comment)
I uploaded a test sample that I have improved a bit : WinUI3_Transparent.zip (tested with VS 2022 on Windows 10 21H1, with WindowsAppSDK 1.1.0-preview1)
@marb2000 / @ranjeshj We might be able to close this out now since this is seemingly supported in WASDK 1.0.
I strongly disagree, the fact still stands that you can't just set the window to be transparent easily like wpf.
I'm with you, at the very least this should be better documented, maybe even with a just decent minimal reproducible example.
After that I think making it easier to do should be it's own issue as this one is long and old and focuses more on the technical side.
If Window had a direct line to the AppWindow class without passing through interop that would be a big improvement. This solution is clunky, but at least it does work. Its more of a usable workaround than mission accomplished.
It doesn't work for me when I'm using separated MSIX project. Border and shadow are still visible. It works only in single project 👌
@riverar this is WinUI 2 backlog, and for WinUI 2 is freezer. When WinUI 3 backlog will be active, we will unfreeze it again.
Is there an update on this? WinUI 3 has been released, but this issue is still in the freezer... Please consider moving it up on the priority list.
Ideally it would be possible with something like.
Window.Style = WindowsStyle.Transparent
Proposal: Transparent background support in apps using WinUI
Summary
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.
Rationale
Scope
Important Notes
This feature could enable designs as shown in this video made by @Niels9001 (source tweet).
This is currently not possible, because: