WPF Blurry fonts ปัญหา - วิธีแก้ไข


153

อธิบายปัญหาและแสดงให้เห็นในลิงค์ต่อไปนี้:

คำอธิบาย: ข้อความชัดเจนใน WPF ลิงค์นี้มีการเปรียบเทียบแบบอักษร

ฉันต้องการรวบรวมวิธีแก้ไขที่เป็นไปได้ทั้งหมดสำหรับปัญหานี้ Microsoft Expression Blend ใช้ WPF แต่แบบอักษรดูอ่านได้

  • พื้นหลังสีเข้มใน Microsoft Expression Blend
  • การเพิ่มขนาดตัวอักษรและการเปลี่ยนแบบอักษร (Calibri ... ) [link]
  • แบบฟอร์มฝังหน้าต่าง[ลิงค์]
  • ใช้คลาส GDI + และ / หรือ Windows Forms TextRenderer เพื่อแสดงข้อความเป็นบิตแมปแล้วเรนเดอร์บิตแมปนั้นเป็นตัวควบคุม WPF [ลิงค์]

มีวิธีแก้ปัญหาเพิ่มเติมอีกไหม?

สิ่งนี้จะได้รับการแก้ไขใน VS2010 (และ WPF4) เบต้า 2

มันดูเหมือนได้รับการแก้ไขในที่สุด!

ComputerZen.com ของ Scott Hanselman: WPF และ Text Blurriness ตอนนี้มีความชัดเจนสมบูรณ์


VS2010RC ไม่สามารถใช้งานได้ทั้งหมดสำหรับฉันmpdreamz.nl/vs2010RC-blur.png
Martijn Laarman

VS2010RC บนเครื่องของฉันดูดีขึ้นแล้วในรูปภาพของคุณจริง ๆ แล้วมีพื้นหลังสีขาวดีมาก แต่ก็ยังมีพื้นหลังสีเข้มอยู่
Robert Vuković

คุณพบทางออกสำหรับปัญหานี้จริง ๆ แล้วฉันมีปัญหาเดียวกันที่นี่ในแอปพลิเคชันของฉันและฉันใช้ WPF 3.5 กับ VS2010
SharpUrBrain

ลิงค์ 3 รายการสุดท้ายนั้นตายแล้ว
SHIN JaeGuk

คำตอบ:


107

พื้นหลังทางเทคนิค

: มีบทความในเชิงลึกเกี่ยวกับการแสดงผล WPF ข้อความจากหนึ่งใน WPF ข้อความผู้จัดการโครงการใน windowsclient.net คือความชัดเจนในข้อความ WPF

ปัญหาเดือดลงมาถึง WPF ซึ่งต้องใช้การปรับขนาดแบบอักษรแบบเชิงเส้นเพื่อให้ภาพเคลื่อนไหวราบรื่น Pure ClearType ในอีกด้านหนึ่งใช้เสรีภาพค่อนข้างน้อยในการใช้แบบอักษรเพื่อดันก้านแนวตั้งเข้าสู่พิกเซลถัดไป

ความแตกต่างชัดเจนถ้าเปรียบเทียบรูปแบบ "น้ำตก" คลาสสิก WinForms ทางด้านซ้ายล่าง WPF ทางด้านขวาบน:

ในขณะที่ฉันไม่ได้เป็นแฟนตัวยงของการแสดงผลแบบอักษรของ WPF ฉันก็จินตนาการได้เลยว่าอนิเมชั่นจะกระโดดอย่างที่พวกเขาทำใน Winforms

เล่นกับรีจิสทรี

สิ่งที่น่าสนใจเป็นพิเศษสำหรับฉันคือลิงค์ไปยังบทความ MSDN " ClearType Registry Settings " ซึ่งจะอธิบายการปรับด้านผู้ใช้ที่เป็นไปได้ในรีจิสทรี:

  • ระดับ ClearType: จำนวนการบอกใบ้ของพิกเซลย่อย
  • ระดับแกมม่า
  • โครงสร้างพิกเซล: วิธีการจัดเรียงแถบสีของพิกเซลการแสดงผล
  • ระดับความคมชัดของข้อความ: ปรับความกว้างของ glyph stems เพื่อทำให้แบบอักษรหนักขึ้น

