none
doublebuffer为true 造成的richtextbox滚动条切换窗口时消失的问题 RRS feed

  • 问题

  • 我在一个usercontrol里放置了一个richtextbox的继承类,richtextbox的背景设成了透明,使用以下api

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr LoadLibrary(string lpFileName);

    protected override CreateParams CreateParams
    {
    get
    {
    CreateParams prams = base.CreateParams;
    if (LoadLibrary("msftedit.dll") != IntPtr.Zero)
    {
    prams.ExStyle |= 0x020; // transparent
    prams.ClassName = "RICHEDIT50W";
    }
    return prams;
    }
    }

    然后在usercontrol里面设置了doublebuffer为true ,

    当键入内容,出现滚动条时,切换以下窗口后,发现滚动条消失了,只有当鼠标再次移到滚动条的位置,或者rtb发生了滚动,滚动条才能再次出现,

    为什么呢?怎么解决?希望高人指点!!


    Just On Life!
    2011年12月13日 7:16

全部回复

  • up,有高手给点建议。
    Just On Life!
    2011年12月14日 0:48
  • 我把 usercontrol的代码也贴一下,

    public partial class ContainerRTB : UserControl
    {
    private Bitmap _MemoryBM;
    private Graphics _Graphy;

    private Single _GridLines_Thickness;


    public Single GridLines_Thickness
    {
    get { return _GridLines_Thickness; }
    set { _GridLines_Thickness = value; }
    }

    private DashStyle _GridLines_Style;


    public DashStyle GridLines_Style
    {
    get { return _GridLines_Style; }
    set { _GridLines_Style = value; }
    }
    private Color _GridLines_Color;


    public Color GridLines_Color
    {
    get { return _GridLines_Color; }
    set { _GridLines_Color = value; }
    }

    private Color _Odd_Color;

    public Color Odd_Color
    {
    get { return _Odd_Color; }
    set { _Odd_Color = value; }
    }
    private Color _Even_Color;

    public Color Even_Color
    {
    get { return _Even_Color; }
    set { _Even_Color = value; }
    }

    public ContainerRTB()
    {
    InitializeComponent();

    this.Invalidate();
    //set doublebuffer as true
     this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);//ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer |
    this.SetStyle(ControlStyles.ResizeRedraw, true);

    this.Margin = new Padding(0);
    this.Padding = new Padding(0, 0, 0, 0);
    UpdateSizeAndPosition();
    _MKRichTextBox.ScrollBars = RichTextBoxScrollBars.Vertical;

    }

    private void CreateBuffer()
    {
    _MemoryBM = new Bitmap(ClientRectangle.Width
    , ClientRectangle.Height);
    _Graphy = Graphics.FromImage(_MemoryBM);
    }
    protected override void OnSizeChanged(EventArgs e)
    {
    CreateBuffer();
    this.Refresh();
    base.OnSizeChanged(e);
    this.Invalidate();
    }

    private void CreateBM(int offset)
    {
    Pen zPen = new Pen(_GridLines_Color, _GridLines_Thickness);

    zPen.DashStyle = _GridLines_Style;
    SolidBrush zBrush = new SolidBrush(this.ForeColor);
    Point zPoint = new Point(0, 0);

    Point zPointInParent = this.PointToScreen(this.ClientRectangle.Location);
    Point zPointInMe = _MKRichTextBox.PointToScreen(new Point(0, 0));

    int zParentInMe = zPointInParent.Y - zPointInMe.Y + 1 + offset;

    TimeSpan zTimeSpan = new TimeSpan(DateTime.Now.Ticks);
    zPoint = _MKRichTextBox.GetPositionFromCharIndex(0);
    SolidBrush colorBrush = null;
    for (int i = 0; i <= getLineCount(_ContentRectangle.Height, _MKRichTextBox.Height); i++)
    {

    if (i % 2 == 0)
    {
    colorBrush = new SolidBrush(_Even_Color);
    }
    else
    {
    colorBrush = new SolidBrush(_Odd_Color);
    }

    {
    _Graphy.FillRectangle(colorBrush, new Rectangle(0, zPoint.Y + _Line_Height * (i - 1) + zParentInMe, _MKRichTextBox.Width , _Line_Height - 1));

    _Graphy.DrawLine(zPen, new Point(0, zPoint.Y + _Line_Height * i + zParentInMe), new Point(_MKRichTextBox.Width , zPoint.Y + _Line_Height * i + zParentInMe));
    }
    if (_isScrolling && DateTime.Now.Ticks > zTimeSpan.Ticks + 500000)
    {

    _isScrolling = false;
    _timer.Start();
    break;
    }

    }

    if ((getLineCount(_ContentRectangle.Height, _MKRichTextBox.Height) + 1) % 2 == 0)
    {
    colorBrush = new SolidBrush(_Even_Color);
    }
    else
    {
    colorBrush = new SolidBrush(_Odd_Color);
    }

    {
    _Graphy.FillRectangle(colorBrush, new Rectangle(0, zPoint.Y + _Line_Height * getLineCount(_ContentRectangle.Height, _MKRichTextBox.Height) + zParentInMe, _MKRichTextBox.Width, _Line_Height - 1));
    }
    if (zPen != null)
    {
    zPen.Dispose();
    }

    if (colorBrush != null)
    {
    colorBrush.Dispose();
    }

    if (zBrush != null)
    {
    zBrush.Dispose();
    }
    }

    private int getLineCount(int contentHeight, int rtbHeight)
    {
    int ret = Math.Max(contentHeight, rtbHeight);
    if (_Line_Height != 0)
    {
    ret = ret / _Line_Height;
    }
    else
    {
    ret = 0;
    }
    return ret;
    }

    private void mkRichTextBox_VScroll(object sender, EventArgs e)
    {

    CreateBM(0);
    this.BackgroundImage = _MemoryBM;

    }

    private void mkRichTextBox_ContentsResized(object sender, ContentsResizedEventArgs e)
    {
    _ContentRectangle = e.NewRectangle;
    }

    private void ContainerRTB_Load(object sender, EventArgs e)
    {
    CreateBM(0);
    this.BackgroundImage = _MemoryBM;
    this.Refresh();
    }
     }

     

    如果把doublebuffer给打开就会出现切换窗口滚动条消失的 情况

    如果把doublebuffer关闭,拖动滚动条闪烁就比较严重,但是即使doublebuffer打开,也会闪烁,各位老师,看看我的代码是不是有问题,怎样来解决闪烁的问题呢??

     


    Just On Life!
    2011年12月14日 3:08
  • Hi Joe,

    欢迎来到 MSDN 论坛!

    根据您提供的代码,我并不能重现该项目。您能够把usercontrol.designer.cs中的代码提供下么?

    您也可以将整个项目发送给我: v-yoyj [at.....microsoft......dot ....com

    关于DoubleBuffer,您可以参考下面的链接:

    Using Double Buffering
    http://msdn.microsoft.com/en-us/library/ms229622.aspx

     

    我建议您单步调试下程序,看下是否有重复的“refresh()” 或者“Invalidate()”这样的方法调用。

     

    同时,下面这个项目提供了许多解决闪烁的方法:

    Don't Flicker! Double Buffer!

    http://www.codeproject.com/KB/graphics/DoubleBuffering.aspx

     

    期待您的回复。

    Yoyo.


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us

    2011年12月15日 15:46
    版主
  • Hi Joe,

    请问您的问题处理的怎么样了? 如果您有任何问题,请您告诉我们.

    谢谢!

    Yoyo.


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    2011年12月22日 3:16
    版主
  • yoyo

    我现在没有完全解决,但是解决了一部分,

    我重写了擦背景方法,但是字在拖拽的时候仍然会闪烁,背景不会再闪了。

    我的demo在

    https://skydrive.live.com/?cid=A655FDCAA663C3BF&id=A655FDCAA663C3BF%21690

    关于字的闪烁问题,希望能得到您的指点。我不大有思路。


    Just On Life!
    2011年12月22日 9:16
  • Hi Joe,

    请您修改下SkyDrive里面这个项目的访问权限。我无法下载该项目。

    谢谢。

    Yoyo.


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    2011年12月22日 12:33
    版主
  • Yoyo

    抱歉,开始不知道skydrive还有权限,我已将此文件放至公共目录下

    mktextbox


    Just On Life!
    2011年12月27日 5:25
  • Hi,

    给MKTextBox 也设置下双缓冲就行了:

            private void SetStyle()
            {
                this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
                //this.SetStyle(ControlStyles.UserPaint, true);
                //this.SetStyle( ControlStyles.AllPaintingInWmPaint, true);//ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer |
                this.SetStyle(ControlStyles.ResizeRedraw, true);
                this.Margin = new Padding(0);
                this.Padding = new Padding(0, 0, 0, 0);
            }
    

    请您至下面的链接下载更新后的项目:

    https://skydrive.live.com/redir.aspx?cid=37142ebae462f7f1&resid=37142EBAE462F7F1!125&parid=37142EBAE462F7F1!118

    祝,顺利!

     

     


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    2011年12月27日 13:53
    版主
  • Hi,

    给MKTextBox 也设置下双缓冲就行了:

     

            private void SetStyle()
            {
                this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
                //this.SetStyle(ControlStyles.UserPaint, true);
                //this.SetStyle( ControlStyles.AllPaintingInWmPaint, true);//ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer |
                this.SetStyle(ControlStyles.ResizeRedraw, true);
                this.Margin = new Padding(0);
                this.Padding = new Padding(0, 0, 0, 0);
            }
    

     

    请您至下面的链接下载更新后的项目:

    https://skydrive.live.com/redir.aspx?cid=37142ebae462f7f1&resid=37142EBAE462F7F1!125&parid=37142EBAE462F7F1!118

    祝,顺利!

     

     


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    yoyo 你把双缓冲打开后,没有发现我标题所述现象么? 就是内容多到有滚动条出现后,切换窗口,再切换回来,滚动条会消失!不知道是为什么,我怀疑是重绘区域计算造成的,但不知道如何解决。

    Just On Life!
    2011年12月28日 5:04
  • Hi Joe,

    请您试下我上传的项目. 我并不能重现您的问题,滚动条并没有因为窗体失去焦点就消失.

    我想您之前的问题大概在于,UpdateSizeAndPosition() 这一方法的调用失当.

    祝,万好.

    Yoyo.


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us

    2011年12月28日 6:19
    版主
  • hi,yoyo

    我下了你的项目,问题依然存在,可能是我说得不够清楚,不是失去焦点的时候滚动条消失,而是滚动条被覆盖后,消失。

    关于updatesizeandposition方法只是为了维持ui同步更新,依我的经验,如果系统在同一位置绘相同的图似乎不会出现闪烁,不知道我这个理解对不对。 在您更新的项目里,如果注掉doublebuffer的代码和updatesizepostion方法依然会出现很强的抖动。

    谢谢您如此快速的回复。


    Just On Life!
    2011年12月28日 6:32
  • 我没有尝试过,你是否可以给richtextbox发一个WM_VSCORLL类似的消息,或是调用SetScorePos方法要求系统来绘制。

    以上方法没测试过,仅是个建议


    2011 c# mvp China. *George读起来像不像“饺子”?我爱吃饺子,我叫George。
    2011年12月29日 3:03
    版主
  • 我没有尝试过,你是否可以给richtextbox发一个WM_VSCORLL类似的消息,或是调用SetScorePos方法要求系统来绘制。

    以上方法没测试过,仅是个建议


    2011 c# mvp China. *George读起来像不像“饺子”?我爱吃饺子,我叫George。
    谢谢wuyazhe的建议。
    SetScrollPos 我尝试过的,结果是仍然滚动条不显示,虽然实际上界面发生了滚动。因为用鼠标中键来滚动,滚动条在消失后也不会再出现,所以wm_scroll我想也不会有效。只有当鼠标移动到滚动条上,滚动条才会再次出现。
    Just On Life!
    2011年12月30日 3:07
  • Hi Joe,

    请您尝试下:   this.SetStyle(ControlStyles.DoubleBuffer, true); 替换之前 MKTextBox内的 this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

    祝,顺利!

     

     


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    2011年12月30日 3:28
    版主
  • Hi Joe,

    请您尝试下:   this.SetStyle(ControlStyles.DoubleBuffer, true); 替换之前 MKTextBox内的 this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

    祝,顺利!

     

     


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    hi,yoyo 这个也试过,效果是同样的。仍然会消失。

    Just On Life!
    2011年12月30日 3:30
  • Hi Joe,

    1. 在我原来上传的项目内,

    1.1 当滚动条被覆盖以后,例如窗体Form1被其他窗体如Windows Explorer (以下简称WE)遮盖,然后移去WE, 滚动条并不会消失.

    1.2 最小化窗体Form1,再Restore,此时滚动条会消失,最大化窗体,或者点击窗体内非滚动条的位置,滚动条并不会消失.只有鼠标点击到滚动条所在位置区域,滚动条才会重新显现.

    1.3 其他任何尝试,尚未发现滚动条消失的情况.

    请问您指的"滚动条消失"是不是情况1.2?

    2. 更新

    2.1 修改我上传的项目内,将 MKTextBox内的SetStyle()改为:

     

            private void SetStyle()
            {
                this.SetStyle(ControlStyles.DoubleBuffer, true);
                //this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
                //this.SetStyle(ControlStyles.UserPaint, true);
                //this.SetStyle( ControlStyles.AllPaintingInWmPaint, true);//ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer |
                this.SetStyle(ControlStyles.ResizeRedraw, true);
                this.Margin = new Padding(0);
                this.Padding = new Padding(0, 0, 0, 0);
            }
    

    效果: 最小化Form1,然后恢复Form1,滚动条并没有消失.

    注意: 我所提及的Form1,均指MKTextBox 方案内,TestApp项目中的Form1窗体.

    2.2 因为我上传的项目还有其他一些细微改动,所以,麻烦您针对我上传的项目进行修改.

    谢谢!

    祝,顺利!


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us


    2011年12月30日 5:30
    版主
  • Hi,

    请问您的问题处理的怎么样了?

    谢谢!

    yoyo


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    2012年1月2日 7:57
    版主
  • yoyo

    我下载了你的项目在我的机器win7pro上仍出现1.1所述问题,1.2原来我并没有注意。

     我注意到似乎不是每次每个窗口都会出现1.1所述问题,当我用一个窗口在滚动条上连续拖动覆盖其一部分,再让其显现出来,似乎效果更明显。


    Just On Life!
    2012年1月4日 1:18
  • Joe, Happy New Year.

    请问您根据此项目修改以后的结果呢? 如我帖子中2.1中所示. 请问1.2的问题解决了么?

     

    至于1.1, 无论此项目有没有作2.1的修改,都没有出现您提及的问题. 我也尝试了用一个窗口在滚动条上连续拖动覆盖其一部分,也没有出现滚动条消失的问题.

    我这边电脑是 Win 7企业版.但是我曾在自己的私人电脑上(Win 7 Pro)测试,也没有出现您所述的1.1 问题.

    请您多试试几台电脑. 

    谢谢.

     

     


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    2012年1月4日 3:15
    版主
  • Dear Yoyo,Happy new year.

    我又在两台xp机器上测试,一台在单位,一台在家里,用您的工程,1.1的问题始终出现。

    非常遗憾。

    我的工程不会出现1.1与1.2的问题,是因为我关掉了doublebuffer,然后重写了重绘方法。


    Just On Life!
    2012年1月4日 14:25