WinForms创建透明的可清除图片框覆盖

时间:2017-03-24 13:56:38

标签: c# winforms graphics picturebox transparent

我想在WinFrom应用程序中为pictureBox创建2个透明叠加层,这样我就可以单独绘制两者,当我想要空白透明叠加层时我也可以清除它。

在一个叠加上我绘制矩形。我一直想要这些矩形。

在第二个叠加层上我绘制圆圈,但我只想绘制1个圆圈,在用户输入后清除此圆圈并绘制另一个圆圈。

现在我正在使用

var transparentOverlay = pictureBox.createGraphics();

但我不知道如何清除叠加到空白透明图形。 我试过了

  1. transparentOverlay.Clear(Color.Transparent)将所有叠加层变为黑色
  2. pictureBox.Invalidate()清除了两个叠加层中的所有图形,因此我的矩形保持原位
  3. 使用我在任何绘图之前创建的一些备份图形,并通过将此图形指定给它transparentOverlay = transparentOverlayBackup来清除我的叠加层,但这没有做任何事情,所有矩形和所有圆圈都保留在它们的位置
  4. 有没有办法创建贴在pictureBox上的可清晰透明图形?

    修改

    我在该图片框中有一张带文字的图片。我想要做的是在文本的单词周围绘制矩形,这个矩形应该一直保留在图片上。

    比我想绘制一个圆圈并等待用户点击屏幕。这一切都还可以,但是当用户点击屏幕时,我想要清除那个圆圈并绘制另一个圆圈。

    first step show one circle second step after user click another circle show up but firs should disappear

    //this method I call by click on a button to start annotation
    private void ExpertAnnotate(object sender, EventArgs e)
    {
        var pen = new Pen(Color.Black, 1);
        if (!annotationIsRunning) //check if annotation is in process or not
        {
            annotationIsRunning = true;
    
            annotationOverlay = pictureBox.CreateGraphics(); //create transparent overlay for drawing
    
            //draw rectangles around all words in text (AOIs)
            annotationAOIs.ForEach(a =>
            {
                annotationOverlay.DrawRectangle(pen, a.Start.X, a.Start.Y, (a.End.X - a.Start.X), (a.End.Y - a.Start.Y));
            });
    
            //subscribe mouseMove and mouseClick events on pictureBox
            pictureBox.MouseMove += HighlightAOI;
            pictureBox.MouseClick += SelectAOI;
        }
    
        //define brushes for drawing circles (fixations)
        var brush = new SolidBrush(Color.FromArgb(128, Color.BlueViolet));
        var dotBrush = new SolidBrush(Color.DarkBlue);
        pen.Color = Color.Blue;
        long sizeOfFixation;
        var f = Fixations[fixationCounter - 1]; //get current fixation to draw
    
        sizeOfFixation = (int)f.Length / FIX_SIZE_COEFICIENT; //compute size of circle
        annotationOverlay.FillEllipse(dotBrush, f.PosX - 1, f.PosY - 1, 3, 3);
        //draw fixation on overlay
        annotationOverlay.FillEllipse(brush, (f.PosX - sizeOfFixation), (f.PosY - sizeOfFixation), sizeOfFixation * 2, sizeOfFixation * 2);
    }
    
    //eventHandler for mouseMove - this method color rectangle over which mouse hover to red border
    private void HighlightAOI(object sender, EventArgs e)
    {
        //this just draw last highlighted rect to black when we not yet hover mouse above it
        if (lastHighlightedAOI != null)
        {
            annotationOverlay.DrawRectangle(new Pen(Color.Black, 1), lastHighlightedAOI.Start.X, lastHighlightedAOI.Start.Y, (lastHighlightedAOI.End.X - lastHighlightedAOI.Start.X), (lastHighlightedAOI.End.Y - lastHighlightedAOI.Start.Y));
        }
        //get position of mouse sursor
        var x = pictureBox.PointToClient(Cursor.Position).X;
        var y = pictureBox.PointToClient(Cursor.Position).Y;
        var tempFix = new Fixation() { PosX = x, PosY = y };
    
        //get rectangle over which mouse hover
        lastHighlightedAOI = tempFix.LiesIn(annotationAOIs).FirstOrDefault();
    
        if (lastHighlightedAOI != null)
        {
            //highlight rectangle by painting red border
            annotationOverlay.DrawRectangle(new Pen(Color.Red, 1), lastHighlightedAOI.Start.X, lastHighlightedAOI.Start.Y, (lastHighlightedAOI.End.X - lastHighlightedAOI.Start.X), (lastHighlightedAOI.End.Y - lastHighlightedAOI.Start.Y));
        }
    }
    
    //eventHandler for mouse click
    private void SelectAOI(object sender, EventArgs e)
    {
        //get position of cursor
        var x = MousePosition.X;
        var y = MousePosition.Y;
        var tempFix = new Fixation() { PosX = x, PosY = y };
    
        //get rectangle which we selected by a mouse click
        var aoi = tempFix.LiesIn(annotationAOIs).FirstOrDefault();
    
        //assign last shown fixation to selected rectangle
        if (aoi != null)
        {
            aoi.AssignedFixations.Add(Fixations[fixationCounter - 1]);
        }
    
        //if it wasn't last fixation again call ExpertAnnotation function to draw another Fixation over image (!!! here I need to clear last drawn fixation (circle) disappear and draw next fixation in ExpertAnnotate method)
        if (fixationCounter != Fixations.Count)
        {
            ExpertAnnotate(sender, e);
        }
        else
        {
            TerminateExpertAnnotation("regular");
        }
    }
    

