帮忙分析下酷我桌面歌词

asight 2011-07-30 06:42:03
求酷我桌面歌词原理。

我使用2种方式,效果都不好,详细如下:

1.SetLayeredWindowAttribute 设置透明色 ,全窗体因透明色而透明,然后GDI刷文本,周围出现很多窗体背景色的残余,非常锯齿。我换用gdi+,使用抗锯齿方式绘制跟gdi没有任何区别。

2.gdi+动态绘制文本为png再刷位图,贴图的方式低效总该无敌了吧,但是效果更差,为之奈何,我觉得酷我歌词就是上面的方式吧,但我实现不了,求高人

2种方式都有背景色残余的锯齿,我觉得应该是每次刷新背景导致的,我重载OnEraseBkgnd直接返回不刷背景色,现在倒好,文本背景直接一个白色矩形



求解答,鄙视灌水!,鄙视沙发!,鄙视废话!。







...全文
588 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
asight 2011-08-07
  • 打赏
  • 举报
回复
虽然问题解决 但是重绘上出现问题 最后找了很久 还是上面的delphi源码帮助我解决 我的updatelayeredWindow使用方式错误 导致重绘有问题
asight 2011-08-02
  • 打赏
  • 举报
回复
谢谢各位,问题解决了,使用GraphicsPath+UpdateLayeredWindow解决的,完美无锯齿
只是updateLayeredWindow调用后 再收不到WM_PAINT了。

有WS_TRANSPARENT风格,背景透明,我没试过,但是感觉应该不行的,RGB跟透明混合的中间色类似COLORREF:0,r,g,b 透明背景:0,X,X,X 这样alpha都是0,做抗锯齿没用,一样有中间色的。

问题解决 结贴了
asight 2011-08-01
  • 打赏
  • 举报
回复
我终于成功调用updateLayeredWindow,很简单,只有一个前提,不调用SetLayeredWindowAttrib就行了,之前我调用这个所以冲突了,关键是,调用之后!!不显示任何东西,包括之前刷的文本没了,窗体没了,Blend的alpha改0改255也不行 什么都不显示了,而且再也接收不到WM_PAINT消息了,现在怎么搞啊,什么都不能绘制了,什么都不能显示了,就算删掉调用updateLayeredWindow这句代码也回不来了,不知道为什么,我还以为是编译器出问题了,新建工程,调用updateLayeredWindow再删除这行代码,一切都不显示了,我哭
asight 2011-08-01
  • 打赏
  • 举报
回复
艹 中国的网络上都是狗屎 全部是创建当前window的hdc,真是操蛋 害死人 找个网页再找网页 继续找 只要中文网页都是他m的一样初始化代码 狗屁变量都是一样的 看看国外MS MVP给出的初始化代码:
HDC hdcScreen = GetDC(NULL);
HDC hDC = CreateCompatibleDC(hdcScreen);
HBITMAP hBmp = CreateCompatibleBitmap(hdcScreen, iWidth, iHeight);
这分明是创建桌面的hdc跟位图,国内的网页不要错都错一样的啊 害死我了 浪费我的时间
asight 2011-08-01
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 bdzwj 的回复:]

你的做法有问题, 使用GDI+分几次绘制,先用完全透明模式,绘制背景,然后使用抗锯齿模式创建一个文字路径,然后使用画刷直接fillpath 完成歌词绘制(中间如果需要处理歌词变色进度之类的,可分几次绘制),最后UpdateLayeredWindow()函数更新窗体刷新。 真没啥复杂的
[/Quote]
我重载EraseBkGnd自己刷透明色的背景行吗 还是SetLaredWindowAttirb指定就行
我已经填path了,还是带中间色残余,update调用失败
asight 2011-08-01
  • 打赏
  • 举报
回复
Update调用失败 不知道怎么搞 正确的不贴 看看代码:
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.AlphaFormat = AC_SRC_ALPHA;
blend.SourceConstantAlpha = 0;
::UpdateLayeredWindow(this->m_hWnd,hdcWnd, NULL,NULL,hdcMem,&p,RGB(0,0,0),&blend,ULW_COLORKEY)
问题就在这两句里面,blend可能初始化错了 其余参数用GetLastError返回0 地址也非NULL 怎么搞啊
allenhiman 2011-08-01
  • 打赏
  • 举报
