1

我的问题:如何禁用用户控件来绘制它的背景(或区域)

注意:我已经尝试覆盖并清空 OnPaintBackground 或将背景颜色设置为透明。

我正在尝试为自定义容器中的自定义用户控件绕过 winform 绘制。为此,我想尝试一下:Beginners-Starting-a-2D-Game-with-GDIplus

我的设置是:

  • 包含以下内容的表格:
    • 用户控件(绘图板)
    • 一个包含元素的容器,我可以将其拖放到此绘图板(它是一个列表框)。

我的渲染循环位于绘图板内,所有元素都在上一个链接中指定。

public DrawingBoard()
{
    InitializeComponent();

    //Resize event are ignored
    SetStyle(ControlStyles.FixedHeight, true);
    SetStyle(ControlStyles.FixedWidth, true);
    SetStyle(System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true);// True is better
    SetStyle(System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer, true); // True is better
    // Disable the on built PAINT event. We dont need it with a renderloop.
    // The form will no longer refresh itself
    // we will raise the paint event ourselves from our renderloop.
    SetStyle(System.Windows.Forms.ControlStyles.UserPaint, false); // False is better
}

#region GDI+ RENDERING
public Timer t = new Timer();
//This is your BackBuffer, a Bitmap:
Bitmap B_BUFFER = null;
//This is the surface that allows you to draw on your backbuffer bitmap.
Graphics G_BUFFER = null;
//This is the surface you will use to draw your backbuffer to your display.
Graphics G_TARGET = null;
Size DisplaySize = new Size(1120, 630);
bool Antialiasing = false;

const int MS_REDRAW = 32;

public void GDIInit()
{
    B_BUFFER = new Bitmap(DisplaySize.Width, DisplaySize.Height);
    G_BUFFER = Graphics.FromImage(B_BUFFER); //drawing surface
    G_TARGET = CreateGraphics();

    // Configure the display (target) graphics for the fastest rendering.
    G_TARGET.CompositingMode    = CompositingMode.SourceCopy;
    G_TARGET.CompositingQuality = CompositingQuality.AssumeLinear;
    G_TARGET.SmoothingMode      = SmoothingMode.None;
    G_TARGET.InterpolationMode  = InterpolationMode.NearestNeighbor;
    G_TARGET.TextRenderingHint  = TextRenderingHint.SystemDefault;
    G_TARGET.PixelOffsetMode    = PixelOffsetMode.HighSpeed;

    // Configure the backbuffer's drawing surface for optimal rendering with optional
    // antialiasing for Text and Polygon Shapes            
    //Antialiasing is a boolean that tells us weather to enable antialiasing.
    //It is declared somewhere else
    if (Antialiasing)
    {
        G_BUFFER.SmoothingMode      = SmoothingMode.AntiAlias;
        G_BUFFER.TextRenderingHint  = TextRenderingHint.AntiAlias;
    }
    else
    {
        // No Text or Polygon smoothing is applied by default
        G_BUFFER.CompositingMode    = CompositingMode.SourceOver;
        G_BUFFER.CompositingQuality = CompositingQuality.HighSpeed;
        G_BUFFER.InterpolationMode  = InterpolationMode.Low;
        G_BUFFER.PixelOffsetMode    = PixelOffsetMode.Half;
    }

    t.Tick += RenderingLoop;
    t.Interval = MS_REDRAW;
    t.Start();
}
void RenderingLoop(object sender, EventArgs e)
{
    try
    {
        G_BUFFER.Clear(Color.DarkSlateGray);
        UIPaint(G_BUFFER);
        G_TARGET.DrawImageUnscaled(B_BUFFER, 0, 0);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}
#endregion

然后我的元素触发事件并尝试绘制我想要的内容:

public override void UIPaint(Graphics g)
{     
    Pen p = new Pen(Color.Blue,4);
    p.Alignment = System.Drawing.Drawing2D.PenAlignment.Inset;          
    g.DrawLines(p, new Point[] { new Point(Location.X, Location.Y), new Point(Location.X + Width, Location.Y), new Point(Location.X + Width, Location.Y + Height), new Point(Location.X, Location.Y + Height), new Point(Location.X, Location.Y - 2) });

    g.DrawImageUnscaled(GDATA.GetWindowImage(), Location);        
    }

这是我的绘图板上发生的事情:

因为我不能发布图片...这里是链接:http ://s8.postimage.org/iqpxtaoht/Winform.jpg

  • 背景是 DarkSlateGray 因为我的 G_BUFFER 状态用它来清除每个刻度,好的
  • 蓝色矩形是我画的,但它被裁剪了,KO
  • 纹理被裁剪,KO
  • 裁剪我的绘图的区域是控件大小。

所以从那里我已经尽我所能禁用 WinForm 在后台制作一些魔术图。试图覆盖和清空所有在 Form/DrawingBoard/Elements 上获得绘制/更新/刷新/无效/验证的所有内容,但没有什么能让我的纹理或绘图不被控件背景裁剪:(

我还尝试将元素的背景设置为透明,并将 Form.TransparencyKey = blabla 设置为每个元素 BackColor = blabla。但每次都失败了。

我当然错过了一些东西:/但我不知道是什么。

4

1 回答 1

2

你为什么不想画背景?为了避免在我的自定义控件(派生自 class Control)中出现闪烁问题,这就是我所做的:

(1) 覆盖OnPaintBackground

protected override void OnPaintBackground(PaintEventArgs pevent)
{
}

(2)画在一个离屏Bitmap,然后转移到屏幕上:

Bitmap _completeFrame;
protected override void OnPaint(PaintEventArgs pe)
{
    DrawFrame(); // draws onto _completeFrame, calling new Bitmap() 
                 // when _completeFrame is null or its Size is wrong
    var g = pe.Graphics;
    g.DrawImage(_completeFrame, new Point());
}
于 2013-07-21T00:16:09.507 回答