/*---------------------------------------------------------------------------*/ // Author : hiyohiyo // Mail : hiyohiyo@crystalmark.info // Web : https://crystalmark.info/ // License : MIT License /*---------------------------------------------------------------------------*/ #include "stdafx.h" #include "MainDialogFx.h" #include #include #include "UtilityFx.h" #include "OsInfoFx.h" using namespace std; CMainDialogFx::CMainDialogFx(UINT dlgResouce, CWnd* pParent) :CDialogFx(dlgResouce, pParent) { // Common m_bStartup = FALSE; m_bWindowMinimizeOnce = TRUE; m_bResident = FALSE; m_bResidentMinimize = FALSE; // Theme m_ThemeKeyName = _T("Theme"); TCHAR* ptrEnd; TCHAR ini[MAX_PATH]; TCHAR tmp[MAX_PATH]; CString directry; GetModuleFileName(NULL, ini, MAX_PATH); if ((ptrEnd = _tcsrchr(ini, '.')) != NULL) { *ptrEnd = '\0'; #if _MSC_VER > 1310 _tcscat_s(ini, MAX_PATH, _T(".ini")); #else _tcscat(ini, _T(".ini")); #endif m_Ini = ini; } #if _MSC_VER > 1310 CString tmpPath; tmpPath = m_Ini; tmpPath.Replace(_T(".ini"), _T(".tmp")); if (! CanWriteFile(tmpPath)) { TCHAR drive[_MAX_DRIVE]; TCHAR ext[_MAX_EXT]; TCHAR appData[MAX_PATH]; TCHAR dir[_MAX_DIR]; TCHAR fileName[_MAX_FNAME]; GetModuleFileName(NULL, ini, MAX_PATH); _tsplitpath(ini, drive, dir, fileName, ext); SHGetSpecialFolderPath(NULL, appData, CSIDL_APPDATA, 0); directry.Format(_T("%s\\%s"), appData, PRODUCT_FILENAME); CreateDirectory(directry, NULL); m_Ini.Format(_T("%s\\%s\\%s.ini"), appData, PRODUCT_FILENAME, fileName); } #endif GetModuleFileName(NULL, tmp, MAX_PATH); if ((ptrEnd = _tcsrchr(tmp, '\\')) != NULL) { *ptrEnd = '\0'; } m_ThemeDir.Format(_T("%s\\%s"), tmp, THEME_DIR); m_LangDir.Format(_T("%s\\%s"), tmp, LANGUAGE_DIR); m_VoiceDir.Format(_T("%s\\%s"), tmp, VOICE_DIR); } CMainDialogFx::~CMainDialogFx() { } BEGIN_MESSAGE_MAP(CMainDialogFx, CDialogFx) ON_WM_WINDOWPOSCHANGING() ON_WM_GETMINMAXINFO() END_MESSAGE_MAP() LRESULT CMainDialogFx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { #if _MSC_VER > 1310 LRESULT lr = 0; if (UAHWndProc(m_hWnd, message, wParam, lParam, &lr)) { return lr; } #endif return CDialogFx::WindowProc(message, wParam, lParam); } int CALLBACK HasFontProc(ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, LPARAM lParam) { *(BOOL*)lParam = TRUE; return 0; } CString CMainDialogFx::GetDefaultFont() { #if _MSC_VER <= 1310 int stockFont = DEFAULT_GUI_FONT; if (IsNT3()) { return _T("MS Shell Dlg"); } HFONT hFont = (HFONT)GetStockObject(stockFont); LOGFONT lf = { 0 }; if (GetObject(hFont, sizeof(LOGFONT), &lf)) { return lf.lfFaceName; } #endif CClientDC dc(this); LOGFONT logfont; BOOL hasFont = FALSE; ZeroMemory(&logfont, sizeof(LOGFONT)); lstrcpy(logfont.lfFaceName, DEFAULT_FONT_FACE_1); logfont.lfCharSet = DEFAULT_CHARSET; ::EnumFontFamiliesEx(dc.m_hDC, &logfont, (FONTENUMPROC)HasFontProc, (LPARAM)(&hasFont), 0); if (hasFont) { return DEFAULT_FONT_FACE_1; } else { return DEFAULT_FONT_FACE_2; } } CString CMainDialogFx::GetCurrentLangPath() { return m_CurrentLangPath; } CString CMainDialogFx::GetDefaultLangPath() { return m_DefaultLangPath; } CString CMainDialogFx::GetThemeDir() { return m_ThemeDir; } CString CMainDialogFx::GetCurrentTheme() { return m_CurrentTheme; } CString CMainDialogFx::GetDefaultTheme() { return m_DefaultTheme; } CString CMainDialogFx::GetParentTheme1() { return m_ParentTheme1; } CString CMainDialogFx::GetParentTheme2() { return m_ParentTheme2; } CString CMainDialogFx::GetIniPath() { return m_Ini; } void CMainDialogFx::SetWindowTitle(CString message) { CString title; if(! message.IsEmpty()) { title.Format(_T(" %s - %s"), PRODUCT_SHORT_NAME, (LPCTSTR)message); } else { title.Format(_T(" %s %s %s"), PRODUCT_NAME, PRODUCT_VERSION, PRODUCT_EDITION); } SetWindowText(title); } void CMainDialogFx::InitThemeLang() { TCHAR str[256]; TCHAR *ptrEnd; WIN32_FIND_DATA findData; HANDLE hFind; CString langPath; int i = 0; WORD PrimaryLangID; CString PrimaryLang; // Set Theme if(m_CurrentTheme.IsEmpty()) { CString defaultTheme = m_DefaultTheme; #if _MSC_VER > 1310 if (IsFileExist(m_ThemeDir + m_RecommendTheme + _T("\\") + m_BackgroundName + _T("-300.png"))) { defaultTheme = m_RecommendTheme; } #else if (IsFileExist(m_ThemeDir + m_RecommendTheme + _T("\\") + m_BackgroundName + _T("-100.png"))) { defaultTheme = m_RecommendTheme; } #endif GetPrivateProfileStringFx(_T("Setting"), m_ThemeKeyName, defaultTheme, str, 256, m_Ini); m_CurrentTheme = str; } // Set Language GetPrivateProfileStringFx(_T("Setting"), _T("Language"), _T(""), str, 256, m_Ini); langPath.Format(_T("%s\\%s.lang"), (LPCTSTR)m_LangDir, str); #ifdef UNICODE m_DefaultLangPath.Format(_T("%s\\%s.lang"), (LPCTSTR)m_LangDir, DEFAULT_LANGUAGE); #else m_DefaultLangPath.Format(_T("%s\\%s9x.lang"), (LPCTSTR)m_LangDir, DEFAULT_LANGUAGE); #endif if(_tcscmp(str, _T("")) != 0 && IsFileExist((LPCTSTR)langPath)) { m_CurrentLang = str; m_CurrentLang.Replace(_T("9x"), _T("")); #ifdef UNICODE m_CurrentLangPath.Format(_T("%s\\%s.lang"), (LPCTSTR)m_LangDir, (LPCTSTR)m_CurrentLang); #else m_CurrentLangPath.Format(_T("%s\\%s9x.lang"), (LPCTSTR)m_LangDir, (LPCTSTR)m_CurrentLang); #endif } else { CString currentLocalID; currentLocalID.Format(_T("0x%04X"), GetUserDefaultLCID()); PrimaryLangID = PRIMARYLANGID(GetUserDefaultLCID()); langPath.Format(_T("%s\\*.lang"), (LPCTSTR)m_LangDir); hFind = ::FindFirstFile(langPath, &findData); if(hFind != INVALID_HANDLE_VALUE) { do{ if(findData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { CString cstr; cstr = findData.cFileName; #ifdef UNICODE if (cstr.Find(_T("9x.lang")) >= 0) { continue; } #else if (cstr.Find(_T("9x.lang")) == -1) { continue; } #endif i++; cstr.Format(_T("%s\\%s"), (LPCTSTR)m_LangDir, findData.cFileName); GetPrivateProfileStringFx(_T("Language"), _T("LOCALE_ID"), _T(""), str, 256, cstr); if((ptrEnd = _tcsrchr(findData.cFileName, '.')) != NULL){*ptrEnd = '\0';} if(_tcsstr(str, currentLocalID) != NULL) { m_CurrentLang = findData.cFileName; m_CurrentLang.Replace(_T("9x"), _T("")); #ifdef UNICODE m_CurrentLangPath.Format(_T("%s\\%s.lang"), (LPCTSTR)m_LangDir, findData.cFileName); #else m_CurrentLangPath.Format(_T("%s\\%s9x.lang"), (LPCTSTR)m_LangDir, findData.cFileName); #endif } if(PrimaryLangID == PRIMARYLANGID(_tcstol(str, NULL, 16))) { PrimaryLang = findData.cFileName; PrimaryLang.Replace(_T("9x"), _T("")); } } }while(::FindNextFile(hFind, &findData) && i <= 0xFF); } FindClose(hFind); if(m_CurrentLang.IsEmpty()) { if(PrimaryLang.IsEmpty()) { m_CurrentLang = DEFAULT_LANGUAGE; #ifdef UNICODE m_CurrentLangPath.Format(_T("%s\\%s.lang"), (LPCTSTR)m_LangDir, (LPCTSTR)m_CurrentLang); #else m_CurrentLangPath.Format(_T("%s\\%s9x.lang"), (LPCTSTR)m_LangDir, (LPCTSTR)m_CurrentLang); #endif } else { m_CurrentLang = PrimaryLang; #ifdef UNICODE m_CurrentLangPath.Format(_T("%s\\%s.lang"), (LPCTSTR)m_LangDir, (LPCTSTR)PrimaryLang); #else m_CurrentLangPath.Format(_T("%s\\%s9x.lang"), (LPCTSTR)m_LangDir, (LPCTSTR)PrimaryLang); #endif } } } UpdateThemeInfo(); } void CMainDialogFx::InitMenu() { CMenu menu; CMenu subMenu; BOOL FlagHitTheme = FALSE; BOOL FlagHitLang = FALSE; UINT newItemID = 0; UINT currentItemID = 0; UINT defaultStyleItemID = 0; WIN32_FIND_DATA findData; HANDLE hFind; CString themePath; CString themeCssPath; CString langPath; int i = 0; TCHAR *ptrEnd = NULL; TCHAR str[256]; srand((unsigned int)std::time(NULL)); menu.Attach(GetMenu()->GetSafeHmenu()); subMenu.Attach(menu.GetSubMenu(MENU_THEME_INDEX)->GetSafeHmenu()); themePath.Format(_T("%s\\*.*"), (LPCTSTR)m_ThemeDir); // Add Random as first choice. subMenu.AppendMenu(MF_STRING, (UINT_PTR)WM_THEME_ID + i, m_RandomThemeLabel + m_RandomThemeName); i++; m_MenuArrayTheme.Add(m_RandomThemeLabel); hFind = ::FindFirstFile(themePath, &findData); if(hFind != INVALID_HANDLE_VALUE) { while(::FindNextFile(hFind, &findData) && i <= 0xFF) { if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { CString name = findData.cFileName; if(CheckThemeEdition(name)) { // Add Theme newItemID = WM_THEME_ID + i; i++; subMenu.AppendMenu(MF_STRING, (UINT_PTR)newItemID, findData.cFileName); m_MenuArrayTheme.Add(findData.cFileName); if(m_CurrentTheme.Compare(findData.cFileName) == 0) { currentItemID = newItemID; FlagHitTheme = TRUE; } if(_tcsstr(findData.cFileName, m_DefaultTheme) != NULL) { defaultStyleItemID = newItemID; } } } } } FindClose(hFind); if(m_CurrentTheme.Compare(m_RandomThemeLabel) == 0) { m_CurrentTheme = GetRandomTheme(); m_RandomThemeName = _T(" (") + m_CurrentTheme + _T(")"); // Keep currentItemID the same as the first item if "Random". currentItemID = WM_THEME_ID; SUBMENU_MODIFY_MENU(WM_THEME_ID, MF_STRING, WM_THEME_ID, m_RandomThemeLabel + m_RandomThemeName); } else if(! FlagHitTheme) { currentItemID = defaultStyleItemID; m_CurrentTheme = m_DefaultTheme; } CMenu subMenuAN; CMenu subMenuOZ; subMenu.CheckMenuRadioItem(WM_THEME_ID, WM_THEME_ID + (UINT)m_MenuArrayTheme.GetSize(), currentItemID, MF_BYCOMMAND); subMenu.Detach(); subMenu.Attach(menu.GetSubMenu(MENU_LANG_INDEX)->GetSafeHmenu()); subMenuAN.Attach(subMenu.GetSubMenu(0)->GetSafeHmenu()); // 1st is "A~N" subMenuAN.RemoveMenu(0, MF_BYPOSITION); subMenuOZ.Attach(subMenu.GetSubMenu(1)->GetSafeHmenu()); // 2nd is "O~Z" subMenuOZ.RemoveMenu(0, MF_BYPOSITION); langPath.Format(_T("%s\\*.lang"), (LPCTSTR)m_LangDir); i = 0; hFind = ::FindFirstFile(langPath, &findData); if(hFind != INVALID_HANDLE_VALUE) { do{ if(findData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { // Add Language CString cstr; cstr = findData.cFileName; #ifdef UNICODE if (cstr.Find(_T("9x.lang")) >= 0) { continue; } #else if (cstr.Find(_T("9x.lang")) == -1) { continue; } #endif newItemID = WM_LANGUAGE_ID + i; i++; cstr.Format(_T("%s\\%s"), (LPCTSTR)m_LangDir, findData.cFileName); GetPrivateProfileStringFx(_T("Language"), _T("LANGUAGE"), _T(""), str, 256, cstr); if((ptrEnd = _tcsrchr(findData.cFileName, L'.')) != NULL) { *ptrEnd = '\0'; } cstr.Format(_T("%s, [%s]"), str, findData.cFileName); if(L'A' <= findData.cFileName[0] && findData.cFileName[0] <= L'N') { subMenuAN.AppendMenu(MF_STRING, (UINT_PTR)newItemID, cstr); } else { subMenuOZ.AppendMenu(MF_STRING, (UINT_PTR)newItemID, cstr); } m_MenuArrayLang.Add(findData.cFileName); cstr = findData.cFileName; #ifndef UNICODE cstr.Replace(_T("9x"), _T("")); #endif if(m_CurrentLang.Compare(cstr) == 0) { currentItemID = newItemID; FlagHitLang = TRUE; } } }while(::FindNextFile(hFind, &findData) && i <= 0xFF); } FindClose(hFind); subMenuAN.CheckMenuRadioItem(WM_LANGUAGE_ID, WM_LANGUAGE_ID + (UINT)m_MenuArrayLang.GetSize(), currentItemID, MF_BYCOMMAND); subMenuOZ.CheckMenuRadioItem(WM_LANGUAGE_ID, WM_LANGUAGE_ID + (UINT)m_MenuArrayLang.GetSize(), currentItemID, MF_BYCOMMAND); subMenuOZ.Detach(); subMenuAN.Detach(); subMenu.Detach(); menu.Detach(); if(! FlagHitLang) { AfxMessageBox(_T("FATAL ERROR: Missing Language File!!")); } } BOOL CMainDialogFx::CheckThemeEdition(CString name) { if (name.Find(_T(".")) != 0) { return TRUE; } return FALSE; } BOOL CMainDialogFx::OnInitDialog() { return CDialogFx::OnInitDialog(); } void CMainDialogFx::ChangeTheme(CString themeName) { WritePrivateProfileStringFx(_T("Setting"), m_ThemeKeyName, themeName, m_Ini); } BOOL CMainDialogFx::OnCommand(WPARAM wParam, LPARAM lParam) { // Select Theme if(WM_THEME_ID <= wParam && wParam < WM_THEME_ID + (WPARAM)m_MenuArrayTheme.GetSize()) { CMenu menu; CMenu subMenu; menu.Attach(GetMenu()->GetSafeHmenu()); subMenu.Attach(menu.GetSubMenu(MENU_THEME_INDEX)->GetSafeHmenu()); m_CurrentTheme = m_MenuArrayTheme.GetAt(wParam - WM_THEME_ID); if (m_CurrentTheme.Compare(m_RandomThemeLabel) == 0) { m_CurrentTheme = GetRandomTheme(); m_RandomThemeLabel = _T("Random"); m_RandomThemeName = _T(" (") + m_CurrentTheme + _T(")"); // ChangeTheme save the theme configuration to profile; so if we are on // Random, then save Random to profile. ChangeTheme(m_RandomThemeLabel); } else { ChangeTheme(m_MenuArrayTheme.GetAt(wParam - WM_THEME_ID)); m_RandomThemeName = _T(""); } SUBMENU_MODIFY_MENU(WM_THEME_ID, MF_STRING, WM_THEME_ID, m_RandomThemeLabel + m_RandomThemeName); subMenu.CheckMenuRadioItem(WM_THEME_ID, WM_THEME_ID + (UINT)m_MenuArrayTheme.GetSize(), (UINT)wParam, MF_BYCOMMAND); subMenu.Detach(); menu.Detach(); UpdateThemeInfo(); UpdateDialogSize(); } return CDialogFx::OnCommand(wParam, lParam); } void CMainDialogFx::OnWindowPosChanging(WINDOWPOS * lpwndpos) { if(! m_bShowWindow) { lpwndpos->flags &= ~SWP_SHOWWINDOW; } if(m_bWindowMinimizeOnce && ! m_bInitializing) { m_bWindowMinimizeOnce = FALSE; if(m_bResident && m_bResidentMinimize) { ShowWindow(SW_MINIMIZE); } } CDialogFx::OnWindowPosChanging(lpwndpos); } void CMainDialogFx::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { lpMMI->ptMinTrackSize.x = m_MinSizeX; lpMMI->ptMinTrackSize.y = m_MinSizeY; lpMMI->ptMaxTrackSize.x = m_MaxSizeX; lpMMI->ptMaxTrackSize.y = m_MaxSizeY; CDialogFx::OnGetMinMaxInfo(lpMMI); } void CMainDialogFx::SaveWindowPosition() { WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) }; GetWindowPlacement(&place); CString x, y; x.Format(_T("%d"), place.rcNormalPosition.left); y.Format(_T("%d"), place.rcNormalPosition.top); WritePrivateProfileStringFx(_T("Setting"), _T("X"), x, m_Ini); WritePrivateProfileStringFx(_T("Setting"), _T("Y"), y, m_Ini); } void CMainDialogFx::RestoreWindowPosition() { const int x = GetPrivateProfileInt(_T("Setting"), _T("X"), INT_MIN, m_Ini); const int y = GetPrivateProfileInt(_T("Setting"), _T("Y"), INT_MIN, m_Ini); RECT rw, rc; GetWindowRect(&rw); rc.left = x; rc.top = y; rc.right = x + rw.right - rw.left; rc.bottom = y + rw.bottom - rw.top; #if _MSC_VER > 1310 HMONITOR hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONULL); if (hMonitor == NULL) { CenterWindow(); } else { // Get Taskbar Size APPBARDATA taskbarInfo = { 0 }; taskbarInfo.cbSize = sizeof(APPBARDATA); taskbarInfo.hWnd = m_hWnd; SHAppBarMessage(ABM_GETTASKBARPOS, &taskbarInfo); CRect taskbarRect = taskbarInfo.rc; if (taskbarInfo.rc.top <= 0 && taskbarInfo.rc.left <= 0) // Top Side or Left Side { if (taskbarRect.Height() > taskbarRect.Width()) // Left Side { if (x < taskbarRect.Width()) // Overlap { SetWindowPos(NULL, taskbarRect.Width(), y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } else { SetWindowPos(NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } } else // Top Side { if (y < taskbarRect.Height()) // Overlap { SetWindowPos(NULL, x, taskbarRect.Height(), 0, 0, SWP_NOSIZE | SWP_NOZORDER); } else { SetWindowPos(NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } } } else { SetWindowPos(NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } } #else CenterWindow(); #endif } DWORD CMainDialogFx::GetZoomType() { return GetPrivateProfileInt(_T("Setting"), _T("ZoomType"), ZoomTypeAuto, m_Ini); } void CMainDialogFx::SetZoomType(DWORD zoomType) { CString cstr; cstr.Format(_T("%d"), m_ZoomType); WritePrivateProfileStringFx(_T("Setting"), _T("ZoomType"), cstr, m_Ini); } void CMainDialogFx::UpdateThemeInfo() { CString theme = m_ThemeDir + m_CurrentTheme + _T("\\theme.ini"); m_LabelText = GetControlColor(_T("LabelText"), 0, theme); m_MeterText = GetControlColor(_T("MeterText"), 0, theme); m_ComboText = GetControlColor(_T("ComboText"), 0, theme); m_ComboTextSelected = GetControlColor(_T("ComboTextSelected"), 0, theme); m_ComboBk = GetControlColor(_T("ComboBk"), 255, theme); m_ComboBkSelected = GetControlColor(_T("ComboBkSelected"), 192, theme); m_ButtonText= GetControlColor(_T("ButtonText"), 0, theme); m_EditText = GetControlColor(_T("EditText"), 0, theme); m_EditBk = GetControlColor(_T("EditBk"), 255, theme); m_ListText1 = GetControlColor(_T("ListText1"), 0, theme); m_ListText2 = GetControlColor(_T("ListText2"), 0, theme); m_ListTextSelected = GetControlColor(_T("ListTextSelected"), 0, theme); m_ListBk1 = GetControlColor(_T("ListBk1"), 255, theme); m_ListBk2 = GetControlColor(_T("ListBk2"), 255, theme); m_ListBkSelected = GetControlColor(_T("ListBkSelected"), 0, theme); m_ListLine1 = GetControlColor(_T("ListLine1"), 0, theme); m_ListLine2 = GetControlColor(_T("ListLine2"), 0, theme); m_Glass = GetControlColor(_T("Glass"), 255, theme); m_Frame = GetControlColor(_T("Frame"), 128, theme); m_Background = GetBackgroundColor(_T("Background"), theme); m_ComboAlpha = GetControlAlpha(_T("ComboAlpha"), 255, theme); m_EditAlpha = GetControlAlpha(_T("EditAlpha"), 255, theme); m_GlassAlpha = GetControlAlpha(_T("GlassAlpha"), 128, theme); m_CharacterPosition = GetCharacterPosition(theme); m_ParentTheme1 = GetParentTheme(1, theme); m_ParentTheme2 = GetParentTheme(2, theme); } COLORREF CMainDialogFx::GetControlColor(CString name, BYTE defaultColor, CString theme) { COLORREF reverseColor; reverseColor = GetPrivateProfileInt(_T("Color"), name, RGB(defaultColor, defaultColor, defaultColor), theme); COLORREF color = RGB(GetBValue(reverseColor), GetGValue(reverseColor), GetRValue(reverseColor)); return color; } COLORREF CMainDialogFx::GetBackgroundColor(CString name, CString theme) { COLORREF reverseColor; reverseColor = GetPrivateProfileInt(_T("Color"), name, 0xFFFFFFFF, theme); if (reverseColor == 0xFFFFFFFF) { return 0xFFFFFFFF; // 0xFFFFFFF = Disabled } else { COLORREF color = RGB(GetBValue(reverseColor), GetGValue(reverseColor), GetRValue(reverseColor)); return color; } } BYTE CMainDialogFx::GetControlAlpha(CString name, BYTE defaultAlpha, CString theme) { BYTE alpha = (BYTE)GetPrivateProfileInt(_T("Alpha"), name, defaultAlpha, theme); return alpha; } BYTE CMainDialogFx::GetCharacterPosition(CString theme) { BYTE position = (BYTE)GetPrivateProfileInt(_T("Character"), _T("Position"), 0, theme); return position; } CString CMainDialogFx::GetParentTheme(int i, CString theme) { CString cstr; cstr.Format(_T("ParentTheme%d"), i); TCHAR str[256]; GetPrivateProfileStringFx(_T("Info"), cstr, _T(""), str, 256, theme); cstr = str; return cstr; } CString CMainDialogFx::GetRandomTheme() { // We need to add/subtract one to exclude first item ("Random"). UINT i = 1 + rand() % ((UINT)m_MenuArrayTheme.GetSize() - 1); return m_MenuArrayTheme.GetAt(i); } void CMainDialogFx::SaveImage() { #if _MSC_VER > 1310 BOOL bDwmEnabled = FALSE; HMODULE hModule = LoadLibraryEx(_T("dwmapi.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); typedef HRESULT(WINAPI* FuncDwmGetWindowAttribute) (HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute); typedef HRESULT(WINAPI* FuncDwmIsCompositionEnabled)(BOOL* pfEnabled); FuncDwmGetWindowAttribute pDwmGetWindowAttribute = NULL; FuncDwmIsCompositionEnabled pDwmIsCompositionEnabled = NULL; if (hModule) { pDwmGetWindowAttribute = (FuncDwmGetWindowAttribute)GetProcAddress(hModule, "DwmGetWindowAttribute"); pDwmIsCompositionEnabled = (FuncDwmIsCompositionEnabled)GetProcAddress(hModule, "DwmIsCompositionEnabled"); } if (pDwmGetWindowAttribute && pDwmIsCompositionEnabled) { pDwmIsCompositionEnabled(&bDwmEnabled); } CRect rc1; CRect rc2; CRect rc3; CImage* image1 = new CImage(); CImage* image2 = new CImage(); CImage* image3 = new CImage(); if (bDwmEnabled) { GetWindowRect(&rc1); if (image1->Create(rc1.Width(), rc1.Height(), 32)) { HDC hImage1DC = image1->GetDC(); if (IsWin81orLater()) { ::PrintWindow(m_hWnd, hImage1DC, 2); // PW_RENDERFULLCONTENT, Windows 8.1 or later GetClientRect(&rc3); if (image3->Create(rc3.Width(), rc3.Height(), 32)) { HDC hImage3DC = image3->GetDC(); ::PrintWindow(m_hWnd, hImage3DC, 1); // PW_CLIENTONLY int targetY = 0; int offsetX = (rc1.Width() - rc3.Width()) / 2; int offsetY = (rc1.Height() - rc3.Height()) / 2; // Compare Screenshot for (int y = offsetY; y < rc1.Height() - rc3.Height(); y++) { for (int x = 0; x < rc3.Width(); x++) { if (image1->GetPixel(offsetX + x, y) == image3->GetPixel(x, 0)) { if (x == rc3.Width() / 2) { for (int yy = 0; yy < rc3.Height(); yy++) { if (image1->GetPixel(offsetX, y + yy) == image3->GetPixel(0, yy)) { if (yy == rc3.Height() / 2) { targetY = y; goto loopEnd; } } else { break; } } } } else { break; } } } loopEnd: if (targetY > 0) { ::BitBlt(hImage1DC, (rc1.Width() - rc3.Width()) / 2, targetY, rc3.Width(), rc3.Height(), hImage3DC, 0, 0, SRCCOPY); } image3->ReleaseDC(); } } else { ::PrintWindow(m_hWnd, hImage1DC, 0); } pDwmGetWindowAttribute(m_hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rc2, sizeof(rc2)); // cstr.Format(_T("Width=%d/%d, Height=%d/%d"), rc1.Width(), rc2.Width(), rc1.Height(), rc2.Height()); // AfxMessageBox(cstr); if (rc1.Width() > rc2.Width()) { if (image2->Create(rc2.Width(), rc2.Height(), 32)) { HDC hImage2DC = image2->GetDC(); ::BitBlt(hImage2DC, 0, 0, rc2.Width(), rc2.Height(), hImage1DC, (rc1.Width() - rc2.Width()) / 2, 0, SRCCOPY); image2->ReleaseDC(); SaveImageDlg(image2); } else { SaveImageDlg(image1); } } else { SaveImageDlg(image1); } image1->ReleaseDC(); } } else { GetWindowRect(&rc1); if (image1->Create(rc1.Width(), rc1.Height(), 32)) { HDC hImage1DC = image1->GetDC(); ::PrintWindow(m_hWnd, hImage1DC, 0); SaveImageDlg(image1); image1->ReleaseDC(); } } SAFE_DELETE(image1); SAFE_DELETE(image2); SAFE_DELETE(image3); #endif } void CMainDialogFx::SaveImageDlg(CImage* image) { CString path; SYSTEMTIME st; GetLocalTime(&st); path.Format(_T("%s_%04d%02d%02d%02d%02d%02d"), PRODUCT_FILENAME, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); CString filter = _T("PNG (*.png)|*.png|BMP (*.bmp)|*.bmp||"); CFileDialog save(FALSE, _T(""), path, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER, filter); if (save.DoModal() == IDOK) { image->Save(save.GetPathName().GetString()); } } ///////////////////////////////////////////////////////////////////////////////////////////////// // // Task Tray // ///////////////////////////////////////////////////////////////////////////////////////////////// #ifdef OPTION_TASK_TRAY UINT CMainDialogFx::wmTaskbarCreated = ::RegisterWindowMessage(_T("TaskbarCreated")); // Add TaskTray BOOL CMainDialogFx::AddTaskTray(UINT id, UINT callback, HICON icon, CString tip) { if(m_bResident) { NOTIFYICONDATA nidata = {0}; nidata.cbSize = sizeof(NOTIFYICONDATA); nidata.hWnd = m_hWnd; nidata.uID = id; nidata.uFlags = NIF_TIP | NIF_ICON | NIF_MESSAGE; nidata.hIcon = icon; nidata.uVersion = NOTIFYICON_VERSION; nidata.uCallbackMessage = callback; _tcscpy_s(nidata.szTip, 128, tip.Left(127)); ::Shell_NotifyIcon(NIM_SETVERSION, &nidata); int waitCount = 10; if(m_bStartup) { waitCount = 20; } for(int i = 0; i < waitCount; i++) { if(::Shell_NotifyIcon(NIM_ADD, &nidata)) { return TRUE; } Sleep(100 * i); } } return FALSE; } // Update TaskTray Icon BOOL CMainDialogFx::ModifyTaskTrayIcon(UINT id, HICON icon) { if(m_bResident) { NOTIFYICONDATA nidata = { 0 }; nidata.cbSize = sizeof(NOTIFYICONDATA); nidata.hWnd = m_hWnd; nidata.uID = id; nidata.uFlags = NIF_ICON; nidata.hIcon = icon; for(int i = 0; i < 3; i++) { if(::Shell_NotifyIcon(NIM_MODIFY, &nidata)) { return TRUE; } Sleep(100 * i); } } return FALSE; } // Update TaskTray Tips BOOL CMainDialogFx::ModifyTaskTrayTip(UINT id, CString tip) { if(m_bResident) { NOTIFYICONDATA nidata = { 0 }; nidata.cbSize = sizeof(NOTIFYICONDATA); nidata.hWnd = m_hWnd; nidata.uID = id; nidata.uFlags = NIF_TIP; _tcscpy_s(nidata.szTip, 128, tip.Left(127)); for(int i = 0; i < 3; i++) { if(::Shell_NotifyIcon(NIM_MODIFY, &nidata)) { return TRUE; } Sleep(100 * i); } } return FALSE; } // Update TaskTray BOOL CMainDialogFx::ModifyTaskTray(UINT id, HICON icon, CString tip) { if(m_bResident) { NOTIFYICONDATA nidata = { 0 }; nidata.cbSize = sizeof(NOTIFYICONDATA); nidata.hWnd = m_hWnd; nidata.uID = id; nidata.uFlags = NIF_TIP|NIF_ICON; nidata.hIcon = icon; _tcscpy_s(nidata.szTip, 128, tip.Left(127)); for(int i = 0; i < 3; i++) { if(::Shell_NotifyIcon(NIM_MODIFY, &nidata)) { return TRUE; } Sleep(100 * i); } } return FALSE; } // Show Balloon BOOL CMainDialogFx::ShowBalloon(UINT id, DWORD infoFlag, CString infoTitle, CString info) { if(m_bResident) { NOTIFYICONDATA nidata = { 0 }; nidata.cbSize = sizeof(NOTIFYICONDATA); nidata.hWnd = m_hWnd; nidata.uID = id; nidata.uFlags = NIF_INFO; nidata.dwInfoFlags = infoFlag; _tcscpy_s(nidata.szInfo, 256, info.Left(255)); _tcscpy_s(nidata.szInfoTitle, 64, infoTitle.Left(63)); for(int i = 0; i < 3; i++) { if(::Shell_NotifyIcon(NIM_MODIFY, &nidata)) { return TRUE; } Sleep(100 * i); } } return FALSE; } // Remove TaskTray BOOL CMainDialogFx::RemoveTaskTray(UINT id) { if(m_bResident) { NOTIFYICONDATA nidata = { 0 }; nidata.cbSize = sizeof(NOTIFYICONDATA); nidata.hWnd = m_hWnd; nidata.uID = id; for(int i = 0; i < 3; i++) { if(::Shell_NotifyIcon(NIM_DELETE, &nidata)) { return TRUE; } Sleep(100 * i); } } return FALSE; } #endif