1 #include "stdafx.h" 2 #include "CUIDrawer.h" 3 #include "MusicPlayer2.h" 4 5 CUIDrawer::CUIDrawer(UIColors& colors) 6 : m_colors(colors) 7 { 8 } 9 10 11 CUIDrawer::~CUIDrawer() 12 { 13 } 14 15 void CUIDrawer::DrawLryicCommon(CRect rect, Alignment align) 16 { 17 SetDrawArea(rect); 18 static int flag{}; 19 if (!IsDrawMultiLine(rect.Height())) 20 DrawLyricTextSingleLine(rect, flag, true, align); 21 else 22 DrawLyricTextMultiLine(rect, align); 23 } 24 25 int CUIDrawer::GetLyricTextHeight() const 26 { 27 //计算文本高度 28 if (!m_for_cortana_lyric) 29 m_pDC->SelectObject(&theApp.m_font_set.lyric.GetFont(theApp.m_ui_data.full_screen)); 30 else 31 m_pDC->SelectObject(&theApp.m_font_set.cortana.GetFont()); 32 return m_pDC->GetTextExtent(L"文").cy; //根据当前的字体设置计算文本的高度 33 } 34 35 void CUIDrawer::Create(CDC* pDC, CWnd* pMainWnd) 36 { 37 CDrawCommon::Create(pDC, pMainWnd); 38 } 39 40 bool CUIDrawer::IsDrawMultiLine(int height) const 41 { 42 return height >= static_cast<int>(GetLyricTextHeight() * 3.5); 43 } 44 45 void CUIDrawer::SetForCortanaLyric(bool for_cortana_lyric) 46 { 47 m_for_cortana_lyric = for_cortana_lyric; 48 } 49 50 void CUIDrawer::DrawLyricTextMultiLine(CRect lyric_area, Alignment align) 51 { 52 // AUTO时多行歌词居中显示 53 if (align == Alignment::AUTO) align = Alignment::CENTER; 54 55 int line_space{}; 56 if (m_for_cortana_lyric) 57 { 58 line_space = theApp.DPI(4); 59 } 60 else 61 { 62 line_space = theApp.m_lyric_setting_data.lyric_line_space; 63 if (theApp.m_ui_data.full_screen) 64 line_space = static_cast<int>(line_space * CONSTVAL::FULL_SCREEN_ZOOM_FACTOR); 65 } 66 67 int lyric_height = GetLyricTextHeight() + line_space; //文本高度加上行间距 68 int lyric_height2 = lyric_height * 2 + line_space; //包含翻译的歌词高度 69 70 CFont* pOldFont = SetLyricFont(); 71 if (CPlayer::GetInstance().IsPlaylistEmpty()) //当前播放为空时在歌词区域显示播放提示 72 { 73 CFont* font = SetFont(&theApp.m_font_set.font10.GetFont()); 74 wstring no_track_tip_str = theApp.m_str_table.LoadTextFormat(L"UI_LYRIC_NO_TRACKS_TIP", { 75 theApp.m_accelerator_res.GetShortcutDescriptionById(ID_SHOW_PLAYLIST), 76 theApp.m_accelerator_res.GetShortcutDescriptionById(ID_FILE_OPEN), 77 theApp.m_accelerator_res.GetShortcutDescriptionById(ID_FILE_OPEN_FOLDER), 78 theApp.m_accelerator_res.GetShortcutDescriptionById(ID_MEDIA_LIB)}); 79 DrawWindowText(lyric_area, no_track_tip_str.c_str(), m_colors.color_text_2, Alignment::LEFT, false, true); 80 SetFont(font); 81 } 82 else if (CPlayerUIHelper::IsMidiLyric()) 83 { 84 wstring current_lyric{ CPlayer::GetInstance().GetMidiLyric() }; 85 DrawWindowText(lyric_area, current_lyric.c_str(), m_colors.color_text, Alignment::CENTER, false, true); 86 } 87 else if (CPlayer::GetInstance().m_Lyrics.IsEmpty()) 88 { 89 //没有歌词时显示歌曲信息 90 if (theApp.m_lyric_setting_data.show_song_info_if_lyric_not_exist) 91 { 92 CString song_info_str; 93 const SongInfo& cur_song{ CPlayer::GetInstance().GetCurrentSongInfo() }; 94 std::wstring artist{ cur_song.album_artist }; 95 if (artist.empty()) 96 artist = cur_song.GetArtist(); 97 song_info_str.Format(_T("%s - %s\r\n%s"), artist.c_str(), cur_song.GetAlbum().c_str(), cur_song.GetTitle().c_str()); 98 DrawWindowText(lyric_area, song_info_str, m_colors.color_text, align, false, true); 99 } 100 //显示“当前歌曲没有歌词” 101 else 102 { 103 static const wstring& no_lyric_info = theApp.m_str_table.LoadText(L"UI_LYRIC_NONE"); 104 DrawWindowText(lyric_area, no_lyric_info.c_str(), m_colors.color_text_2, Alignment::CENTER); 105 } 106 } 107 else 108 { 109 //CRect arect{ lyric_area }; //一行歌词的矩形区域 110 //arect.bottom = arect.top + lyric_height; 111 //vector<CRect> rects(CPlayer::GetInstance().m_Lyrics.GetLyricCount() + 1, arect); 112 //为每一句歌词创建一个矩形,保存在容器里 113 vector<CRect> rects; 114 int lyric_count = CPlayer::GetInstance().m_Lyrics.GetLyricCount() + 1; //获取歌词数量(由于第一行歌词需要显示标题,所以这里要+1) 115 for (int i{}; i < lyric_count; i++) 116 { 117 CRect arect{ lyric_area }; 118 if (!CPlayer::GetInstance().m_Lyrics.GetLyric(i - 1).translate.empty() && theApp.m_lyric_setting_data.show_translate) 119 arect.bottom = arect.top + lyric_height2; 120 else 121 arect.bottom = arect.top + lyric_height; 122 rects.push_back(arect); 123 } 124 int center_pos = (lyric_area.top + lyric_area.bottom) / 2; //歌词区域的中心y坐标 125 Time time{ CPlayer::GetInstance().GetCurrentPosition() }; //当前播放时间 126 int lyric_index = CPlayer::GetInstance().m_Lyrics.GetLyricIndex(time); // 当前歌词的序号 127 int progress{ CPlayer::GetInstance().m_Lyrics.GetLyricProgress(time, false, false, [this](const wstring& str) { return GetTextExtent(str.c_str()).cx; }) }; // 当前歌词进度(范围为0~1000),多行歌词使用的进度不含进度符号 128 int y_progress; //当前歌词在y轴上的进度 129 if (!CPlayer::GetInstance().m_Lyrics.GetLyric(lyric_index).translate.empty() && theApp.m_lyric_setting_data.show_translate) 130 y_progress = progress * lyric_height2 / 1000; 131 else 132 y_progress = progress * lyric_height / 1000; 133 //int start_pos = center_pos - y_progress - (lyric_index + 1)*lyric_height; //第1句歌词的起始y坐标 134 //计算第1句歌词的起始y坐标 135 //由于当前歌词需要显示在歌词区域的中心位置,因此从中心位置开始,减去当前歌词在Y轴上的进度 136 //再依次减去之前每一句歌词的高度,即得到了第一句歌词的起始位置 137 int start_pos; 138 start_pos = center_pos - y_progress; 139 for (int i{ lyric_index - 1 }; i >= -1; i--) 140 { 141 if (theApp.m_lyric_setting_data.show_translate && !CPlayer::GetInstance().m_Lyrics.GetLyric(i).translate.empty()) 142 start_pos -= lyric_height2; 143 else 144 start_pos -= lyric_height; 145 } 146 147 //依次绘制每一句歌词 148 for (int i{ -1 }; i < static_cast<int>(rects.size()) - 1; i++) 149 { 150 //计算每一句歌词的位置 151 if (i == -1) 152 rects[i + 1].MoveToY(start_pos); 153 else 154 rects[i + 1].MoveToY(rects[i].bottom); 155 //绘制歌词文本 156 if (!(rects[i + 1] & lyric_area).IsRectEmpty()) //只有当一句歌词的矩形区域和歌词区域的矩形有交集时,才绘制歌词 157 { 158 //设置歌词文本和翻译文本的矩形区域 159 CRect rect_text{ rects[i + 1] }; 160 CRect rect_translate; 161 const CLyrics::Lyric& lyric_i = CPlayer::GetInstance().m_Lyrics.GetLyric(i); 162 if (!lyric_i.translate.empty() && theApp.m_lyric_setting_data.show_translate) 163 { 164 rect_text.MoveToY(rect_text.top + line_space); 165 rect_text.bottom = rect_text.top + GetLyricTextHeight(); 166 rect_translate = rect_text; 167 rect_translate.MoveToY(rect_text.bottom + line_space); 168 } 169 170 if (i == lyric_index && progress < 1000) //绘制正在播放的歌词(处于逐渐过度到高亮过程中的歌词) 171 { 172 //这里实现文本从非高亮缓慢变化到高亮效果 173 int last_time_span = time - lyric_i.time_start; //当前播放的歌词已持续的时间 174 int fade_percent = last_time_span / 8; //计算颜色高亮变化的百分比,除数越大则持续时间越长,10则为1秒 175 COLORREF text_color = CColorConvert::GetGradientColor(m_colors.color_text_2, m_colors.color_text, fade_percent); 176 //绘制歌词文本 177 SetLyricFont(); 178 if (theApp.m_lyric_setting_data.lyric_karaoke_disp) 179 DrawWindowText(rect_text, lyric_i.text.c_str(), m_colors.color_text, m_colors.color_text_2, progress, align, true); 180 else 181 DrawWindowText(rect_text, lyric_i.text.c_str(), text_color, text_color, progress, align, true); 182 //绘制翻译文本 183 if (!lyric_i.translate.empty() && theApp.m_lyric_setting_data.show_translate) 184 { 185 SetLyricFontTranslated(); 186 DrawWindowText(rect_translate, lyric_i.translate.c_str(), text_color, text_color, progress, align, true); 187 } 188 } 189 else //绘制非正在播放的歌词 190 { 191 SetLyricFont(); 192 COLORREF text_color; 193 if (i == lyric_index - 1 || (i == lyric_index && progress == 1000)) // 绘制正在取消高亮的歌词(这里实现一句歌词颜色从高亮缓慢变化到非高亮效果),逐字歌词最后一句在此处取消高亮 194 { 195 int last_time_span = time - (lyric_i.time_start + lyric_i.time_span); // 引入逐字歌词后上句歌词结束后时长不等于当前播放的歌词已持续的时间,此处应当使用上句歌词结束时间 196 int fade_percent = last_time_span / 20; //计算颜色高亮变化的百分比,当持续时间为2000毫秒时为100%,即颜色缓慢变化的时间为2秒 197 text_color = CColorConvert::GetGradientColor(m_colors.color_text, m_colors.color_text_2, fade_percent); 198 } 199 else 200 { 201 text_color = m_colors.color_text_2; 202 } 203 //绘制歌词文本 204 DrawWindowText(rect_text, lyric_i.text.c_str(), text_color, align, true); 205 //绘制翻译文本 206 if (!lyric_i.translate.empty() && theApp.m_lyric_setting_data.show_translate) 207 { 208 SetLyricFontTranslated(); 209 DrawWindowText(rect_translate, lyric_i.translate.c_str(), text_color, align, true); 210 } 211 } 212 } 213 } 214 } 215 SetFont(pOldFont); 216 } 217 218 void CUIDrawer::DrawLyricTextSingleLine(CRect rect, int& flag, bool double_line, Alignment align) 219 { 220 CFont* pOldFont = SetLyricFont(); 221 222 if (CPlayerUIHelper::IsMidiLyric()) 223 { 224 wstring current_lyric{ CPlayer::GetInstance().GetMidiLyric() }; 225 DrawWindowText(rect, current_lyric.c_str(), m_colors.color_text, Alignment::CENTER, false, true); 226 } 227 else if (CPlayer::GetInstance().m_Lyrics.IsEmpty()) 228 { 229 //没有歌词时显示歌曲信息 230 if (theApp.m_lyric_setting_data.show_song_info_if_lyric_not_exist) 231 { 232 CString song_info_str; 233 const SongInfo& cur_song{ CPlayer::GetInstance().GetCurrentSongInfo() }; 234 song_info_str.Format(_T("%s - %s"), cur_song.GetArtist().c_str(), cur_song.GetTitle().c_str()); 235 static CDrawCommon::ScrollInfo lyric_scroll_info; 236 DrawScrollText(rect, song_info_str, m_colors.color_text, CPlayerUIHelper::GetScrollTextPixel(), theApp.m_lyric_setting_data.lyric_align != Alignment::LEFT, lyric_scroll_info); 237 } 238 //显示“当前歌曲没有歌词” 239 else 240 { 241 static const wstring& no_lyric_info = theApp.m_str_table.LoadText(L"UI_LYRIC_NONE"); 242 DrawWindowText(rect, no_lyric_info.c_str(), m_colors.color_text_2, Alignment::CENTER); 243 } 244 } 245 else 246 { 247 SetDrawArea(rect); 248 CRect lyric_rect = rect; 249 250 static const wstring& empty_lyric = theApp.m_str_table.LoadText(L"UI_LYRIC_EMPTY_LINE"); 251 const bool karaoke{ theApp.m_lyric_setting_data.lyric_karaoke_disp }; 252 const bool ignore_blank{ theApp.m_lyric_setting_data.donot_show_blank_lines}; 253 auto& now_lyrics{ CPlayer::GetInstance().m_Lyrics }; 254 Time time{ CPlayer::GetInstance().GetCurrentPosition() }; 255 CLyrics::Lyric current_lyric{ now_lyrics.GetLyric(time, false, ignore_blank, karaoke) }; 256 int progress{ now_lyrics.GetLyricProgress(time, ignore_blank, karaoke, [this](const wstring& str) { return GetTextExtent(str.c_str()).cx; }) }; 257 bool switch_flag{ flag > 5000 }; 258 switch_flag ^= (flag % 5000) > progress; 259 flag = switch_flag ? 10000 + progress : progress; 260 261 if (current_lyric.text.empty()) 262 current_lyric.text = empty_lyric; 263 //双行显示歌词 264 if (double_line && (current_lyric.translate.empty() || !theApp.m_lyric_setting_data.show_translate) && rect.Height() > static_cast<int>(GetLyricTextHeight() * 1.73)) 265 { 266 wstring next_lyric_text; 267 next_lyric_text = now_lyrics.GetLyric(time, true, ignore_blank, karaoke).text; 268 if (next_lyric_text.empty()) 269 next_lyric_text = empty_lyric; 270 //这里实现文本从非高亮缓慢变化到高亮效果 271 int last_time_span = time - current_lyric.time_start; //当前播放的歌词已持续的时间 272 int fade_percent = last_time_span / 8; //计算颜色高亮变化的百分比,除数越大则持续时间越长,10则为1秒 273 if (progress == 1000) fade_percent = 0; // 进度为1000时当前歌词“已完成”不再高亮 274 // 这里的fade_percent当合并空行开启时可能为负,在颜色渐变处规范取值,此处不再处理 275 DrawLyricDoubleLine(lyric_rect, current_lyric.text.c_str(), next_lyric_text.c_str(), align, progress, switch_flag, fade_percent); 276 } 277 else 278 { 279 // AUTO时单行歌词居中显示 280 if (align == Alignment::AUTO) align = Alignment::CENTER; 281 // 单行歌词在这里显示翻译,同时更新歌词区域为单行有翻译时的位置 282 if (theApp.m_lyric_setting_data.show_translate && !current_lyric.translate.empty() && rect.Height() > static_cast<int>(GetLyricTextHeight() * 1.73)) 283 { 284 lyric_rect.bottom = lyric_rect.top + rect.Height() / 2; 285 CRect translate_rect = lyric_rect; 286 translate_rect.MoveToY(lyric_rect.bottom); 287 288 SetLyricFontTranslated(); 289 DrawWindowText(translate_rect, current_lyric.translate.c_str(), m_colors.color_text, m_colors.color_text, progress, align, true); 290 } 291 // 绘制单行歌词 292 SetLyricFont(); 293 if (theApp.m_lyric_setting_data.lyric_karaoke_disp) 294 DrawWindowText(lyric_rect, current_lyric.text.c_str(), m_colors.color_text, m_colors.color_text_2, progress, align, true); 295 else if (0 < progress && progress < 1000) // 仅高亮“正在进行”的歌词 296 DrawWindowText(lyric_rect, current_lyric.text.c_str(), m_colors.color_text, m_colors.color_text, progress, align, true); 297 else 298 DrawWindowText(lyric_rect, current_lyric.text.c_str(), m_colors.color_text_2, m_colors.color_text_2, progress, align, true); 299 } 300 } 301 302 SetFont(pOldFont); 303 } 304 305 void CUIDrawer::DrawSpectrum(CRect rect, SpectrumCol col, bool draw_reflex /*= false*/, bool low_freq_in_center, bool fixed_width, Alignment alignment) 306 { 307 int cols; //要显示的频谱柱形的数量 308 switch (col) 309 { 310 case CUIDrawer::SC_64: 311 cols = 64; 312 break; 313 case CUIDrawer::SC_32: 314 cols = 32; 315 break; 316 case CUIDrawer::SC_16: 317 cols = 16; 318 break; 319 case CUIDrawer::SC_8: 320 cols = 8; 321 break; 322 default: 323 cols = SPECTRUM_COL; 324 break; 325 } 326 int max_width{ rect.Width() }; 327 if (fixed_width) 328 { 329 if (col == SC_64) 330 { 331 max_width = DPI(280); 332 } 333 } 334 int gap_width{ max_width * (SPECTRUM_COL / cols) / 168 }; //频谱柱形间隙宽度 335 if (theApp.m_ui_data.full_screen && !m_for_cortana_lyric) 336 gap_width = static_cast<int>(gap_width * CONSTVAL::FULL_SCREEN_ZOOM_FACTOR); 337 int width = (max_width - (cols - 1) * gap_width) / (cols - 1); 338 if (gap_width < 1) 339 gap_width = 1; 340 if (width < 1) 341 width = 1; 342 343 if (fixed_width) 344 SetDrawArea(rect); 345 DrawSpectrum(rect, width, gap_width, cols, m_colors.color_spectrum, draw_reflex, low_freq_in_center, alignment); 346 } 347 348 void CUIDrawer::DrawSpectrum(CRect rect, int col_width, int gap_width, int cols, COLORREF color, bool draw_reflex /*= false*/, bool low_freq_in_center, Alignment alignment) 349 { 350 CRect rc_spectrum_top = rect; 351 if (draw_reflex) //如果要绘制倒影,则倒影占总高度的1/3 352 rc_spectrum_top.bottom = rect.top + (rect.Height() * 2 / 3); 353 354 CRect rects[SPECTRUM_COL]; 355 rects[0] = rc_spectrum_top; 356 rects[0].right = rects[0].left + col_width; 357 358 //频谱的实际宽度 359 int width_actrual{ col_width * cols + gap_width * (cols - 1) }; 360 //如果频谱的实际宽度小于矩形的宽度,则让根据alignment的值让频谱居中或右对齐显示 361 if ((width_actrual < rect.Width() && alignment == Alignment::CENTER) || (width_actrual >= rect.Width() && theApp.m_app_setting_data.spectrum_low_freq_in_center)) 362 rects[0].MoveToX(rects[0].left + (rect.Width() - width_actrual) / 2); 363 else if (width_actrual < rect.Width() && alignment == Alignment::RIGHT) 364 rects[0].MoveToX(rects[0].left + (rect.Width() - width_actrual)); 365 366 for (int i{ 1 }; i < cols; i++) 367 { 368 rects[i] = rects[0]; 369 rects[i].left += (i * (col_width + gap_width)); 370 rects[i].right += (i * (col_width + gap_width)); 371 } 372 for (int i{}; i < cols; i++) 373 { 374 int index; 375 if (low_freq_in_center) 376 { 377 if (i < cols / 2) 378 index = (-i + cols / 2) * 2 - 1; 379 else 380 index = (i - cols / 2) * 2; 381 } 382 else 383 { 384 index = i; 385 } 386 if (index >= cols) 387 index = cols; 388 if (index < 0) 389 index = 0; 390 float spetral_data = CPlayer::GetInstance().GetSpectralData()[index * (SPECTRUM_COL / cols)]; 391 float peak_data = CPlayer::GetInstance().GetSpectralPeakData()[index * (SPECTRUM_COL / cols)]; 392 393 CRect rect_tmp{ rects[i] }; 394 int spetral_height = static_cast<int>(spetral_data * rects[0].Height() / 30 * theApp.m_app_setting_data.sprctrum_height / 100); 395 int peak_height = static_cast<int>(peak_data * rects[0].Height() / 30 * theApp.m_app_setting_data.sprctrum_height / 100); 396 if (spetral_height < 0 || CPlayer::GetInstance().IsError()) spetral_height = 0; //如果播放出错,不显示频谱 397 if (peak_height < 0 || CPlayer::GetInstance().IsError()) peak_height = 0; 398 399 int peak_rect_height = max(theApp.DPIRound(1.1), gap_width / 2); //顶端矩形的高度 400 spetral_height += peak_rect_height; //频谱至少和顶端矩形一样高 401 peak_height += peak_rect_height; 402 403 rect_tmp.top = rect_tmp.bottom - spetral_height; 404 if (rect_tmp.top < rects[0].top) rect_tmp.top = rects[0].top; 405 FillRect(rect_tmp, color, true); 406 //绘制倒影 407 if (draw_reflex) 408 { 409 CRect rc_invert = rect_tmp; 410 rc_invert.bottom = rect_tmp.top + rect_tmp.Height() * 2 / 3; 411 rc_invert.MoveToY(rect_tmp.bottom + gap_width); 412 FillAlphaRect(rc_invert, color, 96, true); 413 } 414 415 //绘制顶端 416 CRect rect_peak{ rect_tmp }; 417 rect_peak.bottom = rect_tmp.bottom - peak_height - gap_width; 418 rect_peak.top = rect_peak.bottom - peak_rect_height; 419 FillRect(rect_peak, color, true); 420 ////绘制顶端倒影 421 //CRect rc_peak_invert = rect_peak; 422 //rc_peak_invert.MoveToY(rc_invert.top + peak_height + theApp.DPIRound(1.1)); 423 //FillAlphaRect(rc_peak_invert, color, 96); 424 } 425 426 } 427 428 int CUIDrawer::DPI(int pixel) 429 { 430 if (theApp.m_ui_data.full_screen && !m_for_cortana_lyric) 431 return theApp.DPI(pixel * CONSTVAL::FULL_SCREEN_ZOOM_FACTOR); 432 else 433 return theApp.DPI(pixel); 434 } 435 436 void CUIDrawer::DrawLyricDoubleLine(CRect rect, LPCTSTR lyric, LPCTSTR next_lyric, Alignment align, int progress, bool switch_flag, int fade_percent) 437 { 438 CFont* pOldFont = SetLyricFont(); 439 440 CRect up_rect{ rect }, down_rect{ rect }; //上半部分和下半部分歌词的矩形区域 441 up_rect.bottom = up_rect.top + (up_rect.Height() / 2); 442 down_rect.top = down_rect.bottom - (down_rect.Height() / 2); 443 444 // 对齐方式为AUTO时使用上左下右的卡拉OK对齐方式 445 Alignment up_align{ Alignment::LEFT }, down_align{ Alignment::RIGHT }; 446 if (align != Alignment::AUTO) 447 up_align = down_align = align; 448 449 COLORREF color1, color2; 450 if (theApp.m_lyric_setting_data.lyric_karaoke_disp) 451 { 452 color1 = m_colors.color_text; 453 color2 = m_colors.color_text_2; 454 } 455 else 456 { 457 color1 = color2 = CColorConvert::GetGradientColor(m_colors.color_text_2, m_colors.color_text, fade_percent); 458 } 459 460 // 绘制当前歌词 461 if (!switch_flag) 462 { 463 DrawWindowText(up_rect, lyric, color1, color2, progress, up_align); 464 DrawWindowText(down_rect, next_lyric, m_colors.color_text_2, down_align); 465 } 466 else 467 { 468 DrawWindowText(up_rect, next_lyric, m_colors.color_text_2, up_align); 469 DrawWindowText(down_rect, lyric, color1, color2, progress, down_align); 470 } 471 SetFont(pOldFont); 472 } 473 474 CFont* CUIDrawer::SetLyricFont() 475 { 476 if (!m_for_cortana_lyric) 477 return SetFont(&theApp.m_font_set.lyric.GetFont(theApp.m_ui_data.full_screen)); 478 else 479 return SetFont(&theApp.m_font_set.cortana.GetFont()); 480 } 481 482 CFont* CUIDrawer::SetLyricFontTranslated() 483 { 484 if (!m_for_cortana_lyric) 485 return SetFont(&theApp.m_font_set.lyric_translate.GetFont(theApp.m_ui_data.full_screen)); 486 else 487 return SetFont(&theApp.m_font_set.cortana_translate.GetFont()); 488 } 489