20

我想修改 WPF TextBox 中字符之间的间距。
类似于letter-spacing: 5pxCSS 中可用的东西。
我认为在 XAML 中是可能的;最简单的方法是什么?

我找到了“ GlyphRun 对象和字形元素简介”文档,发现它非常无用。

这是该页面的代码示例:

<!-- "Hello World!" with explicit character widths for proportional font -->
<Glyphs 
   FontUri             = "C:\WINDOWS\Fonts\ARIAL.TTF"
   FontRenderingEmSize = "36"
   UnicodeString       = "Hello World!"
   Indices             = ",80;,80;,80;,80;,80;,80;,80;,80;,80;,80;,80"
   Fill                = "Maroon"
   OriginX             = "50"
   OriginY             = "225"
/>

相同的文档页面对属性的作用给出了这个“解释” Indices

在此处输入图像描述

我不知道这意味着什么。我也不确定索引是正确的——代码中的注释谈到了我不关心的“字符宽度”。我想调整字符之间的宽度。

此外,没有关于如何将Glyphs元素应用于 TextBox 的示例。当我尝试它时,我的 WPF 测试应用程序崩溃了。


我想要做的是稍微增加 WPF 文本框中绘制的字符之间出现的空白空间。文本的长度和内容会有所不同。Indicies每次有新角色时我都必须修改属性吗?有没有办法说“每个角色都比平时多 20% 的空间”。

有谁能够帮助我?

4

4 回答 4

28

我尝试了 Glyphs 和 FontStretch,但无法轻松获得我想要的结果。我能够想出一种适合我的目的的方法。也许它也适用于其他人。

<ItemsControl ItemsSource="{Binding SomeString}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" 
                       Margin="0,0,5,0"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我可以绑定到任何字符串,并且不需要进行任何字符宽度检测来正确设置间距。右边距是字母之间的空间。

例子:

字距调整

于 2013-09-18T16:56:22.930 回答
2

我找到了一种使用TextBlock类来设置字母间距的方法,因为它支持TranslateTransformsPropertyChangedCallback通过用自定义替换默认值TextBlock.TextProperty,我们可以TranslateTransformTextBlock.

这是我所做的完整的分步编码:

首先,我们创建一个自定义类并像这样继承TextBlock

using System.Windows.Controls;

namespace MyApp
{
    class SpacedLetterTextBlock : TextBlock
    {
        public SpacedLetterTextBlock() : base()
        {
        }
    }
}

然后,在 XAML 中,我们将 TextBlock 更改为我们的自定义类(可以在此处找到更多信息):

<Window x:Class="MyApp.MainWindow"
        ...
        xmlns:app="clr-namespace:MyApp">
   <Grid>
       <app:SpacedLetterTextBlock>
           Some Text
       </app:SpacedLetterTextBlock>
   </Grid>
</Window>

最后,在代码隐藏文件中的InitializeComponent()方法之前,添加如下方法:.csOverrideMetadata

// This line of code adds our own callback method to handle any changes in the Text
//   property of the TextBlock
SpacedLetterTextBlock.TextProperty.OverrideMetadata(
    typeof(SpacedLetterTextBlock),
    new FrameworkPropertyMetadata(null,
            FrameworkPropertyMetadataOptions.AffectsRender,
            new PropertyChangedCallback(OnTextChanged)
    )
);

...并在每次更改时应用于TranslateTransform每个字母TextProperty

private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    SpaceLettersOut(d);
}

// This method takes our custom text block and 'moves' each letter left or right by 
//  applying a TranslateTransform
private static void SpaceLettersOut(DependencyObject d)
{
    SpacedLetterTextBlock thisBlock = (SpacedLetterTextBlock)d;
            
    for (int i = 1; i <= thisBlock.Text.Length; i++)
    {
        // TranslateTransform supports doubles and negative numbers, so you can have
        //  whatever spacing you need - do see 'Notes' section in the answer for
        //  some limitations.
        TranslateTransform transform = new TranslateTransform(2, 0);
        TextEffect effect = new TextEffect();
        effect.Transform = transform;
        effect.PositionStart = i;
        effect.PositionCount = thisBlock.Text.Length;

        thisBlock.TextEffects.Add(effect);
        if (effect.CanFreeze)
        {
            effect.Freeze();
        }
    }
}

注意事项

首先,我是 WPF 和 C# 的完全新手,所以我的答案可能不是最干净的解决方案。如果您对如何改进此答案有任何意见,我们将不胜感激!

其次,我没有用大量TextBlock元素测试过这个解决方案,并且(可能)TranslateTransformTextBlock.Text.

最后,文本的任何正值TextBlock超出范围。我认为您可以重新计算宽度,然后以编程方式放置它(?)XTranslateTransformTextBlock

于 2021-07-04T13:14:54.053 回答
1

FontStretch适合您吗?

否则你可能想看看一个图像,显示提前宽度的含义。虽然我以前没有这样做过,也不知道这是否可行,增加左右侧轴承可能是你想要的!

于 2011-04-30T18:14:28.690 回答
-2

物有所值 。. .

如果您可以选择将实现切换到 RichTextBox,这可能比您在 2013 年 9 月找到的解决方法更容易。我只是根据自己的需要尝试过它,它可以满足我的需要。我看不到 RichTextBox 可以像排字机那样控制单个空间的字距调整。但是 TextBox 像 HTML 一样吃掉了额外的空间(将多个相邻的空间合并到一个空间)。我需要空格显示与我的文本字符串中相同的间距,而 RichTextBox 就是这样做的。

<RichTextBox x:Name="MyRichTextBox"></RichTextBox>

我不是专家,但您似乎无法在 XAML 中指定文本内容。我必须在代码隐藏事件中指定它:

this.MyRichTextBox.AppendText("V A R I E D      S P A C E S");
于 2014-05-05T02:34:46.910 回答