การเล่นกับการตั้งค่าเหล่านี้ไม่ได้ช่วยแก้ปัญหาพื้นฐาน แต่สามารถช่วยได้โดยการลดเอฟเฟ็กต์สีตกเลือดสำหรับผู้ใช้ที่มีความละเอียดอ่อน

อีกแนวทางหนึ่ง

คำแนะนำที่ดีที่สุดของบทความความชัดเจนของข้อความคือการเพิ่มขนาดตัวอักษรและการเปลี่ยนแบบอักษร Calibri ทำงานได้ดีกว่า Segoe UI มาตรฐาน เนื่องจากความนิยมของมันเป็นแบบอักษรบนเว็บฉันจึงลอง Verdana ด้วยเช่นกัน แต่มันก็มีน้ำหนักเพิ่มขึ้นอย่างน่าประหลาดใจระหว่าง 14 พอยต์และ 15 พอยต์ซึ่งเห็นได้ชัดเจนเมื่อเคลื่อนไหวขนาดฟอนต์

WPF 4.0

WPF 4 จะได้รับการปรับปรุงให้ดีขึ้นเพื่อสนับสนุนการสร้างการแสดงผลแบบอักษร มีบทความในบล็อกข้อความ WPFอธิบายการเปลี่ยนแปลง สิ่งสำคัญที่สุดคือตอนนี้ (อย่างน้อย) การแสดงผลข้อความสามแบบ:

การเปรียบเทียบการแสดงผลข้อความ

<grumble> นั่นน่าจะเพียงพอสำหรับนักออกแบบทุกคน </grumble>


11
คำอธิบายที่ดีเยี่ยม +1 อาจอธิบายได้ว่าทำไม Flash จึงมีตัวอักษรที่น่าเกลียดน่ากลัวเช่นกัน
Jeff Atwood

1
ใช่. นั่นเป็นคำอธิบายที่ดี แต่ฉันก็ยังหวังว่าจะมีวิธีเปิดแบบอักษรเพื่อให้ดูดีเมื่อคุณรู้ว่าคุณจะไม่เคลื่อนไหว ฉันคิดว่านี่จะหมายถึงสเกลที่กำหนดซึ่งคุณจะปรับคำใบ้ให้เหมาะสมที่สุด สิ่งต่าง ๆ ชนิดนี้ทำให้ WPF ดูเหมือนยังเป็นรุ่นเบต้าสำหรับฉัน
PeterAllenWebb

มันไม่เหมือนกับตัวแปร "ที่ปรับขนาดได้" ไม่ได้ใช้การบอกตัวอักษร แต่เป็นเพียงแค่ว่า WPF ไม่ได้ปรับให้เหมาะสำหรับการตีกริดพิกเซลเช่นเดียวกับ ClearType เนื้อหา SnapToDevicePixels ควรทำงานกับข้อความได้ แต่สิ่งนี้จะต้องได้รับการสืบทอดเนื่องจากตัวควบคุมไม่สามารถรู้ได้ว่ามันอาจจะถ่ายหรือไม่
David Schmitt

2
ที่เกี่ยวข้องโดยเฉพาะอย่างยิ่งเป็น TextOptions.TextFormattingMode คุณสมบัติที่แนบมา ( msdn.microsoft.com/en-us/library/ee169597.aspx ) WPF4 และ Silverlight ยังมีคุณสมบัติ UseLayoutRounding ( msdn.microsoft.com/en-us/library/dd783605.aspx ) และ SnapsToDevicePixels ( msdn.microsoft.com/en-us/library/… ) คุณสมบัติ
Pat

@ ทั้งหมด: ฉันไม่สามารถหาวิธีปิดใช้งานการลบรอยหยักของข้อความใน WPF3.5 และเนื่องจากป้ายข้อความหรือปุ่มผลลัพธ์ดูไม่ดีจริงๆ เป็นการดีที่ฉันต้องการปิดใช้งานการป้องกันนามแฝงทั่วโลกสำหรับแบบอักษร ฉันจะทำสิ่งนี้ได้อย่างไร
SharpUrBrain

128

