闪烁-透明度和BackgroundImages [英] Flickering - Transparency and 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 withSuspendLayout()
andResumeLayout()
.
EDIT ================
2) Try this version ofSetStyle
:
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 typePanel
, 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 bePanel
, but proper base class isControl
. The custom control should set up the anti-flicker property in its constructor:
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
(为表单设置了相同的样式,但没有达到目的.)
任何其他导致或可能导致闪烁的控件也应以类似的方式构建.
免责声明:对于我不知道的OP代码所产生的任何其他闪烁源或任何其他有害影响,我概不负责.
建议OP优先考虑逻辑和理性考虑,而不要使用烹饪食谱. :-)
(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. :-)
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屋!