XAML Islands ProgressRing White Background - wpf

I'm porting a WPF app to WPF .NET Core 3.0. I'm trying to use UWP controls using XAML Islands via WindowsXamlHost from the Community Toolkit. The WindowsXamlHost control itself has a white background and I don't know how to get rid of it. Here's an example of a ProgressRing:
<xamlHost:WindowsXamlHost x:Name="MyRing" InitialTypeName="Windows.UI.Xaml.Controls.ProgressRing"/>
private void MyRing_ChildChanged(object sender, EventArgs e)
{
if (MyRing.Child is ProgressRing progressRing)
{
progressRing.IsActive = true;
var brush = new Windows.UI.Xaml.Media.SolidColorBrush(Windows.UI.Colors.Transparent);
progressRing.Background = brush;
}
}
Giving the ProgressRing object a new background color works but doesn't help if I'm after transparency. I'm using .NET Core 3 preview 7.

I'm not sure whether it is possible. I have a similar issue which I reported here: https://github.com/windows-toolkit/Microsoft.Toolkit.Win32/issues/160#issuecomment-522288462. Hopefully, Microsoft employees will answer there.

Related

WPF published application crashing when changing theme

The application is working fine when i run it from Visual Studio but if i run my application when its published it crashes. This is the first application i have published so i dont know where to start.
I have 2 combo boxes that let you choose the theme color of the application as soon as i choose one it crashes.
This is using Mahapps Metro
The combobox's item source is a metro thememanager
ItemsSource="{x:Static metro:ThemeManager.Accents}"
This is the Selection Changed code
private void ColorsSelectorOnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedColor = this.ColorsSelector.SelectedItem as KeyValuePair<string, Color>?;
if (selectedColor.HasValue)
{
var theme = ThemeManager.DetectAppStyle(Application.Current);
ThemeManagerHelper.CreateAppStyleBy(selectedColor.Value.Value, true);
Application.Current.MainWindow.Activate();
}
When creating a runtime accent resource dictionary:

Standard controls in VS 2012 extension

I am currently changing a company-internal VS extension to support Visual Studio 2012. What I am struggling with is how to make the UI adapting to the active VS theme dynamically.
I found several resource keys for colors/brushes (VsColors/VsBrushes in Microsoft.VisualStudio.Shell.11.0.dll) that I can easily use to change the basic color scheme of the extension. The problem is that the standard controls (text boxes, combo boxes, check boxes) have the default WPF appearance which looks really weird.
So the question is: Is there any possibility to make standard controls in a WPF tool window of a VS extension look similar to the ones used in Visual Studio? I am aware that I could do this myself using control templates or custom controls but I really want to avoid this effort if somehow possible.
Visual Studio 2012 use custom WPF controls. You can verify this yourself by Snoop. WPF visual tree of Visual Studio 2012 contains such controls as Microsoft.VisualStudio.PlatformUI.VsButton, Microsoft.VisualStudio.PlatformUI.Shell.Controls.TabGroupControl, Microsoft.VisualStudio.PlatformUI.SearchControl. Unfortunately, these controls are not documented and are difficult or impossible to reuse. You can only view styles of complex elements and implement similar in your code.
I create similar controls base on Winfried Lötzsch collection (now it is included in the MahApps.Metro toolkit). I also saw another collection of attractive elements. It may be useful too.
To implement support for Visual Studio themes, I use resources from Microsoft.VisualStudio.Shell.VsBrushes/VsColors and own colors. To convert icons to current theme, I use following code:
private readonly IVsUIShell5 _vsUIShell5;
private string _currentThemeId;
// cache icons for specific themes: <<ThemeId, IconForLightTheme>, IconForThemeId>
private readonly Dictionary<Tuple<string, BitmapImage>, BitmapImage> _cacheThemeIcons =
new Dictionary<Tuple<string, BitmapImage>, BitmapImage>();
protected override BitmapImage GetIconCurrentTheme(BitmapImage iconLight)
{
Debug.Assert(iconLight != null);
return _currentThemeId.ToThemesEnum() == Themes.Light ? iconLight : GetCachedIcon(iconLight);
}
private BitmapImage GetCachedIcon(BitmapImage iconLight)
{
BitmapImage cachedIcon;
var key = Tuple.Create(_currentThemeId, iconLight);
if (_cacheThemeIcons.TryGetValue(key, out cachedIcon))
{
return cachedIcon;
}
var backgroundColor = FindResource<Color>(VsColors.ToolWindowBackgroundKey);
cachedIcon = CreateInvertedIcon(iconLight, backgroundColor);
_cacheThemeIcons.Add(key, cachedIcon);
return cachedIcon;
}
private BitmapImage CreateInvertedIcon(BitmapImage inputIcon, Color backgroundColor)
{
using (var bitmap = inputIcon.ToBitmapByPngEncoder())
{
var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
var bitmapData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
var sourcePointer = bitmapData.Scan0;
var length = Math.Abs(bitmapData.Stride) * bitmap.Height;
var outputBytes = new byte[length];
Marshal.Copy(sourcePointer, outputBytes, 0, length);
_vsUIShell5.ThemeDIBits((UInt32)outputBytes.Length, outputBytes, (UInt32)bitmap.Width,
(UInt32)bitmap.Height, true, backgroundColor.ToUInt());
Marshal.Copy(outputBytes, 0, sourcePointer, length);
bitmap.UnlockBits(bitmapData);
return bitmap.ToPngBitmapImage();
}
}
To inverted correctly, the icon of Light theme should be as another Visual Studio icons (with gray rim around, like this ).
There is a themes/generic.baml in the resources of Microsoft.VisualStudio.Shell.12.dll that might contain the styles for the controls you are looking for. I used dotPeek but I don't have a plugin installed to visualize the Baml files, there a few you can try.
You should check if the license allows you to use the extracted styles though =P.

