实现思路
用MFC多年了,在很多框架当道的今天说起MFC颇有点把玩老古董的意味,最近遇到一个任务需要实现透明对话框绘制图形,查找了一些资料,发现网上问MFC透明背景对话框上显示正常的控件或绘图的人很多,但找了许久都没发现有效的方法。最后自己采取了一种稍微取巧的方法实现了对话框背景透明,通过将获取对话框背景颜色并设置为透明实现对话框的透明,这里以实现桌面歌词效果为例来简要说明实现。
开工透明对话框
1.开发环境使用的是VS2015
2.首先创建一个MFC对话框工程,过程比较容易这里就不赘述了,直接来重点。
3.在资源界面,选择创建的对话框,修改右侧的边界属性为无(None)
3. 透明背景对话框核心实现
在对话框的OnInitDialog()函数中,添加如下代码:
BOOL CDesktopMusicLyricDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
LONG para = GetWindowLong(this->GetSafeHwnd(), GWL_EXSTYLE);
para |= WS_EX_LAYERED;
SetWindowLong(this->GetSafeHwnd(), GWL_EXSTYLE, para);
SetLayeredWindowAttributes(GetSysColor(COLOR_BTNFACE), 0, LWA_COLORKEY);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
这里要说一下其中的两个重要的函数:
SetLayeredWindowAttributes
BOOL SetLayeredWindowAttributes(
HWND hwnd, // 指定分层窗口句柄
COLORREF crKey, // 指定需要透明的背景颜色值,可用RGB()宏
BYTE bAlpha, // 设置透明度,0表示完全透明,255表示不透明
DWORD dwFlags // 透明方式
);
dwFlags参数可取以下值
LWA_ALPHA时:crKey参数无效,bAlpha参数有效;
LWA_COLORKEY:窗体中的所有颜色为crKey的地方将变为透明,bAlpha参数无效。其常量值为1。
LWA_ALPHA | LWA_COLORKEY:crKey的地方将变为全透明,而其它地方根据bAlpha参数确定透明度。
正是因为看到dwFlags可以取的值和效果才突然顿悟,可以通过设置crKey为对话框的背景颜色,dwFlags设置为LWA_COLORKEY,这样就会让对话框的背景颜色透明,bAlpha设置为0就可以对话框全透明了。
接下来问题就变成怎么获取到对话框的背景颜色,这里使用GetSysColor函数:
DWORD GetSysColor(int nIndex)
说明:判断指定windows显示对象的颜色。
返回值:DWORD,指定对象的RGB颜色。
nIndex的更多取值可以自行追到相应的头文件中查看,这里选用COLOR_BTNFACE,就得到对话框背景的颜色。
4.运行效果
在win7桌面背景之上,对话框已经透明,但是相应的按钮和文本控件不会透明,完美实现透明窗体效果,而且可以透过对话框选择到桌面上的文件。
实现歌词显示效果
歌词效果比较简单了,先把对话框的按钮和静态文本删除,歌词直接用DC进行绘制,这里就直接在OnPaint()函数进行TextOutW显示歌词。比较简单直接放上代码,设置字体和输出歌词文字。
CPaintDC dc(this); // 用于绘制的设备上下文
CRect rect;
GetClientRect(&rect);
CFont font;
font.CreateFont(23, // 字体的高度
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
0,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS,
_T("宋体"));
CFont *oldfont = dc.SelectObject(&font);
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(RGB(255, 0, 0));
dc.TextOutW(rect.left, rect.top, L"像我这样迷茫的人 像我这样寻找的人 像我这样碌碌无为的人 你还见过多少人");//0点位置
dc.SelectObject(&oldfont);
显示效果如下
源代码工程下载:点击下载代码