同样是菜单项目用到的,本来想做半透明和渐变的菜单,但后来由于各种原因只能放弃,简单记录一下要点,以备以后再用。
1、CDC画半透明(用于菜单项选中时候的选择色)
-
int nAlpha = 100;
-
// 透明度,在0~254之间取值,越大越不透明
-
BLENDFUNCTION stBlend = {AC_SRC_OVER, 0, nAlpha, 0};
-
-
CDC dcAlphaRect;
-
CBitmap bmpAlphaRect;
-
-
dcAlphaRect.CreateCompatibleDC(pDC);
-
-
-
bmpAlphaRect.CreateCompatibleBitmap(pDC,selRect.Width(),selRect.Height());
-
CBitmap* pOld_Bitmap = dcAlphaRect.SelectObject(&bmpAlphaRect);
-
dcAlphaRect.FillSolidRect( 0, 0, selRect.Width(), selRect.Height(), COLOR_SEL );
-
-
AlphaBlend(pDC->m_hDC,
-
selRect.left, selRect.top,
-
selRect.Width(), selRect.Height(),
-
dcAlphaRect.m_hDC,
-
0,0,
-
selRect.Width(), selRect.Height(),
-
stBlend);
-
-
dcAlphaRect.SelectObject(pOld_Bitmap);
-
dcAlphaRect.DeleteDC();
-
bmpAlphaRect.DeleteObject();
2、窗体透明
-
ModifyStyleEx(0, WS_EX_LAYERED);
-
SetLayeredWindowAttributes(0,100,LWA_ALPHA);
以上代码写在OnInitDialog函数中
ModifyStyleEx(0, WS_EX_LAYERED);为窗体添加运行透明属性,而
SetLayeredWindowAttributes则是设置透明度。
LWA_ALPHA表示指定第二个参数为透明度,0~254之间,越大越不透明。参数改为
LWA_COLORKEY则表示第一个参数指定的颜色变为透明。
-
ModifyStyleEx(0, WS_EX_LAYERED);
-
COLORREF crKey = RGB(160, 160, 160);
-
SetLayeredWindowAttributes(crKey,100,LWA_COLORKEY | LWA_ALPHA);
如果将两种参数合并使用,那么颜色值为crKey的地方将变为全透明,并且鼠标是可以穿透过该区域的,而其它地方根据bAlpha参数确定透明度。温馨提示,如果将RGB设置为255,255,255 那么你将连标题框都点击不了。
关于分层窗体和透明窗体的博文,介绍的很深入:http://blog.163.com/ac_bc/blog/static/601647520119475322869/
3、菜单的背景透明(HOOK)
-
DWORD menuStyle = (DWORD)GetWindowLongPtrW(pWPS->hwnd, GWL_EXSTYLE);
-
SetWindowLongPtrW(pWPS->hwnd, GWL_EXSTYLE, menuStyle | WS_EX_LAYERED);
-
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的做法。
-
pDC->Rectangle(selRect);
-
-
int r1,g1,b1;
-
//读取渐变起点的颜色值
-
r1 = GetRValue(COLOR_BK_FROM);
-
g1 = GetGValue(COLOR_BK_FROM);
-
b1 = GetBValue(COLOR_BK_FROM);
-
-
int r2,g2,b2;
-
//读取渐变终点的颜色值
-
r2 = GetRValue(COLOR_BK_TO);
-
g2 = GetGValue(COLOR_BK_TO);
-
b2 = GetBValue(COLOR_BK_TO);
-
-
float r3,g3,b3;//菜单区域水平方向每个点RGB值应该变化的度(范围)
-
-
r3 = ((float)(r2-r1)); // / (float)(itemRect.Width());
-
g3 = (float)(g2-g1); // /(float)(itemRect.Width());
-
b3 = (float)(b2-b1); // /(float)(itemRect.Width());
-
-
float average = r3>g3 ? (r3>b3 ? r3 : b3) : (g3>b3 ? g3 : b3);
-
average = average>(float)selRect.Width() ? (float)selRect.Width() : average;
-
-
r3 /= average;
-
g3 /= average;
-
b3 /= average;
-
-
COLORREF r,g,b;//菜单区域水平方向每个点的颜色值
-
CPen* m_oldpen = NULL;
-
-
for (int i = selRect.left;i<selRect.right;i++)
-
{
-
r = r1+(int)r3*(i-selRect.left);
-
g = g1+(int)g3*(i-selRect.left);
-
b = b1+ (int)b3*(i-selRect.left);
-
-
CPen m_pen (PS_SOLID,1,RGB(r,g,b));
-
m_oldpen = pDC->SelectObject(&m_pen);
-
pDC->MoveTo(i,selRect.top);
-
pDC->LineTo(i,selRect.bottom);
-
}
-
-
pDC->SelectObject(m_oldpen);
代码思路就是将RGB值分开,通过计算将颜色值的改变用线填充起来。刚开始用
r3 = ((float)(r2-r1)) / (float)(itemRect.Width());,但是在做菜单是还没有决定配色,要不断用颜色试效果,有时候因为itemRect比颜色跨度大,会直接变成颜色填充,而不是渐变。因此用r3 g3 b3 之间最大值,并且不大于itemRect.Width的值来算。缺点是变化量过小的时候就只有一部分是渐变,另一部分还是颜色填充。最后因为渐变配色太困难了还是放弃了。
最后记录一个不相关的小技巧。
在一开始想创建好字体供整体使用,但是实在找不到哪里可以获取LOGFONT结构体,所以自己创建。但是字体除了字体字号粗斜体以外,还有一些会被忽略的参数,此时可以在定义了LOGFONT了参数以后,调用CFontDialog,传入LOGFONT,查看返回的LOGFONT各参数哪些和定义的不一样,来确保LOGFONT,设置完成。
阅读(2825) | 评论(0) | 转发(0) |