Winform无边框窗体如何实现贴图的透明效果?

BG 2012-02-18 08:53:33


我想实现的效果是这样的:

通过给无边框的窗体贴上一张【带有阴影效果的图片】从而达到美观的效果。


但是,却遇到了这样的问题:

通过设置窗体的 BackColor 和 Transparencykey 两个属性实现了窗体的透明,但是将一张带有透明效果的PNG图片赋给 BackgroundImage 属性时,【窗体上的图片区域无法透明!】,按我预想的效果应该是【图片区域就是图片本身的效果,因为窗体完全透明了】,而实际情况感觉像是窗体还有一层东西挡住了透明效果。
当然通过设置窗体的 Opacity 属性可以更改窗体的透明度,但是这样一来窗体内包含的控件也就都跟着透明了。


在网上搜寻答案无果才来发帖求高手解决啊,分实在是不多,不好意思呃。

希望同样遇到过这样问题并解决的朋友给出你宝贵的经验啊,不胜感激。

或者说有更好的实现方法也希望你告诉我吧!多谢!


...全文
548 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
BG 2012-02-22
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 crystal_lz 的回复:]

引用 12 楼 fcgksoso 的回复:

引用 11 楼 crystal_lz 的回复:
引用 10 楼 fcgksoso 的回复:

#7的朋友,你的那个例子我已经下过看了,不太会用。

#8的朋友,你的代码我也试了,还是没能解决问题。

多谢。

话说 你调用那个方法了 ? 在 load事件里面 、、调用那个方法 传一个 png图片过去SetBits、、


……
[/Quote]

嗯,我的做法是这样的,那些控件的 BackgroundImage属性我也赋给了有透明度的PNG图,结果底色不是下层窗体的图, 而是上层窗体的BackColor。
crystal_lz 2012-02-22
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 fcgksoso 的回复:]

引用 11 楼 crystal_lz 的回复:
引用 10 楼 fcgksoso 的回复:

#7的朋友,你的那个例子我已经下过看了,不太会用。

#8的朋友,你的代码我也试了,还是没能解决问题。

多谢。

话说 你调用那个方法了 ? 在 load事件里面 、、调用那个方法 传一个 png图片过去SetBits、、


用是会用了,也确实是窗体内的控件都看不到了,但是还……
[/Quote]

在上面放一个 窗体啊 然后把窗体“掏空” 比如 this.backColor = Color.Blue ; Transportationkey = Color.Blue;这样 窗体不是 就空了 ?? 然后再这个窗体上面放你的控件、、
还有 你那句“叠加的那个窗体中放置的控件如果还包含有透明的背景” ?? 什么意思 ?、、、
BG 2012-02-21
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 crystal_lz 的回复:]
引用 10 楼 fcgksoso 的回复:

#7的朋友,你的那个例子我已经下过看了,不太会用。

#8的朋友,你的代码我也试了,还是没能解决问题。

多谢。

话说 你调用那个方法了 ? 在 load事件里面 、、调用那个方法 传一个 png图片过去SetBits、、
[/Quote]

用是会用了,也确实是窗体内的控件都看不到了,但是还能点击得到。
你说的再上面叠加一个窗体用来放控件,我不太明白了。叠加的那个窗体中放置的控件如果还包含有透明的背景,那么还是无法达到效果的。
crystal_lz 2012-02-21
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 fcgksoso 的回复:]

#7的朋友,你的那个例子我已经下过看了,不太会用。

#8的朋友,你的代码我也试了,还是没能解决问题。

多谢。
[/Quote]
话说 你调用那个方法了 ? 在 load事件里面 、、调用那个方法 传一个 png图片过去SetBits、、
BG 2012-02-20
  • 打赏
  • 举报
回复
#7的朋友,你的那个例子我已经下过看了,不太会用。

#8的朋友,你的代码我也试了,还是没能解决问题。

多谢。
BG 2012-02-20
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 ck2022 的回复:]

不如用wpf
[/Quote]