. NET 4 ในที่สุดก็มีทางออกสำหรับคุณภาพการเรนเดอร์ข้อความของ WPF ที่ไม่ดี ตั้งค่าต่อไปนี้สำหรับทุกหน้าต่าง:

TextOptions.TextFormattingMode="Display"

ค่าเริ่มต้นคือ "อุดมคติ" ซึ่งไม่ได้เป็นความหมายของชื่อ

มีสองตัวเลือกอื่น ๆ ใน TextOptions คือ TextHintingMode และ TextRenderingMode แต่ทั้งคู่มีค่าเริ่มต้นที่สมเหตุสมผล


ทั้งหมด. ขอบคุณ ที่ช่วยฉันในการแก้ปัญหา แต่คุณต้องกำหนดว่าครั้งเดียวในภาชนะเช่น <grid>
5251 Peter Du

ใช่และถ้าคุณตั้งไว้บนหน้าต่างมันจะใช้ได้สำหรับทุกสิ่งที่อยู่ในหน้าต่างนั้น
Helge Klein

ใช้เวลามากมายในการค้นหาสิ่งนี้ที่ไซต์และบล็อกมากมายที่มีการจัดรูปแบบข้อความที่ดีขึ้นกว่าเดิมใน VS2010 RTM / .Net 4 (ฉันเห็นด้วย!) แต่ไม่มีใครสนใจที่จะพูดถึงวิธีที่คุณสามารถสร้างแอปพลิเคชัน WPF ที่คุณสร้างด้วยดูดีเช่นกัน เหตุใดคุณสมบัตินั้นจึงซ่อนอยู่อย่างดี ขอบคุณมาก.
M-Peror

5
ทั้งหมดที่ฉันต้องการคือสิ่งนี้! ฉันไม่สนใจว่าการเรนเดอร์ WPF ที่ซับซ้อนเป็นอย่างไรแบบอักษรไม่สามารถยอมรับได้กับทุกคน
Jerry Liang

1
"เหมาะ" เหมาะกับฉันแทน "แสดง" โครงการอยู่ใน. NET 4.6.2 บางทีพวกเขาคงชื่อสับสน
โจ

40

ฉันพบปัญหาในวันอื่น ๆ เมื่อฉันใช้ชายแดนซึ่งมีDropShadowEffectใช้ ผลที่ได้คือข้อความทั้งหมดที่อยู่ในเส้นขอบนั้นพร่ามัวอย่างมาก ไม่สำคัญว่าข้อความจะอยู่ในพาเนลอื่นหรืออยู่ใต้เส้นขอบ - บล็อกข้อความใด ๆ ที่เป็นลูกของผู้ปกครองที่มีเอฟเฟกต์ที่ใช้ดูเหมือนว่าจะได้รับผลกระทบ

วิธีแก้ปัญหากรณีนี้คือการไม่ใส่สิ่งของไว้ในขอบที่มีเอฟเฟกต์ แต่ควรใช้กริด (หรือสิ่งอื่นที่รองรับการวางเนื้อหาไว้ด้านบนของกันและกัน) และวางสี่เหลี่ยมในเซลล์เดียวกันกับข้อความ (เช่น เป็นพี่น้องในต้นไม้ที่มองเห็น) และใส่เอฟเฟกต์ลงไป

ชอบมาก

<!-- don't do this --->
<Border>
     <Border.Effect>
          <DropShadowEffect BlurRadius="25" ShadowDepth="0" Opacity="1"/>
     </Border.Effect>
     <TextBlock Text="This Text Will Be Blurry" />
</Border>

<!-- Do this instead -->
<Grid>
  <Rectangle>
     <Rectangle.Effect>
          <DropShadowEffect BlurRadius="25" ShadowDepth="0" Opacity="1"/>
     </Rectangle.Effect>
  </Rectangle>
  <TextBlock Text="This Text Will Be Crisp and Clear" />
</Grid>

เคล็ดลับนี้ทำได้ดีมาก บิตของแฮ็ค แต่ดีกว่า messing รอบกับการตั้งค่าอื่น ๆ ที่ดีอย่างหนึ่ง ขอบคุณ อย่างไรก็ตามสิ่งหนึ่งที่ฉันต้องทำคือตั้งค่าการเติมสี่เหลี่ยมเป็นบางสิ่ง บางทีนี่อาจเป็นเพียงการตั้งค่าของฉัน
นรก

