2009-08-12 37 views
12

Tôi đang cố gắng "đặt lại" định dạng trong RichTextBox của tôi (WinForms, không phải WPF). Trước đây tôi đã sử dụngĐặt lại RTF trong RichTextBox?

richTextBox.Text = richTextBox.Text; 

Tuy nhiên, điều đó dường như đột nhiên thất bại trong tôi. Bây giờ không có vấn đề gì tôi đặt richTextBox.Text, nó vẫn giữ lại một số định dạng rtf.

Tôi đã thử

richTextBox.Rtf = richTextBox.Text; 

Tuy nhiên, đó phàn nàn về một định dạng không đúng. Có một cách tốt hơn để làm điều này. (Tất nhiên, chọn toàn bộ điều, sau đó đặt lại màu sau, màu sắc và phông chữ hoạt động, nhưng điều đó dẫn đến nhấp nháy khi toàn bộ nội dung được chọn rồi bỏ chọn, cộng với nó chậm hơn và yêu cầu nhiều mã hơn.) bất kỳ ý tưởng?

Edit: tôi đã nhận được để làm việc này:

string tempTxt = richTextBox.Text; 
richTextBox.Clear(); 
richTextBox.Text = tempTxt; 

Nhưng đó có phải là một cách tốt hơn, phải không?

Chỉnh sửa 2: Để rõ ràng, tôi muốn xóa tất cả các định dạng trong khi giữ lại văn bản. Có vẻ như mã trong bản chỉnh sửa đầu tiên sẽ xuất xưởng, trừ khi bất kỳ ai khác có cách mã hóa hiệu quả hơn/tốt hơn.

Sửa 3:

richTextBox.Text = richTextBox.Text.ToString(); 

dường như không làm việc vì nó vẫn không rõ ràng tất cả các định dạng. Lý do tôi không thích phương thức trong Edit đầu tiên ở trên là nó làm cho hộp văn bản "flash" khi nó xóa nó sau đó nhập lại văn bản. Có vẻ như đơn giản chỉ nên có một phương thức richTextBox.ResetFormatting() hoặc một số cách để truy cập cùng chức năng, như phương thức Clear() rõ ràng (không có ý định chơi chữ) thực hiện một số định dạng đặt lại ngoài việc xóa tất cả văn bản .

Để tóm tắt:

Có cách nào (và nếu như vậy, nó là gì) để thiết lập lại định dạng của văn bản trong một RichTextBox mà không thanh toán bù trừ các văn bản như trong ví dụ trên (vì đó tạo ra nhấp nháy không mong muốn)?

Trả lời

22

Thật không may là tôi đã thực hiện nỗ lực hết sức mình để giảm bớt điều này xuống chỉ còn mã yêu cầu. Nó vẫn còn lớn, nhưng nó sẽ hoạt động. Các RichTextBox api trong. Net là rất hạn chế, để làm bất cứ điều gì bạn gần như phải thunk vào thư viện Win32. Tôi đã xây dựng một thư viện toàn bộ xung quanh điều này chỉ vì vậy tôi có thể chuyển đổi đậm và xác định nếu in đậm thực sự được thiết lập trên lựa chọn.

Cách sử dụng:

RichTextBox te = ...; 
te.ClearAllFormatting(new Font("Microsoft Sans Serif", 8.25f)); 

Tấn mã:

