-
-
Notifications
You must be signed in to change notification settings - Fork 517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ribbon Button: when passing the same icon file to the properties Icon and LargeIcon, the control doesn't seem to take the good icon frame #14
Comments
I already modified the code for Fluent to be icon-aware at 96dpi. But then it's not dpi-aware yet, a useful feature in Windows 8.1. Here's the modified source: <!-- example with Themes/Office2010/Controls/Button.xaml, simply add some ConverterParameters with the wanted pixel size at 96dpi wherever needed -->
<Setter Property="Content" TargetName="iconImage" Value="{Binding Icon, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static Converters:StaticConverters.ObjectToImageConverter}, ConverterParameter=16}"/>
<!-- I did the same with Themes/Office2010/Controls/RibbonGroupBox.xaml --> // Fluent/Converters/ObjectToImageConverter.cs, nothing else needs to be modified code-side
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string)
{
var valueString = (string)value;
Func<ImageSource> CreateImageSource = () => {
if (parameter != null && valueString.EndsWith(".ico"))
{ // icon-aware code
var decoder = BitmapDecoder.Create(
new Uri("pack://application:,,," + valueString, UriKind.RelativeOrAbsolute),
BitmapCreateOptions.DelayCreation | BitmapCreateOptions.IgnoreImageCache,
BitmapCacheOption.None
);
var result = decoder.Frames.SingleOrDefault(f => f.Width == System.Convert.ToDouble(parameter));
if (result == default(BitmapFrame))
result = decoder.Frames.OrderBy(f => f.Width).Last();
return result;
}
else
// original code
return new BitmapImage(
new Uri(value as string, UriKind.RelativeOrAbsolute),
new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore)
);
};
var image = new Image
{
Source = CreateImageSource()
};
return image;
}
var imageSource = value as ImageSource;
if (imageSource != null)
{
var image = new Image
{
Source = imageSource
};
return image;
}
return value;
} |
Ok, here's my attempt to make Fluent partially dpi-aware (i.e. with this, it still won't dynamically refresh button icons if moving the main window to another monitor with a different dpi): // Fluent/Converters/ObjectToImageConverter.cs, I just modified the icon-aware section code
var decoder = BitmapDecoder.Create(
new Uri("pack://application:,,," + valueString, UriKind.RelativeOrAbsolute),
BitmapCreateOptions.DelayCreation | BitmapCreateOptions.IgnoreImageCache,
BitmapCacheOption.None
);
// dpi.M11 = dpiX, dpi.M22 = dpiY
Matrix dpi = PresentationSource.FromVisual(Application.Current.MainWindow).CompositionTarget.TransformToDevice;
var result = decoder.Frames.SingleOrDefault(f => f.Width == System.Convert.ToDouble(parameter) * dpi.M11);
if (result == default(BitmapFrame))
result = decoder.Frames.OrderBy(f => f.Width).Last();
return result; It's really simple as |
Adding |
It turned out that I was in the good direction. It's just that some icons didn't have every size. So following my code, buttons were taking the biggest size available (e.g. 256x256) and then WPF scaled this down to the target size (e.g. declared size: 16x16, target size at 144dpi: 24x24). var decoder = BitmapDecoder.Create(
new Uri("pack://application:,,," + valueString, UriKind.RelativeOrAbsolute),
BitmapCreateOptions.DelayCreation | BitmapCreateOptions.IgnoreImageCache,
BitmapCacheOption.None
);
// dpi.M11 = dpiX, dpi.M22 = dpiY
Matrix dpi = PresentationSource.FromVisual(Application.Current.MainWindow).CompositionTarget.TransformToDevice;
var result = decoder.Frames.OrderBy(f => f.Width).Where(f => f.Width >= System.Convert.ToDouble(parameter) * dpi.M11).FirstOrDefault();
if (result == default(BitmapFrame))
result = decoder.Frames.OrderBy(f => f.Width).Last();
return result; Icons still aren't as sharp as they should be, at least when comparing with the rendering at 96dpi, but it's the best I could do. If any expert could come up and gives the definitive solution, I would be thankful for that. |
Last message before somebody reply to my monologue: my modified ObjectToImageConverter.cs upsets the WPF designer with an error "value cannot be null. missing parameter: v.". To fix this, simply ensure that |
I will try to have a look at this at the weekend. |
Could you do your changes in a fork and create a PR for this? Would be much easier for me. |
I have an application with several ribbon buttons, to which I pass icon files to the properties Icon and LargeIcon.
The thing is that button controls don't seem to take the good icon frame for the property Icon.
For instance, I have an icon file, which have several frames from 16x16 to 64x64. When looking at the resulting ribbon button, it seems to always take the 32x32 frame and then resize this one to fit within the button instead of taking the 32x32 frame for LargeIcon and the 16x16 frame for Icon.
Well, it would be the ideal behaviour at 96dpi. But at higher dpi, buttons should try to grab frames with higher pixel sizes.
The text was updated successfully, but these errors were encountered: