기존의 글꼴 크기 및 문자의 WPF 텍스트 블록 너비를 계산하는 방법은 무엇입니까?
예를 들어,TextBlock
텍스트 "Some Text" 및 글꼴 크기 10.0을 지정합니다.
적절한 계산 방법TextBlock
폭?
클래스를 사용합니다.
코드로 도우미 기능을 만들었습니다.
private Size MeasureString(string candidate)
{
var formattedText = new FormattedText(
candidate,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(this.textBlock.FontFamily, this.textBlock.FontStyle, this.textBlock.FontWeight, this.textBlock.FontStretch),
this.textBlock.FontSize,
Brushes.Black,
new NumberSubstitution(),
VisualTreeHelper.GetDpi(this.textBlock).PixelsPerDip);
return new Size(formattedText.Width, formattedText.Height);
}
WPF 레이아웃에서 사용할 수 있는 디바이스에 의존하지 않는 픽셀을 반환합니다.
참고로...오퍼레이터는 텍스트 블록이 비주얼 트리에 추가된 후 차지하는 폭을 프로그램적으로 결정하려고 합니다.IMO는 포맷된 솔루션보다 뛰어난 솔루션텍스트(textWraping 등의 처리를 어떻게 합니까?)는 샘플 TextBlock에서 Measure and Array를 사용하는 것입니다.
var textBlock = new TextBlock { Text = "abc abd adfdfd", TextWrapping = TextWrapping.Wrap };
// auto sized
textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
textBlock.Arrange(new Rect(textBlock.DesiredSize));
Debug.WriteLine(textBlock.ActualWidth); // prints 80.323333333333
Debug.WriteLine(textBlock.ActualHeight);// prints 15.96
// constrain the width to 16
textBlock.Measure(new Size(16, Double.PositiveInfinity));
textBlock.Arrange(new Rect(textBlock.DesiredSize));
Debug.WriteLine(textBlock.ActualWidth); // prints 14.58
Debug.WriteLine(textBlock.ActualHeight);// prints 111.72
제공된 솔루션은 에 적합합니다.다만, Windows 10 DPI 스케일링과 Framework 4.6.x 의 다양한 서포트 레벨에 의해, Net Framework 4.5 에서는, 텍스트의 측정에 사용하는 컨스트럭터가 마크 되고 있습니다.[Obsolete]
를 포함하지 않는 메서드의 컨스트럭터와 함께 사용합니다.pixelsPerDip
파라미터를 지정합니다.
아쉽게도 이 기능은 조금 더 복잡하지만 새로운 확장 기능을 통해 정확도가 향상됩니다.
###픽셀퍼딥
MSDN에 따르면 이는 다음을 나타냅니다.
Pixes Per Density Independent Pixel 값. 스케일 팩터와 동일합니다.예를 들어 화면의 DPI가 120(또는 120/96 = 1.25이므로 1.25)이면 밀도 독립적인 픽셀당 1.25픽셀이 그려집니다.DIP는 디바이스 분해능 및 DPI에 의존하지 않기 위해 WPF에 의해 사용되는 측정 단위입니다.
DPI 스케일링 인식 기능을 갖춘 Microsoft/WPF-Samples GitHub 저장소로부터의 가이던스에 근거해, 선택된 답변을 실장합니다.
Windows 10 Anniversary 시점(이하 코드)에서 DPI 확장을 완전히 지원하려면 몇 가지 추가 구성이 필요합니다.이 기능이 없으면 스케일링이 구성된 단일 모니터로 동작합니다(스케일링 변경도 고려됩니다).위 레포에 있는 Word 문서가 해당 정보의 출처입니다. 왜냐하면 이러한 값을 추가하면 응용 프로그램이 실행되지 않기 때문입니다.같은 레포의 샘플 코드도 참조 포인트로서 도움이 됩니다.
public partial class MainWindow : Window
{
private DpiScale m_dpiInfo;
private readonly object m_sync = new object();
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
private Size MeasureString(string candidate)
{
DpiScale dpiInfo;
lock (m_sync)
dpiInfo = m_dpiInfo;
if (dpiInfo == null)
throw new InvalidOperationException("Window must be loaded before calling MeasureString");
var formattedText = new FormattedText(candidate, CultureInfo.CurrentUICulture,
FlowDirection.LeftToRight,
new Typeface(this.textBlock.FontFamily,
this.textBlock.FontStyle,
this.textBlock.FontWeight,
this.textBlock.FontStretch),
this.textBlock.FontSize,
Brushes.Black,
dpiInfo.PixelsPerDip);
return new Size(formattedText.Width, formattedText.Height);
}
// ... The Rest of Your Class ...
/*
* Event Handlers to get initial DPI information and to set new DPI information
* when the window moves to a new display or DPI settings get changed
*/
private void OnLoaded(object sender, RoutedEventArgs e)
{
lock (m_sync)
m_dpiInfo = VisualTreeHelper.GetDpi(this);
}
protected override void OnDpiChanged(DpiScale oldDpiScaleInfo, DpiScale newDpiScaleInfo)
{
lock (m_sync)
m_dpiInfo = newDpiScaleInfo;
// Probably also a good place to re-draw things that need to scale
}
}
기타 요건
Microsoft/WPF-Samples 의 메뉴얼에 의하면, 복수의 모니터 구성의 디스플레이 마다 다른 DPI 설정을 가지는 Windows 10 Anniversary 의 기능을 커버하기 위해서, 애플리케이션의 매니페스트에 몇개의 설정을 추가할 필요가 있습니다. 창을으로 한 로 이동할 때 Changed 수 로 인해 이 이전 .DpiScale
제가 쓰고 있는 어플리케이션은 저 혼자만의 어플리케이션으로, 그런 셋업이 없기 때문에 테스트할 것이 없고, 가이던스를 따라 했을 때 매니페스토 오류로 인해 부팅이 되지 않는 어플리케이션이 되어 버렸습니다.그래서 포기했습니다만, 그것을 재검토해 매니페스토를 포함하는 어플리케이션을 조정하는 것이 좋을 것 같습니다.
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
</windowsSettings>
</application>
설명서에 따르면:
[이들] 태그의 조합에는 다음과 같은 효과가 있습니다. 1) 모니터 단위 for > = Windows 10 Anniversary Update 2) System < Windows 10 Anniversary Update
백엔드 코드의 요소에 바인딩 경로를 추가하여 이 문제를 해결했습니다.
<TextBlock x:Name="MyText" Width="{Binding Path=ActualWidth, ElementName=MyText}" />
Formated와 같은 상기 참조의 오버헤드를 모두 추가하는 것보다 훨씬 깨끗한 솔루션임을 알게 되었습니다.내 코드로 문자를 보내.
그 후, 나는 이것을 할 수 있었다.
double d_width = MyText.Width;
잘 되는 방법을 찾아냈어
/// <summary>
/// Get the required height and width of the specified text. Uses Glyph's
/// </summary>
public static Size MeasureText(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize)
{
Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);
GlyphTypeface glyphTypeface;
if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
{
return MeasureTextSize(text, fontFamily, fontStyle, fontWeight, fontStretch, fontSize);
}
double totalWidth = 0;
double height = 0;
for (int n = 0; n < text.Length; n++)
{
ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]];
double width = glyphTypeface.AdvanceWidths[glyphIndex] * fontSize;
double glyphHeight = glyphTypeface.AdvanceHeights[glyphIndex] * fontSize;
if (glyphHeight > height)
{
height = glyphHeight;
}
totalWidth += width;
}
return new Size(totalWidth, height);
}
/// <summary>
/// Get the required height and width of the specified text. Uses FortammedText
/// </summary>
public static Size MeasureTextSize(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize)
{
FormattedText ft = new FormattedText(text,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(fontFamily, fontStyle, fontWeight, fontStretch),
fontSize,
Brushes.Black);
return new Size(ft.Width, ft.Height);
}
이거 쓰겠습니다.
var typeface = new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch);
var formattedText = new FormattedText(textBlock.Text, Thread.CurrentThread.CurrentCulture, textBlock.FlowDirection, typeface, textBlock.FontSize, textBlock.Foreground);
var size = new Size(formattedText.Width, formattedText.Height)
검색 결과:
Graphics g = control.CreateGraphics();
int width =(int)g.MeasureString(aString, control.Font).Width;
g.dispose();
언급URL : https://stackoverflow.com/questions/9264398/how-to-calculate-wpf-textblock-width-for-its-known-font-size-and-characters
'programing' 카테고리의 다른 글
단일 WPF 텍스트블록에 여러 값을 바인드하려면 어떻게 해야 합니까? (0) | 2023.04.14 |
---|---|
WPF에 동등한 MessageBox가 있습니까? (0) | 2023.04.14 |
아이폰에서 둥근 모서리 UILABEL을 작성하려면 어떻게 해야 하나요? (0) | 2023.04.14 |
Swift Date 객체를 작성하려면 어떻게 해야 합니까? (0) | 2023.04.14 |
SQL Server DateTime 데이터 유형에서 날짜만 반환하는 방법 (0) | 2023.04.14 |