static class RichTextExtensions 
{ 
    public static void ClearAllFormatting(this RichTextBox te, Font font) 
    { 
     CHARFORMAT2 fmt = new CHARFORMAT2(); 

     fmt.cbSize = Marshal.SizeOf(fmt); 
     fmt.dwMask = CFM_ALL2; 
     fmt.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR; 
     fmt.szFaceName = font.FontFamily.Name; 

     double size = font.Size; 
     size /= 72;//logical dpi (pixels per inch) 
     size *= 1440.0;//twips per inch 

     fmt.yHeight = (int)size;//165 
     fmt.yOffset = 0; 
     fmt.crTextColor = 0; 
     fmt.bCharSet = 1;// DEFAULT_CHARSET; 
     fmt.bPitchAndFamily = 0;// DEFAULT_PITCH; 
     fmt.wWeight = 400;// FW_NORMAL; 
     fmt.sSpacing = 0; 
     fmt.crBackColor = 0; 
     //fmt.lcid = ??? 
     fmt.dwMask &= ~CFM_LCID;//don't know how to get this... 
     fmt.dwReserved = 0; 
     fmt.sStyle = 0; 
     fmt.wKerning = 0; 
     fmt.bUnderlineType = 0; 
     fmt.bAnimation = 0; 
     fmt.bRevAuthor = 0; 
     fmt.bReserved1 = 0; 

     SendMessage(te.Handle, EM_SETCHARFORMAT, SCF_ALL, ref fmt); 
    } 