ใช่คุณถูกต้อง .. สี่เหลี่ยมผืนผ้าเป็นค่าเริ่มต้นที่โปร่งใสซึ่งทำให้เงาเงาดูแปลก ๆ
Isak Savo

สิ่งนี้ไม่ได้เกิดขึ้นในแอปพลิเคชันตัวอย่างของฉันฉันใช้ WPF 3.5
SharpUrBrain

@SharpUrBrain: เกิดอะไรขึ้น? มันยังพร่ามัวแม้หลังจากใช้ตัวอย่างที่สองของฉันไปแล้ว?
Isak Savo

ใช่มันยังพร่ามัวหลังจากใช้ตัวอย่างที่สองของคุณด้วย
SharpUrBrain


6

SnapToDevicePixels นำไปใช้กับรูปร่าง WPF (บรรทัดอื่น ๆ ) เท่านั้นไม่ใช่กับตัวแสดงข้อความ

ไม่มีวิธีแก้ไขเฉพาะหน้าสำหรับปัญหานี้ ตามที่ Microsoft พฤติกรรมคือ "โดยการออกแบบ"

โปรดดูหัวข้อนี้ในฟอรัม Microsoft เพื่อหารือเกี่ยวกับปัญหา - มีการตอบกลับสองสามข้อจากพวก MS ที่ชี้แจงตำแหน่งของพวกเขาเกี่ยวกับปัญหา


แก้ไขใน WPF 4 โดยใช้คุณสมบัติ TextOptions.TextFormattingMode ที่แนบมา ( msdn.microsoft.com/en-us/library/ee169597.aspx )
Pat

1
ชื่อคุณสมบัติคือ "SnapsToDevicePixels" และไม่ใช่ "SnapToDevicePixels" ตามที่เขียนไว้
Nir Kornfeld

6

จากจุดที่นักพัฒนารู้จักเพียงแค่ "การแก้ไขปัญหา" จนถึงปัจจุบันคือการใช้คลาส GDI + และ / หรือ Windows Forms TextRenderer เพื่อแสดงข้อความเป็นบิตแมปแล้วเรนเดอร์บิตแมปนั้นเป็นตัวควบคุม WPF นอกเหนือจากความหมายของประสิทธิภาพที่ชัดเจนสิ่งนี้ไม่ได้ช่วยบรรเทาปัญหาสำหรับแอปพลิเคชันที่มีอยู่

ตอนนี้ฉันได้สร้างตั๋ว Microsoft Connect สำหรับปัญหานี้ (เพื่อความประหลาดใจของฉันแม้จะมีการปฏิเสธทั้งหมดไม่มีรายงานข้อผิดพลาดจริงในตัวติดตามที่กำหนด)

เนื่องจากเป็นหนึ่งในช่องทางที่เป็นทางการในการสื่อสารคำขอและคำถามไปยัง Microsoft ฉันจึงขอแนะนำให้คุณทำเช่นนี้เพื่อรับคำตอบที่รวดเร็วยิ่งขึ้น อย่างน้อยถ้าคุณต้องการให้ปัญหาได้รับการแก้ไขไม่ทางใดก็ทางหนึ่งการลงคะแนนสำหรับตั๋วนั้นที่นั่นและ / หรือการตรวจสอบปัญหาจะช่วยดึงดูดความสนใจของ Microsoft PMs และวิศวกรถึงปัญหานี้และอาจเพิ่มลำดับความสำคัญ


6

ฉันไม่เห็นว่ามันเป็นจุดบกพร่อง แต่การกำหนดค่าเริ่มต้นนั้นน่ารำคาญมาก นี่คือการเปรียบเทียบการรวมกันทั้งหมดของ

TextOptions.TextRenderingMode
TextOptions.TextFormattingMode
RenderOptions.ClearTypeHint

SnapToDevicePixels ไม่ได้สร้างความแตกต่างในการแสดงข้อความ

http://i.stack.imgur.com/cS3S2.png

ฉันชอบ:

TextOptions.TextRenderingMode="Auto"
TextOptions.TextFormattingMode="Ideal"
RenderOptions.ClearTypeHint="Auto"