高手! 能指点一下我该如何实现吗?

或者,你的那DYD的源码可以分享么?

感激不尽啊。
crystal_lz 2012-02-19
  • 打赏
  • 举报
回复
如果 你想用png图片作为背景的话 话说非常麻烦 上次 我试验了一下
用png图片作为窗体成功了 可是窗体上面的控件不能显示了 话说 要什么重新绘制控件 果断绕开
然后 就只用用双层窗体 用那个png做的窗体作为背景 上面在叠加一个窗体显示控件

[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObj);

[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);

[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pptSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}

public const byte AC_SRC_OVER = 0;
public const Int32 ULW_ALPHA = 2;
public const byte AC_SRC_ALPHA = 1;

[DllImport("user32.dll", ExactSpelling = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteDC(IntPtr hDC);

[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteObject(IntPtr hObj);

public void SetBits(Bitmap bitmap) {
if (!Bitmap.IsCanonicalPixelFormat(bitmap.PixelFormat) || !Bitmap.IsAlphaPixelFormat(bitmap.PixelFormat))
throw new ApplicationException("图片必须是32位带Alhpa通道的图片。");

IntPtr oldBits = IntPtr.Zero;
IntPtr screenDC = GetDC(IntPtr.Zero);
IntPtr hBitmap = IntPtr.Zero;
IntPtr memDc = CreateCompatibleDC(screenDC);

try {
Point topLoc = new Point(Left, Top);
Size bitMapSize = new Size(bitmap.Width, bitmap.Height);
BLENDFUNCTION blendFunc = new BLENDFUNCTION();
Point srcLoc = new Point(0, 0);

hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
oldBits = SelectObject(memDc, hBitmap);

blendFunc.BlendOp = AC_SRC_OVER;
blendFunc.SourceConstantAlpha = 255;
blendFunc.AlphaFormat = AC_SRC_ALPHA;
blendFunc.BlendFlags = 0;

UpdateLayeredWindow(Handle, screenDC, ref topLoc, ref bitMapSize, memDc, ref srcLoc, 0, ref blendFunc, ULW_ALPHA);
} finally {
if (hBitmap != IntPtr.Zero) {
SelectObject(memDc, oldBits);
DeleteObject(hBitmap);
}
ReleaseDC(IntPtr.Zero, screenDC);
DeleteDC(memDc);
}
}

protected override void OnHandleCreated(EventArgs e) {
InitializeStyles();
base.OnHandleCreated(e);
}

protected override CreateParams CreateParams {
get {
CreateParams cParms = base.CreateParams;
cParms.ExStyle |= 0x00080000; // WS_EX_LAYERED
return cParms;
}
}

private void InitializeStyles() {
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
UpdateStyles();
}

这个代码是我在被人基础上改的、、、
nonocast 2012-02-19
  • 打赏
  • 举报
回复
http://www.codeproject.com/Articles/29184/A-lovely-goldfish-desktop-pet-using-alpha-PNG-and
dylike 2012-02-19
  • 打赏
  • 举报
回复
虽然我的东西很差劲,但我仍然希望它能够帮助你.
http://download.csdn.net/detail/dylike/4028682
BG 2012-02-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lesice 的回复:]
不如用wpf
[/Quote]

我也想用WPF啊,之前学了一段时间的WPF,感觉非常之棒啊,但是项目的原因,一时难以移植。
BG 2012-02-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 crackdung 的回复:]
用皮膚控件,自己設計皮膚將自己圖片增加進去就ok
[/Quote]

多谢您的提示,我去搜索了皮肤控件相关的内容,感觉收获不少,但是一时还难以实现掌握。
目前这个问题比较急于解决呃。
lesice 2012-02-18
  • 打赏
  • 举报
回复
不如用wpf
crackdung 2012-02-18
  • 打赏
  • 举报
回复
用皮膚控件,自己設計皮膚將自己圖片增加進去就ok
ck2022 2012-02-18
  • 打赏
  • 举报
回复
不如用wpf

110,545

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