    private const UInt32 WM_USER = 0x0400; 
    private const UInt32 EM_GETCHARFORMAT = (WM_USER + 58); 
    private const UInt32 EM_SETCHARFORMAT = (WM_USER + 68); 
    private const UInt32 SCF_ALL = 0x0004; 
    private const UInt32 SCF_SELECTION = 0x0001; 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] 
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, UInt32 wParam, ref CHARFORMAT2 lParam); 

    [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)] 
    struct CHARFORMAT2 
    { 
     public int cbSize; 
     public uint dwMask; 
     public uint dwEffects; 
     public int yHeight; 
     public int yOffset; 
     public int crTextColor; 
     public byte bCharSet; 
     public byte bPitchAndFamily; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
     public string szFaceName; 
     public short wWeight; 
     public short sSpacing; 
     public int crBackColor; 
     public int lcid; 
     public int dwReserved; 
     public short sStyle; 
     public short wKerning; 
     public byte bUnderlineType; 
     public byte bAnimation; 
     public byte bRevAuthor; 
     public byte bReserved1; 
    } 

    #region CFE_ 
    // CHARFORMAT effects 
    const UInt32 CFE_BOLD = 0x0001; 
    const UInt32 CFE_ITALIC = 0x0002; 
    const UInt32 CFE_UNDERLINE = 0x0004; 
    const UInt32 CFE_STRIKEOUT = 0x0008; 
    const UInt32 CFE_PROTECTED = 0x0010; 
    const UInt32 CFE_LINK = 0x0020; 
    const UInt32 CFE_AUTOCOLOR = 0x40000000;   // NOTE: this corresponds to 
    // CFM_COLOR, which controls it 
    // Masks and effects defined for CHARFORMAT2 -- an (*) indicates 
    // that the data is stored by RichEdit 2.0/3.0, but not displayed 
    const UInt32 CFE_SMALLCAPS = CFM_SMALLCAPS; 
    const UInt32 CFE_ALLCAPS = CFM_ALLCAPS; 
    const UInt32 CFE_HIDDEN = CFM_HIDDEN; 
    const UInt32 CFE_OUTLINE = CFM_OUTLINE; 
    const UInt32 CFE_SHADOW = CFM_SHADOW; 
    const UInt32 CFE_EMBOSS = CFM_EMBOSS; 
    const UInt32 CFE_IMPRINT = CFM_IMPRINT; 
    const UInt32 CFE_DISABLED = CFM_DISABLED; 
    const UInt32 CFE_REVISED = CFM_REVISED; 

    // CFE_AUTOCOLOR and CFE_AUTOBACKCOLOR correspond to CFM_COLOR and 
    // CFM_BACKCOLOR, respectively, which control them 
    const UInt32 CFE_AUTOBACKCOLOR = CFM_BACKCOLOR; 
    #endregion 
    #region CFM_ 
    // CHARFORMAT masks 
    const UInt32 CFM_BOLD = 0x00000001; 
    const UInt32 CFM_ITALIC = 0x00000002; 
    const UInt32 CFM_UNDERLINE = 0x00000004; 
    const UInt32 CFM_STRIKEOUT = 0x00000008; 
    const UInt32 CFM_PROTECTED = 0x00000010; 
    const UInt32 CFM_LINK = 0x00000020;   // Exchange hyperlink extension 
    const UInt32 CFM_SIZE = 0x80000000; 
    const UInt32 CFM_COLOR = 0x40000000; 
    const UInt32 CFM_FACE = 0x20000000; 
    const UInt32 CFM_OFFSET = 0x10000000; 
    const UInt32 CFM_CHARSET = 0x08000000; 

    const UInt32 CFM_SMALLCAPS = 0x0040;   // (*) 
    const UInt32 CFM_ALLCAPS = 0x0080;   // Displayed by 3.0 
    const UInt32 CFM_HIDDEN = 0x0100;   // Hidden by 3.0 
    const UInt32 CFM_OUTLINE = 0x0200;   // (*) 
    const UInt32 CFM_SHADOW = 0x0400;   // (*) 
    const UInt32 CFM_EMBOSS = 0x0800;   // (*) 
    const UInt32 CFM_IMPRINT = 0x1000;   // (*) 
    const UInt32 CFM_DISABLED = 0x2000; 
    const UInt32 CFM_REVISED = 0x4000; 

    const UInt32 CFM_BACKCOLOR = 0x04000000; 
    const UInt32 CFM_LCID = 0x02000000; 
    const UInt32 CFM_UNDERLINETYPE = 0x00800000;  // Many displayed by 3.0 
    const UInt32 CFM_WEIGHT = 0x00400000; 
    const UInt32 CFM_SPACING = 0x00200000;  // Displayed by 3.0 
    const UInt32 CFM_KERNING = 0x00100000;  // (*) 
    const UInt32 CFM_STYLE = 0x00080000;  // (*) 
    const UInt32 CFM_ANIMATION = 0x00040000;  // (*) 
    const UInt32 CFM_REVAUTHOR = 0x00008000; 

    const UInt32 CFE_SUBSCRIPT = 0x00010000;  // Superscript and subscript are 
    const UInt32 CFE_SUPERSCRIPT = 0x00020000;  // mutually exclusive   

    const UInt32 CFM_SUBSCRIPT = (CFE_SUBSCRIPT | CFE_SUPERSCRIPT); 
    const UInt32 CFM_SUPERSCRIPT = CFM_SUBSCRIPT; 

    // CHARFORMAT "ALL" masks 
    const UInt32 CFM_EFFECTS = (CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_COLOR | 
         CFM_STRIKEOUT | CFE_PROTECTED | CFM_LINK); 
    const UInt32 CFM_ALL = (CFM_EFFECTS | CFM_SIZE | CFM_FACE | CFM_OFFSET | CFM_CHARSET); 

    const UInt32 CFM_EFFECTS2 = (CFM_EFFECTS | CFM_DISABLED | CFM_SMALLCAPS | CFM_ALLCAPS 
         | CFM_HIDDEN | CFM_OUTLINE | CFM_SHADOW | CFM_EMBOSS 
         | CFM_IMPRINT | CFM_DISABLED | CFM_REVISED 
         | CFM_SUBSCRIPT | CFM_SUPERSCRIPT | CFM_BACKCOLOR); 

    const UInt32 CFM_ALL2 = (CFM_ALL | CFM_EFFECTS2 | CFM_BACKCOLOR | CFM_LCID 
         | CFM_UNDERLINETYPE | CFM_WEIGHT | CFM_REVAUTHOR 
         | CFM_SPACING | CFM_KERNING | CFM_STYLE | CFM_ANIMATION); 
    #endregion 
} 

hơn bạn yêu cầu?

Tôi sử dụng hầu hết điều này thông qua một lớp tiện ích nhỏ kết thúc tốt đẹp cho tất cả các kiểu và thay đổi phông chữ. Bằng cách này bạn có thể thay đổi font-size và không thay đổi tên font chữ, vv

