Creating a transparent portion of a control to see controls underneath it

青春壹個敷衍的年華 提交于 2019-12-01 09:07:48

In Windows Forms, you achieve transparency (or draw irregularly shaped windows) by defining a region. To quote MSDN

The window region is a collection of pixels within the window where the operating system permits drawing.

In your case, you should have a bitmap that you will use as a mask. The bitmap should have at least two distinct colors. One of these colors should represent the part of the control that you want to be transparent.

You would then create a region like this:

// this code assumes that the pixel 0, 0 (the pixel at the top, left corner) 
// of the bitmap passed contains the color you  wish to make transparent.

       private static Region CreateRegion(Bitmap maskImage) {
           Color mask = maskImage.GetPixel(0, 0);
           GraphicsPath grapicsPath = new GraphicsPath(); 
           for (int x = 0; x < maskImage.Width; x++) {
               for (int y = 0; y < maskImage.Height; y++) {
                   if (!maskImage.GetPixel(x, y).Equals(mask)) {
                           grapicsPath.AddRectangle(new Rectangle(x, y, 1, 1));
                       }
                   }
           }

           return new Region(grapicsPath);
       }

You would then set the control’s Region to the Region returned by the CreateRegion method.

this.Region = CreateRegion(YourMaskBitmap);

to remove the transparency:

this.Region = new Region();

As you can probably tell from the code above, creating regions is expensive resource-wise. I'd advice saving regions in variables should you need to use them multiple times. If you use cached regions this way, you'd soon experience another problem. The assignment would work the first time but you would get an ObjectDisposedException on subsequent calls.

A little investigation with refrector would reveal the following code within the set accessor of the Region Property:

         this.Properties.SetObject(PropRegion, value);
            if (region != null)
            {
                region.Dispose();
            }

The Region object is disposed after use! Luckily, the Region is clonable and all you need to do to preserve your Region object is to assign a clone:

private Region _myRegion = null;
private void SomeMethod() {
    _myRegion = CreateRegion(YourMaskBitmap);            
}

private void SomeOtherMethod() {
    this.Region = _myRegion.Clone();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!