Chinaunix首页 | 论坛 | 博客
  • 博客访问: 237228
  • 博文数量: 27
  • 博客积分: 270
  • 博客等级: 二等列兵
  • 技术积分: 444
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-21 19:55
个人简介

Enjoy yourself!

文章分类

分类: C/C++

2015-08-13 14:24:04

同样是菜单项目用到的,本来想做半透明和渐变的菜单,但后来由于各种原因只能放弃,简单记录一下要点,以备以后再用。

1、CDC画半透明(用于菜单项选中时候的选择色)

点击(此处)折叠或打开

  1. int nAlpha = 100;
  2. // 透明度,在0~254之间取值,越大越不透明
  3. BLENDFUNCTION stBlend = {AC_SRC_OVER, 0, nAlpha, 0};
  4.                     
  5. CDC dcAlphaRect;
  6. CBitmap bmpAlphaRect;
  7.                     
  8. dcAlphaRect.CreateCompatibleDC(pDC);
  9.                     

  10. bmpAlphaRect.CreateCompatibleBitmap(pDC,selRect.Width(),selRect.Height());
  11. CBitmap* pOld_Bitmap = dcAlphaRect.SelectObject(&bmpAlphaRect);
  12. dcAlphaRect.FillSolidRect( 0, 0, selRect.Width(), selRect.Height(), COLOR_SEL );

  13. AlphaBlend(pDC->m_hDC,
  14.             selRect.left, selRect.top,
  15.             selRect.Width(), selRect.Height(),
  16.             dcAlphaRect.m_hDC,
  17.             0,0,
  18.             selRect.Width(), selRect.Height(),
  19.             stBlend);

  20. dcAlphaRect.SelectObject(pOld_Bitmap);
  21. dcAlphaRect.DeleteDC();
  22. bmpAlphaRect.DeleteObject();

2、窗体透明

点击(此处)折叠或打开

  1. ModifyStyleEx(0, WS_EX_LAYERED);
  2. SetLayeredWindowAttributes(0,100,LWA_ALPHA);
  以上代码写在OnInitDialog函数中ModifyStyleEx(0, WS_EX_LAYERED);为窗体添加运行透明属性,而SetLayeredWindowAttributes则是设置透明度。LWA_ALPHA表示指定第二个参数为透明度,0~254之间,越大越不透明。参数改为LWA_COLORKEY则表示第一个参数指定的颜色变为透明。
  

点击(此处)折叠或打开

  1. ModifyStyleEx(0, WS_EX_LAYERED);
  2. COLORREF crKey = RGB(160, 160, 160);
  3. SetLayeredWindowAttributes(crKey,100,LWA_COLORKEY | LWA_ALPHA);

  如果将两种参数合并使用,那么颜色值为crKey的地方将变为全透明,并且鼠标是可以穿透过该区域的,而其它地方根据bAlpha参数确定透明度。温馨提示,如果将RGB设置为255,255,255 那么你将连标题框都点击不了。

关于分层窗体和透明窗体的博文,介绍的很深入:http://blog.163.com/ac_bc/blog/static/601647520119475322869/


3、菜单的背景透明(HOOK)

点击(此处)折叠或打开

  1. DWORD menuStyle = (DWORD)GetWindowLongPtrW(pWPS->hwnd, GWL_EXSTYLE);
  2. SetWindowLongPtrW(pWPS->hwnd, GWL_EXSTYLE, menuStyle | WS_EX_LAYERED);
  3. SetLayeredWindowAttributes(pWPS->hwnd, 0, 100, LWA_ALPHA);
  以上这段代码写在处理菜单的窗口过程MenuWndProc中的case WM_CREATE:,判断是否是菜单的创建下。
  但出现了一个非常奇怪的现象。我用的是Win7系统,一开始无论用别人程序还是自己程序,菜单都无法透明,整个菜单内容都没了,只剩一个背景。退出程序后一段时间,整个屏幕会黑屏闪一下,然后闪现菜单,之后又恢复正常。
  并且打开程序并多次召唤那个异常的菜单,整个电脑就会卡死,ctrl+alt+delete能唤出安全选项界面,但点击任何选项都没有办法实现该选项的功能,只能强制重启。以致于一天强制重启不下十遍,百思不得其解。
  (ps:下载了一个别人的程序是整条菜单栏而不是右键菜单,于是乎菜单是透明了,但多次显示子菜单后还是卡死了)
  后来偶然的一次,运行完程序后,桌面Aero效果消失了,然后运行程序竟然菜单内容就回来了,再也不卡死了。估计是钩子和Aero有冲突。网上有专门代码做Aero效果的,但考虑到软件需要向下兼容,就没往下细究了。知道缘由的大大麻烦指导一下啦。

