闪烁-透明度和BackgroundImages [英] Flickering - Transparency and BackgroundImages

查看:81
本文介绍了闪烁-透明度和BackgroundImages的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

***
我已经以自己的想法解决了这个问题.我已经在下面发布了我使用的解决方案.
***


大家好,

我对透明的子成员有问题,导致其父母的GradientBrushed背景图像闪烁.我想完全消除这种闪烁,不确定如何实现.

我将Panel的MouseMouse事件触发时,将Panel的背景图像设置为一个用LinearGradientBrush绘制的位图,并在MouseLeave事件触发时恢复为透明.

***
编辑-
我忘了提一下,我曾尝试使用Panel和每个对应的透明子成员的.SuspendLayout()和.ResumeLayout()来包围对绘画方法的调用.
***
我已经将主要形式的双缓冲和AllPaintingInWmPaint设置为true:

***
I have solved this solution with an idea I thought up myself. I have posted the solution I used below.
***


Hello everyone,

I am having an issue with transparent child members causing a flicker over their parent''s GradientBrushed background image. I would like to remove this flickering completely and am unsure how to make that happen.

I am setting a Panel''s background image to a bitmap painted with a LinearGradientBrush when the MouseEnter event of the Panel fires, and back to transparent once the MouseLeave event fires.

***
Edit -
I forgot to mention that I have tried surrounding the call to the drawing method with .SuspendLayout() and .ResumeLayout() for the Panel and each of the corresponding transparent child members.
***
I have set double buffering and AllPaintingInWmPaint to true for the main form:

// Style
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);



以下是我如何绘制渐变到包含透明标签的面板上的方法:



The following is how I am painting the gradient to the Panel which houses the transparent Labels:

System.Drawing.Drawing2D.LinearGradientBrush gradBrush;
            gradBrush = new System.Drawing.Drawing2D.LinearGradientBrush(
                new Rectangle { Height = panel.Height, Width = panel.Width }, Color.FromArgb(90, Color.DodgerBlue), Color.White, LinearGradientMode.Vertical);
            Bitmap bmp = new Bitmap(panel.Width, panel.Height);

            Graphics g = Graphics.FromImage(bmp);
            g.FillRectangle(gradBrush, new Rectangle(0, 0, panel.Width, panel.Height));
            panel.BackgroundImage = bmp;
            panel.BackgroundImageLayout = ImageLayout.Stretch;



我需要为面板小时候设置的每个标签设置一些东西,以消除闪烁吗?

这是我拍摄的屏幕截图,当我在面板上快速上下移动鼠标时,捕捉到了闪烁的画面:

http://i53.tinypic.com/2vb4wp0.png [



Is there something I need to set for each Label that the Panel has as a child to get the flicker to go away?

Here is a screen shot I have taken which catches the flicker in action as I move my mouse up and down over the panels very quickly:

http://i53.tinypic.com/2vb4wp0.png[^]

推荐答案

0)一次创建背景图像,并使用该预先创建的图像作为背景.之所以会出现闪烁,是因为表单正在重新绘制每个时间的渐变.

编辑================

1)尝试用SuspendLayout()ResumeLayout()包围图形代码.

编辑================

2)尝试使用此版本的SetStyle:

0) Create the background image one time, and use that pre-created image for the background. The flickering is probably being seen because the form is redrawing the gradient each tim.

EDIT ================

1) Try surrounding the drawing code with SuspendLayout() and ResumeLayout().

EDIT ================

2) Try this version of SetStyle:

SetStyle(ControlStyles.SupportsTransparentBackColor | 
         ControlStyles.Opaque | 
         ControlStyles.UserPaint |
         ControlStyles.AllPaintingInWmPaint, true);



编辑================

3)尝试将标签放入自己的透明面板中.

4)尝试绘制位图,然后将其放在带有标签的面板下*



EDIT ================

3) Try putting the labels into their own transparent panel.

4) Try painting to a bitmap and putting that *under* the panel holding the labels


OK,这是基于OP的澄清,它花费了相当长的时间,并且经过了漫长而富有成果的讨论关于正确的成员行为主题:-)我发现至少有一个大故障,肯定会引起强烈的闪烁.

消除闪烁的主要方法是双重缓冲.由于在Panel类型的某些控件上检测到易闪烁的呈现,因此,将Double Buffering应用于该控件很重要.在父窗体上使用此补救措施不会以任何方式影响子控件上的闪烁.

为了改善这种情况,应使用自定义控件.基类可以是Panel,但是正确的基类是Control.自定义控件应在其构造函数中设置anti-flicker属性:

OK, based on the clarifications by OP pulled over a considerable amount of time and between long and fruitful discussions on the topic of proper member behavior :-) I''ve found at least one big fault which certainly should cause strong flickering.

The major way of of fighting flicker is Double Buffering. As the flicker-prone rendering was detected on some control of the type Panel, it is important, that Double Buffering is applied to that control. Using this remedy on the parent Form would not effect flicker on the child control in any way.

To improve the situation, a custom Control should be used. A base class can be Panel, but proper base class is Control. The custom control should set up the anti-flicker property in its constructor:

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);