回复
...可怜的卖女孩的小火柴。。。 做UI的 都被这些东西困扰过 什么锯齿了 半透明了 局部透明了。。。 你的这个需求的确可用 updatelayeredwindow. 你去codeproject找找 我记得我以前搞类似歌词这玩意儿时 看到过 它正好就有歌词的例子 我确认有这个 但是我就不帮你找了哈 呵呵 特别说明一下 这些透明 半透 如果下面放的是视频的话 很多时候是不好用的 (视频如果是GDI输出模式的没关系)
asight 2011-08-01
  • 打赏
  • 举报
回复
真不会用csdn,比博客园差远了,我不会改字体大小,不会改颜色,不会插code效果,不会贴图片,就是一行行字体不变颜色不变没有图片的文字 csdn可悲啊
asight 2011-08-01
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 haogeai123 的回复:]

我试了一下第一种方法,我是用SetLayeredWindowAttributes函数做的,效果几乎没有什么背景色的残留。
只要背景色和字体的颜色很接近是,就看不出残留了。

我测试是用背景色设为RGB(0,0,250),字体的颜色设为RGB(0,0,255),
然后把背景色去掉SetLayeredWindowAttributes(RGB(0,0,250),0,LWA_COLORKEY);……
[/Quote]
的确,我也试过,但是使用渐变画刷,颜色跨度大,中间残余色还是比较明显
asight 2011-08-01
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 tompaz 的回复:]

用UpdateLayeredWindow这个画吧
[/Quote]
我已经SetLayeredWindow过了 fill文字的path之后调用updateLayeredwindow失败 我不知道哪里错了
完整代码贴上 麻烦看看哪里有问题
CDC* pDC = this->GetDC();

StringFormat sf;
Gdiplus::Font font(L"黑体", 18);
FontFamily family;
font.GetFamily(&family);

PointF origin(0,0);


GraphicsPath path;
path.AddString(s, -1,&family, 0,26,origin,&sf);

SolidBrush br(Color::Violet);
Pen pen(Color::Gray,2);
pen.SetLineJoin(LineJoinRound);
Graphics g(pDC->m_hDC);
g.SetSmoothingMode(SmoothingModeHighQuality);
g.DrawPath(&pen,&path);
g.FillPath(&br, &path);
g.ReleaseHDC(pDC->m_hDC);

BLENDFUNCTION blend = { AC_SRC_OVER, 0, /*SourceConstantAlpha*/0, AC_SRC_ALPHA };

HDC hdcDesk = ::GetDC(NULL);
HDC hdcMem = ::CreateCompatibleDC(hdcDesk);
RECT rectWnd;
GetWindowRect(&rectWnd);
int iWidth = rectWnd.right-rectWnd.left;
int iHeight = rectWnd.bottom-rectWnd.top;
HBITMAP hBmp = ::CreateCompatibleBitmap(hdcDesk,iWidth,iHeight);
::SelectObject(hdcMem, hBmp);

POINT p = {0,0};
if (::UpdateLayeredWindow(m_hWnd,hdcDesk, NULL,NULL,hdcMem,&p,0,&blend,ULW_ALPHA))
haogeai123 2011-08-01
  • 打赏
  • 举报
回复
我试了一下第一种方法,我是用SetLayeredWindowAttributes函数做的,效果几乎没有什么背景色的残留。
只要背景色和字体的颜色很接近是,就看不出残留了。

我测试是用背景色设为RGB(0,0,250),字体的颜色设为RGB(0,0,255),
然后把背景色去掉SetLayeredWindowAttributes(RGB(0,0,250),0,LWA_COLORKEY);
由于两种颜色很接近,所以看不出有残留。
tompaz 2011-08-01
  • 打赏
  • 举报
回复
用UpdateLayeredWindow这个画吧
fandh 2011-08-01
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 asight 的回复:]
Update调用失败 不知道怎么搞 正确的不贴 看看代码:
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.AlphaFormat = AC_SRC_ALPHA;
blend.SourceConstantAlpha = 0;
::UpdateLayeredWindow(this-……
[/Quote]
全透明的初始化好像没有错误
jc5566 2011-08-01
  • 打赏
  • 举报
回复
学习中
haogeai123 2011-07-31
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 asight 的回复:]
艹csdn 怎么没有上传图片附件的东东
[/Quote]很多人不会上传图片,看来CSDN还得弄个教程才行啊






