如何实现窗体的半透明效果,但窗体上的控件不需要透明处理

CCED136 2009-04-03 04:22:11
我现在某个程序中,需要一些特殊的现实效果。 现在我有一800X600 的窗体,居中放置了 300X400 的图片。现在显示时要求, 300X400 的图片正常显示,而窗体的空白区域需要实现半透明效果。

我测试了窗体的 AlphiBlend 相关属性, 但是会将 居中显示的 300X400 的图片一并 半透明了。 大家有没有比较好的方法可以实现这个需求?
...全文
756 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
CACACACACA 2009-04-10
  • 打赏
  • 举报
回复
看Jinjazz的BLOG, 他应该是早研究过了. 你下载他的程序看看, 效果如何, 延迟应该没有那么严重.

如何有标准WIN控件,眼前来看只能是叠加窗体.
constantine 2009-04-10
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 CCED136 的回复:]
呵呵,我下午结贴。

叠加窗体的效果确实不怎么样,只要一拖动窗口,延迟的效果太明显了。呵呵,看来这个问题有技术难度哦。
[/Quote]
应该不会吧,或许你写的代码有问题。我见过的例子没有这样的问题,不过是delphi写的。
代码好像是在以前Kingron大牛那个网站下的。不过用的是GDI+配合PNG的方法。

CCED136 2009-04-10
  • 打赏
  • 举报
回复
呵呵,我下午结贴。

叠加窗体的效果确实不怎么样,只要一拖动窗口,延迟的效果太明显了。呵呵,看来这个问题有技术难度哦。
Waiting4you 2009-04-08
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 CCED136 的回复:]
呵呵,刚才测试了 Waiting4you  的代码, 确实可行。

其实我这两天基本已经实现了我需要的功能,但是采用的方法是我前面说的,抓取背景重新蒙版显示。
(这种方法简单倒是简单,但是不能及时更新半透明背景。例如,如果被覆盖的窗口是个动态显示信
息的窗口,【例如正在播放状态的视频播放器或者音频播放器】,那么,一旦我的‘半透明’窗口执
行结束关闭时,这个时候被覆盖的窗口将重新显示出来,因此会给人一种很不真实的…
[/Quote]
这段代码是通过UpdateLayeredWindow直接设置窗体每个像素点,和用GDI+配合PNG的原理是一样的。如果要完美实现部分半透明,目前的方法只有用两个窗体,一个半透明一个不透明并叠在半透明窗体之上,我记得之前BCB版有位同学做了一个仿Vista效果的窗体就是用的这种方法,你可以找找。
constantine 2009-04-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 CCED136 的回复:]
哈哈,飘遥的安吉儿 ,你在 CSDN 的时间也是好几年了哦。记得 2001 的时候你好像就在哦。
[/Quote]

-_-! 我03年才知道有csdn这个网站。
CCED136 2009-04-07
  • 打赏
  • 举报
回复
呵呵,刚才测试了 Waiting4you 的代码, 确实可行。

其实我这两天基本已经实现了我需要的功能,但是采用的方法是我前面说的,抓取背景重新蒙版显示。
(这种方法简单倒是简单,但是不能及时更新半透明背景。例如,如果被覆盖的窗口是个动态显示信
息的窗口,【例如正在播放状态的视频播放器或者音频播放器】,那么,一旦我的‘半透明’窗口执
行结束关闭时,这个时候被覆盖的窗口将重新显示出来,因此会给人一种很不真实的感觉。因为被覆
盖窗口上显示的信息已经变了,但我蒙版时抓取的图片还是一段以前的截图,两项一对比太明显了)

初步测试了 Waiting4you 的代码,基本的效果已经完成了,但是确实存在不支持部分控件显示的
问题,并且像 TSpeedButton 之类的控件,鼠标点击时没有相关的被按下的状态显示了。:)
感觉比较好的地方,就是这段代码实现的效果,确实是真实的半透明状态了,被覆盖的窗口变化都能
够在上层半透明窗口中显示出来。

看来,如果要完美解决此问题,估计确实需要详细分析 Form 继承的 AlphaBlend 相关属性和方法
的实现。

最后2: Waiting4you , 能否深入研究一下此问题,我可以再开贴给分400,:)
CCED136 2009-04-07
  • 打赏
  • 举报
回复
呵呵,昨天没能上网,没看到大家的回复。我去试试,分不够的话我再开贴给分。
cczlp 2009-04-07
  • 打赏
  • 举报
回复
把小图片放在另外一个窗体上,把另外窗体放在主窗体上
ydlchina 2009-04-06
  • 打赏
  • 举报
回复
MARK
Waiting4you 2009-04-04
  • 打赏
  • 举报