2 个答案:

答案 0 :(得分:0)

感谢@Reza Aghaei指导我聊天解决方案。

对我来说,可接受的解决方案是构建多层图像并将其分配给pictureBox.Image属性。

我通过从文件中加载图片来构建图像:

Image im = new Bitmap(path); // loads image from file

然后从此图像创建图形:

var g = Graphics.FromImage(im); // creates graphics from loaded image

将所有需要的矩形绘制到此图像,并将此图像备份到某个全局Image实例:

var pen = new Pen(Color.Black, 1);
// draws all rectangles on the image
annotationAOIs.ForEach(a =>
{
    g.DrawRectangle(pen, a.Start.X, a.Start.Y, (a.End.X - a.Start.X), (a.End.Y - a.Start.Y));
});
g.Dispose(); // disposes used graphics
ImageBackup = new Bitmap(im); // backup image with rectangles

在上面的部分中,我创建了一个静态的图像部分,它不会改变,我会备份它,所以下次我将从备份中创建新的Image实例,而不需要任何矩形绘图。

然后当我想在这张图片上显示新的圆圈时,我只是:

var image = new Bitmap(ImageBackup); // creates new instance of image with rectangles from backup
var g = Graphics.FromImage(image); // creates graphics from image

// in this part draw circle at specific point
var f = Fixations[fixationIndex];
sizeOfFixation = (int)f.Length / FIX_SIZE_COEFICIENT;
g.FillEllipse(dotBrush, f.PosX - 1, f.PosY - 1, 3, 3);
g.FillEllipse(brush, (f.PosX - sizeOfFixation), (f.PosY - sizeOfFixation), sizeOfFixation * 2, sizeOfFixation * 2);

pictureBox.Image.Dispose(); // dispose old pictureBox image
pictureBox.Image = image; // set new image

imageOverlay = pictureBox.CreateGraphics(); // get transparent graphics overlay for pictureBox so we can draw anything else over picture (in my case highlighting rectangles over which I hover a mouse)
g.Dispose(); // dispose used graphics

答案 1 :(得分:-1)

您最好的方法是使用PictureBox控件的OnPaint事件处理程序,并将所有绘图调用放在那里。

您可以使用传递给事件处理程序的Graphics对象来获取要绘制的表面(即图片框),然后使用各种方法绘制您所追求的形状。

画一个透明的'形状只是绘制轮廓而不是填充形状。