maquan 2011-07-31
  • 打赏
  • 举报
回复
我来解释一下你那个“背景色残余的锯齿”的来历吧,如果我说对了,那解决方法就简单了,如果说错了请高手指正。

你在单色背景(比如白色)上用前景色(比如蓝色)写字,系统为你做了抗锯齿处理,也就是在边缘补充了一些中间的过渡色(在这里就是浅蓝色),而你后来设置背景透明,白色部分透明了,而浅蓝色部分没有透明,所以你就看到了背景色残余的锯齿。

你在第 1 个方法中“使用抗锯齿方式绘制跟gdi没有任何区别”,当然,问题就是“抗锯齿”造成的。

问题的来源是“前景色与背景色之间做抗锯齿”导致的,解决方法,最简单就是“禁止抗锯齿”,具体如何做,我不清楚,没做过 :)

但是不抗锯齿会显得粗糙,更好的办法应该是使用 alpha channel,相当于“前景色与无色之间做抗锯齿”。具体如何做,我也不清楚,因为也没做过 :)

如果楼主最后解决了这个问题,希望能把方法贴出来,我也想学习学习。


————————————————————————————————
基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)
asight 2011-07-31
  • 打赏
  • 举报
回复
酷我歌词不是截图当前桌面做背景模仿透明的,是真正的背景透明
浩南_哥 2011-07-31
  • 打赏
  • 举报
回复
酷我的歌词还真没仔细看过,他那个歌词可能是先把桌面截图一下(部分截图)然后画在这上面的,有点类似手写笔,或是屏幕画板这类的。如果真是这样的,在给你推荐一个(也是delphi的)伴水的屏幕画板。
http://topic.csdn.net/u/20110331/02/D6330B1C-B4B3-4DF1-836F-CB08B48EDFE9.html#r_73340803
asight 2011-07-31
  • 打赏
  • 举报
回复
delphi版得很不错 真正实现酷我歌词这种效果 谢谢5楼
asight 2011-07-31
  • 打赏
  • 举报
回复
这个实例带了半透明窗体,只要窗体不是完全透明的,刷文字肯定没问题的,我要酷我歌词这种完全不带窗体的这种方式
加载更多回复(12)
本来在做项目,看到酷我音乐盒的歌词显示挺有趣的,模仿做了一个不完整的。 (只有滚动显示,没有节奏显示)。 原理: (1)定义一个派生自CStatic类的CKaraokeLyricCtrl类(歌词控件),自绘制风格 ; (2)准备一个背景位图(保存在CKaraokeLyricCtrl::m_dcBK中); (3)设置两个计数器(ID分别为1和2),启动自绘制,1用来显示节奏(未实现,只 有框架),2用来滚动歌词; (4)自绘制函数中,将绘制的滚动歌词和背景位图混合,然后输出到屏幕上。滚动 歌词的绘制使用GDI+的Graphics::DrawString函数,歌词文本的大小、位置、字体和 透明度均自动计算和变化,模仿酷我音乐盒的形式。 以上功能均封闭实现在CKaraokeLyricCtrl类中。该类可以直接使用(见下边的使用步骤)。 使用步骤: (1)CKaraokeLyric::InitInstance中启动GDI+; (2)在CKaraokeLyricView::OnInitialUpdate中,创建歌词控件 (CKaraokeLyricCtrl类),其大小和CKaraokeLyricView视图相同,即覆盖了后者; (3)在菜单项响应中,使用CKaraokeLyricCtrl::ReadLyric读取歌词文件,再使用 CKaraokeLyricCtrl::Start即可启动歌词的滚动显示 未实现部分:(歌词的节拍显示) 虽然没有实现,但思路大致是:在后台先用另外一种颜色绘制当前突出显示的歌词(即字体最大的一行歌词),根据歌曲节奏,将还未唱出部分全部涂黑,然后和屏幕上的当前行突出歌词进行混合。

15,976

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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