class RichTextStyle 
{ 
    private readonly Control _textEdit; 
    private readonly CHARFORMAT2 _charFormat; 

    public RichTextStyle(RichTextBox te) 
    { 
     _textEdit = te; 
     _charFormat = new CHARFORMAT2(); 
     _charFormat.cbSize = Marshal.SizeOf(_charFormat); 
     SendMessage(te.Handle, EM_GETCHARFORMAT, SCF_SELECTION, ref _charFormat); 
    } 

    private void SetEffect(UInt32 mask, UInt32 effect, bool valid) 
    { 
     CHARFORMAT2 fmt = new CHARFORMAT2(); 
     fmt.cbSize = Marshal.SizeOf(fmt); 
     fmt.dwMask = mask; 
     fmt.dwEffects = valid ? effect : 0; 
     SendMessage(_textEdit.Handle, EM_SETCHARFORMAT, SCF_SELECTION, ref fmt); 
    } 

    private bool GetEffect(UInt32 mask, UInt32 effect) 
    { 
     return (0 != (_charFormat.dwMask & mask)) && (0 != (_charFormat.dwEffects & effect)); 
    } 

    public bool Bold { get { return GetEffect(CFM_BOLD, CFE_BOLD); } set { SetEffect(CFM_BOLD, CFE_BOLD, value); } } 
    public bool Italic { get { return GetEffect(CFM_ITALIC, CFE_ITALIC); } set { SetEffect(CFM_ITALIC, CFE_ITALIC, value); } } 

    // ... etc ... etc ... you get the idea. 
+0

... wow. Thật tuyệt vời! Cảm ơn bạn. Tôi sẽ kiểm tra điều này ngay khi có thể. Bạn đã phát hành mã này theo giấy phép hay chúng tôi có thể tự do kết hợp nó vào mã của chúng tôi không? – NickAldwin

+0

Mọi thứ trên stackoverflow được cấp phép theo giấy phép commons sáng tạo được tìm thấy tại đây: http://creativecommons.org/licenses/by-sa/2.5/legalcode –

+0

BTW, tôi chấp nhận phiếu bầu và câu trả lời được chấp nhận là thanh toán đầy đủ :) –

2

Chỉ cần sử dụng:

richTextBox1.Clear(); 

... Nên làm các trick. Làm việc cho tôi.

+0

Đối với tôi đó xóa tất cả các văn bản - Tôi cần văn bản để vẫn có mặt ở đó, mà không định dạng. Tôi hiện đang sử dụng .Clear() kết hợp với một chuỗi tạm thời, như đã thấy trong bản chỉnh sửa ở trên. – NickAldwin

3

gì về

richTextBox.Text = richTextBox.Text.ToString(); 
+0

cảm ơn bạn rất nhiều! – NickAldwin

+0

Bạn được chào đón nhiều nhất, tôi rất vui khi thấy một câu hỏi tôi có thể trả lời! –

+0

Ack, chúng tôi đã thực hiện một số thử nghiệm khác và điều này không hoàn toàn phù hợp với chúng tôi. Có vẻ như Clear() làm một cái gì đó mà điều này không. Lấy làm tiếc! – NickAldwin

0

Một cách khác tôi đã tìm thấy (và một trong đó tôi đã chuyển sang sử dụng, vì nó không nhấp nháy) là để lấy các chuỗi rtf ban đầu trước khi bất kỳ định dạng được áp dụng:

string initialRtf = richTextBox.Rtf; 

Sau đó, khi tôi muốn thiết lập lại các định dạng, tôi có thể chỉ cần làm:

richTextBox.Rtf = initialRtf; 

Tuy nhiên, đây không phải là thực sự hoàn hảo, bởi vì nó đòi hỏi rằng văn bản ở lại như nhau và như vậy. Vâng, ít nhất nó tốt hơn một chút so với phương pháp được nêu chi tiết trong câu hỏi.

3

