【Demo 0045】仿酷狗屏幕歌词窗体
今晚用酷狗听歌时看到它的歌词效果做不不错, 真的很棒,所以想玩一玩模仿一下, 就开始分析如何实现,我分析步骤
1. 实现不被最小化的窗体
发现显示桌面时它不会最小化,我在桌面窗体中没有看到它的存在, 难到它不是一个窗体吗? 我用SPY++查看,它是一个窗体,但为何它不会被最小化呢,看到这窗体风格我想是不是只
要设置这些就可以了呢, 开始写程序试,果然是这样的,我才知道只要设了WS_EX_TOPMOST扩展风格之后它就不会被最小化;
2. 字体窗体实现
通过BeginPath和EndPath得到路径再用PathToRegion得到字体的区域并用一个图片填充到区域中最后用SetWindowRgn函数改变窗体成文件区域的形状。 效果应该和这个差不多了。
按照这个思路, 我写了一个Demo, 关键代码
1. 实现第一个问题
DWORD dwStyleEx = WS_EX_LEFT|WS_EX_LTRREADING|WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_NOACTIVATE;
DWORD dwStyle = WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_SYSMENU;
HWND hWnd = CreateWindowEx(dwStyleEx, szClsName, szWndCaption, dwStyle, 0, 0, 930, 100, NULL, NULL, hInstance, NULL);
DWORD dwStyle = WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_SYSMENU;
HWND hWnd = CreateWindowEx(dwStyleEx, szClsName, szWndCaption, dwStyle, 0, 0, 930, 100, NULL, NULL, hInstance, NULL);
2. 实现第二个问题(开始用图片,感觉效果不好, 最后用对字体描述和填充的方式)
case WM_PAINT:
{
PAINTSTRUCT pt;
HDC hDC = BeginPaint(hWnd, &pt);
RECT rtClient;
GetClientRect(hWnd, &rtClient);
RECT rtTopUpper, rtBottomRight;
SetRect(&rtTopUpper, rtClient.left, rtClient.top, rtClient.right, (rtClient.bottom - rtClient.top) / 2);
SetRect(&rtBottomRight, rtClient.left, (rtClient.bottom - rtClient.top) / 2, rtClient.right, rtClient.bottom);
const TCHAR* szText1 = _T("Ôٻص½ËýµÄÉíÅÔ");
const TCHAR* szText2 = _T("¿´ËýµÄÎÂÈáÉÆÁ¼");
LOGFONT LogFont;
GetObject(GetCurrentObject(hDC, OBJ_FONT), sizeof(LOGFONT), &LogFont);
_tcscpy(LogFont.lfFaceName, _T("ºÚÌå"));
LogFont.lfHeight = 38;
LogFont.lfWidth = 19;
LogFont.lfQuality = CLEARTYPE_QUALITY;
HFONT hFont = CreateFontIndirect(&LogFont);
HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);
SelectObject(hDC, GetStockObject(DC_PEN));
SetDCPenColor(hDC, RGB(0, 0, 255));
SelectObject(hDC, GetStockObject(DC_BRUSH));
SetDCBrushColor(hDC, RGB(220, 12, 13));
BeginPath(hDC);
SetBkMode(hDC, TRANSPARENT);
DrawText(hDC, szText1, -1, &rtTopUpper, DT_LEFT|DT_SINGLELINE);
DrawText(hDC, szText2, -1, &rtBottomRight, DT_RIGHT|DT_SINGLELINE);
EndPath(hDC);
StrokeAndFillPath(hDC);
WidenPath(hDC);
BeginPath(hDC);
DrawText(hDC, szText1, -1, &rtTopUpper, DT_LEFT|DT_SINGLELINE);
DrawText(hDC, szText2, -1, &rtBottomRight, DT_RIGHT|DT_SINGLELINE);
EndPath(hDC);
HRGN hRgn = PathToRegion(hDC);
SetWindowRgn(hWnd, hRgn, FALSE);
SelectObject(hDC, hOldFont);
DeleteObject(hFont);
DeleteObject(hRgn);
EndPaint(hWnd, &pt);
return 0;
}
{
PAINTSTRUCT pt;
HDC hDC = BeginPaint(hWnd, &pt);
RECT rtClient;
GetClientRect(hWnd, &rtClient);
RECT rtTopUpper, rtBottomRight;
SetRect(&rtTopUpper, rtClient.left, rtClient.top, rtClient.right, (rtClient.bottom - rtClient.top) / 2);
SetRect(&rtBottomRight, rtClient.left, (rtClient.bottom - rtClient.top) / 2, rtClient.right, rtClient.bottom);
const TCHAR* szText1 = _T("Ôٻص½ËýµÄÉíÅÔ");
const TCHAR* szText2 = _T("¿´ËýµÄÎÂÈáÉÆÁ¼");
LOGFONT LogFont;
GetObject(GetCurrentObject(hDC, OBJ_FONT), sizeof(LOGFONT), &LogFont);
_tcscpy(LogFont.lfFaceName, _T("ºÚÌå"));
LogFont.lfHeight = 38;
LogFont.lfWidth = 19;
LogFont.lfQuality = CLEARTYPE_QUALITY;
HFONT hFont = CreateFontIndirect(&LogFont);
HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);
SelectObject(hDC, GetStockObject(DC_PEN));
SetDCPenColor(hDC, RGB(0, 0, 255));
SelectObject(hDC, GetStockObject(DC_BRUSH));
SetDCBrushColor(hDC, RGB(220, 12, 13));
BeginPath(hDC);
SetBkMode(hDC, TRANSPARENT);
DrawText(hDC, szText1, -1, &rtTopUpper, DT_LEFT|DT_SINGLELINE);
DrawText(hDC, szText2, -1, &rtBottomRight, DT_RIGHT|DT_SINGLELINE);
EndPath(hDC);
StrokeAndFillPath(hDC);
WidenPath(hDC);
BeginPath(hDC);
DrawText(hDC, szText1, -1, &rtTopUpper, DT_LEFT|DT_SINGLELINE);
DrawText(hDC, szText2, -1, &rtBottomRight, DT_RIGHT|DT_SINGLELINE);
EndPath(hDC);
HRGN hRgn = PathToRegion(hDC);
SetWindowRgn(hWnd, hRgn, FALSE);
SelectObject(hDC, hOldFont);
DeleteObject(hFont);
DeleteObject(hRgn);
EndPaint(hWnd, &pt);
return 0;
}
写完这个Demo后,感觉效果太差(比酷狗), 1. 字体锯齿感太强, 2. 还没有去实际字慕滚(效果太差了没欲望往后写)3. 拖动效果; 4. 渐变显示效果
总体来说思路还是比较靠谱,对实行手段要改一下; 算是先写一个雏形吧, 后期再用GDI+去实现,效果就应该会比较接近,灰太狼一句: “我一定还会回来的…”不达目标誓不休