(为表单设置了相同的样式,但没有达到目的.)

任何其他导致或可能导致闪烁的控件也应以类似的方式构建.

免责声明:对于我不知道的OP代码所产生的任何其他闪烁源或任何其他有害影响,我概不负责.

建议OP优先考虑逻辑和理性考虑,而不要使用烹饪食谱. :-)

-SA



(Same styles were set for the Form but did not serve the purpose.)

Any other control which causes or can potentially cause flicker should be build in a similar way.

Disclaimer: I cannot take responsibility for any other source of flicker or any other unwanted effects created by the OP code which I am not aware of.

OP is recommended to prefer logical and rational considerations instead of the approach of cook-book recipe. :-)

—SA


Hello Self,

我相信我为您提供了一个很好的解决方案,具体如下:

无需使用Labels来显示文本,而需要使用Color.Transparent背景来显示Panel的背景,而是简单地创建一个自定义控件来扩展System.Windows.Forms.Panel类并重写OnPaint方法并将所需的文本直接绘制到自定义面板.

***请确保事先获得想要文本开始的确切点以及希望使用的字体.

这是我的写法示例:

Hello Self,

I believe I have a great solution for you, and it is as follows:

Instead of using Labels to display the text, which require a Color.Transparent background to allow for the Panel''s background to show through, simple create a custom control which extends the System.Windows.Forms.Panel class and override the OnPaint method and paint the desired text directly to the custom Panel.

***Be sure to get the exact points for where you want the Text to begin, and the Font you wish to use beforehand.

Here is an example of how I wrote it:

public partial class OpenNewPanel : System.Windows.Forms.Panel
{
    #region Members

    private const float TITLE_POINT_SIZE = 16;
    private const float DESCRIPTION_POINT_SIZE = 9;

    private Bitmap gradientBackground { get; set; }
    private Point titleLocation = new Point(156, 4);
    private Point descriptionLocation = new Point(161, 30);

    public string PanelTitle { get; set; }
    public string PanelDescription { get; set; }

    #endregion // Members

    /// <summary>
    /// Ctor
    /// </summary>
    public OpenNewPanel()
    {
        InitializeComponent();
        // Members
        this.PanelTitle = string.Empty;
        this.PanelDescription = string.Empty;
        // Styles
        SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
        // Misc
        InitializeBackgroundGradient();
        // Events
        this.MouseEnter += new EventHandler(OpenNewPanel_MouseEnter);
        this.MouseLeave += new EventHandler(OpenNewPanel_MouseLeave);
    }

    #region Overrides

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        //
        // --- Custom Paint Operations Below ---
        //
        //e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        Graphics graphics = e.Graphics;
        Font titleFont = new Font("Microsoft Sans Serif", TITLE_POINT_SIZE , FontStyle.Bold, GraphicsUnit.Point);
        Font descriptionFont = new Font("Microsoft Sans Serif", DESCRIPTION_POINT_SIZE , FontStyle.Regular, GraphicsUnit.Point);
        StringFormat format = new StringFormat();
        format.Alignment = StringAlignment.Near;

        this.SuspendLayout();
        this.InvokePaintBackground(this, e);
        // Draw Title
        graphics.DrawString(this.PanelTitle, titleFont, new SolidBrush(Color.Black), (PointF)this.titleLocation);
        // Draw Description
        graphics.DrawString(this.PanelDescription, descriptionFont, Brushes.Black,
            new RectangleF(this.descriptionLocation.X, this.descriptionLocation.Y, this.Width - this.descriptionLocation.X - 10, this.descriptionLocation.Y + 100),
            format);
        this.ResumeLayout();
    }

    #endregion // Overrides

    #region Events

    /// <summary>
    /// Fires when the mouse enters the Open New Panel
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OpenNewPanel_MouseEnter(object sender, EventArgs e)
    {
        SuspendLayout();
        this.BackgroundImage = this.gradientBackground;
        this.BackColor = Color.Transparent;
        ResumeLayout();
    }

    /// <summary>
    /// Fires when the mouse leaves the Open New Panel
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OpenNewPanel_MouseLeave(object sender, EventArgs e)
    {
        SuspendLayout();
        this.BackgroundImage = null;
        this.BackColor = Color.Transparent;
        ResumeLayout();
    }

    #endregion // Events

    #region Methods

    /// <summary>
    /// Creates a Vertical DodgerBlue to White Gradient Bitmap
    /// </summary>
    private void InitializeBackgroundGradient()
    {
        System.Drawing.Drawing2D.LinearGradientBrush gradBrush;
        gradBrush = new System.Drawing.Drawing2D.LinearGradientBrush(
            new Rectangle { Height = this.Height, Width = this.Width }, Color.FromArgb(90, Color.DodgerBlue), Color.White, LinearGradientMode.Vertical);
        Bitmap bmp = new Bitmap(this.Width, this.Height);
        Graphics g = Graphics.FromImage(bmp);
        g.FillRectangle(gradBrush, new Rectangle(0, 0, this.Width, this.Height));
        this.gradientBackground = bmp;
    }

    #endregion // Methods
}


这篇关于闪烁-透明度和BackgroundImages的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