Tôi đã sử dụng

var t = richTextBox1.Text; 
richTextBox1.Text = t; 

EDIT ::

hãy chắc chắn để chèn một chú thích là tại sao bạn đang làm những gì bạn đang làm. Đối với người không biết, có vẻ vô lý.

+0

Chờ đợi, vậy việc sử dụng "var" có khiến bạn nghĩ rằng bạn đang đưa ra văn bản khác không? Bởi vì chỉ richTextBox.Text = richTextBox.Text hoặc = richTextBox.Text.ToString() hoặc sử dụng một chuỗi không hoạt động vì nội bộ nó kiểm tra xem liệu các chuỗi có khác nhau hay không trước khi tiến xa hơn nữa. – NickAldwin

+0

Tôi không biết. Tôi chỉ biết nó làm việc cho tôi. – Cheeso

+0

Tuyệt vời đơn giản! :) –

-1
RichTextBox rtbTemp = new RichTextBox(); 
rtbTemp.Text = rtb.Text; 
rtb.Rtf = rtbTemp.Rtf; 

hy vọng nó hoạt động

0

"Lý do tôi không thích những phương pháp trong Edit đầu tiên ở trên là nó làm cho hộp văn bản "flash" khi nó xóa nó sau đó nhập lại văn bản. "

Bạn sẽ có thể triển khai phương thức SuspendLayout() và ResumeLayout().

string tempTxt = richTextBox.Text; 
rtbIncludes.SuspendLayout(); 
richTextBox.Clear(); 
richTextBox.Text = tempTxt; 
rtbIncludes.ResumeLayout(); 

SuspendLayout() và ResumeLayout() sẽ ngăn điều khiển vẽ khi bạn thao tác dữ liệu. Nếu thao tác không mất nhiều thời gian, bạn sẽ có thể xóa văn bản và gán lại văn bản chưa định dạng mà không xuất hiện để nhấp nháy trên màn hình.

Nếu mất quá nhiều thời gian, điều khiển sẽ xuất hiện dưới dạng hình chữ nhật màu đen cho đến khi ResumeLayout() được gọi.

0

Trong một thời gian, tôi đã sử dụng mã này trong chương trình của riêng mình. Nó đặt RTF của RichTextBox trực tiếp, vì vậy sẽ nhanh hơn nhiều so với thiết lập kiểu theo cách thông thường. Nó lấy một chuỗi (văn bản chính), và tùy chọn cũng lấy mảng Màu, mảng cỡ chữ (int) và mảng trọng số phông chữ (bool), mỗi mảng đại diện cho mọi màu, kích thước hoặc phông chữ cho mỗi ký tự trong chuỗi.

Ngoài ra, bạn có thể chỉ cần giữ kích thước mặc định, trọng số, số nghiêng được cung cấp bởi tiêu đề.

