Replies: 1 comment
-
I found an answer. One need to fill Background property when requesting the image. public static ImageSource? ConvertMonikerToImageSource(
ImageMoniker imageMoniker,
int? width = null,
int? height = null
)
{
var imageService = ServiceProvider.GlobalProvider.GetService(typeof(SVsImageService)) as IVsImageService2;
if (imageService == null || imageMoniker.IsNullImage())
{
return null;
}
var backgroundColor = VSColorTheme.GetThemedColor(EnvironmentColors.ToolWindowBackgroundColorKey);
uint ColorToColorRef(System.Drawing.Color color)
{
return (uint)(
(color.A << 24) |
(color.B << 16) |
(color.G << 8) |
(color.R)
);
}
var imageAttributes = new ImageAttributes
{
Flags = (uint)_ImageAttributesFlags.IAF_RequiredFlags | 0x8000_0000/*this is _ImageAttributesFlags.IAF_Background*/,
Format = (uint)_UIDataFormat.DF_WPF,
ImageType = (uint)_UIImageType.IT_Bitmap,
LogicalWidth = Math.Max(width.GetValueOrDefault(16), 16),
LogicalHeight = Math.Max(height.GetValueOrDefault(16), 16),
Dpi = 96,
StructSize = Marshal.SizeOf<ImageAttributes>(),
Background = ColorToColorRef(backgroundColor)
};
var bitmapFrame = imageService.GetImage(imageMoniker, imageAttributes);
if (bitmapFrame == null)
{
return null;
}
object bitmapSource;
bitmapFrame.get_Data(out bitmapSource);
if (bitmapSource == null)
{
return null;
}
var result = bitmapSource as BitmapSource;
return result;
} Also, if you want to update images at rruntime, when an user changes VS theme, you can use the following: public sealed class PseudoCrispImage : System.Windows.Controls.Image
{
public static readonly DependencyProperty MonikerProperty =
DependencyProperty.Register(
nameof(Moniker),
typeof(ImageMoniker),
typeof(PseudoCrispImage),
new PropertyMetadata(KnownMonikers.QuestionMark, OnKnownMonikerNameChanged)
);
public ImageMoniker Moniker
{
get => (ImageMoniker)GetValue(MonikerProperty);
set => SetValue(MonikerProperty, value);
}
public PseudoCrispImage()
{
Width = 16;
Height = 16;
PseudoCrispImageThemeController.Add(this);
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
UpdateImageSource();
}
private static void OnKnownMonikerNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (PseudoCrispImage)d;
control.UpdateImageSource();
}
public void UpdateImageSource()
{
var dpi = VisualTreeHelper.GetDpi(this);
double realWidth = double.IsNaN(Width) ? 16 : Width;
double realHeight = double.IsNaN(Height) ? 16 : Height;
if (dpi.DpiScaleX > 0 && dpi.DpiScaleY > 0)
{
realWidth *= dpi.DpiScaleX;
realHeight *= dpi.DpiScaleY;
}
Source = CompletionData.ConvertMonikerToImageSource(
Moniker,
(int)realWidth,
(int)realHeight
);
}
~PseudoCrispImage()
{
PseudoCrispImageThemeController.Remove(this);
}
}
public static class PseudoCrispImageThemeController
{
private static readonly object _locker = new();
private static readonly List<WeakReference<PseudoCrispImage>> _references = new();
static PseudoCrispImageThemeController()
{
VSColorTheme.ThemeChanged += VSThemeChanged;
}
public static void Add(PseudoCrispImage image)
{
lock (_locker)
{
_references.Add(
new WeakReference<PseudoCrispImage>(
image
)
);
}
}
public static void Remove(PseudoCrispImage image)
{
lock (_locker)
{
_references.RemoveAll(wr =>
{
var r = wr.TryGetTarget(out var target);
if (!r)
{
return true;
}
if (ReferenceEquals(target, image))
{
return true;
}
return false;
});
}
}
private static void VSThemeChanged(
ThemeChangedEventArgs e
)
{
var images = new List<PseudoCrispImage>();
lock (_locker)
{
foreach (var wr in _references)
{
if (wr.TryGetTarget(out var image))
{
images.Add(image);
}
}
}
images.ForEach(image => image.UpdateImageSource());
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I'm using CrispImage in XAML of my VSIX. If user changed visual theme, some images show blank space.
Looks like it widely known problem, but I did not find the solution. Any ideas? Writing my own analogue of CrispImage did not help, looks like the issue is inside image service or deeper.
Beta Was this translation helpful? Give feedback.
All reactions