上周入手一个二手windows平板(目的只是为了玩),发现习惯使用手机悬浮球后,再转到winpad上操作极为不便,比如想显示桌面都要小心翼翼点,切换任务也比较麻烦(本人不习惯开启平板模式,使用的是常规桌面),只能抽空实现一个再windows上运行悬浮球了。
既然是球,那肯定是个圆的,好多年没碰MFC,依稀记得有一个API可以实现指定窗口透明色,然后达到异形窗口的目的,这就是SetLayeredWindowAttributes,一波操作下来,窗口确实能实现圆球形了,但是圆周边有很多毛边和锯齿,如图:
东西能用,但就是丑,然后继续网上找资料,大致锁定实现策略:
1、制作边缘柔化的PNG图,画布为透明色
2、使用GDI+加载PNG
3、调用UpdateLayeredWindow接口进行透明化窗口
最终效果如下:
最后增加个时钟,实现悬浮球自动贴边、隐藏等功能,回头再看看,终于满足我的审美和要求了,放在平板上运行,一切良好。下面贴出关键代码:
// 加载PNG资源
static Gdiplus::Bitmap* LoadPngRes(HINSTANCE hinst, const wchar_t* name)
{
auto hres = FindResourceW(hinst, name, L"PNG");
if (!hres)
return nullptr;//resource not found
if (auto size = SizeofResource(hinst, hres))
{
if (auto data = LockResource(LoadResource(hinst, hres)))
{
if (auto stream = SHCreateMemStream((const BYTE*)data, size))
{
auto* bmp = new Gdiplus::Bitmap(stream);
if (!bmp)
{
//wrong input, or gdiplus was not initialized
}
stream->Release();
return bmp;
}
}
}
return nullptr;
}
BOOL CMyGraphics::CreatePng(DWORD dwResID)
{
if (m_pMemDC != NULL)
{
m_pMemDC->SelectObject(m_pOldBmpPng);
m_pMemDC->DeleteDC();
delete m_pMemDC;
m_pMemDC = NULL;
}
m_pMemDC = new CDC;
if (!m_pMemDC->CreateCompatibleDC(NULL))
{
return FALSE;
}
m_pPng = LoadPngRes(AfxGetInstanceHandle(), MAKEINTRESOURCEW(dwResID));
Gdiplus::Color color;
HBITMAP hBitmap;
m_pPng->GetHBITMAP(color, &hBitmap);
m_pOldBmpPng = (HBITMAP)m_pMemDC->SelectObject(hBitmap);
m_nWidth = m_pPng->GetWidth();
m_nHeight = m_pPng->GetHeight();
return TRUE;
}
// 在OnPain事件中调用此接口进行贴图并透明化窗口
void CMyGraphics::DrawPng(HWND hWnd, BYTE bAlpha/* = 128*/)
{
CDC* pDestDC = CWnd::FromHandle(hWnd)->GetDC();
BLENDFUNCTION _Blend;
_Blend.BlendOp = 0;
_Blend.BlendFlags = 0;
_Blend.AlphaFormat = 1;
_Blend.SourceConstantAlpha = bAlpha;
CRect rcClient;
GetWindowRect(hWnd, &rcClient);
auto ptTL = CPoint(rcClient.left, rcClient.top);
SIZE sz = { m_nWidth, m_nHeight };
if (!m_fSetStyle)
{
DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
if ((dwExStyle & WS_EX_LAYERED) != WS_EX_LAYERED)
{
SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle | WS_EX_LAYERED);
}
m_fSetStyle = true;
}
UpdateLayeredWindow(hWnd, pDestDC->GetSafeHdc(), &ptTL, &sz, m_pMemDC->GetSafeHdc(), &CPoint(0, 0), 0, &_Blend, ULW_ALPHA);
}
编译好的EXE也已上传(请先安装VC++2015运行库): windows平板悬浮球-桌面系统文档类资源-CSDN下载
补充源码下载: