我正在基于MS RibbonControlsLibrary( 3.5.41019.1 )以编程方式填充功能区(WPF)。所有图像(最明显的大图像)看起来非常糟糕并且“像素化”:
我试图将 BitmapScalingMode 设置为“HighQuality”而没有任何影响,源代码:
BitmapImage img = new BitmapImage();
try
{
Uri uri = new Uri("pack://application:,,,/UIMainWindow;component/Resources/" + iPictureName);
img.BeginInit();
img.SetValue(BitmapImage.CacheOptionProperty, BitmapCacheOption.OnLoad);
RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.HighQuality);
img.UriSource = uri;
img.EndInit();
img.Freeze();
}
catch (Exception ex)
{
throw new Exception("Creation of image failed: " + ex.Message, ex);
}
问题 为什么图像的缩放看起来很糟糕?我该如何解决这个问题?
答案 0 :(得分:1)
上述其他答案都没有为我工作,所以我开始自己的调查。将图像大小调整为32x32 几乎修复了问题,但我们的用户具有不同的DPI设置,并且图像无法在其计算机上正确缩放。我还应该注意到我正在使用System.Windows.Controls.Ribbon组件,它的行为可能与RibbonControlsLibrary略有不同。
我发现RibbonButton的默认ControlTemplate专门指定了NearestNeighbor作为位图缩放选项。好消息是,通过将样式放入Window的资源,可以轻松覆盖此控件模板。有点坏消息是控件模板非常冗长。我将系统上的RibbonButton的默认ControlTemplate转储到一个文件,只是更改了位图缩放选项。
首先,如果你还没有这个名称空间声明,那么你需要这个名称空间声明:
xmlns:s="clr-namespace:System;assembly=mscorlib"
然后将此Style放在Window的资源中,以覆盖RibbonButton外观:
<Style TargetType="RibbonButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RibbonButton">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" CornerRadius="{TemplateBinding RibbonControlService.CornerRadius}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="OuterBorder" SnapsToDevicePixels="True">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" CornerRadius="{TemplateBinding RibbonControlService.CornerRadius}" BorderBrush="#00FFFFFF" Name="InnerBorder">
<StackPanel Name="StackPanel">
<Image Source="{TemplateBinding RibbonControlService.LargeImageSource}" Name="PART_Image" Width="32" Height="32" Margin="{DynamicResource {ComponentResourceKey TypeInTargetAssembly=Ribbon, ResourceId=LargeImageMargin}}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="Center" RenderOptions.BitmapScalingMode="HighQuality" />
<Grid Name="Grid" HorizontalAlignment="Center" VerticalAlignment="Center">
<RibbonTwoLineText TextAlignment="Center" LineHeight="13" LineStackingStrategy="BlockLineHeight" Text="{TemplateBinding RibbonControlService.Label}" Name="TwoLineText" Margin="1,1,1,0" HorizontalAlignment="Center" VerticalAlignment="Top" />
</Grid>
</StackPanel>
</Border>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=ControlSizeDefinition.ImageSize, RelativeSource={RelativeSource Mode=Self}}" Value="Large">
<Setter Property="FrameworkElement.MinWidth">
<Setter.Value>
<s:Double>44</s:Double>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Height">
<Setter.Value>
<s:Double>66</s:Double>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.MinHeight" TargetName="Grid">
<Setter.Value>
<s:Double>26</s:Double>
</Setter.Value>
</Setter>
<Setter Property="RibbonTwoLineText.HasTwoLines" TargetName="TwoLineText">
<Setter.Value>
<s:Boolean>True</s:Boolean>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=ControlSizeDefinition.ImageSize, RelativeSource={RelativeSource Mode=Self}}" Value="Small">
<Setter Property="FrameworkElement.Height">
<Setter.Value>
<s:Double>22</s:Double>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Margin" TargetName="PART_Image">
<Setter.Value>
<Thickness>1,0,1,0</Thickness>
</Setter.Value>
</Setter>
<Setter Property="Image.Source" TargetName="PART_Image">
<Setter.Value>
<Binding Path="SmallImageSource" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Width" TargetName="PART_Image">
<Setter.Value>
<s:Double>16</s:Double>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Height" TargetName="PART_Image">
<Setter.Value>
<s:Double>16</s:Double>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.HorizontalAlignment" TargetName="TwoLineText">
<Setter.Value>
<x:Static Member="HorizontalAlignment.Left" />
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Margin" TargetName="TwoLineText">
<Setter.Value>
<Thickness>1,1,1,1</Thickness>
</Setter.Value>
</Setter>
<Setter Property="StackPanel.Orientation" TargetName="StackPanel">
<Setter.Value>
<x:Static Member="Orientation.Horizontal" />
</Setter.Value>
</Setter>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=ControlSizeDefinition.ImageSize, RelativeSource={RelativeSource Mode=Self}}" Value="Small" />
<Condition Binding="{Binding Path=IsInQuickAccessToolBar, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="FrameworkElement.Height">
<Setter.Value>
<s:Double>NaN</s:Double>
</Setter.Value>
</Setter>
</MultiDataTrigger>
<DataTrigger Binding="{Binding Path=ControlSizeDefinition.IsLabelVisible, RelativeSource={RelativeSource Mode=Self}}" Value="False">
<Setter Property="UIElement.Visibility" TargetName="TwoLineText">
<Setter.Value>
<x:Static Member="Visibility.Collapsed" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=ControlSizeDefinition.ImageSize, RelativeSource={RelativeSource Mode=Self}}" Value="Collapsed">
<Setter Property="UIElement.Visibility" TargetName="PART_Image">
<Setter.Value>
<x:Static Member="Visibility.Collapsed" />
</Setter.Value>
</Setter>
</DataTrigger>
<Trigger Property="UIElement.IsMouseOver">
<Setter Property="Panel.Background" TargetName="OuterBorder">
<Setter.Value>
<Binding Path="MouseOverBackground" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<Binding Path="MouseOverBorderBrush" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="InnerBorder">
<Setter.Value>
<SolidColorBrush>#80FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="UIElement.IsKeyboardFocused">
<Setter Property="Panel.Background" TargetName="OuterBorder">
<Setter.Value>
<Binding Path="FocusedBackground" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<Binding Path="FocusedBorderBrush" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="InnerBorder">
<Setter.Value>
<SolidColorBrush>#80FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="ButtonBase.IsPressed">
<Setter Property="Panel.Background" TargetName="OuterBorder">
<Setter.Value>
<Binding Path="PressedBackground" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<Binding Path="PressedBorderBrush" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="InnerBorder">
<Setter.Value>
<SolidColorBrush>#00FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="RibbonControlService.IsInControlGroup">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<Binding Path="Ribbon.BorderBrush" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderThickness" TargetName="OuterBorder">
<Setter.Value>
<Thickness>0,0,1,0</Thickness>
</Setter.Value>
</Setter>
<Setter Property="Border.CornerRadius" TargetName="OuterBorder">
<Setter.Value>
<CornerRadius>0,0,0,0</CornerRadius>
</Setter.Value>
</Setter>
<Setter Property="Border.CornerRadius" TargetName="InnerBorder">
<Setter.Value>
<CornerRadius>0,0,0,0</CornerRadius>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="UIElement.IsEnabled">
<Setter Property="UIElement.Opacity" TargetName="PART_Image">
<Setter.Value>
<s:Double>0.5</s:Double>
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground" TargetName="OuterBorder">
<Setter.Value>
<SolidColorBrush>#FF9E9E9E</SolidColorBrush>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
<DataTrigger Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True">
<Setter Property="TextElement.Foreground" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.MenuTextBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="Panel.Background" TargetName="OuterBorder">
<Setter.Value>
<SolidColorBrush>#00FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<SolidColorBrush>#00FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="Border.CornerRadius" TargetName="OuterBorder">
<Setter.Value>
<CornerRadius>0,0,0,0</CornerRadius>
</Setter.Value>
</Setter>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True" />
<Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlLightBrushKey}" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True" />
<Condition Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="False" />
<Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource Mode=TemplatedParent}, FallbackValue=false}" Value="True" />
<Condition Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="False" />
<Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlLightBrushKey}" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
<Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Panel.Background" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlLightBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="Border.CornerRadius" TargetName="OuterBorder">
<Setter.Value>
<CornerRadius>0,0,0,0</CornerRadius>
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="InnerBorder">
<Setter.Value>
<SolidColorBrush>#00FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsKeyboardFocused, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
<Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Panel.Background" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlLightBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="Border.CornerRadius" TargetName="OuterBorder">
<Setter.Value>
<CornerRadius>0,0,0,0</CornerRadius>
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="InnerBorder">
<Setter.Value>
<SolidColorBrush>#00FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsPressed, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
<Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Panel.Background" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlDarkBrushKey}" />
</Setter.Value>
</Setter>
<Setter Property="Border.CornerRadius" TargetName="OuterBorder">
<Setter.Value>
<CornerRadius>0,0,0,0</CornerRadius>
</Setter.Value>
</Setter>
<Setter Property="TextElement.Foreground" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsInControlGroup, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
<Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Border.BorderBrush" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlLightLightBrushKey}" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="False" />
<Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="TextElement.Foreground" TargetName="OuterBorder">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
答案 1 :(得分:0)
尝试使用vector graphics。有很多工具可以用来生成相当于这种图像的yaml,你可以看看这个article它可能会有所帮助。
答案 2 :(得分:0)
您使用的是哪种操作系统? - WPF在XP上看起来不太好(不是Vista和7的问题)。 我认为这是由于XP和新操作系统之间抗锯齿的默认设置不同。
将XAML中的宽度和高度设置为48以匹配图像大小(同时检查拉伸参数)。
对于48x48 32位PNG,图像应该看起来很好。
由于色带条没有拉伸,矢量图形是多余的。
如果上述方法无效,请尝试设置align to device pixels并设置LayoutRounding。
正如我在评论中建议的那样,您可以将图像调整为显示尺寸,但是,应该在XAML中明确设置,以确保它们是相同的。
您还可以通过将高度或宽度设置为32并使用ScaleTransform来让WPF重新调整图像大小。
答案 3 :(得分:0)
我遇到了同样的问题,我创建了自己的usercontrol来解决这个问题。
我就这样做了:
<ribbon:Ribbon>
<ribbon:RibbonTab Header="File">
<ribbon:RibbonGroup Header="File">
<views:ImageButton Command="{Binding LoadCommand}" Caption="Open" SourceImage="/Images/save.png"/>
</ribbon:RibbonGroup>
</ribbon:RibbonTab>
</ribbon:Ribbon>
图像按钮usercontrol ImageButton.xaml
<UserControl Name="control"
<Button Command="{Binding Command, ElementName=control}" Style="{x:Null}">
<StackPanel>
<infrastructure:AutoGreyableImage Width="32" Source="{Binding SourceImage, ElementName=control}"/>
<TextBlock Text="{Binding Caption, ElementName=control}"/>
</StackPanel>
</Button>
图像按钮usercontrol ImageButton.xaml.cs
public partial class ImageButton : UserControl
{
public static DependencyProperty CommandProperty = DependencyProperty.Register(
"Command", typeof(ICommand), typeof(ImageButton));
public static DependencyProperty SourceProperty = DependencyProperty.Register(
"SourceImage", typeof(string), typeof(ImageButton));
public static DependencyProperty CaptionProperty = DependencyProperty.Register(
"Caption", typeof(string), typeof(ImageButton));
public ICommand Command
{
get
{
return (ICommand)GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
public string SourceImage
{
get
{
return (string)GetValue(SourceProperty);
}
set
{
SetValue(SourceProperty, value);
}
}
public string Caption
{
get
{
return (string)GetValue(CaptionProperty);
}
set
{
SetValue(CaptionProperty, value);
}
}
public ImageButton()
{
InitializeComponent();
}
}
对于AutogreyableImage,我使用了this post
这是类
的复制粘贴 using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
/// <summary>
/// Class used to have an image that is able to be gray when the control is not enabled.
/// Author: Thomas LEBRUN (http://blogs.developpeur.org/tom)
/// </summary>
public class AutoGreyableImage : Image
{
/// <summary>
/// Initializes a new instance of the <see cref="AutoGreyableImage"/> class.
/// </summary>
static AutoGreyableImage()
{
// Override the metadata of the IsEnabled property.
IsEnabledProperty.OverrideMetadata(typeof(AutoGreyableImage), new FrameworkPropertyMetadata(true, new PropertyChangedCallback(OnAutoGreyScaleImageIsEnabledPropertyChanged)));
}
/// <summary>
/// Called when [auto grey scale image is enabled property changed].
/// </summary>
/// <param name="source">The source.</param>
/// <param name="args">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnAutoGreyScaleImageIsEnabledPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
{
var autoGreyScaleImg = source as AutoGreyableImage;
var isEnable = Convert.ToBoolean(args.NewValue);
if (autoGreyScaleImg != null)
{
if (!isEnable)
{
// Get the source bitmap
var bitmapImage = new BitmapImage(new Uri(autoGreyScaleImg.Source.ToString()));
// Convert it to Gray
autoGreyScaleImg.Source = new FormatConvertedBitmap(bitmapImage, PixelFormats.Gray32Float, null, 0);
// Create Opacity Mask for greyscale image as FormatConvertedBitmap does not keep transparency info
autoGreyScaleImg.OpacityMask = new ImageBrush(bitmapImage);
}
else
{
// Set the Source property to the original value.
autoGreyScaleImg.Source = ((FormatConvertedBitmap)autoGreyScaleImg.Source).Source;
// Reset the Opcity Mask
autoGreyScaleImg.OpacityMask = null;
}
}
}
}
我希望这会帮助你和其他人来