3

我已经修改了CodeProject 中的SuperContextMenuStrip以满足我的一些项目需求。我将它用作GMap.NET Map Control上地图标记的工具提示。这是它的外观示例:

在此处输入图像描述

我想做的就是让它看起来更像一个泡沫,让它看起来更漂亮一点。类似于旧的 Google 地图样式工具提示:

在此处输入图像描述

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

我已经考虑覆盖 的OnPaint方法SuperContextMenuStrip来绘制位于 下方的 GMap.NET 控件的背景SuperContextMenuStrip,但即使在标记挂在 GMap.NET 控件上的情况下也会失败:

在此处输入图像描述

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

4

1 回答 1

3

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

然后将控件的区域设置为 CreateRegion 方法返回的区域。

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();
}
于 2012-11-21T19:22:32.200 回答