回复
下面这段代码可以实现Image1不透明,窗体其它部分半透明。
窗体BorderStyle最好是None,否则bmp的高度和宽度要加上窗体标题栏和边栏部分。
目前窗体其它半透明控件只保证能支持TGraphicControl类型,如TLabel, TSpeedButton等(原因是PaintTo方法不能把Button类的子控件画到bmp上,试了PaintControls好像也不行,不知道大家有没有好办法)

void __fastcall TForm2::FormShow(TObject *Sender)
{
Graphics::TBitmap *bmp = new Graphics::TBitmap;
bmp->PixelFormat = pf32bit;
bmp->Width = Width;
bmp->Height = Height;
this->PaintTo(bmp->Canvas,0,0);

for(int y=0; y<bmp->Height; y++)
{
RGBQUAD *pixel = (RGBQUAD*)bmp->ScanLine[y];
for(int x=0; x<bmp->Width; x++,pixel++)
{
//如果位于Image1范围内,则不透明,否则半透明
if(PtInRect(Image1->BoundsRect,Point(x,y)))
pixel->rgbReserved = 0xff;
else
{
pixel->rgbBlue /= 2;
pixel->rgbGreen /= 2;
pixel->rgbRed /= 2;
pixel->rgbReserved = 0x80;
}
}
}

DWORD dwExStyle = GetWindowLong(Handle, GWL_EXSTYLE);
if ((dwExStyle & WS_EX_LAYERED) != WS_EX_LAYERED) SetWindowLong(Handle, GWL_EXSTYLE, dwExStyle|WS_EX_LAYERED);

// 关联BMP数据到窗体
BLENDFUNCTION blend={
AC_SRC_OVER,0,0xFF,AC_SRC_ALPHA
};
POINT ptWinPos = {Left,Top};
SIZE sizeWindow = {Width, Height};
POINT ptSrc = {0, 0};
UpdateLayeredWindow(Handle, 0, &ptWinPos,
&sizeWindow, bmp->Canvas->Handle , &ptSrc, 0, &blend, ULW_ALPHA);

delete bmp;
}
ahjoe 2009-04-04
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 CCED136 的回复:]
呵呵,谢谢大家关系此难题。我曾经想过,显示 400X300 的图片时,直接将窗口覆盖的背景抓图,然后显示在 800X600的窗体上并做蒙版处理(模拟半透明),最后再把 400X300的图片居中显示出来
[/Quote]

我也这样弄
CACACACACA 2009-04-04
  • 打赏
  • 举报
回复
窗体透明后,如何让窗体上的控件不透明。
以前论坛上有现在找不到了,论坛越升级越不好用
--------------------------------------------------------------- 感谢您使用微软产品。

如果您在Form中设置了您的Form的TransparencyKey的颜色,那么 Form中所有和TransparencyKey的颜色相同的地方都会变成透明的,您可以利用这个特点,实现您需要的效果。

您可以选择一种Form上所有的控件都不可能出现的颜色,把它设置为Form的TransparencyKey,然后把 Form的BackColor中的颜色也设置为TransparencyKey的颜色,您需要使Form上所有控件的前景色和背景色和Form的TransparencyKey设置的颜色不同,否则控件看上去将会变成透明的或者控件上的字将变成透明的。然后将Form的Opacity属性设置为100%,此时在Form上的控件是不透明的,但是Form的背景却是透明的。

此外,您需要注意的是透明的效果只能用于Windows2000和Windows XP。
CCED136 2009-04-04
  • 打赏
  • 举报
回复
呵呵,谢谢大家关系此难题。我曾经想过,显示 400X300 的图片时,直接将窗口覆盖的背景抓图,然后显示在 800X600的窗体上并做蒙版处理(模拟半透明),最后再把 400X300的图片居中显示出来
CACACACACA 2009-04-04
  • 打赏
  • 举报
回复
搞不定.给两个链接参考.

两个模仿 桌面天气秀的皮肤效果

http://rohna.w.blog.163.com/blog/static/145741652009023534832/

http://borland.mblogger.cn/Jinjazz/posts/21093.aspx

hemiya 2009-04-03
  • 打赏
  • 举报
回复
估计只能自己重写TForm的alphabend相关函数。
要是其它区域全透明,通过美工方法实现倒是简单。
fairchild811 2009-04-03
  • 打赏
  • 举报
回复
试了一下好像SetWindowLong和SetWindowAttributes不行
fairchild811 2009-04-03
  • 打赏
  • 举报
回复
alphabend是会这样,不直到setlong能不能单独设置,试试
CCED136 2009-04-03
  • 打赏
  • 举报
回复
哈哈,飘遥的安吉儿 ,你在 CSDN 的时间也是好几年了哦。记得 2001 的时候你好像就在哦。
constantine 2009-04-03
  • 打赏
  • 举报
回复
利用png可以达到你要的效果。记得ccrun的主页上好像有给利用png做半透明的例子。

13,871

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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