开启Aero效果相关博文 http://blog.csdn.net/polytechnic/article/details/5696797


  关于渐变,其实正常来说应该是需要GDI+的吧,但是作为一只菜鸟还没学到GDI+,所以粗略说说GDI的做法。

点击(此处)折叠或打开

  1. pDC->Rectangle(selRect);

  2. int r1,g1,b1;
  3. //读取渐变起点的颜色值
  4. r1 = GetRValue(COLOR_BK_FROM);
  5. g1 = GetGValue(COLOR_BK_FROM);
  6. b1 = GetBValue(COLOR_BK_FROM);

  7. int r2,g2,b2;
  8. //读取渐变终点的颜色值
  9. r2 = GetRValue(COLOR_BK_TO);
  10. g2 = GetGValue(COLOR_BK_TO);
  11. b2 = GetBValue(COLOR_BK_TO);

  12. float r3,g3,b3;//菜单区域水平方向每个点RGB值应该变化的度(范围)
  13.     
  14. r3 = ((float)(r2-r1));  //  / (float)(itemRect.Width());
  15. g3 = (float)(g2-g1);    //  /(float)(itemRect.Width());
  16. b3 = (float)(b2-b1);    //  /(float)(itemRect.Width());

  17. float average = r3>g3 ? (r3>b3 ? r3 : b3) : (g3>b3 ? g3 : b3);
  18. average = average>(float)selRect.Width() ? (float)selRect.Width() : average;

  19. r3 /= average;
  20. g3 /= average;
  21. b3 /= average;
  22.   
  23. COLORREF r,g,b;//菜单区域水平方向每个点的颜色值
  24. CPen* m_oldpen = NULL;
  25.     
  26. for (int i = selRect.left;i<selRect.right;i++)
  27. {
  28.     r = r1+(int)r3*(i-selRect.left);
  29.     g = g1+(int)g3*(i-selRect.left);
  30.     b = b1+ (int)b3*(i-selRect.left);
  31.    
  32.     CPen m_pen (PS_SOLID,1,RGB(r,g,b));
  33.     m_oldpen = pDC->SelectObject(&m_pen);
  34.     pDC->MoveTo(i,selRect.top);
  35.     pDC->LineTo(i,selRect.bottom);
  36. }

  37. pDC->SelectObject(m_oldpen);

  代码思路就是将RGB值分开,通过计算将颜色值的改变用线填充起来。刚开始用r3 = ((float)(r2-r1)/ (float)(itemRect.Width());,但是在做菜单是还没有决定配色,要不断用颜色试效果,有时候因为itemRect比颜色跨度大,会直接变成颜色填充,而不是渐变。因此用r3 g3 b3 之间最大值,并且不大于itemRect.Width的值来算。缺点是变化量过小的时候就只有一部分是渐变,另一部分还是颜色填充。最后因为渐变配色太困难了还是放弃了。


  最后记录一个不相关的小技巧。
  在一开始想创建好字体供整体使用,但是实在找不到哪里可以获取LOGFONT结构体,所以自己创建。但是字体除了字体字号粗斜体以外,还有一些会被忽略的参数,此时可以在定义了LOGFONT了参数以后,调用CFontDialog,传入LOGFONT,查看返回的LOGFONT各参数哪些和定义的不一样,来确保LOGFONT,设置完成。
阅读(2855) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~