ที่เส้นแนวตั้งไม่พร่ามัว

แบบอักษรที่ใช้คือ Open Sans Light ซึ่งสามารถสวยงามได้หากใช้อย่างดีเช่นใน TeamViewer ล่าสุด

สำหรับผู้ที่ใช้ Mahapps.Metro ปัญหาคือTransitioningContentControl https://github.com/MahApps/MahApps.Metro/issues/889


4

เพิ่งลองรุ่น VS2010 เบต้าซึ่งทำใน WPF แล้วและมันก็ทนทุกข์ทรมานจากปัญหาตัวอักษรพร่ามัวอย่างไม่น่าเชื่อ โดยเฉพาะอย่างยิ่งในคำแนะนำเครื่องมือ

ที่ดูเหมือนว่าจะให้หลักฐานบางอย่างที่ WPF4 ในความเป็นจริงจะไม่แก้ปัญหา (ถ้ามีอะไรที่แย่กว่านั้น)


3
ฉันกำลังยื่นข้อบกพร่องกับ VS2010B1 สำหรับแต่ละสถานที่ใน UI ข้อความนั้นไม่ชัดเจน เคล็ดลับเครื่องมือเกือบจะไม่ดีนักฉันก็เห็นด้วย ระบุว่ามันได้รับการบอกกล่าวอย่างชัดเจนว่าจะต้องแก้ไขใน WPF4 นี้ฉันหวังได้เพียงว่ามันไม่ได้ถูกตัดสำหรับเบต้านี้
Will Dean จะ

4

ว้าวฉันไม่อยากจะเชื่อว่าในที่สุดฉันก็สามารถอ่านแบบอักษร WPF ของฉันได้ และฉันก็ไม่อยากจะเชื่อเลยว่าไม่มีกล่องโต้ตอบตัวเลือกเพื่อให้การเปลี่ยนแปลงเหล่านี้ง่ายขึ้นในขณะที่ค่าเริ่มต้นนั้นน่ากลัวบนจอแสดงผลของฉัน

การตั้งค่ารีจิสทรีเหล่านี้(เป็นทศนิยม) ทำงานได้สำหรับฉันและใกล้เคียงกับแบบอักษร cleartype ปกติของฉัน:

  • ClearTypeLevel: 10 (นามแฝงส่วนใหญ่ greyscale)
  • GammaLevel: 1300 (แกมม่าที่สูงกว่าทำให้ตัวอักษรบางเกินไปและฉันเห็นสีในนามแฝง)

3

พวกเขาบอกว่างาน "SnapToDevicePixels = true" แต่ฉันไม่เคยเห็นผลลัพธ์ที่ดีเลย

ฉันต่อสู้กับข้อความที่เบลอโดยการเปลี่ยนไปใช้แบบอักษรอื่น

เห็นได้ชัดว่านี่ไม่ใช่วิธีแก้ปัญหา แต่นี่เป็นวิธีที่ฉันได้แก้ไข


ฉันเพิ่งเปรียบเทียบ TextBlock กับ SnapToDevicePixels = "ถูกต้อง" กับอันเดียวที่ไม่มีและไม่มีความแตกต่างกับแบบอักษร Segoe UI ที่ 12duis ฉันขอแบบอักษรที่คุณใช้ได้ไหม
David Schmitt

เรายังทำให้สถานการณ์ดีขึ้นโดยการเปลี่ยนแบบอักษรของเรา แบบอักษรที่เราเลือกคือ Avenir (ฉันไม่คิดว่าจะติดตั้งตามค่าเริ่มต้นอย่างน้อยก็ไม่ใช่ใน Windows XP)
cplotts

0

หากคุณต้องการใช้คลาสพื้นฐาน C # เพื่อปรับแต่ง windows สำหรับแอพของคุณ (หรือตอนนี้มีเหตุผล) ต่อไปนี้คือวิธีที่คุณตั้งค่าสามารถตั้งค่าการจัดรูปแบบข้อความเพื่อใช้โหมดการแสดงผลที่น่าสนใจ:

public class SnappyWindow : Window
{
    public SnappyWindow()
    {
        SetValue(TextOptions.TextFormattingModeProperty, TextFormattingMode.Display);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.