2010-04-21 9 views
0

J'ai un contrôle personnalisé hérité de RichTextBox. Ce contrôle a la capacité de "désactiver" l'édition de texte enrichi. Je crée cela en définissant simplement la propriété Rtf à la propriété text pendant l'événement TextChanged.Désactiver la peinture de VScrollbar dans un System.Windows.Forms.RichTextBox

c'est ainsi que mon code ressemble à:

 private bool lockTextChanged; 
     void RichTextBox_TextChanged(object sender, EventArgs e) 
     { 
      // prevent StackOverflowException 
      if (lockTextChanged) return; 

      // remember current position 
      int rtbstart = rtb.SelectionStart; 
      int len = rtb.SelectionLength; 


      // prevent painting     
      rtb.SuspendLayout(); 

      // set the text property to remove the entire formatting. 
      lockTextChanged = true; 
      rtb.Text = rtb.Text; 
      rtb.Select(rtbstart, len); 
      lockTextChanged = false; 

      rtb.ResumeLayout(true); 
     } 

Cela a bien fonctionné. Cependant, dans un texte volumineux avec 200 lignes, les commandes tremblent (vous voyez les premières lignes de texte pour le clin d'œil).

Pour éviter que cela se produise, je filtrer les WM_PAINT entre SuspendLayout() et ResumeLayout()

private bool layoutSuspended; 
    public new void SuspendLayout() 
    { 
     layoutSuspended = true; 
     base.SuspendLayout(); 
    } 

    public new void ResumeLayout() 
    { 
     layoutSuspended = false; 
     base.ResumeLayout(); 
    } 

    public new void ResumeLayout(bool performLayout) 
    { 
     layoutSuspended = false; 
     base.ResumeLayout(performLayout); 
    } 

    private const int WM_PAINT = 0x000F; 
    protected override void WndProc(ref System.Windows.Forms.Message m) 
    { 
     if (!(m.Msg == WM_PAINT && layoutSuspended)) 
      base.WndProc(ref m); 

    } 

qui a fait l'affaire, le RichTextBox ne sautillement anymoe.
C'est ce que je voulais faire, sauf une chose:
La barre de défilement est toujours instable chaque fois que je tape du texte à mon contrôle.

Maintenant ma question: Est-ce que quelqu'un a une idée pour moi comment empêcher la barre de défilement de redessiner pendant Suspend/Reprendre la disposition?

Répondre

3

SuspendLayout() ne va pas avoir d'effet, il n'y a pas de contrôles enfants dans un RTB qui doivent être organisés. RTB ne dispose pas des méthodes Begin/EndUpdate() que la plupart des contrôles ont, bien qu'il le prenne en charge. Il suspend la peinture, même si je ne suis pas sûr qu'il suspende les mises à jour de la barre de défilement. Ajoutez-les comme suit:

public void BeginUpdate() { 
    SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero); 
} 
public void EndUpdate() { 
    SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero); 
} 

// P/invoke declarations 
private const int WM_SETREDRAW = 0xb; 
[System.Runtime.InteropServices.DllImport("user32.dll")] 
private extern static IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); 

La meilleure façon d'empêcher l'utilisateur de modifier du texte est de définir la propriété ReadOnly sur True. La suppression complète de la barre de défilement est également possible en surchargeant CreateParams.

+0

Merci beaucoup pour cet indice. Je vais essayer (l'utilisateur devrait être capable de modifier le texte, mais je supprime à la volée tous les objets de mise en forme ou OLE qui provoquent la gigue.Qu'est-ce qu'un message est 0xb? –

+0

@Schla: 0xb est WM_SETREDRAW. –

+0

Cela fonctionne beaucoup, beaucoup, et je peux également ignorer la gestion de la méthode WM_PAINT dans la méthode WndProc. –