创建控件的透明部分以查看其下方的控件

我修改了CodeProject中的SuperContextMenuStrip ,以满足我的一些项目需求。 我将它用作GMap.NET地图控件上地图标记的工具提示。 以下是它的样子:

在此处输入图像描述

我想做的就是通过让它看起来更像泡泡来实现这一点。 与旧的Google Maps Stytle工具提示类似:

在此处输入图像描述

我花了一些时间搜索控制透明度,我知道这不是一件容易的事。 这个SO问题特别说明了这一点。

我已经考虑重写SuperContextMenuStripOnPaint方法来绘制SuperContextMenuStrip下面的SuperContextMenuStrip控件的背景,但即使在标记挂起GMap.NET控件的情况下也会失败:

在此处输入图像描述

创建我正在寻找的透明度类型的正确方法是什么?

在Windows窗体中,您可以通过定义区域来实现透明度(或绘制不规则形状的窗口)。 引用MSDN

窗口区域是操作系统允许绘制的窗口内的像素集合。

在您的情况下,您应该有一个位图,您将用作掩码。 位图应至少有两种不同的颜色。 其中一种颜色应代表您想要透明的控件部分。

然后,您将创建一个这样的区域:

 // 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); } 

然后,您可以将控件的Region设置为CreateRegion方法返回的Region。

 this.Region = CreateRegion(YourMaskBitmap); 

删除透明度:

 this.Region = new Region(); 

正如您可以从上面的代码中看出的那样,创建区域在资源方面是昂贵的。 如果您需要多次使用它们,我建议在变量中保存区域。 如果您以这种方式使用缓存区域,您很快就会遇到另一个问题。 赋值将在第一次工作,但您将在后续调用中获得ObjectDisposedException。

使用refrector进行一些调查会在Region属性的set访问器中显示以下代码:

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

Region对象在使用后处理! 幸运的是,Region是可克隆的,保存Region对象所需要做的就是分配一个克隆:

 private Region _myRegion = null; private void SomeMethod() { _myRegion = CreateRegion(YourMaskBitmap); } private void SomeOtherMethod() { this.Region = _myRegion.Clone(); }