创建控件的透明部分以查看其下方的控件 [英] Creating a transparent portion of a control to see controls underneath it

查看:52
本文介绍了创建控件的透明部分以查看其下方的控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经修改了CodeProject上的

我已经考虑过重写 SuperContextMenuStrip OnPaint 方法,以在 SuperContextMenuStrip 下方绘制GMap.NET控件的背景,但即使在标记悬空于GMap.NET控件的情况下,即使这样也会失败:

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

解决方案

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

窗口区域是窗口内像素的集合,其中操作系统允许绘图.

在您的情况下,您应该有一个位图,它将用作遮罩.位图应至少具有两种不同的颜色.这些颜色之一应表示要透明的控件部分.

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

 //此代码假定像素0、0(像素位于左上角)//传递的位图中的//包含您希望使其透明的颜色.私人静态区域CreateRegion(Bitmap maskImage){色彩遮罩= maskImage.GetPixel(0,0);GraphicsPath grapicsPath = new GraphicsPath();for(int x = 0; x< maskImage.Width; x ++){for(int y = 0; y< maskImage.Height; y ++){如果(!maskImage.GetPixel(x,y).Equals(mask)){grapicsPath.AddRectangle(new Rectangle(x,y,1,1));}}}返回新的Region(grapicsPath);} 

然后将控件的Region设置为CreateRegion方法返回的Region.

  this.Region = CreateRegion(YourMaskBitmap); 

删除透明度:

  this.Region = new Region(); 

从上面的代码中您可能可以看出,创建区域在资源上是昂贵的.如果您需要多次使用区域,我建议您将区域保存在变量中.如果您以这种方式使用缓存区域,您很快就会遇到另一个问题.该分配将在第一次运行,但在随后的调用中您将获得ObjectDisposedException.

对refrector进行的一些调查将发现Region属性的set访问器中的以下代码:

  this.Properties.SetObject(PropRegion,value);如果(区域!=空){region.Dispose();} 

Region对象在使用后被处置!幸运的是,该区域是可克隆的,并且保留区域对象所需要做的就是分配一个克隆:

 私有区域_myRegion = null;私人无效SomeMethod(){_myRegion = CreateRegion(YourMaskBitmap);}私人无效SomeOtherMethod(){this.Region = _myRegion.Clone();} 

I've modified the SuperContextMenuStrip found at CodeProject to meet some of my projects needs. I'm using it as a tooltip for map markers on a GMap.NET Map Control. Here is a sample of what it looks like:

What I would like to do is pretty this up a little by making it look more like a bubble. Similar to an old Google Maps stytle tooltip:

I've spent some time searching on control transparency and I know this isn't an easy thing. This SO question in particular illustrates that.

I have considered overriding the OnPaint method of the SuperContextMenuStrip to draw a background of the GMap.NET control that is underneath the SuperContextMenuStrip, but even that would fail in cases where the marker is hanging off the GMap.NET control:

What is the correct way to create the type of transparency I am looking for?

解决方案

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

这篇关于创建控件的透明部分以查看其下方的控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