1 // LyricsWindow.cpp : 实现文件
2 //
3
4 #include "stdafx.h"
5 #include "LyricsWindow.h"
6
7 // CLyricsWindow
8
9 const Gdiplus::REAL TRANSLATE_FONT_SIZE_FACTOR = 0.88f; //歌词翻译文本大小占歌词文本大小的比例
10
IMPLEMENT_DYNAMIC(CLyricsWindow,CWnd)11 IMPLEMENT_DYNAMIC(CLyricsWindow, CWnd)
12
13 CLyricsWindow::CLyricsWindow()
14 {
15 HDC hDC=::GetDC(NULL);
16 m_hCacheDC=::CreateCompatibleDC(hDC);
17 ::ReleaseDC(NULL,hDC);
18 //---------------------------------
19 m_nHighlight=NULL ; //高亮歌词的百分比 0--100
20 m_TextGradientMode=LyricsGradientMode_Two ; //普通歌词渐变模式
21 m_pTextPen=NULL ; //普通歌词边框画笔
22 m_HighlightGradientMode=LyricsGradientMode_Two ; //高亮歌词渐变模式
23 m_pHighlightPen=NULL ; //高亮歌词边框画笔
24 m_pShadowBrush=NULL ; //阴影画刷,GDIPlus画刷
25 m_nShadowOffset=1 ; //阴影偏移
26 m_pFont=NULL ; //GDIPlus字体
27 m_FontStyle=NULL ;
28 m_FontSize=NULL ;
29 m_pTextFormat=NULL;
30 //---------------------------------
31 m_pFontFamily=new Gdiplus::FontFamily();
32 m_pTextFormat=new Gdiplus::StringFormat();
33 m_pTextFormat->SetFormatFlags(Gdiplus::StringFormatFlagsNoWrap);//不换行
34 m_pTextFormat->SetAlignment(Gdiplus::StringAlignmentCenter); //置水平对齐方式
35 m_pTextFormat->SetLineAlignment(Gdiplus::StringAlignmentNear); //置垂直对齐方式
36 //---------------------------------
37 //SetLyricsFont(L"微软雅黑", 40, Gdiplus::FontStyle::FontStyleRegular);
38 //SetLyricsColor(Gdiplus::Color::Red,Gdiplus::Color(255,172,0),LyricsGradientMode_Three);
39 //SetLyricsBorder(Gdiplus::Color::Black,1);
40 SetLyricsShadow(Gdiplus::Color(150,0,0,0),1);
41 //SetHighlightColor(Gdiplus::Color(255,100,26),Gdiplus::Color(255,255,0),LyricsGradientMode_Three);
42 //SetHighlightBorder(Gdiplus::Color::Black,1);
43
44 }
45
~CLyricsWindow()46 CLyricsWindow::~CLyricsWindow()
47 {
48 if(m_pTextPen){
49 delete m_pTextPen;
50 m_pTextPen=NULL;
51 }
52 if(m_pHighlightPen){
53 delete m_pHighlightPen;
54 m_pHighlightPen=NULL;
55 }
56 if(m_pShadowBrush){
57 delete m_pShadowBrush;
58 m_pShadowBrush=NULL;
59 }
60 if(m_pFontFamily){
61 delete m_pFontFamily;
62 m_pFontFamily=NULL;
63 }
64 if(m_pTextFormat){
65 delete m_pTextFormat;
66 m_pTextFormat=NULL;
67 }
68 if(m_pFont){
69 delete m_pFont;
70 m_pFont=NULL;
71 }
72 }
73
74
BEGIN_MESSAGE_MAP(CLyricsWindow,CWnd)75 BEGIN_MESSAGE_MAP(CLyricsWindow, CWnd)
76 ON_WM_LBUTTONDOWN()
77 END_MESSAGE_MAP()
78
79
80
81 BOOL CLyricsWindow::Create(int nHeight)
82 {
83 return CLyricsWindow::Create(_T("CometLyricsWindow"), -1, nHeight);
84 }
Create(LPCTSTR lpszClassName)85 BOOL CLyricsWindow::Create(LPCTSTR lpszClassName)
86 {
87 return CLyricsWindow::Create(lpszClassName,-1,-1);
88 }
Create(LPCTSTR lpszClassName,int nWidth,int nHeight)89 BOOL CLyricsWindow::Create(LPCTSTR lpszClassName,int nWidth,int nHeight)
90 {
91 if(!RegisterWndClass(lpszClassName))
92 {
93 TRACE(L"Class Registration Failedn");
94 }
95
96 //--------------------------------------------
97 //取出桌面工作区域
98 RECT rcWork;
99 SystemParametersInfo (SPI_GETWORKAREA,NULL,&rcWork,NULL);
100 int nWorkWidth=rcWork.right-rcWork.left;
101 int nWorkHeight=rcWork.bottom-rcWork.top;
102 //未传递宽度、高度参数时设置个默认值
103 if(nWidth<0)nWidth=nWorkWidth*2/3; //默认宽度为桌面宽度的2/3
104 if(nHeight<0)nHeight=150;
105 //设置左边、顶边位置,让窗口在屏幕下方
106 int x=rcWork.left+( (nWorkWidth-nWidth)/2 );
107 int y=rcWork.bottom-nHeight;
108 //--------------------------------------------
109 DWORD dwStyle=WS_POPUP|WS_VISIBLE|WS_THICKFRAME;
110 DWORD dwExStyle=WS_EX_TOOLWINDOW|WS_EX_TOPMOST|WS_EX_LAYERED;
111 BOOL rtn = CWnd::CreateEx(dwExStyle, lpszClassName, NULL, dwStyle, x, y, nWidth, nHeight, NULL, NULL);
112
113 return rtn;
114 }
RegisterWndClass(LPCTSTR lpszClassName)115 BOOL CLyricsWindow::RegisterWndClass(LPCTSTR lpszClassName)
116 {
117 HINSTANCE hInstance=AfxGetInstanceHandle();
118 WNDCLASSEX wndcls;
119 memset(&wndcls,0,sizeof(WNDCLASSEX));
120 wndcls.cbSize=sizeof(WNDCLASSEX);
121 if(GetClassInfoEx(hInstance,lpszClassName,&wndcls))
122 {
123 return TRUE;
124 }
125 if(GetClassInfoEx(NULL,lpszClassName,&wndcls))
126 {
127 return TRUE;
128 }
129
130 wndcls.style=CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
131 wndcls.lpfnWndProc=::DefWindowProc;
132 wndcls.hInstance=hInstance;
133 wndcls.hIcon=NULL;
134 wndcls.hCursor=::LoadCursor(NULL,IDC_ARROW);
135 wndcls.hbrBackground=(HBRUSH)(COLOR_BTNFACE+1);
136 wndcls.lpszMenuName=NULL;
137 wndcls.lpszClassName=lpszClassName;
138 if(!RegisterClassEx(&wndcls))
139 {
140 return FALSE;
141 }
142 return TRUE;
143 }
144
145
SetLyricDoubleLine(bool doubleLine)146 void CLyricsWindow::SetLyricDoubleLine(bool doubleLine)
147 {
148 m_bDoubleLine = doubleLine;
149 }
150
SetShowTranslate(bool showTranslate)151 void CLyricsWindow::SetShowTranslate(bool showTranslate)
152 {
153 m_bShowTranslate = showTranslate;
154 }
155
UpdateLyrics(LPCTSTR lpszLyrics,int nHighlight)156 void CLyricsWindow::UpdateLyrics(LPCTSTR lpszLyrics, int nHighlight)
157 {
158 m_lpszLyrics = lpszLyrics;
159 m_nHighlight = nHighlight;
160 }
161
SetNextLyric(LPCTSTR lpszNextLyric)162 void CLyricsWindow::SetNextLyric(LPCTSTR lpszNextLyric)
163 {
164 m_strNextLyric = lpszNextLyric;
165 }
166
UpdateLyricTranslate(LPCTSTR lpszLyricTranslate)167 void CLyricsWindow::UpdateLyricTranslate(LPCTSTR lpszLyricTranslate)
168 {
169 m_strTranslate = lpszLyricTranslate;
170 }
171
SetLyricChangeFlag(bool bFlag)172 void CLyricsWindow::SetLyricChangeFlag(bool bFlag)
173 {
174 m_lyricChangeFlag = bFlag;
175 }
176
GetLyricStr() const177 const CString& CLyricsWindow::GetLyricStr() const
178 {
179 return m_lpszLyrics;
180 }
181
Draw()182 void CLyricsWindow::Draw()
183 {
184 //CRect rcWindow;
185 GetWindowRect(m_rcWindow);
186 m_nWidth= m_rcWindow.Width();
187 m_nHeight= m_rcWindow.Height();
188 CRect rcClient;
189 GetClientRect(rcClient);
190 m_frameSize.cx = (m_rcWindow.Width() - rcClient.Width()) / 2;
191 m_frameSize.cy = (m_rcWindow.Height() - rcClient.Height()) / 2;
192
193 //----------------------------------
194 BITMAPINFO bitmapinfo;
195 bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
196 bitmapinfo.bmiHeader.biBitCount = 32;
197 bitmapinfo.bmiHeader.biHeight = m_nHeight;
198 bitmapinfo.bmiHeader.biWidth = m_nWidth;
199 bitmapinfo.bmiHeader.biPlanes = 1;
200 bitmapinfo.bmiHeader.biCompression=BI_RGB;
201 bitmapinfo.bmiHeader.biXPelsPerMeter=0;
202 bitmapinfo.bmiHeader.biYPelsPerMeter=0;
203 bitmapinfo.bmiHeader.biClrUsed=0;
204 bitmapinfo.bmiHeader.biClrImportant=0;
205 bitmapinfo.bmiHeader.biSizeImage = bitmapinfo.bmiHeader.biWidth * bitmapinfo.bmiHeader.biHeight * bitmapinfo.bmiHeader.biBitCount / 8;
206 HBITMAP hBitmap=CreateDIBSection (m_hCacheDC,&bitmapinfo, 0,NULL, 0, 0);
207 HBITMAP hOldBitmap = (HBITMAP)SelectObject (m_hCacheDC,hBitmap);
208 //----------------------------------
209 Gdiplus::Graphics* pGraphics=new Gdiplus::Graphics(m_hCacheDC);
210 pGraphics->SetSmoothingMode (Gdiplus::SmoothingModeAntiAlias);
211 pGraphics->SetTextRenderingHint (Gdiplus::TextRenderingHintAntiAlias);
212
213 // 计算逐字进度需要使用 Gdiplus::Graphics*,故在此获取将要显示的歌词、翻译、进度
214 PreDrawLyric(pGraphics, m_pFont);
215
216 bool bDrawTranslate = m_bShowTranslate && !m_strTranslate.IsEmpty();
217 if (m_bDoubleLine && !m_strNextLyric.IsEmpty() && !bDrawTranslate)
218 DrawLyricsDoubleLine(pGraphics);
219 else
220 DrawLyrics(pGraphics);
221 AfterDrawLyric(pGraphics);
222
223 delete pGraphics;
224 //----------------------------------
225 //设置透明窗口
226 CPoint DestPt(0,0);
227 CSize psize(m_nWidth,m_nHeight);
228 BLENDFUNCTION blendFunc32bpp;
229 blendFunc32bpp.AlphaFormat = AC_SRC_ALPHA;
230 blendFunc32bpp.BlendFlags = 0;
231 blendFunc32bpp.BlendOp = AC_SRC_OVER;
232 blendFunc32bpp.SourceConstantAlpha = m_alpha;
233 HDC hDC=::GetDC(m_hWnd);
234 ::UpdateLayeredWindow(m_hWnd,hDC,NULL,&psize,m_hCacheDC,&DestPt,0,&blendFunc32bpp,ULW_ALPHA);
235 //----------------------------------
236 //释放资源
237 ::SelectObject (m_hCacheDC,hOldBitmap);
238 ::DeleteObject(hBitmap);
239 ::ReleaseDC(m_hWnd,hDC);
240 }
241
DrawLyricText(Gdiplus::Graphics * pGraphics,LPCTSTR strText,Gdiplus::RectF rect,bool is_current,bool is_translate,bool draw_highlight)242 void CLyricsWindow::DrawLyricText(Gdiplus::Graphics* pGraphics, LPCTSTR strText, Gdiplus::RectF rect, bool is_current, bool is_translate, bool draw_highlight)
243 {
244 Gdiplus::REAL fontSize = is_translate ? m_FontSize * TRANSLATE_FONT_SIZE_FACTOR : m_FontSize;
245 if (fontSize < 1)
246 fontSize = m_FontSize;
247
248 Gdiplus::REAL textWidth = rect.Width;
249 Gdiplus::REAL highlighWidth = rect.Width * m_nHighlight / 1000;
250
251 if (!is_current) // 非当前歌词则左对齐,否则根据进度滚动
252 {
253 if (rect.X < 0)
254 rect.X = 0;
255 }
256 else
257 {
258 //如果文本宽度大于控件宽度,就要根据分割的位置滚动文本
259 if (textWidth > m_nWidth)
260 {
261 //如果分割的位置(歌词进度)剩下的宽度已经小于控件宽度的一半,此时使文本右侧和控件右侧对齐
262 if (textWidth - highlighWidth < m_nWidth / 2)
263 {
264 rect.X = m_nWidth - textWidth;
265 }
266 //分割位置剩下的宽度还没有到小于控件宽度的一半,但是分割位置的宽度已经大于控件宽度的一半时,需要移动文本使分割位置正好在控件的中间
267 else if (highlighWidth > m_nWidth / 2)
268 {
269 rect.X = m_nWidth / 2 - highlighWidth;
270 }
271 //分割位置还不到控件宽度的一半时,使文本左侧和控件左侧对齐
272 else
273 {
274 rect.X = 0;
275 }
276 }
277 }
278
279 //-----------------------------------------------------------
280 //画出阴影
281 if (m_pShadowBrush) {
282 Gdiplus::RectF layoutRect(0, 0, 0, 0);
283 layoutRect = rect;
284 layoutRect.X = layoutRect.X + m_nShadowOffset;
285 layoutRect.Y = layoutRect.Y + m_nShadowOffset;
286 Gdiplus::GraphicsPath* pShadowPath = new Gdiplus::GraphicsPath(Gdiplus::FillModeAlternate);//创建路径
287 pShadowPath->AddString(strText, -1, m_pFontFamily, m_FontStyle, fontSize, layoutRect, m_pTextFormat); //把文字加入路径
288 pGraphics->FillPath(m_pShadowBrush, pShadowPath);//填充路径
289 delete pShadowPath; //销毁路径
290 }
291
292 //-----------------------------------------------------------
293 //画出歌词
294 Gdiplus::GraphicsPath* pStringPath = new Gdiplus::GraphicsPath(Gdiplus::FillModeAlternate);//创建路径
295 pStringPath->AddString(strText, -1, m_pFontFamily, m_FontStyle, fontSize, rect, m_pTextFormat); //把文字加入路径
296 if (m_pTextPen) {
297 pGraphics->DrawPath(m_pTextPen, pStringPath);//画路径,文字边框
298 }
299 Gdiplus::Brush* pBrush = CreateGradientBrush(m_TextGradientMode, m_TextColor1, m_TextColor2, rect);
300 pGraphics->FillPath(pBrush, pStringPath);//填充路径
301 delete pBrush;//销毁画刷
302 if(draw_highlight)
303 DrawHighlightLyrics(pGraphics, pStringPath, rect);
304 delete pStringPath; //销毁路径
305 }
306
DrawLyrics(Gdiplus::Graphics * pGraphics)307 void CLyricsWindow::DrawLyrics(Gdiplus::Graphics* pGraphics)
308 {
309 int lyricHeight = m_nHeight - m_toobar_height;
310 //先取出文字宽度和高度
311 Gdiplus::RectF layoutRect(0,0,0,0);
312 Gdiplus::RectF boundingBox;
313 pGraphics->MeasureString (m_lpszLyrics, -1, m_pFont,layoutRect, m_pTextFormat,&boundingBox, 0, 0);
314 boundingBox.Width += 1; //测量到的文本宽度加1,以防止出现使用某些字体时,最后一个字符无法显示的问题
315 //计算歌词画出的位置
316 Gdiplus::RectF dstRect; //文字的矩形
317 Gdiplus::RectF transRect; //翻译文本的矩形
318 bool bDrawTranslate = m_bShowTranslate && !m_strTranslate.IsEmpty();
319 if(!bDrawTranslate)
320 {
321 switch (m_alignment)
322 {
323 case Alignment::LEFT:
324 dstRect = Gdiplus::RectF(0, m_toobar_height + (lyricHeight - boundingBox.Height) / 2, boundingBox.Width, boundingBox.Height);
325 break;
326 case Alignment::RIGHT:
327 dstRect = Gdiplus::RectF(m_nWidth - boundingBox.Width, m_toobar_height + (lyricHeight - boundingBox.Height) / 2, boundingBox.Width, boundingBox.Height);
328 break;
329 //居中
330 default:
331 dstRect = Gdiplus::RectF((m_nWidth - boundingBox.Width) / 2, m_toobar_height + (lyricHeight - boundingBox.Height) / 2, boundingBox.Width, boundingBox.Height);
332 }
333 }
334 else
335 {
336 Gdiplus::RectF transBoundingBox;
337 pGraphics->MeasureString(m_strTranslate, -1, m_pFont, layoutRect, m_pTextFormat, &transBoundingBox, 0, 0);
338 transBoundingBox.Width += 1; //测量到的文本宽度加1,以防止出现使用某些字体时,最后一个字符无法显示的问题
339 Gdiplus::REAL translateHeight = transBoundingBox.Height * TRANSLATE_FONT_SIZE_FACTOR;
340 Gdiplus::REAL translateWidth = transBoundingBox.Width * TRANSLATE_FONT_SIZE_FACTOR;
341 Gdiplus::REAL gapHeight = boundingBox.Height * 0.2f; //歌词和翻译之间的间隙
342 Gdiplus::REAL height = boundingBox.Height + gapHeight + translateHeight;
343 switch (m_alignment)
344 {
345 case Alignment::LEFT:
346 dstRect = Gdiplus::RectF(0, m_toobar_height + (lyricHeight - height) / 2, boundingBox.Width, boundingBox.Height);
347 transRect = Gdiplus::RectF(0, dstRect.GetBottom() + gapHeight, translateWidth, translateHeight);
348 break;
349 case Alignment::RIGHT:
350 dstRect = Gdiplus::RectF((m_nWidth - boundingBox.Width), m_toobar_height + (lyricHeight - height) / 2, boundingBox.Width, boundingBox.Height);
351 transRect = Gdiplus::RectF((m_nWidth - translateWidth), dstRect.GetBottom() + gapHeight, translateWidth, translateHeight);
352 break;
353 default:
354 dstRect = Gdiplus::RectF((m_nWidth - boundingBox.Width) / 2, m_toobar_height + (lyricHeight - height) / 2, boundingBox.Width, boundingBox.Height);
355 transRect = Gdiplus::RectF((m_nWidth - translateWidth) / 2, dstRect.GetBottom() + gapHeight, translateWidth, translateHeight);
356 break;
357 }
358 }
359
360 DrawLyricText(pGraphics, m_lpszLyrics, dstRect, true, false, m_lyric_karaoke_disp); // 是当前歌词,不是翻译,开启卡拉OK模式时高亮
361 if (bDrawTranslate)
362 DrawLyricText(pGraphics, m_strTranslate, transRect, true, true, false); // 是当前歌词,是翻译,不绘制高亮
363 }
364
DrawLyricsDoubleLine(Gdiplus::Graphics * pGraphics)365 void CLyricsWindow::DrawLyricsDoubleLine(Gdiplus::Graphics* pGraphics)
366 {
367 int lyricHeight = m_nHeight - m_toobar_height;
368 static bool bSwap{};
369 bSwap ^= m_lyricChangeFlag; // 如果歌词发生了改变,则交换当前歌词和下一句歌词的位置
370 //先取出文字宽度和高度
371 Gdiplus::RectF layoutRect(0, 0, 0, 0);
372 Gdiplus::RectF boundingBox;
373 pGraphics->MeasureString(m_lpszLyrics, -1, m_pFont, layoutRect, m_pTextFormat, &boundingBox, 0, 0);
374 boundingBox.Width += 1; //测量到的文本宽度加1,以防止出现使用某些字体时,最后一个字符无法显示的问题
375 Gdiplus::RectF nextBoundingBox;
376 pGraphics->MeasureString(m_strNextLyric, -1, m_pFont, layoutRect, m_pTextFormat, &nextBoundingBox, 0, 0);
377 nextBoundingBox.Width += 1; //测量到的文本宽度加1,以防止出现使用某些字体时,最后一个字符无法显示的问题
378 // 计算歌词画出的位置
379 Gdiplus::RectF dstRect{0, m_toobar_height + (lyricHeight / 2 - boundingBox.Height) / 2, boundingBox.Width, boundingBox.Height};
380 Gdiplus::RectF nextRect{0, dstRect.Y + lyricHeight / 2, nextBoundingBox.Width, nextBoundingBox.Height};
381 if (bSwap) std::swap(dstRect.Y, nextRect.Y);
382 switch (m_alignment)
383 {
384 case Alignment::RIGHT:
385 dstRect.X = m_nWidth - dstRect.Width;
386 nextRect.X = m_nWidth - nextRect.Width;
387 break;
388 case Alignment::AUTO:
389 if (bSwap)
390 dstRect.X = m_nWidth - dstRect.Width;
391 else
392 nextRect.X = m_nWidth - nextRect.Width;
393 break;
394 case Alignment::CENTER:
395 dstRect.X = (m_nWidth - dstRect.Width) / 2.0f;
396 nextRect.X = (m_nWidth - nextRect.Width) / 2.0f;
397 break;
398 default:
399 break;
400 }
401 DrawLyricText(pGraphics, m_lpszLyrics, dstRect, true, false, true); // 当前歌词,不是翻译,显示高亮
402 DrawLyricText(pGraphics, m_strNextLyric, nextRect, false, false, false); // 下一句歌词,不是翻译,不显示高亮
403 }
404
405 //绘制高亮歌词
DrawHighlightLyrics(Gdiplus::Graphics * pGraphics,Gdiplus::GraphicsPath * pPath,Gdiplus::RectF & dstRect)406 void CLyricsWindow::DrawHighlightLyrics(Gdiplus::Graphics* pGraphics,Gdiplus::GraphicsPath* pPath, Gdiplus::RectF& dstRect)
407 {
408 if (m_nHighlight <= 0 || m_nHighlight >= 1000) return; // 对于大于等于1000的进度不绘制高亮
409 Gdiplus::Region* pRegion=NULL;
410 if (m_lyric_karaoke_disp){ // 卡拉OK模式下需要根据进度裁剪绘制高亮区域
411 Gdiplus::RectF CliptRect(dstRect);
412 CliptRect.Width=CliptRect.Width * m_nHighlight / 1000;
413 pRegion=new Gdiplus::Region(CliptRect);
414 pGraphics->SetClip(pRegion, Gdiplus::CombineModeReplace);
415 }
416 //--------------------------------------------
417 if(m_pHighlightPen){
418 pGraphics->DrawPath (m_pHighlightPen,pPath);//画路径,文字边框
419 }
420 Gdiplus::Brush* pBrush = CreateGradientBrush(m_HighlightGradientMode, m_HighlightColor1,m_HighlightColor2,dstRect);
421 pGraphics->FillPath (pBrush,pPath);//填充路径
422 delete pBrush;//销毁画刷
423 //--------------------------------------------
424 if(pRegion){
425 pGraphics->ResetClip();
426 delete pRegion;
427 }
428 }
429
430 //创建渐变画刷
CreateGradientBrush(LyricsGradientMode TextGradientMode,Gdiplus::Color & Color1,Gdiplus::Color & Color2,Gdiplus::RectF & dstRect)431 Gdiplus::Brush* CLyricsWindow::CreateGradientBrush(LyricsGradientMode TextGradientMode,Gdiplus::Color& Color1,Gdiplus::Color& Color2, Gdiplus::RectF& dstRect)
432 {
433 // 单色画刷
434 if (TextGradientMode != LyricsGradientMode_Two && TextGradientMode != LyricsGradientMode_Three)
435 {
436 Gdiplus::SolidBrush* pSolidBrush = new Gdiplus::SolidBrush(Color1);
437 return static_cast<Gdiplus::Brush*>(pSolidBrush);
438 }
439
440 Gdiplus::PointF point1(dstRect.X, dstRect.Y);
441 Gdiplus::PointF point2(dstRect.X, dstRect.Y);
442 if (TextGradientMode == LyricsGradientMode_Two)
443 point2.Y += dstRect.Height;
444 else
445 point2.Y += dstRect.Height / 2; // 这里的三色渐变是靠环绕模式对映
446
447 // 创建线性渐变画刷
448 Gdiplus::LinearGradientBrush* pLinearGradientBrush = new Gdiplus::LinearGradientBrush(point1, point2, Gdiplus::Color(), Gdiplus::Color());
449 // 定义插值点的数量, 创建颜色和位置的向量
450 const int colorCount = 10;
451 std::array<Gdiplus::Color, colorCount> colors{};
452 std::array<Gdiplus::REAL, colorCount> positions{};
453 for (int i = 0; i < colorCount; ++i)
454 { // CDrawingManager::SmartMixColors产生的渐变色更好,GDI+默认的渐变色有很多灰色
455 COLORREF interpolatedColor = CDrawingManager::SmartMixColors(Color1.ToCOLORREF(), Color2.ToCOLORREF(), 1.0, colorCount - i, i);
456 colors[i].SetFromCOLORREF(interpolatedColor);
457 positions[i] = static_cast<Gdiplus::REAL>(i) / (colorCount - 1);
458 }
459 // 设置插值颜色
460 pLinearGradientBrush->SetInterpolationColors(colors.data(), positions.data(), colorCount);
461 pLinearGradientBrush->SetWrapMode(Gdiplus::WrapModeTileFlipXY);// 设置环绕模式
462 return static_cast<Gdiplus::Brush*>(pLinearGradientBrush);
463 }
464
465 //设置歌词颜色
SetLyricsColor(Gdiplus::Color TextColor1)466 void CLyricsWindow::SetLyricsColor(Gdiplus::Color TextColor1)
467 {
468 CLyricsWindow::SetLyricsColor(TextColor1,Gdiplus::Color::Black,LyricsGradientMode_None);
469 }
SetLyricsColor(Gdiplus::Color TextColor1,Gdiplus::Color TextColor2,LyricsGradientMode TextGradientMode)470 void CLyricsWindow::SetLyricsColor(Gdiplus::Color TextColor1,Gdiplus::Color TextColor2,LyricsGradientMode TextGradientMode)
471 {
472 m_TextColor1=TextColor1;
473 m_TextColor2=TextColor2;
474 m_TextGradientMode=TextGradientMode;
475
476 }
477 //设置歌词边框
SetLyricsBorder(Gdiplus::Color BorderColor,Gdiplus::REAL BorderWidth)478 void CLyricsWindow::SetLyricsBorder(Gdiplus::Color BorderColor, Gdiplus::REAL BorderWidth)
479 {
480 if(m_pTextPen){
481 delete m_pTextPen;
482 m_pTextPen=NULL;
483 }
484 if(BorderColor.GetA()>0 && BorderWidth>0)
485 m_pTextPen=new Gdiplus::Pen(BorderColor,BorderWidth);
486 }
487 //设置高亮歌词颜色
SetHighlightColor(Gdiplus::Color TextColor1)488 void CLyricsWindow::SetHighlightColor(Gdiplus::Color TextColor1)
489 {
490 CLyricsWindow::SetHighlightColor(TextColor1,Gdiplus::Color::Black,LyricsGradientMode_None);
491 }
SetHighlightColor(Gdiplus::Color TextColor1,Gdiplus::Color TextColor2,LyricsGradientMode TextGradientMode)492 void CLyricsWindow::SetHighlightColor(Gdiplus::Color TextColor1,Gdiplus::Color TextColor2,LyricsGradientMode TextGradientMode)
493 {
494 m_HighlightColor1=TextColor1;
495 m_HighlightColor2=TextColor2;
496 m_HighlightGradientMode=TextGradientMode;
497
498 }
499 //设置高亮歌词边框
SetHighlightBorder(Gdiplus::Color BorderColor,Gdiplus::REAL BorderWidth)500 void CLyricsWindow::SetHighlightBorder(Gdiplus::Color BorderColor, Gdiplus::REAL BorderWidth)
501 {
502 if(m_pHighlightPen){
503 delete m_pHighlightPen;
504 m_pHighlightPen=NULL;
505 }
506 if(BorderColor.GetA()>0 && BorderWidth>0)
507 m_pHighlightPen=new Gdiplus::Pen(BorderColor,BorderWidth);
508 }
509 //设置歌词阴影
SetLyricsShadow(Gdiplus::Color ShadowColor,int nShadowOffset)510 void CLyricsWindow::SetLyricsShadow(Gdiplus::Color ShadowColor,int nShadowOffset)
511 {
512 if(m_pShadowBrush){
513 delete m_pShadowBrush;
514 m_pShadowBrush=NULL;
515 }
516 if(ShadowColor.GetA()>0 && nShadowOffset>0){
517 m_nShadowOffset=nShadowOffset;
518 m_pShadowBrush=new Gdiplus::SolidBrush(ShadowColor);
519 }else{
520 m_nShadowOffset=0;
521 }
522 }
523 //设置歌词字体
SetLyricsFont(const WCHAR * familyName,Gdiplus::REAL emSize,INT style,Gdiplus::Unit unit)524 void CLyricsWindow::SetLyricsFont(const WCHAR * familyName, Gdiplus::REAL emSize,INT style, Gdiplus::Unit unit)
525 {
526 if(m_pFont){
527 delete m_pFont;
528 m_pFont=NULL;
529 }
530 Gdiplus::FontFamily family(familyName,NULL);
531 Gdiplus::Status lastResult = family.GetLastStatus();
532 if (lastResult != Gdiplus::Ok)
533 {
534 HFONT hFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT);
535 LOGFONTW lf;
536 ZeroMemory(&lf,sizeof(LOGFONTW));
537 GetObjectW(hFont,sizeof(LOGFONTW),&lf);
538 Gdiplus::FontFamily family2(lf.lfFaceName,NULL);
539 m_pFont=new Gdiplus::Font(&family2,emSize,style,unit);
540 }else{
541 m_pFont=new Gdiplus::Font(&family,emSize,style,unit);
542 }
543 //----------------
544 //保存一些字体属性,加入路径时要用到
545 m_pFont->GetFamily (m_pFontFamily);
546 m_FontSize=m_pFont->GetSize ();
547 m_FontStyle=m_pFont->GetStyle ();
548
549
550
551 }
552
SetAlpha(int alpha)553 void CLyricsWindow::SetAlpha(int alpha)
554 {
555 m_alpha = alpha;
556 }
557
SetAlignment(Alignment alignment)558 void CLyricsWindow::SetAlignment(Alignment alignment)
559 {
560 m_alignment = alignment;
561 }
562
SetLyricKaraokeDisplay(bool karaoke_disp)563 void CLyricsWindow::SetLyricKaraokeDisplay(bool karaoke_disp)
564 {
565 m_lyric_karaoke_disp = karaoke_disp;
566 }
567
OnLButtonDown(UINT nFlags,CPoint point)568 void CLyricsWindow::OnLButtonDown(UINT nFlags, CPoint point)
569 {
570
571 CWnd::OnLButtonDown(nFlags, point);
572 //ReleaseCapture();
573 //SendMessage(WM_NCLBUTTONDOWN,HTCAPTION,NULL);
574 }
575