最近做了一个透明窗口,实现这样的功能:一个窗体完全透明,上面有几个图标,每个图标可以点击,但是透明窗体必须挡住后面的窗体,即禁止后面的窗体激活。此时必须使用两个窗体实现,一个为主窗体(TransparencyDlg),100%透明(采用LWA_COLORKEY过滤白色),上面有图标。另外一个窗体(CoverDlg)盖在它上面,99%透明(采用LWA_ALPHA实现),防止背后窗体激活。核心代码如下:
BOOL CTransparencyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
CCoverDlg *pDlg = new CCoverDlg();
pDlg->m_hTargetWnd = GetSafeHwnd();
pDlg->Create(IDD_DLGCOVER);
pDlg->ShowWindow(SW_SHOW);
HWND hWnd = GetSafeHwnd();
::SetWindowLong(hWnd, GWL_EXSTYLE, ::GetWindowLong(hWnd, GWL_EXSTYLE)|WS_EX_LAYERED|WS_EX_TOOLWINDOW);
::SetLayeredWindowAttributes(hWnd, RGB(255,255,255), 0, LWA_COLORKEY);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CTransparencyDlg::OnPaint()
{
if (!IsIconic())
{
CDialog::OnPaint();
RECT rect;
::GetWindowRect(::GetDesktopWindow(), &rect);
::MoveWindow(GetSafeHwnd(), 0, 0, rect.right-rect.left
, (UINT32)((rect.bottom-rect.top)*0.04), TRUE);
}
}
HBRUSH CTransparencyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何属性
if (nCtlColor==CTLCOLOR_DLG || nCtlColor==CTLCOLOR_STATIC)
{
return CreateSolidBrush(RGB(255, 255, 255));
}
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return hbr;
}
void CTransparencyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
TRACE2("CTransparencyDlg::OnLButtonDown(%d,%d)/r/n", point.x, point.y);
RECT rect;
HWND hFather = GetSafeHwnd();
HWND hNextChild = ::GetWindow(hFather, GW_CHILD);
while (::IsWindow(hNextChild))
{
if (::GetParent(hNextChild) == hFather
&& (::GetWindowLong(hNextChild, GWL_STYLE)&WS_VISIBLE) != NULL) //子窗体有效且可见
{
::GetWindowRect(hNextChild, &rect);
if(::PtInRect(&rect, point))
{
::SendMessage(hNextChild, WM_LBUTTONDOWN, (WPARAM)nFlags, MAKELPARAM(point.x, point.y));
break;
}
}
hNextChild = ::GetWindow(hNextChild, GW_HWNDNEXT);
}
CDialog::OnLButtonDown(nFlags, point);
}
void CTransparencyDlg::OnStnClickedPicture()
{
// TODO: 在此添加控件通知处理程序代码
TRACE("CTransparencyDlg::OnStnClickedPicture/r/n");
}
BOOL CCoverDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: 在此添加额外的初始化代码
HWND hWnd = GetSafeHwnd();
::SetWindowLong(hWnd, GWL_EXSTYLE, ::GetWindowLong(hWnd, GWL_EXSTYLE)|WS_EX_LAYERED|WS_EX_TOOLWINDOW);
::SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CCoverDlg::OnPaint()
{
if (!IsIconic())
{
CDialog::OnPaint();
RECT rect;
::GetWindowRect(::GetDesktopWindow(), &rect);
::MoveWindow(GetSafeHwnd(), 0, 0, rect.right-rect.left
, (UINT32)((rect.bottom-rect.top)*0.04), TRUE);
}
}
void CCoverDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
TRACE2("CCoverDlg::OnLButtonDown(%d,%d)/r/n", point.x, point.y);
::SendMessage(m_hTargetWnd, WM_LBUTTONDOWN, (WPARAM)nFlags, MAKELPARAM(point.x, point.y));
CDialog::OnLButtonDown(nFlags, point);
}
BOOL CTransparencyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
CCoverDlg *pDlg = new CCoverDlg();
pDlg->m_hTargetWnd = GetSafeHwnd();
pDlg->Create(IDD_DLGCOVER);
pDlg->ShowWindow(SW_SHOW);
HWND hWnd = GetSafeHwnd();
::SetWindowLong(hWnd, GWL_EXSTYLE, ::GetWindowLong(hWnd, GWL_EXSTYLE)|WS_EX_LAYERED|WS_EX_TOOLWINDOW);
::SetLayeredWindowAttributes(hWnd, RGB(255,255,255), 0, LWA_COLORKEY);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CTransparencyDlg::OnPaint()
{
if (!IsIconic())
{
CDialog::OnPaint();
RECT rect;
::GetWindowRect(::GetDesktopWindow(), &rect);
::MoveWindow(GetSafeHwnd(), 0, 0, rect.right-rect.left
, (UINT32)((rect.bottom-rect.top)*0.04), TRUE);
}
}
HBRUSH CTransparencyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何属性
if (nCtlColor==CTLCOLOR_DLG || nCtlColor==CTLCOLOR_STATIC)
{
return CreateSolidBrush(RGB(255, 255, 255));
}
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return hbr;
}
void CTransparencyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
TRACE2("CTransparencyDlg::OnLButtonDown(%d,%d)/r/n", point.x, point.y);
RECT rect;
HWND hFather = GetSafeHwnd();
HWND hNextChild = ::GetWindow(hFather, GW_CHILD);
while (::IsWindow(hNextChild))
{
if (::GetParent(hNextChild) == hFather
&& (::GetWindowLong(hNextChild, GWL_STYLE)&WS_VISIBLE) != NULL) //子窗体有效且可见
{
::GetWindowRect(hNextChild, &rect);
if(::PtInRect(&rect, point))
{
::SendMessage(hNextChild, WM_LBUTTONDOWN, (WPARAM)nFlags, MAKELPARAM(point.x, point.y));
break;
}
}
hNextChild = ::GetWindow(hNextChild, GW_HWNDNEXT);
}
CDialog::OnLButtonDown(nFlags, point);
}
void CTransparencyDlg::OnStnClickedPicture()
{
// TODO: 在此添加控件通知处理程序代码
TRACE("CTransparencyDlg::OnStnClickedPicture/r/n");
}
BOOL CCoverDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: 在此添加额外的初始化代码
HWND hWnd = GetSafeHwnd();
::SetWindowLong(hWnd, GWL_EXSTYLE, ::GetWindowLong(hWnd, GWL_EXSTYLE)|WS_EX_LAYERED|WS_EX_TOOLWINDOW);
::SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CCoverDlg::OnPaint()
{
if (!IsIconic())
{
CDialog::OnPaint();
RECT rect;
::GetWindowRect(::GetDesktopWindow(), &rect);
::MoveWindow(GetSafeHwnd(), 0, 0, rect.right-rect.left
, (UINT32)((rect.bottom-rect.top)*0.04), TRUE);
}
}
void CCoverDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
TRACE2("CCoverDlg::OnLButtonDown(%d,%d)/r/n", point.x, point.y);
::SendMessage(m_hTargetWnd, WM_LBUTTONDOWN, (WPARAM)nFlags, MAKELPARAM(point.x, point.y));
CDialog::OnLButtonDown(nFlags, point);
}