public string text2RTF(string text, Color[] color = null, bool[] bold = null, int[] size = null, 
         string font = "Microsoft Sans Serif", double defaultFontSize = 16, 
         bool defaultFontBold = false, bool defaultFontItalic = false, char align = 'l') 
{ 
    StringBuilder rtf = new StringBuilder(); 
    rtf.Append(@"{\rtf1\ansi\ansicpg1252\deff0\deflang2057{\fonttbl{\f0\fnil\fcharset0 "); 
    rtf.Append(font); 
    rtf.Append(@";}}{\colortbl ;"); 

    if (color != null) 
    { 
     rtf.Append("\\red" + (color[0].R).ToString() + "\\green" + (color[0].G).ToString() + "\\blue" + (color[0].B).ToString() + ";"); 
     for (int i = 1; i < text.Length; i++) 
     { 
      if ((color[i].R != color[i - 1].R || color[i].G != color[i - 1].G || color[i].B != color[i - 1].B)) 
      { 
       rtf.Append("\\red" + (color[i].R).ToString() + "\\green" + (color[i].G).ToString() + "\\blue" + (color[i].B).ToString() + ";"); 
      } 
     } 
    } 


    rtf.Append("}\n\\viewkind4\\uc1\\pard"); 
    if (defaultFontBold == true) rtf.Append("\\b"); 
    if (defaultFontItalic == true) rtf.Append("\\i"); 

    if (align == 'r') rtf.Append("\\qr"); 

    rtf.Append("\\f0\\fs" + (Math.Round(defaultFontSize)).ToString()+" "); 
    int startOfActualText = rtf.Length; 

    int count = 1; 
    for (int i = 0; i < text.Length; i++) 
    { 
     if (color!=null && (i == 0 || color[i].R != color[i - 1].R || color[i].G != color[i - 1].G || color[i].B != color[i - 1].B)) 
     { 
      rtf.Append("\\cf"); rtf.Append(count.ToString() + " "); count++; 
     } 
     if (bold!=null && (i == 0 || bold[i] != bold[i - 1])) 
     { 
      if (bold[i] == true) rtf.Append("\\b1 "); 
      else rtf.Append("\\b0 "); 
     } 
     if (size!=null && (i == 0 || size[i] != size[i - 1])) 
     { 
      rtf.Append("\\fs"+size[i].ToString()+" ");     
     } 

     if (text[i] == '\\' || text[i] == '}' || text[i] == '{') rtf.Append('\\'); 

     // GetRtfUnicodeOfChar: 
     string st=""; 
     if (text[i] <= 0x7f) st = text[i].ToString(); 
     else st = "\\u" + Convert.ToUInt32(text[i]) + "?"; 


     rtf.Append(st); 
    } 

    rtf.Append("\n}"); 
    rtf.Replace("\n", "\\par\n", startOfActualText, rtf.Length - startOfActualText); 


    return rtf.ToString(); 

} 
+0

Văn bản đầu vào có ở định dạng RTF đang được phân tích cú pháp trong vòng lặp for không? Bạn có thể thêm một số ví dụ sử dụng không? Cảm ơn mã này! –

+0

@osstekz: Chuỗi văn bản đầu vào sẽ chỉ là văn bản tiếng Anh đơn giản. Mã sẽ tự động chuyển đổi văn bản thuần thành RTF. –

1

tôi thấy rằng có rất nhiều câu trả lời, nhưng tôi nghĩ rằng có đơn giản hơn và tiếp cận dễ dàng như phần mở rộng để xóa tất cả các định dạng:

Trong trường hợp của tôi, tôi cần rõ ràng định dạng và để lại một trống RichTextBox, do đó tôi đã thực hiện chức năng này:

private void ClearRichTextBox() 
{ 
    this.richTextBox1.ForeColor = Color.Empty; 
    this.richTextBox1.BackColor = Color.Empty; 
    this.richTextBox1.SelectAll(); 
    this.richTextBox1.SelectionColor = Color.Empty; 
    this.richTextBox1.SelectionBackColor = Color.Empty; 
    this.richTextBox1.SelectionFont = this.richTextBox1.Font; 
    this.richTextBox1.Clear(); 
} 

Sau đó, giải pháp dễ dàng là:

string backUp = this.richTextBox1.Text; 
ClearRichTextBox(); 
this.richTextBox1.Text = backUp; 

Hoặc chỉ cần xóa dòng this.richTextBox1.Clear(); trong chức năng rõ ràng. (Điều này có thể cũng sẽ hoạt động nhưng tôi không đảm bảo vì tôi đã thử nghiệm điều này chỉ trên các định dạng đơn giản. Do đó, có thể, bất kỳ dòng nào khác sẽ được thêm vào để xóa một định dạng khác.)

Khi văn bản cần không được xóa nhớ để lưu trữ vị trí/lựa chọn trước đó và trạng thái làm mới sau khi biến dạng dữ liệu.

-1

hoạt động tốt ..

var TempString = richTextBox1.Text; 
richTextBox1.Rtf = string.Empty; 
richTextBox1.Text = TempString ;