Add a WPF UserControl to a TaskPane

I am developing an addin to Microsoft Outlook.
The following code works fine if I use an winforms UserControl:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
var testControlView1 = new UserControl1();
var MyCustomPane = this.CustomTaskPanes.Add(testControlView, "Hello");
}
How can I do it with a WPF UserControl, instead? Does anybody know how I would achieve similar functionality?
As far as I can tell the CustomTaskPanes only allow Winforms Controls to be added to it.
Just found a solution,
https://stevepietrekweblog.wordpress.com/2009/03/24/vsto-display-wpf-user-control-in-custom-task-pane/
This update was just to update the link.

Putting a WPF UserControl on the TaskPane of an Excel2007 Addin

I am making a Excel Addin in VS2010.
The following code work fines if I make a winforms usercontrol
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
var testControlView1 = new UserControl1();
var MyCustomPane = this.CustomTaskPanes.Add(testControlView, "Hello");
}
However I would like to make my UserControl1 be a WPF UserControl. Does anybody know how I would achieve similar functionality or an alternate approach?
As far as I can tell the CustomTaskPanes only allows Winforms Controls to be added to it.
Answer summary:
1. Add a .net winforms usercontrol
2. Add a SWF.Integration.ElementHost control to the user control.
3. Add a Wpf control to your project seperately (not to the user control).
3. Use the Hosted Content property (hostedcontentName) of the ElementHost control and set it to the wpf control.
I found this blog post that answered it great...

How can one host Flash content in a WPF application and use transparency?

How can I go about hosting flash content inside a WPF form and still use transparency/alpha on my WPF window? Hosting a WinForms flash controls does not allow this.
Unless the control you use to display the Flash content is built in WPF, you will run in to these "airspace" issues. Every display technology from Win32 to WinForms used HWNDs "under the hood", but WPF uses DirectX. The Window Manager in Windows however, still only understands HWNDs, so WPF apps have one top-level HWND-based window, and everything under that is done in DirectX (actually things like context menus and tooltips also have top-level HWNDs as well). Adam Nathan has a very good description of WPF interop in this article.
Although I haven't done it, you can probably use the WebBrowser control found in WPF 3.5 sp1 to wrap your Flash content within WPF. I'm not sure how the transparency will be affected though.
Can you use Expression to convert the flash content to XAML? I believe that there are tools in there or off to the side that do this.
Just have been struggling with same problem of how to upload & Make WPF transparent with ability of displaying Flash, because if you enable on your MainWindow "Allow transparency" Flash will not show once the application will run.
1) I used WebBrowser Control to play Flash(.swf) files. They are on my PC, however it can play from internet or wherever you have hosted them. Don't forget to name your WebBrowser Control to get to it in C#.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
MyHelper.ExtendFrame(this, new Thickness(-1));
this.MyBrowser.Navigate(#"C:\Happy\Download\flash\PlayWithMEGame.swf");
}
2) Now for transparency. I have set in WPF 'false' to "Allow Transparency" and set "Window Style" to 'None'. After that I have used information from HERE and HERE and created a following code that produced desired effect of allowing transparency on MainWindow and running Flash at same time, here is my code:
public class MyHelper
{
public static bool ExtendFrame(Window window, Thickness margin)
{
IntPtr hwnd = new WindowInteropHelper(window).Handle;
window.Background = Brushes.Transparent;
HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent;
MARGINS margins = new MARGINS(margin);
DwmExtendFrameIntoClientArea(hwnd, ref margins);
return true;
}
[DllImport("dwmapi.dll", PreserveSig = false)]
static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
}
struct MARGINS
{
public MARGINS(Thickness t)
{
Left = (int)t.Left;
Right = (int)t.Right;
Top = (int)t.Top;
Bottom = (int)t.Bottom;
}
public int Left;
public int Right;
public int Top;
public int Bottom;
}
And called it from Window_Loaded() + you need 'below' line for 'DllImport' to work.
using System.Runtime.InteropServices;
using System.Windows.Interop;

Resources