diff --git a/Language/Language.vcxproj b/Language/Language.vcxproj index 4dc4a5f7..cd7518e6 100644 --- a/Language/Language.vcxproj +++ b/Language/Language.vcxproj @@ -1,43 +1,42 @@ - - - - - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A} - DynamicLibrary - 1033 - - - - - - - - - - - - $(OutDir)Languages\ - - - - true - - - Default - true - - - _UNICODE;UNICODE;%(PreprocessorDefinitions) - true - - - - - - true - - - - - + + + + + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A} + DynamicLibrary + 1033 + + + + + + + + + + + + $(OutDir)Languages\ + + + + true + + + Default + true + + + _UNICODE;UNICODE;%(PreprocessorDefinitions) + true + + + + + true + + + + + \ No newline at end of file diff --git a/Language/Language.vcxproj.filters b/Language/Language.vcxproj.filters index b0480503..ac243043 100644 --- a/Language/Language.vcxproj.filters +++ b/Language/Language.vcxproj.filters @@ -1,25 +1,22 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Resource Files - - - Resource Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + \ No newline at end of file diff --git a/Language/Resource.rc b/Language/Resource.rc index b28c0761..2221fad8 100644 --- a/Language/Resource.rc +++ b/Language/Resource.rc @@ -1,173 +1,173 @@ -#include -#include "../Library/resource.h" -#include "../Version.h" - -#ifdef LANGUAGE_RTL -#define DIALOG_EXSTYLE_FLAGS WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | WS_EX_LAYOUTRTL -#define STR_ISRTL "1" -#else -#define DIALOG_EXSTYLE_FLAGS WS_EX_APPWINDOW | WS_EX_CONTROLPARENT -#define STR_ISRTL "0" -#endif - - -#define MAKESTRING2(num) #num -#define MAKESTRING(num) MAKESTRING2(num) - -#define STR_NUM_BUTTONWIDTH MAKESTRING(NUM_BUTTONWIDTH) -#define STR_NUM_LABELWIDTH MAKESTRING(NUM_LABELWIDTH) - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -{ - ID_STR_NUM_BUTTONWIDTH, STR_NUM_BUTTONWIDTH - ID_STR_NUM_LABELWIDTH, STR_NUM_LABELWIDTH - ID_STR_ISRTL, STR_ISRTL - ID_STR_UPDATEAVAILABLE, STR_UPDATEAVAILABLE - ID_STR_MANAGE, STR_MANAGE - ID_STR_ABOUT, STR_ABOUT - ID_STR_HELP, STR_HELP - ID_STR_SKINS, STR_SKINS - ID_STR_NOSKINS, STR_NOSKINS - ID_STR_OPENFOLDER, STR_OPENFOLDER - ID_STR_DISABLEDRAGGING, STR_DISABLEDRAGGING - ID_STR_THEMES, STR_THEMES - ID_STR_NOTHEMES, STR_NOTHEMES - ID_STR_EDITSETTINGS, STR_EDITSETTINGS - ID_STR_REFRESHALL, STR_REFRESHALL - ID_STR_LOGGING, STR_LOGGING - ID_STR_SHOWLOGFILE, STR_SHOWLOGFILE - ID_STR_STARTLOGGING, STR_STARTLOGGING - ID_STR_STOPLOGGING, STR_STOPLOGGING - ID_STR_DELETELOGFILE, STR_DELETELOGFILE - ID_STR_DEBUGMODE, STR_DEBUGMODE - ID_STR_EXIT, STR_EXIT - ID_STR_VARIANTS, STR_VARIANTS - ID_STR_SETTINGS, STR_SETTINGS - ID_STR_POSITION, STR_POSITION - ID_STR_DISPLAYMONITOR, STR_DISPLAYMONITOR - ID_STR_USEDEFAULTMONITOR, STR_USEDEFAULTMONITOR - ID_STR_VIRTUALSCREEN, STR_VIRTUALSCREEN - ID_STR_AUTOSELECTMONITOR, STR_AUTOSELECTMONITOR - ID_STR_STAYTOPMOST, STR_STAYTOPMOST - ID_STR_TOPMOST, STR_TOPMOST - ID_STR_NORMAL, STR_NORMAL - ID_STR_BOTTOM, STR_BOTTOM - ID_STR_ONDESKTOP, STR_ONDESKTOP - ID_STR_FROMRIGHT, STR_FROMRIGHT - ID_STR_FROMBOTTOM, STR_FROMBOTTOM - ID_STR_XASPERCENTAGE, STR_XASPERCENTAGE - ID_STR_YASPERCENTAGE, STR_YASPERCENTAGE - ID_STR_TRANSPARENCY, STR_TRANSPARENCY - ID_STR_0PERCENT, "0%" - ID_STR_10PERCENT, "10%" - ID_STR_20PERCENT, "20%" - ID_STR_30PERCENT, "30%" - ID_STR_40PERCENT, "40%" - ID_STR_50PERCENT, "50%" - ID_STR_60PERCENT, "60%" - ID_STR_70PERCENT, "70%" - ID_STR_80PERCENT, "80%" - ID_STR_90PERCENT, "90%" - ID_STR_FADEIN, STR_FADEIN - ID_STR_FADEOUT, STR_FADEOUT - ID_STR_HIDEONMOUSEOVER, STR_HIDEONMOUSEOVER - ID_STR_DRAGGABLE, STR_DRAGGABLE - ID_STR_SAVEPOSITION, STR_SAVEPOSITION - ID_STR_SNAPTOEDGES, STR_SNAPTOEDGES - ID_STR_CLICKTHROUGH, STR_CLICKTHROUGH - ID_STR_KEEPONSCREEN, STR_KEEPONSCREEN - ID_STR_MANAGESKIN, STR_MANAGESKIN - ID_STR_EDITSKIN, STR_EDITSKIN - ID_STR_REFRESHSKIN, STR_REFRESHSKIN - ID_STR_UNLOADSKIN, STR_UNLOADSKIN - ID_STR_CLOSE, STR_CLOSE - ID_STR_ABOUTRAINMETER, STR_ABOUTRAINMETER - ID_STR_LOG, STR_LOG - ID_STR_MEASURES, STR_MEASURES - ID_STR_VARIABLES, STR_VARIABLES - ID_STR_PLUGINS, STR_PLUGINS - ID_STR_VERSION, STR_VERSION - ID_STR_TYPE, STR_TYPE - ID_STR_TIME, STR_TIME - ID_STR_MESSAGE, STR_MESSAGE - ID_STR_NAME, STR_NAME - ID_STR_RANGE, STR_RANGE - ID_STR_VALUE, STR_VALUE - ID_STR_AUTHOR, STR_AUTHOR - ID_STR_ERROR, STR_ERROR - ID_STR_WARNING, STR_WARNING - ID_STR_NOTICE, STR_NOTICE - ID_STR_DEBUG, STR_DEBUG - ID_STR_GETLATESTVERSION, STR_GETLATESTVERSION - ID_STR_COPYRIGHTNOTICE, STR_COPYRIGHTNOTICE - ID_STR_COPYTOCLIPBOARD, STR_COPYTOCLIPBOARD - ID_STR_MANAGERAINMETER, STR_MANAGERAINMETER - ID_STR_ACTIVESKINS, STR_ACTIVESKINS - ID_STR_EXPAND, STR_EXPAND - ID_STR_COLLAPSE, STR_COLLAPSE - ID_STR_OPENLOG, STR_OPENLOG - ID_STR_LOAD, STR_LOAD - ID_STR_UNLOAD, STR_UNLOAD - ID_STR_REFRESH, STR_REFRESH - ID_STR_EDIT, STR_EDIT - ID_STR_AUTHORSC, STR_AUTHORSC - ID_STR_VERSIONSC, STR_VERSIONSC - ID_STR_LICENSESC, STR_LICENSESC - ID_STR_INFORMATIONSC, STR_INFORMATIONSC - ID_STR_ADDMETADATA, STR_ADDMETADATA - ID_STR_COORDINATESSC, STR_COORDINATESSC - ID_STR_POSITIONSC, STR_POSITIONSC - ID_STR_LOADORDERSC, STR_LOADORDERSC - ID_STR_TRANSPARENCYSC, STR_TRANSPARENCYSC - ID_STR_ONHOVERSC, STR_ONHOVERSC - ID_STR_DONOTHING, STR_DONOTHING - ID_STR_HIDE, STR_HIDE - ID_STR_SAVENEWTHEME, STR_SAVENEWTHEME - ID_STR_THEMEDESCRIPTION, STR_THEMEDESCRIPTION - ID_STR_SAVEASEMPTYTHEME, STR_SAVEASEMPTYTHEME - ID_STR_EXCLUDEUNUSEDSKINS, STR_EXCLUDEUNUSEDSKINS - ID_STR_INCLUDEWALLPAPER, STR_INCLUDEWALLPAPER - ID_STR_NAMESC, STR_NAMESC - ID_STR_SAVE, STR_SAVE - ID_STR_SAVEDTHEMES, STR_SAVEDTHEMES - ID_STR_DELETE, STR_DELETE -// ID_STR_BACKUP, STR_BACKUP -// ID_STR_BACKUPDESCRIPTION, STR_BACKUPDESCRIPTION -// ID_STR_BACKUPE, STR_BACKUPE - ID_STR_LANGUAGESC, STR_LANGUAGESC - ID_STR_GENERAL, STR_GENERAL - ID_STR_CHECKFORUPDATES, STR_CHECKFORUPDATES - ID_STR_RESETSTATISTICS, STR_RESETSTATISTICS - ID_STR_LOGTOFILE, STR_LOGTOFILE - ID_STR_SETTINGSNOTWRITABLE, STR_SETTINGSNOTWRITABLE - ID_STR_SETTINGSMOVEFILE, STR_SETTINGSMOVEFILE - ID_STR_SETTINGSREADONLY, STR_SETTINGSREADONLY - ID_STR_THEMEALREADYEXISTS, STR_THEMEALREADYEXISTS - ID_STR_THEMESAVEFAIL, STR_THEMESAVEFAIL - ID_STR_THEMEDELETE, STR_THEMEDELETE - ID_STR_LOGFILECREATEFAIL, STR_LOGFILECREATEFAIL - ID_STR_LOGFILEDELETE, STR_LOGFILEDELETE - ID_STR_NOAVAILABLESKINS, STR_NOAVAILABLESKINS - ID_STR_UNABLETOACTIVATESKIN, STR_UNABLETOACTIVATESKIN - ID_STR_UNABLETOREFRESHSKIN, STR_UNABLETOREFRESHSKIN - ID_STR_NEWVERSIONREQUIRED, STR_NEWVERSIONREQUIRED - ID_STR_NOMETERSINSKIN, STR_NOMETERSINSKIN - ID_STR_INCLUDEINFINITELOOP, STR_INCLUDEINFINITELOOP - ID_STR_WELCOME, STR_WELCOME - ID_STR_CLICKTOMANAGE, STR_CLICKTOMANAGE - ID_STR_CLICKTODOWNLOAD, STR_CLICKTODOWNLOAD - ID_STR_CREATERMSKINPACKAGE, STR_CREATERMSKIN - ID_STR_EDITORSC, STR_EDITORSC - ID_STR_ELLIPSIS, "..." - ID_STR_SHOWNOTIFICATIONAREAICON, STR_SHOWNOTIFAREAICON - ID_STR_SOURCE, STR_SOURCE - ID_STR_USED2D, STR_USED2D - ID_STR_CLEAR, STR_CLEAR -} +#include +#include "../Library/resource.h" +#include "../Version.h" + +#ifdef LANGUAGE_RTL +#define DIALOG_EXSTYLE_FLAGS WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | WS_EX_LAYOUTRTL +#define STR_ISRTL "1" +#else +#define DIALOG_EXSTYLE_FLAGS WS_EX_APPWINDOW | WS_EX_CONTROLPARENT +#define STR_ISRTL "0" +#endif + + +#define MAKESTRING2(num) #num +#define MAKESTRING(num) MAKESTRING2(num) + +#define STR_NUM_BUTTONWIDTH MAKESTRING(NUM_BUTTONWIDTH) +#define STR_NUM_LABELWIDTH MAKESTRING(NUM_LABELWIDTH) + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +{ + ID_STR_NUM_BUTTONWIDTH, STR_NUM_BUTTONWIDTH + ID_STR_NUM_LABELWIDTH, STR_NUM_LABELWIDTH + ID_STR_ISRTL, STR_ISRTL + ID_STR_UPDATEAVAILABLE, STR_UPDATEAVAILABLE + ID_STR_MANAGE, STR_MANAGE + ID_STR_ABOUT, STR_ABOUT + ID_STR_HELP, STR_HELP + ID_STR_SKINS, STR_SKINS + ID_STR_NOSKINS, STR_NOSKINS + ID_STR_OPENFOLDER, STR_OPENFOLDER + ID_STR_DISABLEDRAGGING, STR_DISABLEDRAGGING + ID_STR_THEMES, STR_THEMES + ID_STR_NOTHEMES, STR_NOTHEMES + ID_STR_EDITSETTINGS, STR_EDITSETTINGS + ID_STR_REFRESHALL, STR_REFRESHALL + ID_STR_LOGGING, STR_LOGGING + ID_STR_SHOWLOGFILE, STR_SHOWLOGFILE + ID_STR_STARTLOGGING, STR_STARTLOGGING + ID_STR_STOPLOGGING, STR_STOPLOGGING + ID_STR_DELETELOGFILE, STR_DELETELOGFILE + ID_STR_DEBUGMODE, STR_DEBUGMODE + ID_STR_EXIT, STR_EXIT + ID_STR_VARIANTS, STR_VARIANTS + ID_STR_SETTINGS, STR_SETTINGS + ID_STR_POSITION, STR_POSITION + ID_STR_DISPLAYMONITOR, STR_DISPLAYMONITOR + ID_STR_USEDEFAULTMONITOR, STR_USEDEFAULTMONITOR + ID_STR_VIRTUALSCREEN, STR_VIRTUALSCREEN + ID_STR_AUTOSELECTMONITOR, STR_AUTOSELECTMONITOR + ID_STR_STAYTOPMOST, STR_STAYTOPMOST + ID_STR_TOPMOST, STR_TOPMOST + ID_STR_NORMAL, STR_NORMAL + ID_STR_BOTTOM, STR_BOTTOM + ID_STR_ONDESKTOP, STR_ONDESKTOP + ID_STR_FROMRIGHT, STR_FROMRIGHT + ID_STR_FROMBOTTOM, STR_FROMBOTTOM + ID_STR_XASPERCENTAGE, STR_XASPERCENTAGE + ID_STR_YASPERCENTAGE, STR_YASPERCENTAGE + ID_STR_TRANSPARENCY, STR_TRANSPARENCY + ID_STR_0PERCENT, "0%" + ID_STR_10PERCENT, "10%" + ID_STR_20PERCENT, "20%" + ID_STR_30PERCENT, "30%" + ID_STR_40PERCENT, "40%" + ID_STR_50PERCENT, "50%" + ID_STR_60PERCENT, "60%" + ID_STR_70PERCENT, "70%" + ID_STR_80PERCENT, "80%" + ID_STR_90PERCENT, "90%" + ID_STR_FADEIN, STR_FADEIN + ID_STR_FADEOUT, STR_FADEOUT + ID_STR_HIDEONMOUSEOVER, STR_HIDEONMOUSEOVER + ID_STR_DRAGGABLE, STR_DRAGGABLE + ID_STR_SAVEPOSITION, STR_SAVEPOSITION + ID_STR_SNAPTOEDGES, STR_SNAPTOEDGES + ID_STR_CLICKTHROUGH, STR_CLICKTHROUGH + ID_STR_KEEPONSCREEN, STR_KEEPONSCREEN + ID_STR_MANAGESKIN, STR_MANAGESKIN + ID_STR_EDITSKIN, STR_EDITSKIN + ID_STR_REFRESHSKIN, STR_REFRESHSKIN + ID_STR_UNLOADSKIN, STR_UNLOADSKIN + ID_STR_CLOSE, STR_CLOSE + ID_STR_ABOUTRAINMETER, STR_ABOUTRAINMETER + ID_STR_LOG, STR_LOG + ID_STR_MEASURES, STR_MEASURES + ID_STR_VARIABLES, STR_VARIABLES + ID_STR_PLUGINS, STR_PLUGINS + ID_STR_VERSION, STR_VERSION + ID_STR_TYPE, STR_TYPE + ID_STR_TIME, STR_TIME + ID_STR_MESSAGE, STR_MESSAGE + ID_STR_NAME, STR_NAME + ID_STR_RANGE, STR_RANGE + ID_STR_VALUE, STR_VALUE + ID_STR_AUTHOR, STR_AUTHOR + ID_STR_ERROR, STR_ERROR + ID_STR_WARNING, STR_WARNING + ID_STR_NOTICE, STR_NOTICE + ID_STR_DEBUG, STR_DEBUG + ID_STR_GETLATESTVERSION, STR_GETLATESTVERSION + ID_STR_COPYRIGHTNOTICE, STR_COPYRIGHTNOTICE + ID_STR_COPYTOCLIPBOARD, STR_COPYTOCLIPBOARD + ID_STR_MANAGERAINMETER, STR_MANAGERAINMETER + ID_STR_ACTIVESKINS, STR_ACTIVESKINS + ID_STR_EXPAND, STR_EXPAND + ID_STR_COLLAPSE, STR_COLLAPSE + ID_STR_OPENLOG, STR_OPENLOG + ID_STR_LOAD, STR_LOAD + ID_STR_UNLOAD, STR_UNLOAD + ID_STR_REFRESH, STR_REFRESH + ID_STR_EDIT, STR_EDIT + ID_STR_AUTHORSC, STR_AUTHORSC + ID_STR_VERSIONSC, STR_VERSIONSC + ID_STR_LICENSESC, STR_LICENSESC + ID_STR_INFORMATIONSC, STR_INFORMATIONSC + ID_STR_ADDMETADATA, STR_ADDMETADATA + ID_STR_COORDINATESSC, STR_COORDINATESSC + ID_STR_POSITIONSC, STR_POSITIONSC + ID_STR_LOADORDERSC, STR_LOADORDERSC + ID_STR_TRANSPARENCYSC, STR_TRANSPARENCYSC + ID_STR_ONHOVERSC, STR_ONHOVERSC + ID_STR_DONOTHING, STR_DONOTHING + ID_STR_HIDE, STR_HIDE + ID_STR_SAVENEWTHEME, STR_SAVENEWTHEME + ID_STR_THEMEDESCRIPTION, STR_THEMEDESCRIPTION + ID_STR_SAVEASEMPTYTHEME, STR_SAVEASEMPTYTHEME + ID_STR_EXCLUDEUNUSEDSKINS, STR_EXCLUDEUNUSEDSKINS + ID_STR_INCLUDEWALLPAPER, STR_INCLUDEWALLPAPER + ID_STR_NAMESC, STR_NAMESC + ID_STR_SAVE, STR_SAVE + ID_STR_SAVEDTHEMES, STR_SAVEDTHEMES + ID_STR_DELETE, STR_DELETE +// ID_STR_BACKUP, STR_BACKUP +// ID_STR_BACKUPDESCRIPTION, STR_BACKUPDESCRIPTION +// ID_STR_BACKUPE, STR_BACKUPE + ID_STR_LANGUAGESC, STR_LANGUAGESC + ID_STR_GENERAL, STR_GENERAL + ID_STR_CHECKFORUPDATES, STR_CHECKFORUPDATES + ID_STR_RESETSTATISTICS, STR_RESETSTATISTICS + ID_STR_LOGTOFILE, STR_LOGTOFILE + ID_STR_SETTINGSNOTWRITABLE, STR_SETTINGSNOTWRITABLE + ID_STR_SETTINGSMOVEFILE, STR_SETTINGSMOVEFILE + ID_STR_SETTINGSREADONLY, STR_SETTINGSREADONLY + ID_STR_THEMEALREADYEXISTS, STR_THEMEALREADYEXISTS + ID_STR_THEMESAVEFAIL, STR_THEMESAVEFAIL + ID_STR_THEMEDELETE, STR_THEMEDELETE + ID_STR_LOGFILECREATEFAIL, STR_LOGFILECREATEFAIL + ID_STR_LOGFILEDELETE, STR_LOGFILEDELETE + ID_STR_NOAVAILABLESKINS, STR_NOAVAILABLESKINS + ID_STR_UNABLETOACTIVATESKIN, STR_UNABLETOACTIVATESKIN + ID_STR_UNABLETOREFRESHSKIN, STR_UNABLETOREFRESHSKIN + ID_STR_NEWVERSIONREQUIRED, STR_NEWVERSIONREQUIRED + ID_STR_NOMETERSINSKIN, STR_NOMETERSINSKIN + ID_STR_INCLUDEINFINITELOOP, STR_INCLUDEINFINITELOOP + ID_STR_WELCOME, STR_WELCOME + ID_STR_CLICKTOMANAGE, STR_CLICKTOMANAGE + ID_STR_CLICKTODOWNLOAD, STR_CLICKTODOWNLOAD + ID_STR_CREATERMSKINPACKAGE, STR_CREATERMSKIN + ID_STR_EDITORSC, STR_EDITORSC + ID_STR_ELLIPSIS, "..." + ID_STR_SHOWNOTIFICATIONAREAICON, STR_SHOWNOTIFAREAICON + ID_STR_SOURCE, STR_SOURCE + ID_STR_USED2D, STR_USED2D + ID_STR_CLEAR, STR_CLEAR +} diff --git a/Library/CommandHandler.cpp b/Library/CommandHandler.cpp index 59789766..232b48b3 100644 --- a/Library/CommandHandler.cpp +++ b/Library/CommandHandler.cpp @@ -20,13 +20,10 @@ #include "../Common/PathUtil.h" #include "CommandHandler.h" #include "ConfigParser.h" -#include "DialogAbout.h" -#include "DialogManage.h" #include "Measure.h" #include "Logger.h" #include "Rainmeter.h" #include "System.h" -#include "TrayWindow.h" #include "resource.h" namespace { @@ -708,26 +705,12 @@ void CommandHandler::DoSetWallpaperBang(std::vector& args, MeterWi void CommandHandler::DoAboutBang(std::vector& args, MeterWindow* meterWindow) { - DialogAbout::Open(args.empty() ? L"" : args[0].c_str()); + LogErrorF(L"!About: about bang is unsupported."); } void CommandHandler::DoManageBang(std::vector& args, MeterWindow* meterWindow) { - const size_t argsSize = args.size(); - if (argsSize >= 2 && argsSize <= 3) - { - DialogManage::Open(args[0].c_str(), - args[1].c_str(), - (argsSize == 3) ? args[2].c_str() : L""); - } - else if (argsSize <= 1) - { - DialogManage::Open(args.empty() ? L"" : args[0].c_str()); - } - else - { - LogErrorF(meterWindow, L"!Manage: Invalid parameters"); - } + LogErrorF(L"!Manage: manage bang is unsupported."); } void CommandHandler::DoSkinMenuBang(std::vector& args, MeterWindow* skin) diff --git a/Library/ConfigParser.cpp b/Library/ConfigParser.cpp index b8ff8271..25404965 100644 --- a/Library/ConfigParser.cpp +++ b/Library/ConfigParser.cpp @@ -92,7 +92,7 @@ void ConfigParser::SetBuiltInVariables(const std::wstring& filename, const std:: return m_BuiltInVariables.insert(std::make_pair(name, value)); }; - insertVariable(L"PROGRAMPATH", GetRainmeter().GetPath()); + insertVariable(L"PROGRAMPATH", GetRainmeter().GetWorkDirectory()); insertVariable(L"PROGRAMDRIVE", GetRainmeter().GetDrive()); insertVariable(L"SETTINGSPATH", GetRainmeter().GetSettingsPath()); insertVariable(L"SKINSPATH", GetRainmeter().GetSkinPath()); diff --git a/Library/ContextMenu.cpp b/Library/ContextMenu.cpp deleted file mode 100644 index 1088f4e7..00000000 --- a/Library/ContextMenu.cpp +++ /dev/null @@ -1,690 +0,0 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/MenuTemplate.h" -#include "../Common/Gfx/CanvasD2D.h" -#include "ContextMenu.h" -#include "Rainmeter.h" -#include "Litestep.h" -#include "MeterWindow.h" -#include "System.h" -#include "TrayWindow.h" -#include "resource.h" - -ContextMenu::ContextMenu() : - m_MenuActive(false) -{ -} - -/* -** Opens the context menu in given coordinates. -*/ -void ContextMenu::ShowMenu(POINT pos, MeterWindow* meterWindow) -{ - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_MANAGE, ID_STR_MANAGE), - MENU_ITEM(IDM_ABOUT, ID_STR_ABOUT), - MENU_ITEM(IDM_SHOW_HELP, ID_STR_HELP), - MENU_SEPARATOR(), - MENU_SUBMENU(ID_STR_SKINS, - MENU_ITEM_GRAYED(0, ID_STR_NOSKINS), - MENU_SEPARATOR(), - MENU_ITEM(IDM_OPENSKINSFOLDER, ID_STR_OPENFOLDER), - MENU_ITEM(IDM_DISABLEDRAG, ID_STR_DISABLEDRAGGING)), - MENU_SUBMENU(ID_STR_THEMES, - MENU_ITEM_GRAYED(0, ID_STR_NOTHEMES)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_EDITCONFIG, ID_STR_EDITSETTINGS), - MENU_ITEM(IDM_REFRESH, ID_STR_REFRESHALL), - MENU_SEPARATOR(), - MENU_SUBMENU(ID_STR_LOGGING, - MENU_ITEM(IDM_SHOWLOGFILE, ID_STR_SHOWLOGFILE), - MENU_SEPARATOR(), - MENU_ITEM(IDM_STARTLOG, ID_STR_STARTLOGGING), - MENU_ITEM(IDM_STOPLOG, ID_STR_STOPLOGGING), - MENU_SEPARATOR(), - MENU_ITEM(IDM_DELETELOGFILE, ID_STR_DELETELOGFILE), - MENU_ITEM(IDM_DEBUGLOG, ID_STR_DEBUGMODE)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_QUIT, ID_STR_EXIT) - }; - - if (m_MenuActive || (meterWindow && meterWindow->IsClosing())) return; - - // Show context menu, if no actions were executed - HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - if (!menu) return; - - m_MenuActive = true; - Rainmeter& rainmeter = GetRainmeter(); - - SetMenuDefaultItem(menu, IDM_MANAGE, MF_BYCOMMAND); - - if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) == -1) - { - EnableMenuItem(menu, IDM_SHOWLOGFILE, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(menu, IDM_DELETELOGFILE, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(menu, IDM_STOPLOG, MF_BYCOMMAND | MF_GRAYED); - } - else - { - EnableMenuItem( - menu, - (GetLogger().IsLogToFile()) ? IDM_STARTLOG : IDM_STOPLOG, - MF_BYCOMMAND | MF_GRAYED); - } - - if (rainmeter.m_Debug) - { - CheckMenuItem(menu, IDM_DEBUGLOG, MF_BYCOMMAND | MF_CHECKED); - } - - HMENU allSkinsMenu = GetSubMenu(menu, 4); - if (allSkinsMenu) - { - if (!rainmeter.m_SkinRegistry.IsEmpty()) - { - DeleteMenu(allSkinsMenu, 0, MF_BYPOSITION); // "No skins available" menuitem - CreateAllSkinsMenu(allSkinsMenu); - } - - if (rainmeter.m_DisableDragging) - { - CheckMenuItem(allSkinsMenu, IDM_DISABLEDRAG, MF_BYCOMMAND | MF_CHECKED); - } - } - - HMENU layoutMenu = GetSubMenu(menu, 5); - if (layoutMenu) - { - if (!rainmeter.m_Layouts.empty()) - { - DeleteMenu(layoutMenu, 0, MF_BYPOSITION); // "No layouts available" menuitem - CreateLayoutMenu(layoutMenu); - } - } - - if (meterWindow) - { - HMENU rainmeterMenu = menu; - menu = CreateSkinMenu(meterWindow, 0, allSkinsMenu); - - InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_POPUP, (UINT_PTR)rainmeterMenu, L"Rainmeter"); - InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_SEPARATOR, 0, nullptr); - } - else - { - InsertMenu(menu, 12, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - - // Create a menu for all active skins - int index = 0; - std::map::const_iterator iter = rainmeter.m_MeterWindows.begin(); - for (; iter != rainmeter.m_MeterWindows.end(); ++iter) - { - MeterWindow* mw = ((*iter).second); - HMENU skinMenu = CreateSkinMenu(mw, index, allSkinsMenu); - InsertMenu(menu, 12, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinMenu, mw->GetFolderPath().c_str()); - ++index; - } - - // Add update notification item - if (rainmeter.m_NewVersion) - { - InsertMenu(menu, 0, MF_BYPOSITION, IDM_NEW_VERSION, GetString(ID_STR_UPDATEAVAILABLE)); - HiliteMenuItem(rainmeter.GetTrayWindow()->GetWindow(), menu, 0, MF_BYPOSITION | MF_HILITE); - InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } - } - - HWND hWnd = WindowFromPoint(pos); - if (hWnd != nullptr) - { - MeterWindow* mw = rainmeter.GetMeterWindow(hWnd); - if (mw) - { - // Cancel the mouse event beforehand - mw->SetMouseLeaveEvent(true); - } - } - - DisplayMenu(pos, menu, meterWindow ? meterWindow->GetWindow() : rainmeter.m_TrayWindow->GetWindow()); - DestroyMenu(menu); - - m_MenuActive = false; -} - -void ContextMenu::ShowSkinCustomMenu(POINT pos, MeterWindow* meterWindow) -{ - if (m_MenuActive || meterWindow->IsClosing()) return; - - m_MenuActive = true; - - HMENU menu = CreatePopupMenu(); - AppendSkinCustomMenu(meterWindow, 0, menu, true); - - DisplayMenu(pos, menu, meterWindow->GetWindow()); - DestroyMenu(menu); - - m_MenuActive = false; -} - -void ContextMenu::DisplayMenu(POINT pos, HMENU menu, HWND parentWindow) -{ - // Set the window to foreground - HWND foregroundWindow = GetForegroundWindow(); - if (foregroundWindow != parentWindow) - { - const DWORD foregroundThreadID = GetWindowThreadProcessId(foregroundWindow, nullptr); - const DWORD currentThreadID = GetCurrentThreadId(); - AttachThreadInput(currentThreadID, foregroundThreadID, TRUE); - SetForegroundWindow(parentWindow); - AttachThreadInput(currentThreadID, foregroundThreadID, FALSE); - } - - // Show context menu - TrackPopupMenu( - menu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN | (*GetString(ID_STR_ISRTL) == L'1' ? TPM_LAYOUTRTL : 0), - pos.x, - pos.y, - 0, - parentWindow, - nullptr); -} - -HMENU ContextMenu::CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu) -{ - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_SKIN_OPENSKINSFOLDER, 0), - MENU_SEPARATOR(), - MENU_SUBMENU(ID_STR_VARIANTS, - MENU_SEPARATOR()), - MENU_SEPARATOR(), - MENU_SUBMENU(ID_STR_SETTINGS, - MENU_SUBMENU(ID_STR_POSITION, - MENU_SUBMENU(ID_STR_DISPLAYMONITOR, - MENU_ITEM(IDM_SKIN_MONITOR_PRIMARY, ID_STR_USEDEFAULTMONITOR), - MENU_ITEM(ID_MONITOR_FIRST, ID_STR_VIRTUALSCREEN), - MENU_SEPARATOR(), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_MONITOR_AUTOSELECT, ID_STR_AUTOSELECTMONITOR)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_VERYTOPMOST, ID_STR_STAYTOPMOST), - MENU_ITEM(IDM_SKIN_TOPMOST, ID_STR_TOPMOST), - MENU_ITEM(IDM_SKIN_NORMAL, ID_STR_NORMAL), - MENU_ITEM(IDM_SKIN_BOTTOM, ID_STR_BOTTOM), - MENU_ITEM(IDM_SKIN_ONDESKTOP, ID_STR_ONDESKTOP), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_FROMRIGHT, ID_STR_FROMRIGHT), - MENU_ITEM(IDM_SKIN_FROMBOTTOM, ID_STR_FROMBOTTOM), - MENU_ITEM(IDM_SKIN_XPERCENTAGE, ID_STR_XASPERCENTAGE), - MENU_ITEM(IDM_SKIN_YPERCENTAGE, ID_STR_YASPERCENTAGE)), - MENU_SUBMENU(ID_STR_TRANSPARENCY, - MENU_ITEM(IDM_SKIN_TRANSPARENCY_0, ID_STR_0PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_10, ID_STR_10PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_20, ID_STR_20PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_30, ID_STR_30PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_40, ID_STR_40PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_50, ID_STR_50PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_60, ID_STR_60PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_70, ID_STR_70PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_80, ID_STR_80PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_90, ID_STR_90PERCENT), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEIN, ID_STR_FADEIN), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEOUT, ID_STR_FADEOUT)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_HIDEONMOUSE, ID_STR_HIDEONMOUSEOVER), - MENU_ITEM(IDM_SKIN_DRAGGABLE, ID_STR_DRAGGABLE), - MENU_ITEM(IDM_SKIN_REMEMBERPOSITION, ID_STR_SAVEPOSITION), - MENU_ITEM(IDM_SKIN_SNAPTOEDGES, ID_STR_SNAPTOEDGES), - MENU_ITEM(IDM_SKIN_CLICKTHROUGH, ID_STR_CLICKTHROUGH), - MENU_ITEM(IDM_SKIN_KEEPONSCREEN, ID_STR_KEEPONSCREEN), - MENU_ITEM(IDM_SKIN_USED2D, ID_STR_USED2D)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_MANAGESKIN, ID_STR_MANAGESKIN), - MENU_ITEM(IDM_SKIN_EDITSKIN, ID_STR_EDITSKIN), - MENU_ITEM(IDM_SKIN_REFRESH, ID_STR_REFRESHSKIN), - MENU_SEPARATOR(), - MENU_ITEM(IDM_CLOSESKIN, ID_STR_UNLOADSKIN) - }; - - HMENU skinMenu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - if (!skinMenu) return nullptr; - - // Tick the position - HMENU settingsMenu = GetSubMenu(skinMenu, 4); - if (settingsMenu) - { - HMENU posMenu = GetSubMenu(settingsMenu, 0); - if (posMenu) - { - const UINT checkPos = IDM_SKIN_NORMAL - (UINT)meterWindow->GetWindowZPosition(); - CheckMenuRadioItem(posMenu, checkPos, checkPos, checkPos, MF_BYCOMMAND); - - if (meterWindow->GetXFromRight()) CheckMenuItem(posMenu, IDM_SKIN_FROMRIGHT, MF_BYCOMMAND | MF_CHECKED); - if (meterWindow->GetYFromBottom()) CheckMenuItem(posMenu, IDM_SKIN_FROMBOTTOM, MF_BYCOMMAND | MF_CHECKED); - if (meterWindow->GetXPercentage()) CheckMenuItem(posMenu, IDM_SKIN_XPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); - if (meterWindow->GetYPercentage()) CheckMenuItem(posMenu, IDM_SKIN_YPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); - - HMENU monitorMenu = GetSubMenu(posMenu, 0); - if (monitorMenu) - { - CreateMonitorMenu(monitorMenu, meterWindow); - } - } - - // Tick the transparency - HMENU alphaMenu = GetSubMenu(settingsMenu, 1); - if (alphaMenu) - { - UINT checkPos = (UINT)(10 - meterWindow->GetAlphaValue() / 25.5); - checkPos = min(9, checkPos); - checkPos = max(0, checkPos); - CheckMenuRadioItem(alphaMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); - - switch (meterWindow->GetWindowHide()) - { - case HIDEMODE_FADEIN: - CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_CHECKED); - EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); - break; - - case HIDEMODE_FADEOUT: - CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_CHECKED); - EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); - break; - - case HIDEMODE_HIDE: - EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); - break; - } - } - - // Tick the settings - switch (meterWindow->GetWindowHide()) - { - case HIDEMODE_HIDE: - CheckMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_CHECKED); - break; - - case HIDEMODE_FADEIN: - case HIDEMODE_FADEOUT: - EnableMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_GRAYED); - break; - } - - if (meterWindow->GetSnapEdges()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_SNAPTOEDGES, MF_BYCOMMAND | MF_CHECKED); - } - - if (meterWindow->GetSavePosition()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_REMEMBERPOSITION, MF_BYCOMMAND | MF_CHECKED); - } - - if (GetRainmeter().m_DisableDragging) - { - EnableMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_GRAYED); - } - else if (meterWindow->GetWindowDraggable()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_CHECKED); - } - - if (meterWindow->GetClickThrough()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_CLICKTHROUGH, MF_BYCOMMAND | MF_CHECKED); - } - - if (meterWindow->GetKeepOnScreen()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_KEEPONSCREEN, MF_BYCOMMAND | MF_CHECKED); - } - - if (Gfx::CanvasD2D::Initialize()) - { - if (!GetRainmeter().GetUseD2D()) - { - EnableMenuItem(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND | MF_GRAYED); - } - else if (meterWindow->GetUseD2D()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND | MF_CHECKED); - } - } - else - { - DeleteMenu(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND); - } - Gfx::CanvasD2D::Finalize(); - } - - // Add the name of the Skin to the menu - const std::wstring& skinName = meterWindow->GetFolderPath(); - ModifyMenu(skinMenu, IDM_SKIN_OPENSKINSFOLDER, MF_BYCOMMAND, IDM_SKIN_OPENSKINSFOLDER, skinName.c_str()); - SetMenuDefaultItem(skinMenu, IDM_SKIN_OPENSKINSFOLDER, FALSE); - - // Remove dummy menuitem from the variants menu - HMENU variantsMenu = GetSubMenu(skinMenu, 2); - if (variantsMenu) - { - DeleteMenu(variantsMenu, 0, MF_BYPOSITION); - } - - // Give the menuitem the unique id that depends on the skin - ChangeSkinIndex(skinMenu, index); - - // Add the variants menu - if (variantsMenu) - { - const SkinRegistry::Folder& skinFolder = *GetRainmeter().m_SkinRegistry.FindFolder(skinName); - for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) - { - InsertMenu(variantsMenu, i, MF_BYPOSITION, skinFolder.baseID + i, skinFolder.files[i].c_str()); - } - - if (skinFolder.active) - { - UINT checkPos = skinFolder.active - 1; - CheckMenuRadioItem(variantsMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); - } - } - - // Add skin root menu - int itemCount = GetMenuItemCount(menu); - if (itemCount > 0) - { - std::wstring root = meterWindow->GetFolderPath(); - std::wstring::size_type pos = root.find_first_of(L'\\'); - if (pos != std::wstring::npos) - { - root.erase(pos); - } - - for (int i = 0; i < itemCount; ++i) - { - const UINT state = GetMenuState(menu, i, MF_BYPOSITION); - if (state == 0xFFFFFFFF || (state & MF_POPUP) == 0) break; - - WCHAR buffer[MAX_PATH]; - if (GetMenuString(menu, i, buffer, MAX_PATH, MF_BYPOSITION)) - { - if (_wcsicmp(root.c_str(), buffer) == 0) - { - HMENU skinRootMenu = GetSubMenu(menu, i); - if (skinRootMenu) - { - InsertMenu(skinMenu, 3, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinRootMenu, root.c_str()); - } - break; - } - } - } - } - - AppendSkinCustomMenu(meterWindow, index, skinMenu, false); - - return skinMenu; -} - -void ContextMenu::AppendSkinCustomMenu( - MeterWindow* meterWindow, int index, HMENU menu, bool standaloneMenu) -{ - // Add custom actions to the context menu - std::wstring contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextTitle", L""); - if (contextTitle.empty()) - { - return; - } - - auto isTitleSeparator = [](const std::wstring& title) - { - return title.find_first_not_of(L'-') == std::wstring::npos; - }; - - std::wstring contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextAction", L""); - if (contextAction.empty() && !isTitleSeparator(contextTitle)) - { - return; - } - - std::vector cTitles; - WCHAR buffer[128]; - int i = 1; - - while (!contextTitle.empty() && - (!contextAction.empty() || isTitleSeparator(contextTitle)) && - (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i - 1) <= IDM_SKIN_CUSTOMCONTEXTMENU_LAST) // Set maximum context items in resource.h - { - // Trim long titles - if (contextTitle.size() > 30) - { - contextTitle.replace(27, contextTitle.size() - 27, L"..."); - } - - cTitles.push_back(contextTitle); - - _snwprintf_s(buffer, _TRUNCATE, L"ContextTitle%i", ++i); - contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", buffer, L""); - _snwprintf_s(buffer, _TRUNCATE, L"ContextAction%i", i); - contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", buffer, L""); - } - - // Build a sub-menu if more than three items - const size_t titleSize = cTitles.size(); - if (titleSize <= 3 || standaloneMenu) - { - size_t position = 0; - for (size_t i = 0; i < titleSize; ++i) - { - if (isTitleSeparator(cTitles[i])) - { - if (standaloneMenu) - { - AppendMenu(menu, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } - else - { - // Separators not allowed in main top-level menu - --position; - } - } - else - { - const UINT_PTR id = (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i); - InsertMenu(menu, (UINT)(position + 1), MF_BYPOSITION | MF_STRING, id, cTitles[i].c_str()); - } - - ++position; - } - - if (position != 0 && !standaloneMenu) - { - InsertMenu(menu, 1, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, L"Custom skin actions"); - InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } - } - else - { - HMENU customMenu = CreatePopupMenu(); - InsertMenu(menu, 1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)customMenu, L"Custom skin actions"); - - for (size_t i = 0; i < titleSize; ++i) - { - if (isTitleSeparator(cTitles[i])) - { - AppendMenu(customMenu, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } - else - { - const UINT_PTR id = (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i); - AppendMenu(customMenu, MF_BYPOSITION | MF_STRING, id, cTitles[i].c_str()); - } - } - - InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } -} - -int ContextMenu::CreateAllSkinsMenuRecursive(HMENU skinMenu, int index) -{ - SkinRegistry& skinRegistry = GetRainmeter().m_SkinRegistry; - const int initialLevel = skinRegistry.GetFolder(index).level; - int menuIndex = 0; - - const size_t max = skinRegistry.GetFolderCount(); - while (index < max) - { - const SkinRegistry::Folder& skinFolder = skinRegistry.GetFolder(index); - if (skinFolder.level != initialLevel) - { - return index - 1; - } - - HMENU subMenu = CreatePopupMenu(); - - // Add current folder - InsertMenu(skinMenu, menuIndex, MF_POPUP | MF_BYPOSITION, (UINT_PTR)subMenu, skinFolder.name.c_str()); - - // Add subfolders - const bool hasSubfolder = (index + 1) < max && skinRegistry.GetFolder(index + 1).level == initialLevel + 1; - if (hasSubfolder) - { - index = CreateAllSkinsMenuRecursive(subMenu, index + 1); - } - - // Add files - { - int fileIndex = 0; - const int fileCount = (int)skinFolder.files.size(); - for ( ; fileIndex < fileCount; ++fileIndex) - { - InsertMenu(subMenu, fileIndex, MF_STRING | MF_BYPOSITION, skinFolder.baseID + fileIndex, skinFolder.files[fileIndex].c_str()); - } - - if (skinFolder.active) - { - UINT checkPos = skinFolder.active - 1; - CheckMenuRadioItem(subMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); - } - - if (hasSubfolder && fileIndex != 0) - { - InsertMenu(subMenu, fileIndex, MF_SEPARATOR | MF_BYPOSITION, 0, nullptr); - } - } - - ++menuIndex; - ++index; - } - - return index; -} - -void ContextMenu::CreateLayoutMenu(HMENU layoutMenu) -{ - const auto& layouts = GetRainmeter().m_Layouts; - for (size_t i = 0, isize = layouts.size(); i < isize; ++i) - { - InsertMenu(layoutMenu, (UINT)i, MF_BYPOSITION, ID_THEME_FIRST + i, layouts[i].c_str()); - } -} - -void ContextMenu::CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow) -{ - const bool screenDefined = meterWindow->GetXScreenDefined(); - const int screenIndex = meterWindow->GetXScreen(); - - // for the "Specified monitor" (@n) - const size_t numOfMonitors = System::GetMonitorCount(); // intentional - const std::vector& monitors = System::GetMultiMonitorInfo().monitors; - - int i = 1; - for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) - { - WCHAR buffer[64]; - size_t len = _snwprintf_s(buffer, _TRUNCATE, L"@%i: ", i); - - std::wstring item(buffer, len); - - if ((*iter).monitorName.size() > 32) - { - item.append((*iter).monitorName, 0, 32); - item += L"..."; - } - else - { - item += (*iter).monitorName; - } - - const UINT flags = - MF_BYPOSITION | - ((screenDefined && screenIndex == i) ? MF_CHECKED : MF_UNCHECKED) | - ((*iter).active ? MF_ENABLED : MF_GRAYED); - InsertMenu(monitorMenu, i + 2, flags, ID_MONITOR_FIRST + i, item.c_str()); - } - - if (!screenDefined) - { - CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_PRIMARY, MF_BYCOMMAND | MF_CHECKED); - } - - if (screenDefined && screenIndex == 0) - { - CheckMenuItem(monitorMenu, ID_MONITOR_FIRST, MF_BYCOMMAND | MF_CHECKED); - } - - if (meterWindow->GetAutoSelectScreen()) - { - CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_AUTOSELECT, MF_BYCOMMAND | MF_CHECKED); - } -} - -void ContextMenu::ChangeSkinIndex(HMENU menu, int index) -{ - if (index > 0) - { - const int count = GetMenuItemCount(menu); - for (int i = 0; i < count; ++i) - { - HMENU subMenu = GetSubMenu(menu, i); - if (subMenu) - { - ChangeSkinIndex(subMenu, index); - } - else - { - MENUITEMINFO mii = {sizeof(MENUITEMINFO)}; - mii.fMask = MIIM_FTYPE | MIIM_ID; - GetMenuItemInfo(menu, i, TRUE, &mii); - if ((mii.fType & MFT_SEPARATOR) == 0) - { - mii.wID |= (index << 16); - mii.fMask = MIIM_ID; - SetMenuItemInfo(menu, i, TRUE, &mii); - } - } - } - } -} diff --git a/Library/ContextMenu.h b/Library/ContextMenu.h deleted file mode 100644 index cc6f759d..00000000 --- a/Library/ContextMenu.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_LIBRARY_CONTEXTMENU_H -#define RM_LIBRARY_CONTEXTMENU_H - -#include - -class MeterWindow; - -// Handles the creation and display of Rainmeter and skin context menus. -class ContextMenu -{ -public: - ContextMenu(); - - ContextMenu(const ContextMenu& other) = delete; - ContextMenu& operator=(ContextMenu other) = delete; - - bool IsMenuActive() { return m_MenuActive; } - - void ShowMenu(POINT pos, MeterWindow* meterWindow); - void ShowSkinCustomMenu(POINT pos, MeterWindow* meterWindow); - - static void CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow); - -private: - static void DisplayMenu(POINT pos, HMENU menu, HWND parentWindow); - - static HMENU CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu); - static void AppendSkinCustomMenu( - MeterWindow* meterWindow, int index, HMENU menu, bool standaloneMenu); - static void ChangeSkinIndex(HMENU subMenu, int index); - - static void CreateAllSkinsMenu(HMENU skinMenu) { CreateAllSkinsMenuRecursive(skinMenu, 0); } - static int CreateAllSkinsMenuRecursive(HMENU skinMenu, int index); - - static void CreateLayoutMenu(HMENU layoutMenu); - - bool m_MenuActive; -}; - -#endif diff --git a/Library/DialogAbout.cpp b/Library/DialogAbout.cpp deleted file mode 100644 index cda90bab..00000000 --- a/Library/DialogAbout.cpp +++ /dev/null @@ -1,1331 +0,0 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas, Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Rainmeter.h" -#include "System.h" -#include "MeterWindow.h" -#include "TrayWindow.h" -#include "Measure.h" -#include "resource.h" -#include "DialogAbout.h" -#include "../Version.h" -#include "../Common/Platform.h" - -WINDOWPLACEMENT DialogAbout::c_WindowPlacement = {0}; -DialogAbout* DialogAbout::c_Dialog = nullptr; - -/* -** Constructor. -** -*/ -DialogAbout::DialogAbout() : Dialog() -{ -} - -/* -** Destructor. -** -*/ -DialogAbout::~DialogAbout() -{ -} - -/* -** Opens the About dialog. -** -*/ -void DialogAbout::Open(int tab) -{ - if (!c_Dialog) - { - c_Dialog = new DialogAbout(); - } - - c_Dialog->ShowDialogWindow( - GetString(ID_STR_ABOUTRAINMETER), - 0, 0, 400, 210, - DS_CENTER | WS_POPUP | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, - WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | ((*GetString(ID_STR_ISRTL) == L'1') ? WS_EX_LAYOUTRTL : 0), - GetRainmeter().GetWindow()); - - // Fake WM_NOTIFY to change tab - NMHDR nm; - nm.code = TCN_SELCHANGE; - nm.idFrom = Id_Tab; - nm.hwndFrom = c_Dialog->GetControl(Id_Tab); - TabCtrl_SetCurSel(nm.hwndFrom, tab); - c_Dialog->OnNotify(0, (LPARAM)&nm); -} - -/* -** Opens the About dialog by tab name. -** -*/ -void DialogAbout::Open(const WCHAR* name) -{ - int tab = 0; - - if (name) - { - if (_wcsicmp(name, L"Skins") == 0 || - _wcsicmp(name, L"Measures") == 0) // For backwards compatibility - { - tab = 1; - } - else if (_wcsicmp(name, L"Plugins") == 0) - { - tab = 2; - } - else if (_wcsicmp(name, L"Version") == 0) - { - tab = 3; - } - } - - Open(tab); -} - -/* -** Shows log if dialog isn't already open. -** -*/ -void DialogAbout::ShowAboutLog() -{ - if (!c_Dialog) - { - Open(); - } -} - -void DialogAbout::AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message) -{ - if (c_Dialog && c_Dialog->m_TabLog.IsInitialized()) - { - c_Dialog->m_TabLog.AddItem(level, time, source, message); - } -} - -void DialogAbout::UpdateSkins() -{ - if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) - { - c_Dialog->m_TabSkins.UpdateSkinList(); - } -} - -void DialogAbout::UpdateMeasures(MeterWindow* meterWindow) -{ - if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) - { - c_Dialog->m_TabSkins.UpdateMeasureList(meterWindow); - } -} - -Dialog::Tab& DialogAbout::GetActiveTab() -{ - int sel = TabCtrl_GetCurSel(GetControl(Id_Tab)); - if (sel == 0) - { - return m_TabLog; - } - else if (sel == 1) - { - return m_TabSkins; - } - else if (sel == 2) - { - return m_TabPlugins; - } - else // if (sel == 3) - { - return m_TabVersion; - } -} - -INT_PTR DialogAbout::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_INITDIALOG: - return OnInitDialog(wParam, lParam); - - case WM_ACTIVATE: - return OnActivate(wParam, lParam); - - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - - case WM_GETMINMAXINFO: - { - MINMAXINFO* mmi = (MINMAXINFO*)lParam; - mmi->ptMinTrackSize.x = 700; - mmi->ptMinTrackSize.y = 350; - } - return TRUE; - - case WM_SIZE: - { - if (wParam != SIZE_MINIMIZED) - { - int w = LOWORD(lParam); - int h = HIWORD(lParam); - RECT r; - - HWND item = GetControl(Id_Tab); - SetWindowPos(item, nullptr, 0, 0, w - 18, h - 47, SWP_NOMOVE | SWP_NOZORDER); - - item = GetControl(Id_CloseButton); - GetClientRect(item, &r); - SetWindowPos(item, nullptr, w - r.right - 9, h - r.bottom - 8, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - w -= 48; - h -= 100; - m_TabLog.Resize(w, h); - m_TabSkins.Resize(w, h); - m_TabPlugins.Resize(w, h); - m_TabVersion.Resize(w, h); - } - } - return TRUE; - - case WM_CLOSE: - { - GetWindowPlacement(m_Window, &c_WindowPlacement); - if (c_WindowPlacement.showCmd == SW_SHOWMINIMIZED) - { - c_WindowPlacement.showCmd = SW_SHOWNORMAL; - } - - delete c_Dialog; - c_Dialog = nullptr; - } - return TRUE; - } - - return FALSE; -} - -INT_PTR DialogAbout::OnInitDialog(WPARAM wParam, LPARAM lParam) -{ - static const ControlTemplate::Control s_Controls[] = - { - CT_BUTTON(Id_CloseButton, ID_STR_CLOSE, - 344, 191, 50, 14, - WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), - CT_TAB(Id_Tab, 0, - 6, 6, 388, 181, - WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order. - }; - - CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString); - - HWND item = GetControl(Id_Tab); - m_TabLog.Create(m_Window); - m_TabSkins.Create(m_Window); - m_TabPlugins.Create(m_Window); - m_TabVersion.Create(m_Window); - - TCITEM tci = {0}; - tci.mask = TCIF_TEXT; - tci.pszText = GetString(ID_STR_LOG); - TabCtrl_InsertItem(item, 0, &tci); - tci.pszText = GetString(ID_STR_SKINS); - TabCtrl_InsertItem(item, 1, &tci); - tci.pszText = GetString(ID_STR_PLUGINS); - TabCtrl_InsertItem(item, 2, &tci); - tci.pszText = GetString(ID_STR_VERSION); - TabCtrl_InsertItem(item, 3, &tci); - - HICON hIcon = GetIcon(IDI_RAINMETER); - SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); - - item = GetControl(Id_CloseButton); - SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE); - - if (IsWindowsVistaOrGreater()) - { - item = m_TabLog.GetControl(TabLog::Id_ItemsListView); - SetWindowTheme(item, L"explorer", nullptr); - item = m_TabSkins.GetControl(TabSkins::Id_ItemsListView); - SetWindowTheme(item, L"explorer", nullptr); - } - - if (c_WindowPlacement.length == 0) - { - c_WindowPlacement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(m_Window, &c_WindowPlacement); - } - SetWindowPlacement(m_Window, &c_WindowPlacement); - - return TRUE; -} - -INT_PTR DialogAbout::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_CloseButton: - PostMessage(m_Window, WM_CLOSE, 0, 0); - break; - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR DialogAbout::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->idFrom) - { - case Id_Tab: - if (nm->code == TCN_SELCHANGE) - { - // Disable all tab windows first - EnableWindow(m_TabLog.GetWindow(), FALSE); - EnableWindow(m_TabSkins.GetWindow(), FALSE); - EnableWindow(m_TabPlugins.GetWindow(), FALSE); - EnableWindow(m_TabVersion.GetWindow(), FALSE); - - GetActiveTab().Activate(); - } - break; - - default: - return 1; - } - - return 0; -} - -// ----------------------------------------------------------------------------------------------- -// -// Log tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogAbout::TabLog::TabLog() : Tab(), - m_Error(true), - m_Warning(true), - m_Notice(true), - m_Debug(true) -{ -} - -void DialogAbout::TabLog::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 370, 148, owner); - - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - static const ControlTemplate::Control s_Controls[] = - { - CT_LISTVIEW(Id_ItemsListView, 0, - 0, 0, 368, 135, - WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_ICON | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0), - CT_CHECKBOX(Id_ErrorCheckBox, ID_STR_ERROR, - 0, 139, 70, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_WarningCheckBox, ID_STR_WARNING, - 70, 139, 70, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_NoticeCheckBox, ID_STR_NOTICE, - 140, 139, 70, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_DebugCheckBox, ID_STR_DEBUG, - 210, 139, 70, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_ClearButton, ID_STR_CLEAR, - (368 - buttonWidth), 139, buttonWidth, 14, - WS_VISIBLE | WS_TABSTOP, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -/* -** Called when tab is displayed. -** -*/ -void DialogAbout::TabLog::Initialize() -{ - // Add columns to the list view - HWND item = GetControl(Id_ItemsListView); - ListView_SetExtendedListViewStyleEx(item, 0, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); - - // Set folder/.ini icons for tree list - HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR32, 3, 1); - HMODULE hDLL = GetModuleHandle(L"user32"); - - HICON hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(103), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); - ImageList_AddIcon(hImageList, hIcon); - DeleteObject(hIcon); - - hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); - ImageList_AddIcon(hImageList, hIcon); - DeleteObject(hIcon); - - hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(104), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); - ImageList_AddIcon(hImageList, hIcon); - DeleteObject(hIcon); - - ListView_SetImageList(item, (WPARAM)hImageList, LVSIL_SMALL); - - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; // left-aligned column - lvc.iSubItem = 0; - lvc.cx = 75; - lvc.pszText = GetString(ID_STR_TYPE); - ListView_InsertColumn(item, 0, &lvc); - lvc.iSubItem = 1; - lvc.cx = 85; - lvc.pszText = GetString(ID_STR_TIME); - ListView_InsertColumn(item, 1, &lvc); - lvc.iSubItem = 2; - lvc.cx = 225; - lvc.pszText = GetString(ID_STR_SOURCE); - ListView_InsertColumn(item, 2, &lvc); - lvc.iSubItem = 4; - - // Start 4th column at max width - RECT rect; - lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 405) : 180; - lvc.pszText = GetString(ID_STR_MESSAGE); - ListView_InsertColumn(item, 3, &lvc); - - // Add stored entires - for (const auto& entry : GetLogger().GetEntries()) - { - AddItem(entry.level, entry.timestamp.c_str(), entry.source.c_str(), entry.message.c_str()); - } - - item = GetControl(Id_ErrorCheckBox); - Button_SetCheck(item, BST_CHECKED); - - item = GetControl(Id_WarningCheckBox); - Button_SetCheck(item, BST_CHECKED); - - item = GetControl(Id_NoticeCheckBox); - Button_SetCheck(item, BST_CHECKED); - - item = GetControl(Id_DebugCheckBox); - Button_SetCheck(item, BST_CHECKED); - - m_Initialized = true; -} - -/* -** Resizes window and repositions controls. -** -*/ -void DialogAbout::TabLog::Resize(int w, int h) -{ - SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); - - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - RECT r; - LONG bottom; - HWND item = GetControl(Id_ClearButton); - GetClientRect(item, &r); - bottom = r.bottom; - - SetWindowPos(item, nullptr, w - r.right, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_ErrorCheckBox); - GetClientRect(item, &r); - SetWindowPos(item, nullptr, 0, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_WarningCheckBox); - SetWindowPos(item, nullptr, r.right, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_NoticeCheckBox); - SetWindowPos(item, nullptr, r.right * 2, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_DebugCheckBox); - SetWindowPos(item, nullptr, r.right * 3, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_ItemsListView); - SetWindowPos(item, nullptr, 0, 0, w, h - bottom - 10, SWP_NOMOVE | SWP_NOZORDER); - - // Adjust 4th colum - LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH; - lvc.cx = w - 20 - - (ListView_GetColumnWidth(item, 0) + - ListView_GetColumnWidth(item, 1) + - ListView_GetColumnWidth(item, 2)); - ListView_SetColumn(item, 3, &lvc); -} - -/* -** Adds item to log. -** -*/ -void DialogAbout::TabLog::AddItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message) -{ - WCHAR buffer[32]; - LVITEM vitem; - vitem.mask = LVIF_IMAGE | LVIF_TEXT; - vitem.iItem = 0; - vitem.iSubItem = 0; - vitem.pszText = buffer; - HWND item; - - switch (level) - { - case Logger::Level::Error: - if (!m_Error) return; - item = GetControl(Id_ErrorCheckBox); - vitem.iImage = 0; - break; - - case Logger::Level::Warning: - if (!m_Warning) return; - item = GetControl(Id_WarningCheckBox); - vitem.iImage = 1; - break; - - case Logger::Level::Notice: - if (!m_Notice) return; - item = GetControl(Id_NoticeCheckBox); - vitem.iImage = 2; - break; - - case Logger::Level::Debug: - if (!m_Debug) return; - item = GetControl(Id_DebugCheckBox); - vitem.iImage = I_IMAGENONE; - break; - } - - GetWindowText(item, buffer, 32); - item = GetControl(Id_ItemsListView); - ListView_InsertItem(item, &vitem); - ListView_SetItemText(item, vitem.iItem, 1, (WCHAR*)time); - ListView_SetItemText(item, vitem.iItem, 2, (WCHAR*)source); - ListView_SetItemText(item, vitem.iItem, 3, (WCHAR*)message); - if (!ListView_IsItemVisible(item, 0)) - { - ListView_Scroll(item, 0, 16); - } -} - -INT_PTR DialogAbout::TabLog::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogAbout::TabLog::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_ErrorCheckBox: - if (HIWORD(wParam) == BN_CLICKED) - { - m_Error = !m_Error; - } - break; - - case Id_WarningCheckBox: - if (HIWORD(wParam) == BN_CLICKED) - { - m_Warning = !m_Warning; - } - break; - - case Id_NoticeCheckBox: - if (HIWORD(wParam) == BN_CLICKED) - { - m_Notice = !m_Notice; - } - break; - - case Id_DebugCheckBox: - if (HIWORD(wParam) == BN_CLICKED) - { - m_Debug = !m_Debug; - } - break; - - case Id_ClearButton: - if (HIWORD(wParam) == BN_CLICKED) - { - HWND item = GetControl(Id_ItemsListView); - ListView_DeleteAllItems(item); - } - break; - - default: - return 1; - } - - return 0; -} - -INT_PTR DialogAbout::TabLog::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case LVN_KEYDOWN: - { - NMLVKEYDOWN* lvkd = (NMLVKEYDOWN*)nm; - if (lvkd->wVKey == 0x43 && // C key. - IsCtrlKeyDown()) - { - const int sel = ListView_GetNextItem(nm->hwndFrom, -1, LVNI_FOCUSED | LVNI_SELECTED); - if (sel != -1) - { - WCHAR buffer[512]; - - // Get message. - ListView_GetItemText(nm->hwndFrom, sel, 3, buffer, 512); - std::wstring message = buffer; - - // Get source (if any). - ListView_GetItemText(nm->hwndFrom, sel, 2, buffer, 512); - if (*buffer) - { - message += L" ("; - message += buffer; - message += L')'; - } - - System::SetClipboardText(message); - } - } - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Measures tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogAbout::TabSkins::TabSkins() : Tab(), - m_SkinWindow() -{ -} - -void DialogAbout::TabSkins::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 370, 148, owner); - - static const ControlTemplate::Control s_Controls[] = - { - CT_LISTBOX(Id_SkinsListBox, 0, - 0, 0, 120, 148, - WS_VISIBLE | WS_TABSTOP | LBS_NOTIFY | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL, WS_EX_CLIENTEDGE), - CT_LISTVIEW(Id_ItemsListView, 0, - 125, 0, 242, 148, - WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogAbout::TabSkins::Initialize() -{ - // Add columns to the list view - HWND item = GetControl(Id_ItemsListView); - ListView_SetExtendedListViewStyleEx(item, 0, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); - - LVGROUP lvg; - lvg.cbSize = sizeof(LVGROUP); - lvg.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_STATE; - lvg.state = (IsWindowsVistaOrGreater()) ? LVGS_COLLAPSIBLE : LVGS_NORMAL; - lvg.iGroupId = 0; - lvg.pszHeader = GetString(ID_STR_MEASURES); - ListView_InsertGroup(item, 0, &lvg); - lvg.iGroupId = 1; - lvg.pszHeader = GetString(ID_STR_VARIABLES); - ListView_InsertGroup(item, 1, &lvg); - - ListView_EnableGroupView(item, TRUE); - - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; - lvc.iSubItem = 0; - lvc.cx = 120; - lvc.pszText = GetString(ID_STR_NAME); - ListView_InsertColumn(item, 0, &lvc); - lvc.iSubItem = 1; - lvc.cx = 90; - lvc.pszText = GetString(ID_STR_RANGE); - ListView_InsertColumn(item, 1, &lvc); - lvc.iSubItem = 2; - - // Start 3rd column at max width - RECT rect; - lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 230) : 130; - lvc.pszText = GetString(ID_STR_VALUE); - ListView_InsertColumn(item, 2, &lvc); - - UpdateSkinList(); - - m_Initialized = true; -} - -/* -** Resizes window and repositions controls. -** -*/ -void DialogAbout::TabSkins::Resize(int w, int h) -{ - SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); - - HWND item = GetControl(Id_SkinsListBox); - SetWindowPos(item, nullptr, 0, 0, 265, h, SWP_NOMOVE | SWP_NOZORDER); - - item = GetControl(Id_ItemsListView); - SetWindowPos(item, nullptr, 275, 0, w - 275, h, SWP_NOZORDER); - - // Adjust third column - LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH; - lvc.cx = w - 275 - 20 - - (ListView_GetColumnWidth(item, 0) + - ListView_GetColumnWidth(item, 1)); - ListView_SetColumn(item, 2, &lvc); -} - -/* -** Updates the list of skins. -** -*/ -void DialogAbout::TabSkins::UpdateSkinList() -{ - // Delete all entries - HWND item = GetControl(Id_SkinsListBox); - ListBox_ResetContent(item); - - // Add entries for each skin - std::wstring::size_type maxLength = 0; - const std::map& windows = GetRainmeter().GetAllMeterWindows(); - std::map::const_iterator iter = windows.begin(); - bool found = false; - for ( ; iter != windows.end(); ++iter) - { - const std::wstring& skinName = (*iter).first; - std::wstring::size_type curLength = skinName.length(); - if (curLength > maxLength) - { - maxLength = curLength; - } - - const WCHAR* name = skinName.c_str(); - int index = ListBox_AddString(item, name); - if (!found && m_SkinWindow == (*iter).second) - { - found = true; - m_SkinWindow = (*iter).second; - ListBox_SetCurSel(item, index); - } - } - - ListBox_SetHorizontalExtent(item, 6 * maxLength); - - if (!found) - { - if (windows.empty()) - { - m_SkinWindow = nullptr; - item = GetControl(Id_ItemsListView); - ListView_DeleteAllItems(item); - } - else - { - // Default to first skin - m_SkinWindow = (*windows.begin()).second; - ListBox_SetCurSel(item, 0); - UpdateMeasureList(m_SkinWindow); - } - } -} - -/* -** Updates the list of measures and values. -** -*/ -void DialogAbout::TabSkins::UpdateMeasureList(MeterWindow* meterWindow) -{ - if (!meterWindow) - { - // Find selected skin - HWND item = GetControl(Id_SkinsListBox); - int selected = (int)SendMessage(item, LB_GETCURSEL, 0, 0); - - const std::map& windows = GetRainmeter().GetAllMeterWindows(); - std::map::const_iterator iter = windows.begin(); - while (selected && iter != windows.end()) - { - ++iter; - --selected; - } - - m_SkinWindow = (*iter).second; - } - else if (meterWindow != m_SkinWindow) - { - // Called by a skin other than currently visible one, so return - return; - } - - HWND item = GetControl(Id_ItemsListView); - SendMessage(item, WM_SETREDRAW, FALSE, 0); - int count = ListView_GetItemCount(item); - - LVITEM lvi; - lvi.mask = LVIF_TEXT | LVIF_GROUPID | LVIF_PARAM; - lvi.iSubItem = 0; - lvi.iItem = 0; - lvi.lParam = 0; - - lvi.iGroupId = 0; - const std::vector& measures = m_SkinWindow->GetMeasures(); - std::vector::const_iterator j = measures.begin(); - for ( ; j != measures.end(); ++j) - { - lvi.pszText = (WCHAR*)(*j)->GetName(); - - if (lvi.iItem < count) - { - ListView_SetItem(item, &lvi); - } - else - { - ListView_InsertItem(item, &lvi); - } - - WCHAR buffer[256]; - Measure::GetScaledValue(AUTOSCALE_ON, 1, (*j)->GetMinValue(), buffer, _countof(buffer)); - std::wstring range = buffer; - range += L" - "; - Measure::GetScaledValue(AUTOSCALE_ON, 1, (*j)->GetMaxValue(), buffer, _countof(buffer)); - range += buffer; - - ListView_SetItemText(item, lvi.iItem, 1, (WCHAR*)range.c_str()); - ListView_SetItemText(item, lvi.iItem, 2, (WCHAR*)(*j)->GetStringOrFormattedValue( - AUTOSCALE_OFF, 1, -1, false)); - ++lvi.iItem; - } - - lvi.iGroupId = 1; - const auto& variables = m_SkinWindow->GetParser().GetVariables(); - for (auto iter = variables.cbegin(); iter != variables.cend(); ++iter) - { - const WCHAR* name = (*iter).first.c_str(); - lvi.lParam = (LPARAM)name; - - if (wcscmp(name, L"@") == 0) - { - // Ignore reserved variables - continue; - } - - std::wstring tmpStr = (*iter).first; - _wcslwr(&tmpStr[0]); - lvi.pszText = (WCHAR*)tmpStr.c_str(); - - if (lvi.iItem < count) - { - ListView_SetItem(item, &lvi); - } - else - { - ListView_InsertItem(item, &lvi); - } - - ListView_SetItemText(item, lvi.iItem, 1, L""); - ListView_SetItemText(item, lvi.iItem, 2, (WCHAR*)(*iter).second.c_str()); - ++lvi.iItem; - } - - // Delete unnecessary items - while (count > lvi.iItem) - { - ListView_DeleteItem(item, lvi.iItem); - --count; - } - - int selIndex = ListView_GetNextItem(item, -1, LVNI_FOCUSED | LVNI_SELECTED); - - ListView_SortItems(item, ListSortProc, 0); - - if (selIndex != -1) - { - // Re-select previously selected item - ListView_SetItemState(item, selIndex, LVIS_FOCUSED | LVNI_SELECTED, LVIS_FOCUSED | LVNI_SELECTED); - } - - SendMessage(item, WM_SETREDRAW, TRUE, 0); -} - -int CALLBACK DialogAbout::TabSkins::ListSortProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) -{ - // Measures - if (!lParam1 && !lParam2) return 0; - if (!lParam1) return -1; - if (!lParam2) return 1; - - // Variables - return wcscmp((const WCHAR*)lParam1, (const WCHAR*)lParam2); -} - -INT_PTR DialogAbout::TabSkins::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogAbout::TabSkins::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_SkinsListBox: - if (HIWORD(wParam) == LBN_SELCHANGE) - { - UpdateMeasureList(nullptr); - } - break; - - default: - return 1; - } - - return 0; -} - -INT_PTR DialogAbout::TabSkins::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case LVN_KEYDOWN: - { - NMLVKEYDOWN* lvkd = (NMLVKEYDOWN*)nm; - if (lvkd->wVKey == 0x43 && IsCtrlKeyDown()) // CTRL + C. - { - int sel = ListView_GetNextItem(nm->hwndFrom, -1, LVNI_FOCUSED | LVNI_SELECTED); - if (sel != -1) - { - std::wstring tmpSz(512, L'0'); - ListView_GetItemText(nm->hwndFrom, sel, 2, &tmpSz[0], 512); - System::SetClipboardText(tmpSz); - } - } - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Plugins tab -// -// ----------------------------------------------------------------------------------------------- - -DialogAbout::TabPlugins::TabPlugins() : Tab() -{ -} - -void DialogAbout::TabPlugins::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 370, 148, owner); - - static const ControlTemplate::Control s_Controls[] = - { - CT_LISTVIEW(Id_ItemsListView, 0, - 0, 0, 368, 148, - WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogAbout::TabPlugins::Initialize() -{ - // Add columns to the list view - HWND item = GetControl(Id_ItemsListView); - - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; // left-aligned column - lvc.iSubItem = 0; - lvc.cx = 140; - lvc.pszText = GetString(ID_STR_NAME); - ListView_InsertColumn(item, 0, &lvc); - lvc.iSubItem = 1; - lvc.cx = 80; - lvc.pszText = GetString(ID_STR_VERSION); - ListView_InsertColumn(item, 1, &lvc); - lvc.iSubItem = 2; - - // Start 3rd column at max width - RECT rect; - lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 193) : 290; - lvc.pszText = GetString(ID_STR_AUTHOR); - ListView_InsertColumn(item, 2, &lvc); - - LVITEM vitem; - vitem.mask = LVIF_TEXT; - vitem.iItem = 0; - vitem.iSubItem = 0; - - auto findPlugins = [&](const std::wstring& path) - { - std::wstring filter = path + L"*.dll"; - - WIN32_FIND_DATA fd; - HANDLE hSearch = FindFirstFile(filter.c_str(), &fd); - if (hSearch == INVALID_HANDLE_VALUE) - { - return; - } - - int index = 0; - do - { - // Try to get the version and author - std::wstring tmpSz = path + fd.cFileName; - const WCHAR* path = tmpSz.c_str(); - - vitem.iItem = index; - vitem.pszText = fd.cFileName; - - // Try to get version and author from file resources first - DWORD handle; - DWORD versionSize = GetFileVersionInfoSize(path, &handle); - if (versionSize) - { - bool found = false; - void* data = new BYTE[versionSize]; - if (GetFileVersionInfo(path, 0, versionSize, data)) - { - UINT len; - struct LANGCODEPAGE - { - WORD wLanguage; - WORD wCodePage; - } *lcp; - - if (VerQueryValue(data, L"\\VarFileInfo\\Translation", (LPVOID*)&lcp, &len)) - { - WCHAR key[64]; - LPWSTR value; - - _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\ProductName", lcp[0].wLanguage, lcp[0].wCodePage); - if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len) && - wcscmp(value, L"Rainmeter") == 0) - { - ListView_InsertItem(item, &vitem); - ++index; - found = true; - - _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\FileVersion", lcp[0].wLanguage, lcp[0].wCodePage); - if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len)) - { - ListView_SetItemText(item, vitem.iItem, 1, value); - } - - _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\LegalCopyright", lcp[0].wLanguage, lcp[0].wCodePage); - if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len)) - { - ListView_SetItemText(item, vitem.iItem, 2, value); - } - } - } - } - - delete [] data; - if (found) continue; - } - - // Try old calling GetPluginVersion/GetPluginAuthor for backwards compatibility - DWORD err = 0; - HMODULE dll = System::RmLoadLibrary(path, &err); - if (dll) - { - ListView_InsertItem(item, &vitem); - ++index; - - GETPLUGINVERSION GetVersionFunc = (GETPLUGINVERSION)GetProcAddress(dll, "GetPluginVersion"); - if (GetVersionFunc) - { - UINT version = GetVersionFunc(); - WCHAR buffer[64]; - _snwprintf_s(buffer, _TRUNCATE, L"%u.%u", version / 1000, version % 1000); - ListView_SetItemText(item, vitem.iItem, 1, buffer); - } - - GETPLUGINAUTHOR GetAuthorFunc = (GETPLUGINAUTHOR)GetProcAddress(dll, "GetPluginAuthor"); - if (GetAuthorFunc) - { - LPCTSTR author = GetAuthorFunc(); - if (author && *author) - { - ListView_SetItemText(item, vitem.iItem, 2, (LPWSTR)author); - } - } - - FreeLibrary(dll); - } - else - { - LogErrorF(L"About Dialog - Unable to load plugin: %s (%u)", tmpSz.c_str(), err); - } - } - while (FindNextFile(hSearch, &fd)); - FindClose(hSearch); - }; - - findPlugins(GetRainmeter().GetPluginPath()); - if (GetRainmeter().HasUserPluginPath()) - { - findPlugins(GetRainmeter().GetUserPluginPath()); - } - - m_Initialized = true; -} - -/* -** Resizes window and repositions controls. -** -*/ -void DialogAbout::TabPlugins::Resize(int w, int h) -{ - SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); - - HWND item = GetControl(Id_ItemsListView); - SetWindowPos(item, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); - - // Adjust third colum - LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH; - lvc.cx = w - 20 - - (ListView_GetColumnWidth(item, 0) + - ListView_GetColumnWidth(item, 1)); - ListView_SetColumn(item, 2, &lvc); -} - -// ----------------------------------------------------------------------------------------------- -// -// Version tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogAbout::TabVersion::TabVersion() : Tab() -{ -} - -void DialogAbout::TabVersion::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 370, 148, owner); - - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - const ControlTemplate::Control s_Controls[] = - { - CT_ICON(Id_AppIcon, 0, - 0, 8, 24, 24, - WS_VISIBLE, 0), - CT_LABEL(Id_VersionLabel, 0, - 28, 0, 300, 9, - WS_VISIBLE, 0), - CT_LINKLABEL(Id_HomeLink, ID_STR_GETLATESTVERSION, - 28, 13, 300, 9, - WS_VISIBLE, 0), - CT_LINKLABEL(Id_LicenseLink, ID_STR_COPYRIGHTNOTICE, - 28, 26, 300, 9, - WS_VISIBLE, 0), - CT_LABEL(Id_WinVerLabel, 0, - 0, 43, 360, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_PathLabel, 0, - 0, 56, 360, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_IniFileLabel, 0, - 0, 69, 360, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_SkinPathLabel, 0, - 0, 82, 360, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_BUTTON(Id_CopyButton, ID_STR_COPYTOCLIPBOARD, - 0, 98, buttonWidth + 25, 14, - WS_VISIBLE | WS_TABSTOP, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogAbout::TabVersion::Initialize() -{ - HWND item = GetControl(Id_AppIcon); - HICON icon = GetIcon(IDI_RAINMETER, true); - Static_SetIcon(item, icon); - - item = GetControl(Id_VersionLabel); - WCHAR tmpSz[64]; - _snwprintf_s(tmpSz, _TRUNCATE, L"%s%s r%i %s (%s)", APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS, APPDATE); - SetWindowText(item, tmpSz); - - item = GetControl(Id_WinVerLabel); - SetWindowText(item, Platform::GetPlatformFriendlyName().c_str()); - - item = GetControl(Id_PathLabel); - std::wstring text = L"Path: " + GetRainmeter().GetPath(); - SetWindowText(item, text.c_str()); - - item = GetControl(Id_IniFileLabel); - text = L"IniFile: " + GetRainmeter().GetIniFile(); - SetWindowText(item, text.c_str()); - - item = GetControl(Id_SkinPathLabel); - text = L"SkinPath: " + GetRainmeter().GetSkinPath(); - SetWindowText(item, text.c_str()); - - m_Initialized = true; -} - -/* -** Resizes window and repositions controls. -** -*/ -void DialogAbout::TabVersion::Resize(int w, int h) -{ - SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); -} - -INT_PTR DialogAbout::TabVersion::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogAbout::TabVersion::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_CopyButton: - { - WCHAR tmpSz[64]; - int len = _snwprintf_s(tmpSz, _TRUNCATE, L"%s%s r%i %s (%s)", APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS, APPDATE); - std::wstring text(tmpSz, len); - text += L'\n'; - text += Platform::GetPlatformFriendlyName(); - text += L"\nPath: "; - text += GetRainmeter().GetPath(); - text += L"\nIniFile: "; - text += GetRainmeter().GetIniFile(); - text += L"\nSkinPath: "; - text += GetRainmeter().GetSkinPath(); - System::SetClipboardText(text); - } - break; - - default: - return 1; - } - - return 0; -} - -INT_PTR DialogAbout::TabVersion::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case NM_CLICK: - if (nm->idFrom == Id_HomeLink) - { - CommandHandler::RunFile(L"http://rainmeter.net"); - } - else if (nm->idFrom == Id_HomeLink) - { - CommandHandler::RunFile(L"http://gnu.org/licenses"); - } - break; - - default: - return FALSE; - } - - return TRUE; -} diff --git a/Library/DialogAbout.h b/Library/DialogAbout.h deleted file mode 100644 index 6b8a1a59..00000000 --- a/Library/DialogAbout.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __DIALOGABOUT_H__ -#define __DIALOGABOUT_H__ - -#include "../Common/Dialog.h" -#include "Logger.h" -#include "MeterWindow.h" - -class DialogAbout : public Dialog -{ -public: - DialogAbout(); - virtual ~DialogAbout(); - - DialogAbout(const DialogAbout& other) = delete; - DialogAbout& operator=(DialogAbout other) = delete; - - static Dialog* GetDialog() { return c_Dialog; } - - static void Open(int tab = 0); - static void Open(const WCHAR* name); - static void ShowAboutLog(); - - static void AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message); - static void UpdateSkins(); - static void UpdateMeasures(MeterWindow* meterWindow); - -protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - -private: - // Log tab - class TabLog : public Tab - { - public: - enum Id - { - Id_ItemsListView = 100, - Id_ErrorCheckBox, - Id_WarningCheckBox, - Id_NoticeCheckBox, - Id_DebugCheckBox, - Id_ClearButton - }; - - TabLog(); - - void Create(HWND owner); - virtual void Initialize(); - virtual void Resize(int w, int h); - - void AddItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - - private: - bool m_Error; - bool m_Warning; - bool m_Notice; - bool m_Debug; - }; - - // Measures tab - class TabSkins : public Tab - { - public: - enum Id - { - Id_SkinsListBox = 100, - Id_ItemsListView - }; - - TabSkins(); - - void Create(HWND owner); - virtual void Initialize(); - virtual void Resize(int w, int h); - - void UpdateSkinList(); - void UpdateMeasureList(MeterWindow* meterWindow); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - - private: - static int CALLBACK ListSortProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); - - MeterWindow* m_SkinWindow; - }; - - // Plugins tab - class TabPlugins : public Tab - { - public: - enum Id - { - Id_ItemsListView = 100 - }; - - TabPlugins(); - - void Create(HWND owner); - virtual void Initialize(); - virtual void Resize(int w, int h); - - private: - typedef LPCTSTR (*GETPLUGINAUTHOR)(); - typedef UINT (*GETPLUGINVERSION)(); - }; - - // Version tab - class TabVersion : public Tab - { - public: - enum Id - { - Id_AppIcon = 100, - Id_VersionLabel, - Id_HomeLink, - Id_LicenseLink, - Id_WinVerLabel, - Id_PathLabel, - Id_IniFileLabel, - Id_SkinPathLabel, - Id_CopyButton - }; - - TabVersion(); - - void Create(HWND owner); - virtual void Initialize(); - virtual void Resize(int w, int h); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - }; - - enum Id - { - Id_CloseButton = IDCLOSE, - Id_Tab = 100 - }; - - Tab& GetActiveTab(); - - TabLog m_TabLog; - TabSkins m_TabSkins; - TabPlugins m_TabPlugins; - TabVersion m_TabVersion; - - static WINDOWPLACEMENT c_WindowPlacement; - static DialogAbout* c_Dialog; -}; - -#endif diff --git a/Library/DialogManage.cpp b/Library/DialogManage.cpp deleted file mode 100644 index eff83e47..00000000 --- a/Library/DialogManage.cpp +++ /dev/null @@ -1,2137 +0,0 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/MenuTemplate.h" -#include "Rainmeter.h" -#include "System.h" -#include "MeterWindow.h" -#include "TrayWindow.h" -#include "Measure.h" -#include "resource.h" -#include "DialogManage.h" -#include "DialogAbout.h" -#include "../Version.h" -#include - -WINDOWPLACEMENT DialogManage::c_WindowPlacement = {0}; -DialogManage* DialogManage::c_Dialog = nullptr; - -/* -** Constructor. -** -*/ -DialogManage::DialogManage() : Dialog() -{ -} - -/* -** Destructor. -** -*/ -DialogManage::~DialogManage() -{ -} - -/* -** Opens the Manage dialog by tab name. -** -*/ -void DialogManage::Open(const WCHAR* name) -{ - int tab = 0; - - if (name) - { - if (_wcsicmp(name, L"Layouts") == 0 || - _wcsicmp(name, L"Themes") == 0) // For backwards compatibility. - { - tab = 1; - } - else if (_wcsicmp(name, L"Settings") == 0) - { - tab = 2; - } - } - - Open(tab); -} - -/* -** Opens the Manage dialog. -** -*/ -void DialogManage::Open(int tab) -{ - if (!c_Dialog) - { - c_Dialog = new DialogManage(); - } - - c_Dialog->ShowDialogWindow( - GetString(ID_STR_MANAGERAINMETER), - 0, 0, 500, 322, - DS_CENTER | WS_POPUP | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU, - WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | ((*GetString(ID_STR_ISRTL) == L'1') ? WS_EX_LAYOUTRTL : 0), - GetRainmeter().GetWindow()); - - // Fake WM_NOTIFY to change tab - NMHDR nm; - nm.code = TCN_SELCHANGE; - nm.idFrom = Id_Tab; - nm.hwndFrom = c_Dialog->GetControl(Id_Tab); - TabCtrl_SetCurSel(nm.hwndFrom, tab); - c_Dialog->OnNotify(0, (LPARAM)&nm); -} - -/* -** Opens the Manage dialog Skins tab with skin selected. -** -*/ -void DialogManage::OpenSkin(MeterWindow* meterWindow) -{ - Open(); - - if (c_Dialog) - { - std::wstring name = meterWindow->GetFolderPath() + L'\\'; - name += meterWindow->GetFileName(); - - HWND item = c_Dialog->m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); - c_Dialog->m_TabSkins.SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); - } -} - -/* -** Opens the Manage dialog tab with parameters -** -*/ -void DialogManage::Open(const WCHAR* tabName, const WCHAR* param1, const WCHAR* param2) -{ - Open(tabName); - - if (c_Dialog) - { - // "Skins" tab - if (_wcsicmp(tabName, L"Skins") == 0) - { - // |param1| represents the config (ie. "illustro\Clock") - // |param2| represents the file (ie. "Clock.ini") - - std::wstring name = param1; - - if (param2) - { - name += L'\\'; - name += param2; - } - - HWND item = c_Dialog->m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); - c_Dialog->m_TabSkins.SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); - } - // Future use: Allow optional params for different tabs - //else if (_wcsicmp(tabName, L"Layouts") == 0) - } -} - -void DialogManage::UpdateSkins(MeterWindow* meterWindow, bool deleted) -{ - if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) - { - c_Dialog->m_TabSkins.Update(meterWindow, deleted); - } -} - -void DialogManage::UpdateLayouts() -{ - if (c_Dialog && c_Dialog->m_TabLayouts.IsInitialized()) - { - c_Dialog->m_TabLayouts.Update(); - } -} - -Dialog::Tab& DialogManage::GetActiveTab() -{ - int sel = TabCtrl_GetCurSel(GetControl(Id_Tab)); - if (sel == 0) - { - return m_TabSkins; - } - else if (sel == 1) - { - return m_TabLayouts; - } - else // if (sel == 2) - { - return m_TabSettings; - } -} - -INT_PTR DialogManage::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_INITDIALOG: - return OnInitDialog(wParam, lParam); - - case WM_ACTIVATE: - return OnActivate(wParam, lParam); - - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - - case WM_CLOSE: - { - GetWindowPlacement(m_Window, &c_WindowPlacement); - if (c_WindowPlacement.showCmd == SW_SHOWMINIMIZED) - { - c_WindowPlacement.showCmd = SW_SHOWNORMAL; - } - - delete c_Dialog; - c_Dialog = nullptr; - } - return TRUE; - } - - return FALSE; -} - -INT_PTR DialogManage::OnInitDialog(WPARAM wParam, LPARAM lParam) -{ - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - const ControlTemplate::Control s_Controls[] = - { - CT_BUTTON(Id_RefreshAllButton, ID_STR_REFRESHALL, - 5, 303, buttonWidth, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_EditSettingsButton, ID_STR_EDITSETTINGS, - buttonWidth + 9, 303, buttonWidth, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_OpenLogButton, ID_STR_OPENLOG, - buttonWidth + buttonWidth + 13, 303, buttonWidth, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_HelpButton, ID_STR_HELP, - 389, 303, 50, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_CloseButton, ID_STR_CLOSE, - 444, 303, 50, 14, - WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), - CT_TAB(Id_Tab, 0, - 6, 6, 488, 293, - WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order. - }; - - CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString); - - HWND item = GetControl(Id_Tab); - m_TabSkins.Create(m_Window); - m_TabLayouts.Create(m_Window); - m_TabSettings.Create(m_Window); - - TCITEM tci = {0}; - tci.mask = TCIF_TEXT; - tci.pszText = GetString(ID_STR_SKINS); - TabCtrl_InsertItem(item, 0, &tci); - tci.pszText = GetString(ID_STR_THEMES); - TabCtrl_InsertItem(item, 1, &tci); - tci.pszText = GetString(ID_STR_SETTINGS); - TabCtrl_InsertItem(item, 2, &tci); - - HICON hIcon = GetIcon(IDI_RAINMETER); - SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); - - item = GetControl(Id_CloseButton); - SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE); - - item = m_TabSkins.GetControl(TabSkins::Id_FileLabel); - SendMessage(item, WM_SETFONT, (WPARAM)m_FontBold, 0); - - if (IsWindowsVistaOrGreater()) - { - // Use arrows instead of plus/minus in the tree for Vista+ - item = m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); - SetWindowTheme(item, L"explorer", nullptr); - } - - if (c_WindowPlacement.length == 0) - { - c_WindowPlacement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(m_Window, &c_WindowPlacement); - } - - SetWindowPlacement(m_Window, &c_WindowPlacement); - - return FALSE; -} - -INT_PTR DialogManage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_RefreshAllButton: - GetRainmeter().RefreshAll(); - break; - - case Id_EditSettingsButton: - GetRainmeter().EditSettings(); - break; - - case Id_OpenLogButton: - DialogAbout::Open(); - break; - - case Id_CloseButton: - HandleMessage(WM_CLOSE, 0, 0); - break; - - case Id_HelpButton: - { - std::wstring url = L"http://docs.rainmeter.net/manual/user-interface/manage#"; - - Tab& tab = GetActiveTab(); - if (&tab == &m_TabSkins) - { - url += L"Skins"; - } - else if (&tab == &m_TabLayouts) - { - url += L"Layouts"; - } - else // if (&tab == &m_TabSettings) - { - url += L"Settings"; - } - - url += L"Tab"; - ShellExecute(m_Window, L"open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL); - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR DialogManage::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->idFrom) - { - case Id_Tab: - if (nm->code == TCN_SELCHANGE) - { - // Disable all tab windows first - EnableWindow(m_TabSkins.GetWindow(), FALSE); - EnableWindow(m_TabLayouts.GetWindow(), FALSE); - EnableWindow(m_TabSettings.GetWindow(), FALSE); - - GetActiveTab().Activate(); - } - break; - - default: - return 1; - } - - return 0; -} - -// ----------------------------------------------------------------------------------------------- -// -// Skins tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogManage::TabSkins::TabSkins() : Tab(), - m_SkinWindow(), - m_HandleCommands(false), - m_IgnoreUpdate(false) -{ -} - -void DialogManage::TabSkins::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 470, 260, owner); - - // FIXME: Temporary hack. - short labelWidth = (short)_wtoi(GetString(ID_STR_NUM_LABELWIDTH)); - - const ControlTemplate::Control s_Controls[] = - { - CT_BUTTON(Id_ActiveSkinsButton, ID_STR_ACTIVESKINS, - 0, 0, 146, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_TREEVIEW(Id_SkinsTreeView, 0, - 0, 18, 145, 221, - WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | WS_VSCROLL, WS_EX_CLIENTEDGE), - CT_BUTTON(Id_CreateSkinPackageButton, ID_STR_CREATERMSKINPACKAGE, - 0, 244, 146, 14, - WS_VISIBLE | WS_TABSTOP, 0), - - CT_LABEL(Id_FileLabel, ID_STR_ELLIPSIS, - 165, 0, 130, 14, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_ConfigLabel, 0, - 165, 15, 130, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_BUTTON(Id_LoadButton, ID_STR_LOAD, - 310, 0, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_BUTTON(Id_RefreshButton, ID_STR_REFRESH, - 364, 0, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_BUTTON(Id_EditButton, ID_STR_EDIT, - 418, 0, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - - CT_LABEL(-1, ID_STR_AUTHORSC, - 165, 30, 80, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_AuthorLabel, 0, - 230, 30, 245, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(-1, ID_STR_VERSIONSC, - 165, 43, 80, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_VersionLabel, 0, - 230, 43, 245, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(-1, ID_STR_LICENSESC, - 165, 56, 80, 9, - WS_VISIBLE | WS_TABSTOP | SS_NOPREFIX, 0), - CT_LABEL(Id_LicenseLabel, 0, - 230, 56, 245, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(-1, ID_STR_INFORMATIONSC, - 165, 69, 80, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_EDIT(Id_DescriptionLabel, 0, - 228, 69, 238, 64, - WS_VISIBLE | ES_MULTILINE | ES_READONLY, 0), - CT_LINKLABEL(Id_AddMetadataLink, ID_STR_ADDMETADATA, - 165, 142, 150, 9, - 0, 0), - - CT_LINEH(-1, ID_STR_COORDINATESSC, - 165, 156, 304, 1, - WS_VISIBLE, 0), - - CT_LABEL(-1, ID_STR_COORDINATESSC, - 165, 169, labelWidth, 9, - WS_VISIBLE, 0), - CT_EDIT(Id_XPositionEdit, 0, - 165 + labelWidth, 166, 38, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), - CT_EDIT(Id_YPositionEdit, 0, - 165 + labelWidth + 42, 166, 38, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), - CT_LABEL(-1, ID_STR_POSITIONSC, - 165, 190, labelWidth, 9, - WS_VISIBLE, 0), - CT_COMBOBOX(Id_ZPositionDropDownList, 0, - 165 + labelWidth, 187, 80, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), - CT_LABEL(-1, ID_STR_LOADORDERSC, - 165, 208, labelWidth, 9, - WS_VISIBLE, 0), - CT_EDIT(Id_LoadOrderEdit, 0, - 165 + labelWidth, 205, 80, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), - CT_LABEL(-1, ID_STR_TRANSPARENCYSC, - 165, 229, labelWidth, 9, - WS_VISIBLE, 0), - CT_COMBOBOX(Id_TransparencyDropDownList, 0, - 165 + labelWidth, 226, 80, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), - CT_LABEL(-1, ID_STR_ONHOVERSC, - 165, 247, labelWidth, 9, - WS_VISIBLE, 0), - CT_COMBOBOX(Id_OnHoverDropDownList, 0, - 165 + labelWidth, 244, 80, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), - - CT_BUTTON(Id_DisplayMonitorButton, ID_STR_DISPLAYMONITOR, - 350, 166, 118, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_DraggableCheckBox, ID_STR_DRAGGABLE, - 350, 190, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_ClickThroughCheckBox, ID_STR_CLICKTHROUGH, - 350, 203, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_KeepOnScreenCheckBox, ID_STR_KEEPONSCREEN, - 350, 216, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_SavePositionCheckBox, ID_STR_SAVEPOSITION, - 350, 229, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_SnapToEdgesCheckBox, ID_STR_SNAPTOEDGES, - 350, 242, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogManage::TabSkins::Initialize() -{ - BUTTON_SPLITINFO bsi; - bsi.mask = BCSIF_SIZE; - bsi.size.cx = 20; - bsi.size.cy = 14; - - HWND item = GetControl(Id_ActiveSkinsButton); - Dialog::SetMenuButton(item); - - item = GetControl(Id_DisplayMonitorButton); - Dialog::SetMenuButton(item); - - // Load folder/.ini icons from shell32 - HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR32, 2, 10); - HMODULE hDLL = GetModuleHandle(L"shell32"); - - HICON hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(4), IMAGE_ICON, 16, 16, LR_SHARED); - ImageList_AddIcon(hImageList, hIcon); - hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(151), IMAGE_ICON, 16, 16, LR_SHARED); - ImageList_AddIcon(hImageList, hIcon); - - // Apply icons and populate tree - item = GetControl(Id_SkinsTreeView); - TreeView_SetImageList(item, hImageList, TVSIL_NORMAL); - Update(nullptr, false); - - // Get rid of the EDITTEXT control border - item = GetControl(Id_DescriptionLabel); - SetWindowLongPtr(item, GWL_EXSTYLE, GetWindowLongPtr(item, GWL_EXSTYLE) &~ WS_EX_CLIENTEDGE); - SetWindowPos(item, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); - - item = GetControl(Id_TransparencyDropDownList); - ComboBox_AddString(item, L"0%"); - ComboBox_AddString(item, L"10%"); - ComboBox_AddString(item, L"20%"); - ComboBox_AddString(item, L"30%"); - ComboBox_AddString(item, L"40%"); - ComboBox_AddString(item, L"50%"); - ComboBox_AddString(item, L"60%"); - ComboBox_AddString(item, L"70%"); - ComboBox_AddString(item, L"80%"); - ComboBox_AddString(item, L"90%"); - - item = GetControl(Id_ZPositionDropDownList); - ComboBox_AddString(item, GetString(ID_STR_ONDESKTOP)); - ComboBox_AddString(item, GetString(ID_STR_BOTTOM)); - ComboBox_AddString(item, GetString(ID_STR_NORMAL)); - ComboBox_AddString(item, GetString(ID_STR_TOPMOST)); - ComboBox_AddString(item, GetString(ID_STR_STAYTOPMOST)); - - item = GetControl(Id_OnHoverDropDownList); - ComboBox_AddString(item, GetString(ID_STR_DONOTHING)); - ComboBox_AddString(item, GetString(ID_STR_HIDE)); - ComboBox_AddString(item, GetString(ID_STR_FADEIN)); - ComboBox_AddString(item, GetString(ID_STR_FADEOUT)); - - m_Initialized = true; - m_HandleCommands = true; -} - -/* -** Updates metadata and settings when changed. -** -*/ -void DialogManage::TabSkins::Update(MeterWindow* meterWindow, bool deleted) -{ - if (meterWindow) - { - if (!deleted && m_IgnoreUpdate) - { - // Changed setting from dialog, no need to update - m_IgnoreUpdate = false; - } - else if (m_SkinWindow && m_SkinWindow == meterWindow) - { - // Update from currently open skin - m_HandleCommands = false; - if (deleted) - { - DisableControls(); - m_SkinWindow = nullptr; - } - else - { - SetControls(); - } - m_HandleCommands = true; - } - else if (wcscmp(meterWindow->GetFolderPath().c_str(), m_SkinFolderPath.c_str()) == 0 && - wcscmp(meterWindow->GetFileName().c_str(), m_SkinFileName.c_str()) == 0) - { - ReadSkin(); - } - } - else - { - // Populate tree - HWND item = GetControl(Id_SkinsTreeView); - TreeView_DeleteAllItems(item); - - TVINSERTSTRUCT tvi = {0}; - tvi.hInsertAfter = TVI_LAST; - tvi.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - tvi.item.iImage = tvi.item.iSelectedImage = 0; - - if (!GetRainmeter().m_SkinRegistry.IsEmpty()) - { - PopulateTree(item, tvi); - } - } -} - -void DialogManage::TabSkins::SetControls() -{ - WCHAR buffer[64]; - - HWND item = GetControl(Id_EditButton); - EnableWindow(item, TRUE); - - item = GetControl(Id_LoadButton); - EnableWindow(item, TRUE); - - if (m_SkinWindow) - { - SetWindowText(item, GetString(ID_STR_UNLOAD)); - - item = GetControl(Id_RefreshButton); - EnableWindow(item, TRUE); - - item = GetControl(Id_XPositionEdit); - EnableWindow(item, TRUE); - _itow_s(m_SkinWindow->GetX(), buffer, 10); - SetWindowText(item, buffer); - - item = GetControl(Id_YPositionEdit); - EnableWindow(item, TRUE); - _itow_s(m_SkinWindow->GetY(), buffer, 10); - SetWindowText(item, buffer); - - item = GetControl(Id_DisplayMonitorButton); - EnableWindow(item, TRUE); - - item = GetControl(Id_DraggableCheckBox); - if (GetRainmeter().GetDisableDragging()) - { - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - } - else - { - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetWindowDraggable()); - } - - item = GetControl(Id_ClickThroughCheckBox); - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetClickThrough()); - - item = GetControl(Id_KeepOnScreenCheckBox); - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetKeepOnScreen()); - - item = GetControl(Id_SavePositionCheckBox); - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetSavePosition()); - - item = GetControl(Id_SnapToEdgesCheckBox); - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetSnapEdges()); - - item = GetControl(Id_TransparencyDropDownList); - EnableWindow(item, TRUE); - int value = (int)(10 - m_SkinWindow->GetAlphaValue() / 25.5); - value = min(9, value); - value = max(0, value); - ComboBox_SetCurSel(item, value); - - item = GetControl(Id_ZPositionDropDownList); - EnableWindow(item, TRUE); - ComboBox_SetCurSel(item, m_SkinWindow->GetWindowZPosition() + 2); - - item = GetControl(Id_LoadOrderEdit); - EnableWindow(item, TRUE); - _itow_s(GetRainmeter().GetLoadOrder(m_SkinFolderPath), buffer, 10); - SetWindowText(item, buffer); - - item = GetControl(Id_OnHoverDropDownList); - EnableWindow(item, TRUE); - ComboBox_SetCurSel(item, m_SkinWindow->GetWindowHide()); - } - else - { - SetWindowText(item, GetString(ID_STR_LOAD)); - } -} - -void DialogManage::TabSkins::DisableControls(bool clear) -{ - HWND item = GetControl(Id_LoadButton); - SetWindowText(item, GetString(ID_STR_LOAD)); - - if (clear) - { - EnableWindow(item, FALSE); - - item = GetControl(Id_EditButton); - EnableWindow(item, FALSE); - - item = GetControl(Id_FileLabel); - SetWindowText(item, GetString(ID_STR_ELLIPSIS)); - - item = GetControl(Id_ConfigLabel); - SetWindowText(item, L""); - - item = GetControl(Id_AuthorLabel); - SetWindowText(item, L""); - - item = GetControl(Id_VersionLabel); - SetWindowText(item, L""); - - item = GetControl(Id_LicenseLabel); - SetWindowText(item, L""); - - item = GetControl(Id_DescriptionLabel); - SetWindowText(item, L""); - ShowScrollBar(item, SB_VERT, FALSE); - - item = GetControl(Id_AddMetadataLink); - ShowWindow(item, SW_HIDE); - } - else - { - EnableWindow(item, TRUE); - } - - item = GetControl(Id_RefreshButton); - EnableWindow(item, FALSE); - - item = GetControl(Id_XPositionEdit); - SetWindowText(item, L""); - EnableWindow(item, FALSE); - - item = GetControl(Id_YPositionEdit); - SetWindowText(item, L""); - EnableWindow(item, FALSE); - - item = GetControl(Id_DisplayMonitorButton); - EnableWindow(item, FALSE); - - item = GetControl(Id_DraggableCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_ClickThroughCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_KeepOnScreenCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_SavePositionCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_SnapToEdgesCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_TransparencyDropDownList); - EnableWindow(item, FALSE); - ComboBox_SetCurSel(item, -1); - - item = GetControl(Id_ZPositionDropDownList); - EnableWindow(item, FALSE); - ComboBox_SetCurSel(item, -1); - - item = GetControl(Id_LoadOrderEdit); - SetWindowText(item, L""); - EnableWindow(item, FALSE); - - item = GetControl(Id_OnHoverDropDownList); - EnableWindow(item, FALSE); - ComboBox_SetCurSel(item, -1); -} - -void DialogManage::TabSkins::ReadSkin() -{ - HWND item = GetControl(Id_FileLabel); - SetWindowText(item, m_SkinFileName.c_str()); - - PathSetDlgItemPath(m_Window, Id_ConfigLabel, m_SkinFolderPath.c_str()); - - item = GetControl(Id_EditButton); - EnableWindow(item, TRUE); - - std::wstring file = GetRainmeter().GetSkinPath() + m_SkinFolderPath; - file += L'\\'; - file += m_SkinFileName; - m_SkinWindow = GetRainmeter().GetMeterWindowByINI(file); - if (!m_SkinWindow) - { - DisableControls(); - } - - SetControls(); - - WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; - const WCHAR* fileSz = file.c_str(); - - item = GetControl(Id_AuthorLabel); - if (GetPrivateProfileString(L"Metadata", L"Author", nullptr, buffer, MAX_LINE_LENGTH, fileSz) == 0) - { - // For backwards compatibility. - GetPrivateProfileString(L"Rainmeter", L"Author", nullptr, buffer, MAX_LINE_LENGTH, fileSz); - } - SetWindowText(item, buffer); - - item = GetControl(Id_AddMetadataLink); - if (GetPrivateProfileSection(L"Metadata", buffer, 8, fileSz) > 0) - { - ShowWindow(item, SW_HIDE); - - // Set metadata - item = GetControl(Id_VersionLabel); - GetPrivateProfileString(L"Metadata", L"Version", nullptr, buffer, MAX_LINE_LENGTH, fileSz); - SetWindowText(item, buffer); - - item = GetControl(Id_LicenseLabel); - GetPrivateProfileString(L"Metadata", L"License", nullptr, buffer, MAX_LINE_LENGTH, fileSz); - SetWindowText(item, buffer); - - item = GetControl(Id_DescriptionLabel); - std::wstring text; - if (GetPrivateProfileString(L"Metadata", L"Information", nullptr, buffer, MAX_LINE_LENGTH, fileSz) > 0) - { - text = buffer; - } - else - { - // For backwards compatibility - GetPrivateProfileString(L"Metadata", L"Description", nullptr, buffer, MAX_LINE_LENGTH, fileSz); - text = buffer; - - if (GetPrivateProfileString(L"Metadata", L"Instructions", nullptr, buffer, MAX_LINE_LENGTH, fileSz) > 0) - { - text += L"\r\n\r\n"; - text += buffer; - } - } - - // Replace | with newline - std::wstring::size_type pos; - while ((pos = text.find_first_of(L'|')) != std::wstring::npos) - { - size_t count = (pos + 1 < text.length() && text[pos + 1] == L' ') ? 2 : 1; - if (text[pos - 1] == L' ') - { - --pos; - count += 1; - } - text.replace(pos, count, L"\r\n"); - } - - SetWindowText(item, text.c_str()); - - int lines = Edit_GetLineCount(item); - ShowScrollBar(item, SB_VERT, (BOOL)(lines > 6)); - } - else - { - ShowWindow(item, SW_SHOWNORMAL); - - item = GetControl(Id_VersionLabel); - SetWindowText(item, L""); - - item = GetControl(Id_LicenseLabel); - SetWindowText(item, L""); - - item = GetControl(Id_DescriptionLabel); - SetWindowText(item, L""); - ShowScrollBar(item, SB_VERT, FALSE); - } - - delete [] buffer; -} - -std::wstring DialogManage::TabSkins::GetTreeSelectionPath(HWND tree) -{ - WCHAR buffer[MAX_PATH]; - - // Get current selection name - TVITEM tvi = {0}; - tvi.hItem = TreeView_GetSelection(tree); - tvi.mask = TVIF_TEXT; - tvi.pszText = buffer; - tvi.cchTextMax = MAX_PATH; - TreeView_GetItem(tree, &tvi); - - std::wstring path = buffer; - while ((tvi.hItem = TreeView_GetParent(tree, tvi.hItem)) != nullptr) - { - TreeView_GetItem(tree, &tvi); - path.insert(0, 1, L'\\'); - path.insert(0, buffer); - } - - return path; -} - -/* -** Populates the treeview with folders and skins. -** -*/ -int DialogManage::TabSkins::PopulateTree(HWND tree, TVINSERTSTRUCT& tvi, int index) -{ - int initialLevel = GetRainmeter().m_SkinRegistry.GetFolder(index).level; - - const size_t max = GetRainmeter().m_SkinRegistry.GetFolderCount(); - while (index < max) - { - const auto& skinFolder = GetRainmeter().m_SkinRegistry.GetFolder(index); - if (skinFolder.level != initialLevel) - { - return index - 1; - } - - HTREEITEM oldParent = tvi.hParent; - - // Add folder - tvi.item.iImage = tvi.item.iSelectedImage = 0; - tvi.item.pszText = (WCHAR*)skinFolder.name.c_str(); - tvi.hParent = TreeView_InsertItem(tree, &tvi); - - // Add subfolders - if ((index + 1) < max && - GetRainmeter().m_SkinRegistry.GetFolder(index + 1).level == initialLevel + 1) - { - index = PopulateTree(tree, tvi, index + 1); - } - - // Add files - tvi.item.iImage = tvi.item.iSelectedImage = 1; - for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) - { - tvi.item.pszText = (WCHAR*)skinFolder.files[i].c_str(); - TreeView_InsertItem(tree, &tvi); - } - - tvi.hParent = oldParent; - - ++index; - } - - return index; -} - -/* -** Selects an item in the treeview. -** -*/ -void DialogManage::TabSkins::SelectTreeItem(HWND tree, HTREEITEM item, LPCWSTR name) -{ - WCHAR buffer[MAX_PATH]; - TVITEM tvi = {0}; - tvi.mask = TVIF_TEXT; - tvi.hItem = item; - tvi.pszText = buffer; - - const WCHAR* pos = wcschr(name, L'\\'); - if (pos) - { - const int folderLen = (int)(pos - name); - tvi.cchTextMax = folderLen + 1; // Length of folder name plus 1 for nullptr - - // Find and expand the folder - do - { - TreeView_GetItem(tree, &tvi); - if (wcsncmp(buffer, name, folderLen) == 0) - { - if ((item = TreeView_GetChild(tree, tvi.hItem)) != nullptr) - { - TreeView_Expand(tree, tvi.hItem, TVE_EXPAND); - TreeView_Select(tree, tvi.hItem, TVGN_CARET); - ++pos; // Skip the slash - SelectTreeItem(tree, item, pos); - } - - break; - } - } - while ((tvi.hItem = TreeView_GetNextSibling(tree, tvi.hItem)) != nullptr); - } - else - { - tvi.cchTextMax = MAX_PATH; - - // Find and select the file - do - { - TreeView_GetItem(tree, &tvi); - if (wcscmp(buffer, name) == 0) - { - TreeView_Select(tree, tvi.hItem, TVGN_CARET); - break; - } - } - while ((tvi.hItem = TreeView_GetNextSibling(tree, tvi.hItem)) != nullptr); - } -} - -INT_PTR DialogManage::TabSkins::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogManage::TabSkins::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (!m_HandleCommands) - { - // Values are being changed/reset, no need to apply changes. - return FALSE; - } - - switch (LOWORD(wParam)) - { - case Id_ActiveSkinsButton: - { - HMENU menu = CreatePopupMenu(); - - // Add active skins to menu - std::map::const_iterator iter = GetRainmeter().GetAllMeterWindows().begin(); - int index = 0; - for ( ; iter != GetRainmeter().GetAllMeterWindows().end(); ++iter) - { - std::wstring name = ((*iter).second)->GetFolderPath() + L'\\'; - name += ((*iter).second)->GetFileName(); - InsertMenu(menu, index, MF_BYPOSITION, ID_CONFIG_FIRST + index, name.c_str()); - ++index; - } - - if (index > 0) - { - RECT r; - GetWindowRect((HWND)lParam, &r); - - // Show context menu - TrackPopupMenu( - menu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN, - (*GetString(ID_STR_ISRTL) == L'1') ? r.right : r.left, - --r.bottom, - 0, - m_Window, - nullptr - ); - } - - DestroyMenu(menu); - } - break; - - case Id_CreateSkinPackageButton: - { - std::wstring file = GetRainmeter().GetPath() + L"SkinInstaller.exe"; - CommandHandler::RunFile(file.c_str(), L"/Packager"); - } - break; - - case Id_LoadButton: - { - if (!m_SkinWindow) - { - // Skin not active, load - const SkinRegistry::Indexes indexes = - GetRainmeter().m_SkinRegistry.FindIndexes(m_SkinFolderPath, m_SkinFileName); - if (indexes.IsValid()) - { - m_HandleCommands = false; - GetRainmeter().ActivateSkin(indexes.folder, indexes.file); - m_HandleCommands = true; - - // Fake selection change to update controls - NMHDR nm; - nm.code = TVN_SELCHANGED; - nm.idFrom = Id_SkinsTreeView; - nm.hwndFrom = GetControl(Id_SkinsTreeView); - OnNotify(0, (LPARAM)&nm); - } - } - else - { - m_HandleCommands = false; - GetRainmeter().DeactivateSkin(m_SkinWindow, -1); - } - } - break; - - case Id_RefreshButton: - if (m_SkinWindow) - { - m_SkinWindow->Refresh(false); - } - break; - - case Id_EditButton: - GetRainmeter().EditSkinFile(m_SkinFolderPath, m_SkinFileName); - break; - - case Id_XPositionEdit: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[32]; - m_IgnoreUpdate = true; - int x = (GetWindowText((HWND)lParam, buffer, 32) > 0) ? _wtoi(buffer) : 0; - m_SkinWindow->MoveWindow(x, m_SkinWindow->GetY()); - - if (x > m_SkinWindow->GetX()) - { - _itow_s(m_SkinWindow->GetX(), buffer, 10); - Edit_SetText((HWND)lParam, buffer); - } - } - break; - - case Id_YPositionEdit: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[32]; - m_IgnoreUpdate = true; - int y = (GetWindowText((HWND)lParam, buffer, 32) > 0) ? _wtoi(buffer) : 0; - m_SkinWindow->MoveWindow(m_SkinWindow->GetX(), y); - - if (y > m_SkinWindow->GetY()) - { - _itow_s(m_SkinWindow->GetY(), buffer, 10); - Edit_SetText((HWND)lParam, buffer); - } - } - break; - - case Id_LoadOrderEdit: - if (HIWORD(wParam) == EN_CHANGE) - { - if (m_IgnoreUpdate) - { - // To avoid infinite loop after setting value below - m_IgnoreUpdate = false; - } - else - { - // Convert text to number and set it to get rid of extra chars - WCHAR buffer[32]; - int len = GetWindowText((HWND)lParam, buffer, 32); - if ((len == 0) || (len == 1 && buffer[0] == L'-')) - { - // Ignore if empty or if - is only char - break; - } - - // Get selection - DWORD sel = Edit_GetSel((HWND)lParam); - - // Reset value (to get rid of invalid chars) - m_IgnoreUpdate = true; - int value = _wtoi(buffer); - - _itow_s(value, buffer, 10); - SetWindowText((HWND)lParam, buffer); - - // Reset selection - Edit_SetSel((HWND)lParam, LOWORD(sel), HIWORD(sel)); - - WritePrivateProfileString(m_SkinFolderPath.c_str(), L"LoadOrder", buffer, GetRainmeter().GetIniFile().c_str()); - const SkinRegistry::Indexes indexes = GetRainmeter().m_SkinRegistry.FindIndexes( - m_SkinWindow->GetFolderPath(), m_SkinWindow->GetFileName()); - if (indexes.IsValid()) - { - GetRainmeter().SetLoadOrder(indexes.folder, value); - - std::multimap windows; - GetRainmeter().GetMeterWindowsByLoadOrder(windows); - - System::PrepareHelperWindow(); - - // Reorder window z-position to reflect load order - std::multimap::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - MeterWindow* mw = (*iter).second; - mw->ChangeZPos(mw->GetWindowZPosition(), true); - } - } - } - } - break; - - case Id_DisplayMonitorButton: - { - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_SKIN_MONITOR_PRIMARY, ID_STR_USEDEFAULTMONITOR), - MENU_ITEM(ID_MONITOR_FIRST, ID_STR_VIRTUALSCREEN), - MENU_SEPARATOR(), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_MONITOR_AUTOSELECT, ID_STR_AUTOSELECTMONITOR) - }; - - HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - if (menu) - { - ContextMenu::CreateMonitorMenu(menu, m_SkinWindow); - - RECT r; - GetWindowRect((HWND)lParam, &r); - - // Show context menu - TrackPopupMenu( - menu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN, - (*GetString(ID_STR_ISRTL) == L'1') ? r.right : r.left, - --r.bottom, - 0, - m_Window, - nullptr - ); - - DestroyMenu(menu); - } - } - break; - - case Id_DraggableCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetWindowDraggable(!m_SkinWindow->GetWindowDraggable()); - break; - - case Id_ClickThroughCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetClickThrough(!m_SkinWindow->GetClickThrough()); - break; - - case Id_KeepOnScreenCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetKeepOnScreen(!m_SkinWindow->GetKeepOnScreen()); - break; - - case Id_SavePositionCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetSavePosition(!m_SkinWindow->GetSavePosition()); - break; - - case Id_SnapToEdgesCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetSnapEdges(!m_SkinWindow->GetSnapEdges()); - break; - - case Id_ZPositionDropDownList: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - m_IgnoreUpdate = true; - ZPOSITION zpos = (ZPOSITION)(ComboBox_GetCurSel((HWND)lParam) - 2); - m_SkinWindow->SetWindowZPosition(zpos); - } - break; - - case Id_TransparencyDropDownList: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - m_IgnoreUpdate = true; - int sel = ComboBox_GetCurSel((HWND)lParam) + IDM_SKIN_TRANSPARENCY_0; - SendMessage(m_SkinWindow->GetWindow(), WM_COMMAND, sel, 0); - } - break; - - case Id_OnHoverDropDownList: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - m_IgnoreUpdate = true; - HIDEMODE hide = (HIDEMODE)ComboBox_GetCurSel((HWND)lParam); - m_SkinWindow->SetWindowHide(hide); - } - break; - - case IDM_MANAGESKINSMENU_EXPAND: - { - HWND tree = GetControl(Id_SkinsTreeView); - HTREEITEM item = TreeView_GetSelection(tree); - TreeView_Expand(tree, item, TVE_TOGGLE); - } - break; - - case IDM_MANAGESKINSMENU_OPENFOLDER: - { - HWND tree = GetControl(Id_SkinsTreeView); - GetRainmeter().OpenSkinFolder(GetTreeSelectionPath(tree)); - } - break; - - default: - if (wParam >= ID_CONFIG_FIRST && wParam <= ID_CONFIG_LAST) - { - std::map::const_iterator iter = GetRainmeter().GetAllMeterWindows().begin(); - int index = (int)wParam - ID_CONFIG_FIRST; - int i = 0; - for ( ; iter != GetRainmeter().GetAllMeterWindows().end(); ++iter) - { - if (i == index) - { - std::wstring name = ((*iter).second)->GetFolderPath() + L'\\'; - name += ((*iter).second)->GetFileName(); - - HWND item = GetControl(Id_SkinsTreeView); - SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); - break; - } - - ++i; - } - } - else if (wParam == IDM_SKIN_MONITOR_AUTOSELECT || - wParam == IDM_SKIN_MONITOR_PRIMARY || - wParam >= ID_MONITOR_FIRST && wParam <= ID_MONITOR_LAST) - { - if (m_SkinWindow) - { - SendMessage(m_SkinWindow->GetWindow(), WM_COMMAND, wParam, 0); - } - break; - } - - return 1; - } - - return 0; -} - -INT_PTR DialogManage::TabSkins::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case NM_CLICK: - if (nm->idFrom == Id_AddMetadataLink) - { - std::wstring file = GetRainmeter().GetSkinPath() + m_SkinFolderPath; - file += L'\\'; - file += m_SkinFileName; - const WCHAR* str = L"\r\n" // Hack to add below [Rainmeter]. - L"[Metadata]\r\n" - L"Name=\r\n" - L"Author=\r\n" - L"Information=\r\n" - L"License=\r\n" - L"Version"; - WritePrivateProfileString(L"Rainmeter", str, L"", file.c_str()); - SendMessage(m_Window, WM_COMMAND, MAKEWPARAM(Id_EditButton, 0), 0); - ShowWindow(nm->hwndFrom, SW_HIDE); - } - break; - - case NM_DBLCLK: - if (nm->idFrom == Id_SkinsTreeView && !m_SkinFileName.empty()) - { - OnCommand(MAKEWPARAM(Id_LoadButton, 0), 0); - } - break; - - case NM_RCLICK: - if (nm->idFrom == Id_SkinsTreeView) - { - POINT pt = System::GetCursorPosition(); - - TVHITTESTINFO ht; - ht.pt = pt; - ScreenToClient(nm->hwndFrom, &ht.pt); - - if (TreeView_HitTest(nm->hwndFrom, &ht) && !(ht.flags & TVHT_NOWHERE)) - { - TreeView_SelectItem(nm->hwndFrom, ht.hItem); - - TVITEM tvi = {0}; - tvi.hItem = TreeView_GetSelection(nm->hwndFrom); - tvi.mask = TVIF_STATE; - - if (TreeView_GetItem(nm->hwndFrom, &tvi)) - { - HMENU menu = nullptr; - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(MENUITEMINFO); - mii.fMask = MIIM_STRING; - - if (m_SkinFileName.empty()) - { - // Folder menu. - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_MANAGESKINSMENU_EXPAND, ID_STR_EXPAND), - MENU_ITEM(IDM_MANAGESKINSMENU_OPENFOLDER, ID_STR_OPENFOLDER), - }; - - menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - SetMenuDefaultItem(menu, IDM_MANAGESKINSMENU_EXPAND, MF_BYCOMMAND); - - if (tvi.state & TVIS_EXPANDED) - { - mii.dwTypeData = GetString(ID_STR_COLLAPSE); - SetMenuItemInfo(menu, IDM_MANAGESKINSMENU_EXPAND, MF_BYCOMMAND, &mii); - } - } - else - { - // Skin menu. - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_MANAGESKINSMENU_LOAD, ID_STR_LOAD), - MENU_ITEM(IDM_MANAGESKINSMENU_REFRESH, ID_STR_REFRESH), - MENU_ITEM(IDM_MANAGESKINSMENU_EDIT, ID_STR_EDIT), - }; - - menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - SetMenuDefaultItem(menu, IDM_MANAGESKINSMENU_LOAD, MF_BYCOMMAND); - - if (m_SkinWindow) - { - mii.dwTypeData = GetString(ID_STR_UNLOAD); - SetMenuItemInfo(menu, IDM_MANAGESKINSMENU_LOAD, MF_BYCOMMAND, &mii); - } - else - { - EnableMenuItem(menu, IDM_MANAGESKINSMENU_REFRESH, MF_BYCOMMAND | MF_GRAYED); - } - } - - // Show context menu - TrackPopupMenu( - menu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN, - pt.x, - pt.y, - 0, - m_Window, - nullptr - ); - - DestroyMenu(menu); - } - } - } - break; - - case TVN_SELCHANGED: - if (nm->idFrom == Id_SkinsTreeView) - { - m_SkinWindow = nullptr; - m_SkinFileName.clear(); - m_SkinFolderPath.clear(); - - // Temporarily disable handling commands - m_HandleCommands = false; - - WCHAR buffer[MAX_PATH]; - - // Get current selection name - TVITEM tvi = {0}; - tvi.hItem = TreeView_GetSelection(nm->hwndFrom); - tvi.mask = TVIF_TEXT | TVIF_CHILDREN; - tvi.pszText = buffer; - tvi.cchTextMax = MAX_PATH; - TreeView_GetItem(nm->hwndFrom, &tvi); - - if (tvi.cChildren == 0) - { - // Current selection is file - m_SkinFileName = buffer; - tvi.mask = TVIF_TEXT; - - // Loop through parents to get skin folder - m_SkinFolderPath.clear(); - while ((tvi.hItem = TreeView_GetParent(nm->hwndFrom, tvi.hItem)) != nullptr) - { - TreeView_GetItem(nm->hwndFrom, &tvi); - m_SkinFolderPath.insert(0, 1, L'\\'); - m_SkinFolderPath.insert(0, buffer); - } - - m_SkinFolderPath.resize(m_SkinFolderPath.length() - 1); // Get rid of trailing slash - - ReadSkin(); - } - else - { - DisableControls(true); - } - - m_HandleCommands = true; - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Layouts tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogManage::TabLayouts::TabLayouts() : Tab() -{ -} - -void DialogManage::TabLayouts::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 470, 260, owner); - - static const ControlTemplate::Control s_Controls[] = - { - CT_GROUPBOX(-1, ID_STR_SAVENEWTHEME, - 0, 0, 230, 150, - WS_VISIBLE, 0), - CT_LABEL(-1, ID_STR_THEMEDESCRIPTION, - 6, 16, 205, 44, - WS_VISIBLE, 0), - CT_CHECKBOX(Id_SaveEmptyThemeCheckBox, ID_STR_SAVEASEMPTYTHEME, - 6, 70, 220, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_ExcludeUnusedSkinsCheckBox, ID_STR_EXCLUDEUNUSEDSKINS, - 6, 83, 220, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_IncludeWallpaperCheckBox, ID_STR_INCLUDEWALLPAPER, - 6, 96, 220, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_LABEL(-1, ID_STR_NAMESC, - 6, 115, 100, 9, - WS_VISIBLE, 0), - CT_EDIT(Id_NameLabel, 0, - 6, 128, 162, 14, - WS_VISIBLE | WS_TABSTOP, WS_EX_CLIENTEDGE), - CT_BUTTON(Id_SaveButton, ID_STR_SAVE, - 172, 128, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - - CT_GROUPBOX(-1, ID_STR_SAVEDTHEMES, - 238, 0, 230, 150, - WS_VISIBLE, 0), - CT_LISTBOX(Id_List, 0, - 244, 16, 160, 125, - WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_SORT | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT, WS_EX_CLIENTEDGE), - CT_BUTTON(Id_LoadButton, ID_STR_LOAD, - 410, 16, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_BUTTON(Id_EditButton, ID_STR_EDIT, - 410, 34, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_BUTTON(Id_DeleteButton, ID_STR_DELETE, - 410, 52, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogManage::TabLayouts::Initialize() -{ - HWND item = GetControl(Id_List); - ListBox_ResetContent(item); - const std::vector& layouts = GetRainmeter().GetAllLayouts(); - for (size_t i = 0, isize = layouts.size(); i < isize; ++i) - { - ListBox_AddString(item, layouts[i].c_str()); - } - - m_Initialized = true; -} - -void DialogManage::TabLayouts::Update() -{ - Initialize(); -} - -INT_PTR DialogManage::TabLayouts::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogManage::TabLayouts::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_SaveEmptyThemeCheckBox: - { - BOOL state = !(Button_GetCheck((HWND)lParam) == BST_CHECKED); - - HWND item = GetControl(Id_ExcludeUnusedSkinsCheckBox); - EnableWindow(item, state); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_IncludeWallpaperCheckBox); - EnableWindow(item, state); - Button_SetCheck(item, BST_UNCHECKED); - } - break; - - case Id_NameLabel: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[32]; - int len = Edit_GetText((HWND)lParam, buffer, 32); - - // Disable save button if no text or if backup - BOOL state = (len > 0 && _wcsicmp(buffer, L"@Backup") != 0); - EnableWindow(GetControl(Id_SaveButton), state); - } - break; - - case Id_List: - if (HIWORD(wParam) == LBN_SELCHANGE) - { - // Ignore clicks that don't hit items - if (ListBox_GetCurSel((HWND)lParam) != LB_ERR) - { - HWND item = GetControl(Id_LoadButton); - EnableWindow(item, TRUE); - item = GetControl(Id_DeleteButton); - EnableWindow(item, TRUE); - item = GetControl(Id_EditButton); - EnableWindow(item, TRUE); - - const std::vector& layouts = GetRainmeter().GetAllLayouts(); - item = GetControl(Id_List); - int sel = ListBox_GetCurSel(item); - - item = GetControl(Id_NameLabel); - Edit_SetText(item, layouts[sel].c_str()); - } - } - break; - - case Id_SaveButton: - { - WCHAR buffer[MAX_PATH]; - HWND item = GetControl(Id_NameLabel); - Edit_GetText(item, buffer, MAX_PATH); - - std::wstring layout = buffer; - std::wstring path = GetRainmeter().GetLayoutPath(); - CreateDirectory(path.c_str(), 0); - - path += layout; - bool alreadyExists = (_waccess(path.c_str(), 0) != -1); - if (alreadyExists) - { - std::wstring text = GetFormattedString(ID_STR_THEMEALREADYEXISTS, layout.c_str()); - if (GetRainmeter().ShowMessage(m_Window, text.c_str(), MB_ICONWARNING | MB_YESNO) != IDYES) - { - // Cancel - break; - } - } - else - { - // Make sure path exists - CreateDirectory(path.c_str(), nullptr); - } - - path += L"\\Rainmeter.ini"; - - item = GetControl(Id_SaveEmptyThemeCheckBox); - if (Button_GetCheck(item) != BST_CHECKED) - { - if (!System::CopyFiles(GetRainmeter().GetIniFile(), path)) - { - std::wstring text = GetFormattedString(ID_STR_THEMESAVEFAIL, path.c_str()); - GetRainmeter().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONERROR); - break; - } - - // Exclude unused skins - item = GetControl(Id_ExcludeUnusedSkinsCheckBox); - if (Button_GetCheck(item) == BST_CHECKED) - { - ConfigParser parser; - parser.Initialize(path); - - // Remove sections with Active=0 - std::list::const_iterator iter = parser.GetSections().begin(); - for ( ; iter != parser.GetSections().end(); ++iter) - { - if (parser.GetValue(*iter, L"Active", L"") == L"0") - { - WritePrivateProfileString((*iter).c_str(), nullptr, nullptr, path.c_str()); - } - } - } - - // Save wallpaper - item = GetControl(Id_IncludeWallpaperCheckBox); - if (Button_GetCheck(item) == BST_CHECKED) - { - // Get current wallpaper - if (SystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH, &buffer, 0)) - { - std::wstring::size_type pos = path.find_last_of(L'\\'); - path.replace(pos + 1, path.length() - pos - 1, L"Wallpaper.bmp"); - System::CopyFiles((std::wstring)buffer, path); - } - } - } - else - { - // Create empty layout - HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file == INVALID_HANDLE_VALUE) - { - std::wstring text = GetFormattedString(ID_STR_THEMESAVEFAIL, path.c_str()); - GetRainmeter().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONERROR); - break; - } - - CloseHandle(file); - } - - if (!alreadyExists) - { - item = GetControl(Id_List); - ListBox_AddString(item, layout.c_str()); - - GetRainmeter().ScanForLayouts(); - } - } - break; - - case Id_LoadButton: - { - HWND item = GetControl(Id_List); - int sel = ListBox_GetCurSel(item); - GetRainmeter().LoadLayout(GetRainmeter().m_Layouts[sel]); - } - break; - - case Id_EditButton: - { - HWND item = GetControl(Id_List); - int sel = ListBox_GetCurSel(item); - const std::vector& layouts = GetRainmeter().GetAllLayouts(); - - std::wstring args = L"\"" + GetRainmeter().GetLayoutPath(); - args += layouts[sel]; - args += L"\\Rainmeter.ini"; - args += L'"'; - CommandHandler::RunFile(GetRainmeter().GetSkinEditor().c_str(), args.c_str()); - } - break; - - case Id_DeleteButton: - { - HWND item = GetControl(Id_List); - int sel = ListBox_GetCurSel(item); - std::vector& layouts = const_cast&>(GetRainmeter().GetAllLayouts()); - - std::wstring text = GetFormattedString(ID_STR_THEMEDELETE, layouts[sel].c_str()); - if (GetRainmeter().ShowMessage(m_Window, text.c_str(), MB_ICONQUESTION | MB_YESNO) != IDYES) - { - // Cancel - break; - } - - std::wstring folder = GetRainmeter().GetLayoutPath(); - folder += layouts[sel]; - - if (System::RemoveFolder(folder)) - { - ListBox_DeleteString(item, sel); - - // Remove layout from vector - std::vector::iterator iter = layouts.begin(); - for ( ; iter != layouts.end(); ++iter) - { - if (wcscmp(layouts[sel].c_str(), (*iter).c_str()) == 0) - { - layouts.erase(iter); - break; - } - } - - EnableWindow(GetControl(Id_LoadButton), FALSE); - EnableWindow(GetControl(Id_DeleteButton), FALSE); - EnableWindow(GetControl(Id_EditButton), FALSE); - } - } - break; - - default: - return 1; - } - - return 0; -} - -// ----------------------------------------------------------------------------------------------- -// -// Settings tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogManage::TabSettings::TabSettings() : Tab() -{ -} - -void DialogManage::TabSettings::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 470, 260, owner); - - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - const ControlTemplate::Control s_Controls[] = - { - CT_GROUPBOX(-1, ID_STR_GENERAL, - 0, 0, 468, 131, - WS_VISIBLE, 0), - CT_LABEL(-1, ID_STR_LANGUAGESC, - 6, 16, 107, 14, - WS_VISIBLE, 0), - CT_COMBOBOX(Id_LanguageDropDownList, 0, - 107, 13, 222, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 0), - CT_LABEL(-1, ID_STR_EDITORSC, - 6, 37, 107, 9, - WS_VISIBLE, 0), - CT_EDIT(Id_EditorEdit, 0, - 107, 34, 222, 14, - WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY, WS_EX_CLIENTEDGE), - CT_BUTTON(Id_EditorBrowseButton, ID_STR_ELLIPSIS, - 333, 34, 25, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_CheckForUpdatesCheckBox, ID_STR_CHECKFORUPDATES, - 6, 55, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_LockSkinsCheckBox, ID_STR_DISABLEDRAGGING, - 6, 68, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_ShowTrayIconCheckBox, ID_STR_SHOWNOTIFICATIONAREAICON, - 6, 81, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_UseD2DCheckBox, ID_STR_USED2D, - 6, 94, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_ResetStatisticsButton, ID_STR_RESETSTATISTICS, - 6, 110, buttonWidth + 20, 14, - WS_VISIBLE | WS_TABSTOP, 0), - - CT_GROUPBOX(-1, ID_STR_LOGGING, - 0, 138, 468, 66, - WS_VISIBLE, 0), - CT_CHECKBOX(Id_VerboseLoggingCheckbox, ID_STR_DEBUGMODE, - 6, 154, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_LogToFileCheckBox, ID_STR_LOGTOFILE, - 6, 167, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_ShowLogFileButton, ID_STR_SHOWLOGFILE, - 6, 183, buttonWidth + 20, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_DeleteLogFileButton, ID_STR_DELETELOGFILE, - buttonWidth + 30, 183, buttonWidth + 20, 14, - WS_VISIBLE | WS_TABSTOP, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogManage::TabSettings::Initialize() -{ - // Scan for languages - HWND item = GetControl(Id_LanguageDropDownList); - - std::wstring files = GetRainmeter().GetPath() + L"Languages\\*.dll"; - WIN32_FIND_DATA fd; - HANDLE hSearch = FindFirstFile(files.c_str(), &fd); - if (hSearch != INVALID_HANDLE_VALUE) - { - do - { - WCHAR* pos = wcschr(fd.cFileName, L'.'); - if (pos) - { - LCID lcid = (LCID)wcstoul(fd.cFileName, &pos, 10); - if (pos != fd.cFileName && - _wcsicmp(pos, L".dll") == 0 && - GetLocaleInfo(lcid, LOCALE_SENGLISHLANGUAGENAME, fd.cFileName, MAX_PATH) > 0) - { - // Strip brackets in language name - std::wstring text = fd.cFileName; - text += L" - "; - - GetLocaleInfo(lcid, LOCALE_SNATIVEDISPLAYNAME, fd.cFileName, MAX_PATH); - text += fd.cFileName; - - int index = ComboBox_AddString(item, text.c_str()); - ComboBox_SetItemData(item, index, (LPARAM)lcid); - - if (lcid == GetRainmeter().GetResourceLCID()) - { - ComboBox_SetCurSel(item, index); - } - } - } - } - while (FindNextFile(hSearch, &fd)); - - FindClose(hSearch); - } - - Button_SetCheck(GetControl(Id_CheckForUpdatesCheckBox), !GetRainmeter().GetDisableVersionCheck()); - Button_SetCheck(GetControl(Id_LockSkinsCheckBox), GetRainmeter().GetDisableDragging()); - Button_SetCheck(GetControl(Id_LogToFileCheckBox), GetLogger().IsLogToFile()); - Button_SetCheck(GetControl(Id_VerboseLoggingCheckbox), GetRainmeter().GetDebug()); - - BOOL isLogFile = (_waccess(GetLogger().GetLogFilePath().c_str(), 0) != -1); - EnableWindow(GetControl(Id_ShowLogFileButton), isLogFile); - EnableWindow(GetControl(Id_DeleteLogFileButton), isLogFile); - - Edit_SetText(GetControl(Id_EditorEdit), GetRainmeter().GetSkinEditor().c_str()); - - bool iconEnabled = GetRainmeter().GetTrayWindow()->IsTrayIconEnabled(); - Button_SetCheck(GetControl(Id_ShowTrayIconCheckBox), iconEnabled); - - if (IsWindowsVistaOrGreater()) - { - Button_SetCheck(GetControl(Id_UseD2DCheckBox), GetRainmeter().GetUseD2D()); - } - else - { - Button_Enable(GetControl(Id_UseD2DCheckBox), FALSE); - } - - m_Initialized = true; -} - -INT_PTR DialogManage::TabSettings::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogManage::TabSettings::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (!m_Initialized) - { - return FALSE; - } - - switch (LOWORD(wParam)) - { - case Id_LanguageDropDownList: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - int sel = ComboBox_GetCurSel((HWND)lParam); - LCID lcid = (LCID)ComboBox_GetItemData((HWND)lParam, sel); - if (lcid != GetRainmeter().m_ResourceLCID) - { - WCHAR buffer[16]; - _ultow(lcid, buffer, 10); - WritePrivateProfileString(L"Rainmeter", L"Language", buffer, GetRainmeter().GetIniFile().c_str()); - - std::wstring resource = GetRainmeter().GetPath() + L"Languages\\"; - resource += buffer; - resource += L".dll"; - FreeLibrary(GetRainmeter().m_ResourceInstance); - GetRainmeter().m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); - GetRainmeter().m_ResourceLCID = lcid; - - if (DialogAbout::GetDialog()) - { - int sel = TabCtrl_GetCurSel(DialogAbout::GetDialog()->GetControl(DialogManage::Id_Tab)); - SendMessage(DialogAbout::GetDialog()->GetWindow(), WM_CLOSE, 0, 0); - if (sel == 0) - { - GetRainmeter().DelayedExecuteCommand(L"!About"); - } - else if (sel == 1) - { - GetRainmeter().DelayedExecuteCommand(L"!About Skins"); - } - else if (sel == 2) - { - GetRainmeter().DelayedExecuteCommand(L"!About Plugins"); - } - else //if (sel == 3) - { - GetRainmeter().DelayedExecuteCommand(L"!About Version"); - } - } - - SendMessage(c_Dialog->GetWindow(), WM_CLOSE, 0, 0); - GetRainmeter().DelayedExecuteCommand(L"!Manage Settings"); - } - } - break; - - case Id_CheckForUpdatesCheckBox: - GetRainmeter().SetDisableVersionCheck(!GetRainmeter().GetDisableVersionCheck()); - break; - - case Id_LockSkinsCheckBox: - GetRainmeter().SetDisableDragging(!GetRainmeter().GetDisableDragging()); - break; - - case Id_ResetStatisticsButton: - GetRainmeter().ResetStats(); - break; - - case Id_ShowLogFileButton: - GetRainmeter().ShowLogFile(); - break; - - case Id_DeleteLogFileButton: - GetLogger().DeleteLogFile(); - if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) == -1) - { - Button_SetCheck(GetControl(Id_LogToFileCheckBox), BST_UNCHECKED); - EnableWindow(GetControl(Id_ShowLogFileButton), FALSE); - EnableWindow(GetControl(Id_DeleteLogFileButton), FALSE); - } - break; - - case Id_LogToFileCheckBox: - if (GetLogger().IsLogToFile()) - { - GetLogger().StopLogFile(); - } - else - { - GetLogger().StartLogFile(); - if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) != -1) - { - EnableWindow(GetControl(Id_ShowLogFileButton), TRUE); - EnableWindow(GetControl(Id_DeleteLogFileButton), TRUE); - } - } - break; - - case Id_VerboseLoggingCheckbox: - GetRainmeter().SetDebug(!GetRainmeter().GetDebug()); - break; - - case Id_EditorEdit: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[MAX_PATH]; - if (GetWindowText((HWND)lParam, buffer, _countof(buffer)) > 0) - { - GetRainmeter().SetSkinEditor(buffer); - } - } - break; - - case Id_EditorBrowseButton: - { - WCHAR buffer[MAX_PATH]; - buffer[0] = L'\0'; - - std::wstring editor = GetRainmeter().GetSkinEditor(); - editor = editor.substr(0, editor.find_last_of(L"/\\")).c_str(); - - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - ofn.Flags = OFN_FILEMUSTEXIST; - ofn.lpstrFilter = L"Executable File (.exe)\0*.exe"; - ofn.lpstrTitle = L"Select executable file"; - ofn.lpstrDefExt = L"exe"; - ofn.lpstrInitialDir = editor.c_str(); - ofn.nFilterIndex = 0; - ofn.lpstrFile = buffer; - ofn.nMaxFile = _countof(buffer); - ofn.hwndOwner = c_Dialog->GetWindow(); - - if (!GetOpenFileName(&ofn)) - { - break; - } - - Edit_SetText(GetControl(Id_EditorEdit), buffer); - } - break; - - case Id_ShowTrayIconCheckBox: - GetRainmeter().GetTrayWindow()->SetTrayIcon(!GetRainmeter().GetTrayWindow()->IsTrayIconEnabled()); - break; - - case Id_UseD2DCheckBox: - GetRainmeter().SetUseD2D(!GetRainmeter().GetUseD2D()); - break; - - default: - return 1; - } - - return 0; -} \ No newline at end of file diff --git a/Library/DialogManage.h b/Library/DialogManage.h deleted file mode 100644 index 1308128c..00000000 --- a/Library/DialogManage.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __DIALOGMANAGE_H__ -#define __DIALOGMANAGE_H__ - -#include "../Common/Dialog.h" -#include "resource.h" - -class DialogManage : public Dialog -{ -public: - DialogManage(); - virtual ~DialogManage(); - - DialogManage(const DialogManage& other) = delete; - DialogManage& operator=(DialogManage other) = delete; - - static Dialog* GetDialog() { return c_Dialog; } - - static void Open(const WCHAR* tabName, const WCHAR* param1, const WCHAR* param2); - static void Open(const WCHAR* name); - static void Open(int tab = 0); - static void OpenSkin(MeterWindow* meterWindow); - - static void UpdateSkins(MeterWindow* meterWindow, bool deleted = false); - static void UpdateLayouts(); - -protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - -private: - // Skins tab - class TabSkins : public Tab - { - public: - enum Id - { - Id_ActiveSkinsButton = 100, - Id_SkinsTreeView, - Id_CreateSkinPackageButton, - Id_FileLabel, - Id_ConfigLabel, - Id_AuthorLabel, - Id_VersionLabel, - Id_LicenseLabel, - Id_DescriptionLabel, - Id_AddMetadataLink, - Id_XPositionEdit, - Id_YPositionEdit, - Id_ZPositionDropDownList, - Id_LoadOrderEdit, - Id_OnHoverDropDownList, - Id_TransparencyDropDownList, - Id_DisplayMonitorButton, - Id_DraggableCheckBox, - Id_ClickThroughCheckBox, - Id_KeepOnScreenCheckBox, - Id_SavePositionCheckBox, - Id_SnapToEdgesCheckBox, - - Id_LoadButton = IDM_MANAGESKINSMENU_LOAD, - Id_RefreshButton = IDM_MANAGESKINSMENU_REFRESH, - Id_EditButton = IDM_MANAGESKINSMENU_EDIT - }; - - TabSkins(); - - void Create(HWND owner); - virtual void Initialize(); - - void Update(MeterWindow* meterWindow, bool deleted); - - static void SelectTreeItem(HWND tree, HTREEITEM item, LPCWSTR name); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - - private: - void SetControls(); - void DisableControls(bool clear = false); - void ReadSkin(); - - static std::wstring GetTreeSelectionPath(HWND tree); - static int PopulateTree(HWND tree, TVINSERTSTRUCT& tvi, int index = 0); - - std::wstring m_SkinFileName; - std::wstring m_SkinFolderPath; - MeterWindow* m_SkinWindow; - bool m_HandleCommands; - bool m_IgnoreUpdate; - }; - - // Layouts tab - class TabLayouts : public Tab - { - public: - enum Id - { - Id_List = 100, - Id_LoadButton, - Id_DeleteButton, - Id_EditButton, - Id_SaveButton, - Id_SaveEmptyThemeCheckBox, - Id_ExcludeUnusedSkinsCheckBox, - Id_IncludeWallpaperCheckBox, - Id_NameLabel - }; - - TabLayouts(); - - void Create(HWND owner); - virtual void Initialize(); - - void Update(); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - }; - - // Settings tab - class TabSettings : public Tab - { - public: - enum Id - { - Id_CheckForUpdatesCheckBox = 100, - Id_LockSkinsCheckBox, - Id_ResetStatisticsButton, - Id_LogToFileCheckBox, - Id_VerboseLoggingCheckbox, - Id_ShowLogFileButton, - Id_DeleteLogFileButton, - Id_LanguageDropDownList, - Id_EditorEdit, - Id_EditorBrowseButton, - Id_ShowTrayIconCheckBox, - Id_UseD2DCheckBox - }; - - TabSettings(); - - void Create(HWND owner); - virtual void Initialize(); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - }; - - enum Id - { - Id_CloseButton = IDCLOSE, - Id_Tab = 100, - Id_RefreshAllButton, - Id_EditSettingsButton, - Id_OpenLogButton, - Id_HelpButton - }; - - Tab& GetActiveTab(); - - TabSkins m_TabSkins; - TabLayouts m_TabLayouts; - TabSettings m_TabSettings; - - static WINDOWPLACEMENT c_WindowPlacement; - static DialogManage* c_Dialog; -}; - -#endif diff --git a/Library/Exports_Common.h b/Library/Exports_Common.h index 8c1f2da8..db961266 100644 --- a/Library/Exports_Common.h +++ b/Library/Exports_Common.h @@ -1,3 +1,13 @@ #pragma once #define EXPORT extern "C" _declspec(dllexport) + +namespace Results { + + enum CallResult + { + Ok = 0, + InvalidHandle = 1 + }; + +} diff --git a/Library/Exports_Group.cpp b/Library/Exports_Group.cpp index da0884ad..454c0a01 100644 --- a/Library/Exports_Group.cpp +++ b/Library/Exports_Group.cpp @@ -4,29 +4,29 @@ #include "HandleManager.h" #include "Exports_Common.h" -EXPORT bool Group_BelongsToGroup (bool* result, int32_t handle, LPWSTR str) +EXPORT int Group_BelongsToGroup(bool* result, int32_t handle, LPWSTR str) { - Group* group = (Group*)handle_get_resource (handle); + Group* group = (Group*) handle_get_resource(handle); if (group != nullptr) { - *result = group->BelongsToGroup (str); - return true; + *result = group->BelongsToGroup(str); + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Group_Destroy (int32_t handle) +EXPORT int Group_Destroy(int32_t handle) { - Group* group = (Group*)handle_get_resource (handle); + Group* group = (Group*) handle_get_resource(handle); if (group != nullptr) { - handle_free (handle); + handle_free(handle); delete group; - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } \ No newline at end of file diff --git a/Library/Exports_Meter.cpp b/Library/Exports_Meter.cpp index b5178cd6..1ec58a02 100644 --- a/Library/Exports_Meter.cpp +++ b/Library/Exports_Meter.cpp @@ -4,18 +4,16 @@ #include "HandleManager.h" #include "Exports_Common.h" - - -EXPORT bool Meter_Destroy (int handle) +EXPORT int Meter_Destroy(int handle) { - Meter* meter = (Meter*)handle_get_resource (handle); + Meter* meter = (Meter*) handle_get_resource(handle); if (meter != nullptr) { - handle_free (handle); + handle_free(handle); delete meter; - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } \ No newline at end of file diff --git a/Library/Exports_MeterString.cpp b/Library/Exports_MeterString.cpp index 4e8baca4..50a705dd 100644 --- a/Library/Exports_MeterString.cpp +++ b/Library/Exports_MeterString.cpp @@ -4,32 +4,32 @@ #include "HandleManager.h" #include "Exports_Common.h" -EXPORT bool MeterString_Init (int* handle_result, int meterCanvasHandle, LPCWSTR name) +EXPORT int MeterString_Init(int* handle_result, int meterCanvasHandle, LPCWSTR name) { - MeterWindow* w = (MeterWindow*) handle_get_resource (meterCanvasHandle); + MeterWindow* w = (MeterWindow*) handle_get_resource(meterCanvasHandle); if (w != nullptr) { - MeterString* result = new MeterString (w, name); - *handle_result = handle_allocate (result); + MeterString* result = new MeterString(w, name); + *handle_result = handle_allocate(result); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool MeterString_Destroy (int handle) +EXPORT int MeterString_Destroy(int handle) { - MeterString* ms = (MeterString*) handle_get_resource (handle); + MeterString* ms = (MeterString*) handle_get_resource(handle); if (ms != nullptr) { - handle_free (handle); + handle_free(handle); delete ms; - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } diff --git a/Library/Exports_Rainmeter.cpp b/Library/Exports_Rainmeter.cpp index 4ca632bf..a1f74c98 100644 --- a/Library/Exports_Rainmeter.cpp +++ b/Library/Exports_Rainmeter.cpp @@ -7,10 +7,10 @@ */ bool Rainmeter_Initialize() { - int res = GetRainmeter().Initialize(nullptr, nullptr); - + int res = GetRainmeter().Initialize(); + // Success? - if (res == 0) + if (res == 0) return &GetRainmeter(); return nullptr; @@ -22,6 +22,6 @@ bool Rainmeter_Initialize() */ void Rainmeter_Finalize(void* ptr) { - Rainmeter* rainmeter = (Rainmeter*)ptr; + Rainmeter* rainmeter = (Rainmeter*) ptr; rainmeter->Finalize(); } diff --git a/Library/Exports_Section.cpp b/Library/Exports_Section.cpp index 50cad1c8..1e34da5e 100644 --- a/Library/Exports_Section.cpp +++ b/Library/Exports_Section.cpp @@ -2,130 +2,130 @@ #include "Exports_Common.h" #include "Section.h" -EXPORT bool Section_GetName (LPCWCHAR* result, int32_t handle) +EXPORT int Section_GetName(LPCWCHAR* result, int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { *result = section->GetName(); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_GetOriginalName (LPCWCHAR* result, int32_t handle) +EXPORT int Section_GetOriginalName(LPCWCHAR* result, int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { *result = section->GetOriginalName().c_str(); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_HasDynamicVariables (bool* result, int32_t handle) +EXPORT int Section_HasDynamicVariables(bool* result, int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { *result = section->HasDynamicVariables(); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_SetDynamicVariables (int32_t handle, bool value) +EXPORT int Section_SetDynamicVariables(int32_t handle, bool value) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { section->SetDynamicVariables(value); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_ResetUpdateCounter (int32_t handle) +EXPORT int Section_ResetUpdateCounter(int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { section->ResetUpdateCounter(); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_GetUpdateCounter (int* result, int32_t handle) +EXPORT int Section_GetUpdateCounter(int* result, int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { *result = section->GetUpdateCounter(); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_GetUpdateDivider (int* result, int32_t handle) +EXPORT int Section_GetUpdateDivider(int* result, int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { *result = section->GetUpdateDivider(); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_GetOnUpdateAction (LPCWCHAR* result, int32_t handle) +EXPORT int Section_GetOnUpdateAction(LPCWCHAR* result, int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { *result = section->GetOnUpdateAction().c_str(); - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_DoUpdateAction (int32_t handle) +EXPORT int Section_DoUpdateAction(int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { - section->DoUpdateAction (); - return true; + section->DoUpdateAction(); + return Results::Ok; } - return false; + return Results::InvalidHandle; } -EXPORT bool Section_Destroy (int32_t handle) +EXPORT int Section_Destroy(int32_t handle) { - Section* section = (Section*) handle_get_resource (handle); + Section* section = (Section*) handle_get_resource(handle); if (section != nullptr) { - handle_free (handle); + handle_free(handle); delete section; - return true; + return Results::Ok; } - return false; + return Results::InvalidHandle; } \ No newline at end of file diff --git a/Library/Library.vcxproj b/Library/Library.vcxproj index c83e061f..2353a396 100644 --- a/Library/Library.vcxproj +++ b/Library/Library.vcxproj @@ -1,172 +1,168 @@ - - - - - {BE9D2400-7F1C-49D6-8498-5CE495491AD6} - DynamicLibrary - Rainmeter - - - - - - - - - - - - - .\;lua/include;lua/lua;%(AdditionalIncludeDirectories) - _USRDLL;LIBRARY_EXPORTS;%(PreprocessorDefinitions) - Use - - - comctl32.lib;Wininet.lib;UxTheme.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;d2d1.lib;dwrite.lib;windowscodecs.lib;Version.lib;%(AdditionalDependencies) - Winmm.dll;Version.dll;d2d1.dll;dwrite.dll;$(DelayLoadTestDLL) - - - - - - - - - $(ExcludeTests) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(ExcludeTests) - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {19312085-aa51-4bd6-be92-4b6098cca539} - - - - - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6} - - - - - {6D61FBE9-6913-4885-A95D-1A8C0C223D82} - - - - - + + + + + {BE9D2400-7F1C-49D6-8498-5CE495491AD6} + DynamicLibrary + Rainmeter + + + + + + + + + + + + + .\;lua/include;lua/lua;%(AdditionalIncludeDirectories) + _USRDLL;LIBRARY_EXPORTS;%(PreprocessorDefinitions) + Use + + + comctl32.lib;Wininet.lib;UxTheme.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;d2d1.lib;dwrite.lib;windowscodecs.lib;Version.lib;%(AdditionalDependencies) + Winmm.dll;Version.dll;d2d1.dll;dwrite.dll;$(DelayLoadTestDLL) + + + + + + + + + $(ExcludeTests) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + CppHeader + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {19312085-aa51-4bd6-be92-4b6098cca539} + + + + + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6} + + + + + {6D61FBE9-6913-4885-A95D-1A8C0C223D82} + + + + + \ No newline at end of file diff --git a/Library/Library.vcxproj.filters b/Library/Library.vcxproj.filters index 540a7b85..17cc4629 100644 --- a/Library/Library.vcxproj.filters +++ b/Library/Library.vcxproj.filters @@ -1,358 +1,352 @@ - - - - - {976df8a7-1f37-4f6c-a341-22311ba418a3} - cpp;c;cxx;rc;def;r;odl;idl;hpj;bat - - - {d68c51de-41f6-4d17-8f8b-c03388b8c59d} - h;hpp;hxx;hm;inl - - - {2d6bf39d-48e1-4de3-8924-46c5666cb141} - ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - {6570e2b7-2e40-4fba-a051-01de85760fea} - - - {941dce28-a314-4492-befb-5770432c98bf} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Lua - - - Lua - - - Lua\glue - - - Lua\glue - - - Lua\glue - - - Lua\glue - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Lua - - - Lua - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Source Files - - + + + + + {976df8a7-1f37-4f6c-a341-22311ba418a3} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {d68c51de-41f6-4d17-8f8b-c03388b8c59d} + h;hpp;hxx;hm;inl + + + {2d6bf39d-48e1-4de3-8924-46c5666cb141} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {6570e2b7-2e40-4fba-a051-01de85760fea} + + + {941dce28-a314-4492-befb-5770432c98bf} + + + {86873eb6-7daf-4cde-b957-2c1bfc5aa066} + + + {2bd33bb1-d45c-4072-9ef2-cfa77bbf82df} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Lua + + + Lua + + + Lua\glue + + + Lua\glue + + + Lua\glue + + + Lua\glue + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Exports + + + Source Files\Exports + + + Source Files\Exports + + + Source Files\Exports + + + Source Files\Exports + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Lua + + + Lua + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\Exports + + + + + Resource Files + + + Resource Files + + + + + Source Files + + \ No newline at end of file diff --git a/Library/Litestep.cpp b/Library/Litestep.cpp index 6e83c537..731d9b3a 100644 --- a/Library/Litestep.cpp +++ b/Library/Litestep.cpp @@ -31,7 +31,7 @@ UINT GetUniqueID() WCHAR* GetString(UINT id) { LPWSTR pData; - int len = LoadString(GetRainmeter().GetResourceInstance(), id, (LPWSTR)&pData, 0); + int len = LoadString(GetRainmeter().GetModuleInstance(), id, (LPWSTR)&pData, 0); return len ? pData : L""; } diff --git a/Library/Logger.cpp b/Library/Logger.cpp index 4f077ed4..15758c7a 100644 --- a/Library/Logger.cpp +++ b/Library/Logger.cpp @@ -33,7 +33,7 @@ const size_t MAX_LOG_ENTIRES = 20; } // namespace Logger::Logger() : - m_LogToFile(false) + m_LoggerCallback (nullptr) { System::InitializeCriticalSection(&m_CsLog); System::InitializeCriticalSection(&m_CsLogDelay); @@ -51,56 +51,6 @@ Logger& Logger::GetInstance() return s_Logger; } -void Logger::StartLogFile() -{ - const WCHAR* filePath = m_LogFilePath.c_str(); - if (_waccess(filePath, 0) == -1) - { - // Create empty log file. - HANDLE file = CreateFile(filePath, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file != INVALID_HANDLE_VALUE) - { - CloseHandle(file); - } - else - { - const std::wstring text = GetFormattedString(ID_STR_LOGFILECREATEFAIL, filePath); - GetRainmeter().ShowMessage(nullptr, text.c_str(), MB_OK | MB_ICONERROR); - SetLogToFile(false); - return; - } - } - - SetLogToFile(true); -} - -void Logger::StopLogFile() -{ - SetLogToFile(false); -} - -void Logger::DeleteLogFile() -{ - const WCHAR* filePath = m_LogFilePath.c_str(); - if (_waccess(filePath, 0) != -1) - { - const std::wstring text = GetFormattedString(ID_STR_LOGFILEDELETE, filePath); - const int res = GetRainmeter().ShowMessage(nullptr, text.c_str(), MB_YESNO | MB_ICONQUESTION); - if (res == IDYES) - { - SetLogToFile(false); - System::RemoveFile(m_LogFilePath); - } - } -} - -void Logger::SetLogToFile(bool logToFile) -{ - m_LogToFile = logToFile; - WritePrivateProfileString( - L"Rainmeter", L"Logging", logToFile ? L"1" : L"0", GetRainmeter().GetIniFile().c_str()); -} - void Logger::LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg) { WCHAR timestampSz[128]; @@ -121,15 +71,11 @@ void Logger::LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, m_Entries.pop_front(); } - DialogAbout::AddLogItem(level, timestampSz, source, msg); - WriteToLogFile(entry); -} + // Call callback function + if (m_LoggerCallback != nullptr) + (*m_LoggerCallback)(entry.level, entry.timestamp.c_str(), source, msg); -void Logger::WriteToLogFile(Entry& entry) -{ -#ifndef _DEBUG - if (!m_LogToFile) return; -#endif +#ifdef _DEBUG const WCHAR* levelSz = (entry.level == Level::Error) ? L"ERRO" : @@ -146,26 +92,9 @@ void Logger::WriteToLogFile(Entry& entry) message += entry.message; message += L'\n'; -#ifdef _DEBUG - _RPTW0(_CRT_WARN, message.c_str()); - if (!m_LogToFile) return; -#endif + OutputDebugStringW (message.c_str ()); - const WCHAR* filePath = m_LogFilePath.c_str(); - if (_waccess(filePath, 0) == -1) - { - // The file has been deleted manually. - StopLogFile(); - } - else - { - FILE* file = _wfopen(filePath, L"a+, ccs=UTF-8"); - if (file) - { - fputws(message.c_str(), file); - fclose(file); - } - } +#endif } void Logger::Log(Level level, const WCHAR* source, const WCHAR* msg) diff --git a/Library/Logger.h b/Library/Logger.h index f8165ffa..3ddf7cf8 100644 --- a/Library/Logger.h +++ b/Library/Logger.h @@ -1,130 +1,120 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_LOGGER_H_ -#define RM_LOGGER_H_ - -#include -#include -#include -#include - -class Section; -class MeterWindow; - -// Singleton class to handle and store log messages and control the log file. -class Logger -{ -public: - enum class Level - { - Error = 1, - Warning = 2, - Notice = 3, - Debug = 4 - }; - - struct Entry - { - Level level; - std::wstring timestamp; - std::wstring source; - std::wstring message; - }; - - static Logger& GetInstance(); - - void SetLogFilePath(std::wstring path) { m_LogFilePath = path; } - - void StartLogFile(); - void StopLogFile(); - void DeleteLogFile(); - - bool IsLogToFile() { return m_LogToFile; } - void SetLogToFile(bool logToFile); - - void Log(Level level, const WCHAR* source, const WCHAR* msg); - void LogVF(Level level, const WCHAR* source, const WCHAR* format, va_list args); - void LogMeterWindowVF(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args); - void LogSection(Logger::Level level, Section* section, const WCHAR* message); - void LogSectionVF(Logger::Level level, Section* section, const WCHAR* format, va_list args); - - const std::wstring& GetLogFilePath() { return m_LogFilePath; } - - const std::list& GetEntries() { return m_Entries; } - -private: - void LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg); - - // Appends |entry| to the log file. - void WriteToLogFile(Entry& entry); - - Logger(); - ~Logger(); - - Logger(const Logger& other) = delete; - Logger& operator=(Logger other) = delete; - - bool m_LogToFile; - std::wstring m_LogFilePath; - - std::list m_Entries; - - CRITICAL_SECTION m_CsLog; - CRITICAL_SECTION m_CsLogDelay; -}; - -// Convenience functions. -inline Logger& GetLogger() { return Logger::GetInstance(); } - -#define RM_LOGGER_DEFINE_LOG_FUNCTIONS(name) \ - inline void Log ## name(const WCHAR* msg) \ - { \ - GetLogger().Log(Logger::Level::name, L"", msg); \ - } \ - \ - inline void Log ## name ## F(const WCHAR* format, ...) \ - { \ - va_list args; \ - va_start(args, format); \ - GetLogger().LogVF(Logger::Level::name, L"", format, args); \ - va_end(args); \ - } \ - \ - inline void Log ## name ## F(Section* section, const WCHAR* format, ...) \ - { \ - va_list args; \ - va_start(args, format); \ - GetLogger().LogSectionVF(Logger::Level::name, section, format, args); \ - va_end(args); \ - } \ - \ - inline void Log ## name ## F(MeterWindow* meterWindow, const WCHAR* format, ...) \ - { \ - va_list args; \ - va_start(args, format); \ - GetLogger().LogMeterWindowVF(Logger::Level::name, meterWindow, format, args); \ - va_end(args); \ - } - -RM_LOGGER_DEFINE_LOG_FUNCTIONS(Error) -RM_LOGGER_DEFINE_LOG_FUNCTIONS(Warning) -RM_LOGGER_DEFINE_LOG_FUNCTIONS(Notice) -RM_LOGGER_DEFINE_LOG_FUNCTIONS(Debug) - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_LOGGER_H_ +#define RM_LOGGER_H_ + +#include +#include +#include +#include + +class Section; +class MeterWindow; + +// Singleton class to handle and store log messages and control the log file. +class Logger +{ +public: + enum class Level + { + Error = 1, + Warning = 2, + Notice = 3, + Debug = 4 + }; + + struct Entry + { + Level level; + std::wstring timestamp; + std::wstring source; + std::wstring message; + }; + + static Logger& GetInstance(); + + typedef void (*LoggerCallback) (Level level, LPCWSTR timestamp, LPCWSTR source, LPCWSTR message); + + void SetLogCallback(LoggerCallback callback) { m_LoggerCallback = callback; } + + void Log(Level level, const WCHAR* source, const WCHAR* msg); + void LogVF(Level level, const WCHAR* source, const WCHAR* format, va_list args); + void LogMeterWindowVF(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args); + void LogSection(Logger::Level level, Section* section, const WCHAR* message); + void LogSectionVF(Logger::Level level, Section* section, const WCHAR* format, va_list args); + + const std::list& GetEntries() { return m_Entries; } + +private: + void LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg); + + Logger(); + ~Logger(); + + Logger(const Logger& other) = delete; + Logger& operator=(Logger other) = delete; + + bool m_LogToFile; + LoggerCallback m_LoggerCallback; + + std::list m_Entries; + + CRITICAL_SECTION m_CsLog; + CRITICAL_SECTION m_CsLogDelay; +}; + +// Convenience functions. +inline Logger& GetLogger() { return Logger::GetInstance(); } + +#define RM_LOGGER_DEFINE_LOG_FUNCTIONS(name) \ + inline void Log ## name(const WCHAR* msg) \ + { \ + GetLogger().Log(Logger::Level::name, L"", msg); \ + } \ + \ + inline void Log ## name ## F(const WCHAR* format, ...) \ + { \ + va_list args; \ + va_start(args, format); \ + GetLogger().LogVF(Logger::Level::name, L"", format, args); \ + va_end(args); \ + } \ + \ + inline void Log ## name ## F(Section* section, const WCHAR* format, ...) \ + { \ + va_list args; \ + va_start(args, format); \ + GetLogger().LogSectionVF(Logger::Level::name, section, format, args); \ + va_end(args); \ + } \ + \ + inline void Log ## name ## F(MeterWindow* meterWindow, const WCHAR* format, ...) \ + { \ + va_list args; \ + va_start(args, format); \ + GetLogger().LogMeterWindowVF(Logger::Level::name, meterWindow, format, args); \ + va_end(args); \ + } + +RM_LOGGER_DEFINE_LOG_FUNCTIONS(Error) +RM_LOGGER_DEFINE_LOG_FUNCTIONS(Warning) +RM_LOGGER_DEFINE_LOG_FUNCTIONS(Notice) +RM_LOGGER_DEFINE_LOG_FUNCTIONS(Debug) + #endif \ No newline at end of file diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index 2168af44..2ce8f433 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -19,13 +19,10 @@ #include "StdAfx.h" #include "MeterWindow.h" #include "Rainmeter.h" -#include "TrayWindow.h" #include "System.h" #include "Error.h" #include "Meter.h" #include "Measure.h" -#include "DialogAbout.h" -#include "DialogManage.h" #include "resource.h" #include "Litestep.h" #include "MeasureCalc.h" @@ -414,7 +411,7 @@ void MeterWindow::Refresh(bool init, bool all) if (!ReadSkin()) { - GetRainmeter().DeactivateSkin(this, -1); + GetRainmeter().DeactivateSkin(this); return; } @@ -798,7 +795,7 @@ void MeterWindow::DoBang(Bang bang, const std::vector& args) case Bang::UpdateMeasure: UpdateMeasure(args[0]); - DialogAbout::UpdateMeasures(this); + // TODO: update measure callback break; case Bang::DisableMeasureGroup: @@ -827,7 +824,7 @@ void MeterWindow::DoBang(Bang bang, const std::vector& args) case Bang::UpdateMeasureGroup: UpdateMeasure(args[0], true); - DialogAbout::UpdateMeasures(this); + // DialogAbout::UpdateMeasures(this); break; case Bang::Show: @@ -1880,7 +1877,7 @@ void MeterWindow::ScreenToWindow() */ void MeterWindow::ReadOptions() { - WCHAR buffer[32]; + /*WCHAR buffer[32]; const WCHAR* section = m_FolderPath.c_str(); ConfigParser parser; @@ -1953,7 +1950,7 @@ void MeterWindow::ReadOptions() } // Set WindowXScreen/WindowYScreen temporarily - WindowToScreen(); + WindowToScreen();*/ } /* @@ -1962,7 +1959,7 @@ void MeterWindow::ReadOptions() */ void MeterWindow::WriteOptions(INT setting) { - const WCHAR* iniFile = GetRainmeter().GetIniFile().c_str(); + /*const WCHAR* iniFile = GetRainmeter().GetIniFile().c_str(); if (*iniFile) { @@ -1971,7 +1968,7 @@ void MeterWindow::WriteOptions(INT setting) if (setting != OPTION_ALL) { - DialogManage::UpdateSkins(this); + //DialogManage::UpdateSkins(this); } if (setting & OPTION_POSITION) @@ -2046,7 +2043,7 @@ void MeterWindow::WriteOptions(INT setting) { WritePrivateProfileString(section, L"UseD2D", m_UseD2D ? L"1" : L"0", iniFile); } - } + }*/ } /* @@ -2063,7 +2060,7 @@ bool MeterWindow::ReadSkin() if (_waccess(iniFile.c_str(), 0) == -1) { std::wstring message = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, m_FolderPath.c_str(), m_FileName.c_str()); - GetRainmeter().ShowMessage(m_Window, message.c_str(), MB_OK | MB_ICONEXCLAMATION); + // unsupported: GetRainmeter().ShowMessage(m_Window, message.c_str(), MB_OK | MB_ICONEXCLAMATION); return false; } @@ -2095,8 +2092,7 @@ bool MeterWindow::ReadSkin() _snwprintf_s(buffer, _TRUNCATE, L"%u.%u", appVersion / 1000000, (appVersion / 1000) % 1000); } - std::wstring text = GetFormattedString(ID_STR_NEWVERSIONREQUIRED, m_FolderPath.c_str(), m_FileName.c_str(), buffer); - GetRainmeter().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONEXCLAMATION); + // TODO: throw error or something return false; } @@ -2234,7 +2230,7 @@ bool MeterWindow::ReadSkin() do { // Try program folder first - std::wstring szFontFile = GetRainmeter().GetPath() + L"Fonts\\"; + std::wstring szFontFile = GetRainmeter().GetWorkDirectory() + L"Fonts\\"; szFontFile += localFont; if (!m_FontCollection->AddFile(szFontFile.c_str())) { @@ -2310,7 +2306,7 @@ bool MeterWindow::ReadSkin() if (m_Meters.empty()) { std::wstring text = GetFormattedString(ID_STR_NOMETERSINSKIN, m_FolderPath.c_str(), m_FileName.c_str()); - GetRainmeter().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONEXCLAMATION); + // Unsupported: GetRainmeter().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONEXCLAMATION); return false; } @@ -2767,7 +2763,7 @@ void MeterWindow::Update(bool refresh) } } - DialogAbout::UpdateMeasures(this); + // TODO: call update measures callback // Update all meters bool bActiveTransition = false; @@ -2792,12 +2788,7 @@ void MeterWindow::Update(bool refresh) SetResizeWindowMode(RESIZEMODE_CHECK); } - // If our option is to disable when in an RDP session, then check if in an RDP session. - // Only redraw if we are not in a remote session - if (GetRainmeter().IsRedrawable()) - { - Redraw(); - } + Redraw(); } // Post-updates @@ -3391,22 +3382,10 @@ LRESULT MeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (wParam) { - case IDM_SKIN_EDITSKIN: - GetRainmeter().EditSkinFile(m_FolderPath, m_FileName); - break; - case IDM_SKIN_REFRESH: Refresh(false); break; - case IDM_SKIN_OPENSKINSFOLDER: - GetRainmeter().OpenSkinFolder(m_FolderPath); - break; - - case IDM_SKIN_MANAGESKIN: - DialogManage::OpenSkin(this); - break; - case IDM_SKIN_VERYTOPMOST: SetWindowZPosition(ZPOSITION_ONTOPMOST); break; @@ -3466,7 +3445,7 @@ LRESULT MeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) case IDM_CLOSESKIN: if (m_State != STATE_CLOSING) { - GetRainmeter().DeactivateSkin(this, -1); + GetRainmeter().DeactivateSkin(this); } break; @@ -3559,20 +3538,6 @@ LRESULT MeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) GetRainmeter().ExecuteCommand(action.c_str(), this); } } - else - { - // Forward to tray window, which handles all the other commands - HWND tray = GetRainmeter().GetTrayWindow()->GetWindow(); - - if (wParam == IDM_QUIT) - { - PostMessage(tray, WM_COMMAND, wParam, lParam); - } - else - { - SendMessage(tray, WM_COMMAND, wParam, lParam); - } - } break; } @@ -3667,7 +3632,7 @@ void MeterWindow::SavePositionIfAppropriate() else { ScreenToWindow(); - DialogManage::UpdateSkins(this); + // TODO: call update skins callback } } diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index d9166c24..7056c3d0 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -14,74 +14,47 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ + */ #include "StdAfx.h" #include "../Common/PathUtil.h" #include "Rainmeter.h" -#include "TrayWindow.h" #include "System.h" #include "Error.h" -#include "DialogAbout.h" -#include "DialogManage.h" #include "MeasureNet.h" #include "MeasureCPU.h" #include "MeterString.h" -#include "UpdateCheck.h" #include "../Version.h" using namespace Gdiplus; enum TIMER { - TIMER_NETSTATS = 1 + TIMER_NETSTATS = 1 }; enum INTERVAL { INTERVAL_NETSTATS = 120000 }; -/* -** Initializes Rainmeter. -** -*/ -int RainmeterMain(LPWSTR cmdLine) -{ - auto& rainmeter = GetRainmeter(); - int ret = rainmeter.Initialize(nullptr, nullptr); - if (ret == 0) - { - ret = rainmeter.MessagePump(); - } - rainmeter.Finalize(); - - return ret; -} - /* ** Constructor ** */ Rainmeter::Rainmeter() : - m_TrayWindow(), - m_UseD2D(true), - m_Debug(false), - m_DisableVersionCheck(false), - m_NewVersion(false), - m_DesktopWorkAreaChanged(false), - m_DesktopWorkAreaType(false), - m_NormalStayDesktop(true), - m_DisableRDP(false), - m_DisableDragging(false), - m_CurrentParser(), - m_Window(), - m_Mutex(), - m_Instance(), - m_ResourceInstance(), - m_ResourceLCID(), - m_GDIplusToken(), - m_GlobalOptions() +m_UseD2D(true), +m_Debug(false), +m_DesktopWorkAreaChanged(false), +m_DesktopWorkAreaType(false), +m_NormalStayDesktop(true), +m_DisableDragging(false), +m_CurrentParser(), +m_Window(), +m_Mutex(), +m_Instance(), +m_GDIplusToken(), +m_GlobalOptions() { CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); @@ -103,7 +76,7 @@ Rainmeter::~Rainmeter() GdiplusShutdown(m_GDIplusToken); } -Rainmeter& GetRainmeter() +Rainmeter& Rainmeter::GetInstance() { static Rainmeter s_Rainmeter; return s_Rainmeter; @@ -113,59 +86,14 @@ Rainmeter& GetRainmeter() ** The main initialization function for the module. ** */ -int Rainmeter::Initialize(LPCWSTR iniPath, LPCWSTR layout) +int Rainmeter::Initialize() { m_Instance = GetModuleHandle(L"Rainmeter"); + m_UseCurrentDirectory = true; - WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; - GetModuleFileName(m_Instance, buffer, MAX_LINE_LENGTH); - - // Remove the module's name from the path - WCHAR* pos = wcsrchr(buffer, L'\\'); - m_Path.assign(buffer, pos ? pos - buffer + 1 : 0); - m_Drive = PathUtil::GetVolume(m_Path); - - bool bDefaultIniLocation = false; - if (iniPath) - { - // The command line defines the location of Rainmeter.ini (or whatever it calls it). - std::wstring iniFile = iniPath; - PathUtil::ExpandEnvironmentVariables(iniFile); - - if (iniFile.empty() || PathUtil::IsSeparator(iniFile[iniFile.length() - 1])) - { - iniFile += L"Rainmeter.ini"; - } - else if (iniFile.length() <= 4 || _wcsicmp(iniFile.c_str() + (iniFile.length() - 4), L".ini") != 0) - { - iniFile += L"\\Rainmeter.ini"; - } - - if (!PathUtil::IsSeparator(iniFile[0]) && iniFile.find_first_of(L':') == std::wstring::npos) - { - // Make absolute path - iniFile.insert(0, m_Path); - } - - m_IniFile = iniFile; - bDefaultIniLocation = true; - } - else - { - m_IniFile = m_Path; - m_IniFile += L"Rainmeter.ini"; - - // If the ini file doesn't exist in the program folder store it to the %APPDATA% instead so that things work better in Vista/Win7 - if (_waccess(m_IniFile.c_str(), 0) == -1) - { - m_IniFile = L"%APPDATA%\\Rainmeter\\Rainmeter.ini"; - PathUtil::ExpandEnvironmentVariables(m_IniFile); - bDefaultIniLocation = true; - } - } - + // Create a window WNDCLASS wc = {0}; - wc.lpfnWndProc = (WNDPROC)MainWndProc; + wc.lpfnWndProc = (WNDPROC) MainWndProc; wc.hInstance = m_Instance; wc.lpszClassName = RAINMETER_CLASS_NAME; ATOM className = RegisterClass(&wc); @@ -186,151 +114,21 @@ int Rainmeter::Initialize(LPCWSTR iniPath, LPCWSTR layout) if (!m_Window) return 1; + // Set up logger Logger& logger = GetLogger(); - const WCHAR* iniFile = m_IniFile.c_str(); - // Set file locations - { - m_SettingsPath = PathUtil::GetFolderFromFilePath(m_IniFile); - - size_t len = m_IniFile.length(); - if (len > 4 && _wcsicmp(iniFile + (len - 4), L".ini") == 0) - { - len -= 4; - } - - std::wstring logFile(m_IniFile, 0, len); - m_DataFile = m_StatsFile = logFile; - logFile += L".log"; - m_StatsFile += L".stats"; - m_DataFile += L".data"; - - logger.SetLogFilePath(logFile); - } - - // Create a default Rainmeter.ini file if needed - if (_waccess(iniFile, 0) == -1) - { - CreateOptionsFile(); - } - - bool dataFileCreated = false; - if (_waccess(m_DataFile.c_str(), 0) == -1) - { - dataFileCreated = true; - CreateDataFile(); - } - - // Reset log file - System::RemoveFile(logger.GetLogFilePath()); - - m_Debug = 0!=GetPrivateProfileInt(L"Rainmeter", L"Debug", 0, iniFile); - - const bool logging = GetPrivateProfileInt(L"Rainmeter", L"Logging", 0, iniFile) != 0; - logger.SetLogToFile(logging); - if (logging) - { - logger.StartLogFile(); - } - - // Determine the language resource to load - std::wstring resource = m_Path + L"Languages\\"; - if (GetPrivateProfileString(L"Rainmeter", L"Language", L"", buffer, MAX_LINE_LENGTH, iniFile) == 0) - { - // Use whatever the user selected for the installer - DWORD size = MAX_LINE_LENGTH; - HKEY hKey; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Rainmeter", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS) - { - DWORD type = 0; - if (RegQueryValueEx(hKey, L"Language", nullptr, &type, (LPBYTE)buffer, (LPDWORD)&size) != ERROR_SUCCESS || - type != REG_SZ) - { - buffer[0] = L'\0'; - } - RegCloseKey(hKey); - } - } - if (buffer[0] != L'\0') - { - // Try selected language - m_ResourceLCID = wcstoul(buffer, nullptr, 10); - resource += buffer; - resource += L".dll"; - - m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); - } - if (!m_ResourceInstance) - { - // Try English - resource = m_Path; - resource += L"Languages\\1033.dll"; - m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); - m_ResourceLCID = 1033; - if (!m_ResourceInstance) - { - MessageBox(nullptr, L"Unable to load language library", APPNAME, MB_OK | MB_TOPMOST | MB_ICONERROR); - return 1; - } - } - - // Get skin folder path - size_t len = GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, iniFile); - if (len > 0 && - _waccess(buffer, 0) != -1) // Temporary fix - { - // Try Rainmeter.ini first - m_SkinPath.assign(buffer, len); - PathUtil::ExpandEnvironmentVariables(m_SkinPath); - PathUtil::AppendBacklashIfMissing(m_SkinPath); - } - else if (bDefaultIniLocation && - SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, buffer))) - { - // Use My Documents/Rainmeter/Skins - m_SkinPath = buffer; - m_SkinPath += L"\\Rainmeter\\"; - CreateDirectory(m_SkinPath.c_str(), nullptr); - m_SkinPath += L"Skins\\"; - - WritePrivateProfileString(L"Rainmeter", L"SkinPath", m_SkinPath.c_str(), iniFile); - } - else - { - m_SkinPath = m_Path + L"Skins\\"; - } + // TODO: figure if we need language library // Create user skins, layouts, addons, and plugins folders if needed - CreateComponentFolders(bDefaultIniLocation); - - delete [] buffer; - buffer = nullptr; - - LogNoticeF(L"Path: %s", m_Path.c_str()); - LogNoticeF(L"IniFile: %s", iniFile); - LogNoticeF(L"SkinPath: %s", m_SkinPath.c_str()); - - // Test that the Rainmeter.ini file is writable - TestSettingsFile(bDefaultIniLocation); + LogNoticeF(L"Path: %s", GetWorkDirectory().c_str()); + // Initialize static stuff System::Initialize(m_Instance); MeasureNet::InitializeStatic(); MeasureCPU::InitializeStatic(); MeterString::InitializeStatic(); - // Tray must exist before skins are read - m_TrayWindow = new TrayWindow(); - m_TrayWindow->Initialize(); - - ReloadSettings(); - - if (m_SkinRegistry.IsEmpty()) - { - std::wstring error = GetFormattedString(ID_STR_NOAVAILABLESKINS, m_SkinPath.c_str()); - ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONERROR); - } - ResetStats(); ReadStats(); @@ -340,27 +138,6 @@ int Rainmeter::Initialize(LPCWSTR iniPath, LPCWSTR layout) UpdateDesktopWorkArea(false); } - bool layoutLoaded = false; - if (layout) - { - std::vector args = CommandHandler::ParseString(layout); - layoutLoaded = (args.size() == 1 && LoadLayout(args[0])); - } - - if (!layoutLoaded) - { - ActivateActiveSkins(); - } - - if (dataFileCreated) - { - m_TrayWindow->ShowWelcomeNotification(); - } - else if (!m_DisableVersionCheck) - { - CheckUpdate(); - } - return 0; // All is OK } @@ -372,8 +149,6 @@ void Rainmeter::Finalize() DeleteAllMeterWindows(); DeleteAllUnmanagedMeterWindows(); // Redelete unmanaged windows caused by OnCloseAction - delete m_TrayWindow; - System::Finalize(); MeasureNet::UpdateIFTable(); @@ -390,7 +165,6 @@ void Rainmeter::Finalize() UpdateDesktopWorkArea(true); } - if (m_ResourceInstance) FreeLibrary(m_ResourceInstance); if (m_Mutex) ReleaseMutex(m_Mutex); } @@ -407,70 +181,67 @@ int Rainmeter::MessagePump() break; } - if (!Dialog::HandleMessage(msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + TranslateMessage(&msg); + DispatchMessage(&msg); } - return (int)msg.wParam; + return (int) msg.wParam; } LRESULT CALLBACK Rainmeter::MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { - case WM_DESTROY: - PostQuitMessage(0); - break; + case WM_DESTROY: + PostQuitMessage(0); + break; - case WM_COPYDATA: + case WM_COPYDATA: { - COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; + COPYDATASTRUCT* cds = (COPYDATASTRUCT*) lParam; if (cds) { - const WCHAR* data = (const WCHAR*)cds->lpData; + const WCHAR* data = (const WCHAR*) cds->lpData; if (cds->dwData == 1 && (cds->cbData > 0)) { GetRainmeter().DelayedExecuteCommand(data); } } } - break; + break; - case WM_TIMER: - if (wParam == TIMER_NETSTATS) - { - MeasureNet::UpdateIFTable(); - MeasureNet::UpdateStats(); - GetRainmeter().WriteStats(false); - } - break; + case WM_TIMER: + if (wParam == TIMER_NETSTATS) + { + MeasureNet::UpdateIFTable(); + MeasureNet::UpdateStats(); + GetRainmeter().WriteStats(false); + } + break; - case WM_RAINMETER_DELAYED_REFRESH_ALL: - GetRainmeter().RefreshAll(); - break; + case WM_RAINMETER_DELAYED_REFRESH_ALL: + GetRainmeter().RefreshAll(); + break; - case WM_RAINMETER_DELAYED_EXECUTE: - if (lParam) - { - // Execute bang - WCHAR* bang = (WCHAR*)lParam; - GetRainmeter().ExecuteCommand(bang, nullptr); - free(bang); // _wcsdup() - } - break; + case WM_RAINMETER_DELAYED_EXECUTE: + if (lParam) + { + // Execute bang + WCHAR* bang = (WCHAR*) lParam; + GetRainmeter().ExecuteCommand(bang, nullptr); + free(bang); // _wcsdup() + } + break; - case WM_RAINMETER_EXECUTE: - if (GetRainmeter().HasMeterWindow((MeterWindow*)wParam)) - { - GetRainmeter().ExecuteCommand((const WCHAR*)lParam, (MeterWindow*)wParam); - } - break; + case WM_RAINMETER_EXECUTE: + if (GetRainmeter().HasMeterWindow((MeterWindow*) wParam)) + { + GetRainmeter().ExecuteCommand((const WCHAR*) lParam, (MeterWindow*) wParam); + } + break; - default: - return DefWindowProc(hWnd, uMsg, wParam, lParam); + default: + return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; @@ -481,393 +252,70 @@ void Rainmeter::SetNetworkStatisticsTimer() static bool set = SetTimer(m_Window, TIMER_NETSTATS, INTERVAL_NETSTATS, nullptr) != 0; } -void Rainmeter::CreateOptionsFile() +void Rainmeter::ActivateSkin(std::wstring file) { - CreateDirectory(m_SettingsPath.c_str(), nullptr); + file = NormalizePath(file); - std::wstring defaultIni = GetDefaultLayoutPath(); - defaultIni += L"illustro default\\Rainmeter.ini"; - System::CopyFiles(defaultIni, m_IniFile); -} - -void Rainmeter::CreateDataFile() -{ - std::wstring tmpSz = m_SettingsPath + L"Plugins.ini"; - - const WCHAR* pluginsFile = tmpSz.c_str(); - const WCHAR* dataFile = m_DataFile.c_str(); - - if (_waccess(pluginsFile, 0) == 0) + // Verify that the skin is not already active + std::map::const_iterator iter = m_MeterWindows.find(file); + if (iter != m_MeterWindows.end()) { - MoveFile(pluginsFile, dataFile); - } - else - { - // Create empty file - HANDLE file = CreateFile(dataFile, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file != INVALID_HANDLE_VALUE) + if (wcscmp(((*iter).second)->GetFileName().c_str(), file.c_str()) == 0) { - CloseHandle(file); - } - } -} - -void Rainmeter::CreateComponentFolders(bool defaultIniLocation) -{ - std::wstring path; - - if (CreateDirectory(m_SkinPath.c_str(), nullptr)) - { - // Folder just created, so copy default skins there - std::wstring from = GetDefaultSkinPath(); - from += L"*.*"; - System::CopyFiles(from, m_SkinPath); - } - else - { - path = m_SkinPath; - path += L"Backup"; - if (_waccess(path.c_str(), 0) != -1) - { - std::wstring newPath = m_SkinPath + L"@Backup"; - MoveFile(path.c_str(), newPath.c_str()); - } - } - - path = GetLayoutPath(); - if (_waccess(path.c_str(), 0) == -1) - { - std::wstring themesPath = m_SettingsPath + L"Themes"; - if (_waccess(themesPath.c_str(), 0) != -1) - { - // Migrate Themes into Layouts for backwards compatibility and rename - // Rainmeter.thm to Rainmeter.ini and RainThemes.bmp to Wallpaper.bmp. - MoveFile(themesPath.c_str(), path.c_str()); - - path += L'*'; // For FindFirstFile. - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFile(path.c_str(), &fd); - path.pop_back(); // Remove '*'. - - if (hFind != INVALID_HANDLE_VALUE) - { - do - { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && - PathUtil::IsDotOrDotDot(fd.cFileName)) - { - std::wstring layoutFolder = path + fd.cFileName; - layoutFolder += L'\\'; - - std::wstring file = layoutFolder + L"Rainmeter.thm"; - if (_waccess(file.c_str(), 0) != -1) - { - std::wstring newFile = layoutFolder + L"Rainmeter.ini"; - MoveFile(file.c_str(), newFile.c_str()); - } - - file = layoutFolder + L"RainThemes.bmp"; - if (_waccess(file.c_str(), 0) != -1) - { - std::wstring newFile = layoutFolder + L"Wallpaper.bmp"; - MoveFile(file.c_str(), newFile.c_str()); - } - } - } - while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - } + LogWarningF((*iter).second, L"!ActivateConfig: \"%s\" already active", file.c_str()); + return; } else { - std::wstring from = GetDefaultLayoutPath(); - if (_waccess(from.c_str(), 0) != -1) - { - System::CopyFiles(from, m_SettingsPath); - } + // Deactivate the existing skin + DeactivateSkin((*iter).second); } } - else + + // Verify whether the ini-file exists + if (_waccess(file.c_str(), 0) == -1) { - path += L"Backup"; - if (_waccess(path.c_str(), 0) != -1) - { - std::wstring newPath = GetLayoutPath(); - newPath += L"@Backup"; - MoveFile(path.c_str(), newPath.c_str()); - } + throw std::exception("Skin file not found"); } - if (defaultIniLocation) - { - path = GetUserPluginPath(); - if (_waccess(path.c_str(), 0) == -1) - { - std::wstring from = GetDefaultPluginPath(); - if (_waccess(from.c_str(), 0) != -1) - { - System::CopyFiles(from, m_SettingsPath); - } - } - - path = GetAddonPath(); - if (_waccess(path.c_str(), 0) == -1) - { - std::wstring from = GetDefaultAddonPath(); - if (_waccess(from.c_str(), 0) != -1) - { - System::CopyFiles(from, m_SettingsPath); - } - } - - path = m_SettingsPath; - path += L"Rainmeter.exe"; - const WCHAR* pathSz = path.c_str(); - if (_waccess(pathSz, 0) == -1) - { - // Create a hidden stub Rainmeter.exe into SettingsPath for old addon - // using relative path to Rainmeter.exe - std::wstring from = m_Path + L"Rainmeter.exe"; - System::CopyFiles(from, path); - - // Get rid of all resources from the stub executable - HANDLE stub = BeginUpdateResource(pathSz, TRUE); - - // Add the manifest of Rainmeter.dll to the stub - HRSRC manifest = FindResource(m_Instance, MAKEINTRESOURCE(2), RT_MANIFEST); - DWORD manifestSize = SizeofResource(m_Instance, manifest); - HGLOBAL manifestLoad = LoadResource(m_Instance, manifest); - void* manifestLoadData = LockResource(manifestLoad); - if (manifestLoadData) - { - LANGID langID = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); - UpdateResource(stub, RT_MANIFEST, MAKEINTRESOURCE(1), langID, manifestLoadData, manifestSize); - } - - EndUpdateResource(stub, FALSE); - SetFileAttributes(pathSz, FILE_ATTRIBUTE_HIDDEN); - } - } + CreateMeterWindow(file); } -void Rainmeter::ReloadSettings() +void Rainmeter::DeactivateSkin(MeterWindow* meterWindow) { - ScanForSkins(); - ScanForLayouts(); - ReadGeneralSettings(m_IniFile); -} - -void Rainmeter::EditSettings() -{ - std::wstring file = L'"' + m_IniFile; - file += L'"'; - CommandHandler::RunFile(m_SkinEditor.c_str(), file.c_str()); -} - -void Rainmeter::EditSkinFile(const std::wstring& name, const std::wstring& iniFile) -{ - std::wstring args = L'"' + m_SkinPath; - args += name; - args += L'\\'; - args += iniFile; - args += L'"'; - CommandHandler::RunFile(m_SkinEditor.c_str(), args.c_str()); -} - -void Rainmeter::OpenSkinFolder(const std::wstring& name) -{ - std::wstring folderPath = m_SkinPath + name; - CommandHandler::RunFile(folderPath.c_str()); -} - -void Rainmeter::ActivateActiveSkins() -{ - std::multimap::const_iterator iter = m_SkinOrders.begin(); - for ( ; iter != m_SkinOrders.end(); ++iter) - { - const SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder((*iter).second); - if (skinFolder.active > 0 && skinFolder.active <= (uint16_t)skinFolder.files.size()) - { - ActivateSkin((*iter).second, skinFolder.active - 1); - } - } -} - -/* -** Activates the skin, or, if it is already active, the next variant of the skin. Returns true -** if the skin was activated (or was already active). -*/ -bool Rainmeter::ActivateSkin(const std::wstring& folderPath) -{ - const int index = m_SkinRegistry.FindFolderIndex(folderPath); - if (index != -1) - { - const SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); - if (!(skinFolder.active == 1 && skinFolder.files.size() == 1)) - { - // Activate the next index. - ActivateSkin( - index, (skinFolder.active < skinFolder.files.size()) ? skinFolder.active : 0); - } - - return true; - } - - return false; -} - -/* -** Activates the skin, or, if it is already active, the next variant of the skin. Returns true -** if the skin was activated (or was already active). -*/ -bool Rainmeter::ActivateSkin(const std::wstring& folderPath, const std::wstring& file) -{ - const SkinRegistry::Indexes indexes = m_SkinRegistry.FindIndexes(folderPath, file); - if (indexes.IsValid()) - { - ActivateSkin(indexes.folder, indexes.file); - return true; - } - - return false; -} - -void Rainmeter::ActivateSkin(int folderIndex, int fileIndex) -{ - if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount() && - fileIndex >= 0 && fileIndex < m_SkinRegistry.GetFolder(folderIndex).files.size()) - { - auto& skinFolder = m_SkinRegistry.GetFolder(folderIndex); - const std::wstring& file = skinFolder.files[fileIndex]; - const WCHAR* fileSz = file.c_str(); - - std::wstring folderPath = m_SkinRegistry.GetFolderPath(folderIndex); - - // Verify that the skin is not already active - std::map::const_iterator iter = m_MeterWindows.find(folderPath); - if (iter != m_MeterWindows.end()) - { - if (wcscmp(((*iter).second)->GetFileName().c_str(), fileSz) == 0) - { - LogWarningF((*iter).second, L"!ActivateConfig: \"%s\" already active", folderPath.c_str()); - return; - } - else - { - // Deactivate the existing skin - DeactivateSkin((*iter).second, folderIndex); - } - } - - // Verify whether the ini-file exists - std::wstring skinIniPath = m_SkinPath + folderPath; - skinIniPath += L'\\'; - skinIniPath += file; - - if (_waccess(skinIniPath.c_str(), 0) == -1) - { - std::wstring message = GetFormattedString(ID_STR_UNABLETOACTIVATESKIN, folderPath.c_str(), fileSz); - ShowMessage(nullptr, message.c_str(), MB_OK | MB_ICONEXCLAMATION); - return; - } - - if (skinFolder.active != fileIndex + 1) - { - // Write only if changed. - skinFolder.active = fileIndex + 1; - WriteActive(folderPath, fileIndex); - } - - CreateMeterWindow(folderPath, file); - } -} - -void Rainmeter::DeactivateSkin(MeterWindow* meterWindow, int folderIndex, bool save) -{ - if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount()) - { - m_SkinRegistry.GetFolder(folderIndex).active = 0; // Deactivate the skin - } - else if (folderIndex == -1 && meterWindow) - { - SkinRegistry::Folder* folder = m_SkinRegistry.FindFolder(meterWindow->GetFolderPath()); - if (folder) - { - folder->active = 0; - } - } - if (meterWindow) { - if (save) - { - // Disable the skin in the ini-file - WriteActive(meterWindow->GetFolderPath(), -1); - } - meterWindow->Deactivate(); } } -void Rainmeter::ToggleSkin(int folderIndex, int fileIndex) +void Rainmeter::ToggleSkin(std::wstring file) { - if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount() && - fileIndex >= 0 && fileIndex < m_SkinRegistry.GetFolder(folderIndex).files.size()) + file = GetAbsolutePath(file); + std::wstring folder = PathUtil::GetFolderFromFilePath(file); + + MeterWindow* meterWindow = GetMeterWindow(file); + + if (meterWindow) { - if (m_SkinRegistry.GetFolder(folderIndex).active == fileIndex + 1) - { - MeterWindow* meterWindow = GetMeterWindow(m_SkinRegistry.GetFolderPath(folderIndex)); - DeactivateSkin(meterWindow, folderIndex); - } - else - { - ActivateSkin(folderIndex, fileIndex); - } + DeactivateSkin(meterWindow); + } + else + { + ActivateSkin(file); } } -void Rainmeter::ToggleSkinWithID(UINT id) +void Rainmeter::CreateMeterWindow(std::wstring file) { - const SkinRegistry::Indexes indexes = m_SkinRegistry.FindIndexesForID(id); - if (indexes.IsValid()) - { - ToggleSkin(indexes.folder, indexes.file); - } -} - -void Rainmeter::SetSkinPath(const std::wstring& skinPath) -{ - WritePrivateProfileString(L"Rainmeter", L"SkinPath", skinPath.c_str(), m_IniFile.c_str()); -} - -void Rainmeter::SetSkinEditor(const std::wstring& path) -{ - if (!path.empty()) - { - m_SkinEditor = path; - WritePrivateProfileString(L"Rainmeter", L"ConfigEditor", path.c_str(), m_IniFile.c_str()); - } -} - -void Rainmeter::WriteActive(const std::wstring& folderPath, int fileIndex) -{ - WCHAR buffer[32]; - _itow_s(fileIndex + 1, buffer, 10); - WritePrivateProfileString(folderPath.c_str(), L"Active", buffer, m_IniFile.c_str()); -} - -void Rainmeter::CreateMeterWindow(const std::wstring& folderPath, const std::wstring& file) -{ - MeterWindow* mw = new MeterWindow(folderPath, file); + file = NormalizePath(file); + std::wstring folder = PathUtil::GetFolderFromFilePath(file); + MeterWindow* mw = new MeterWindow(folder, file.substr(folder.size())); //TODO: temporary workaround // Note: May modify existing key - m_MeterWindows[folderPath] = mw; + m_MeterWindows[file] = mw; mw->Initialize(); - - DialogAbout::UpdateSkins(); - DialogManage::UpdateSkins(mw); } void Rainmeter::DeleteAllMeterWindows() @@ -878,7 +326,6 @@ void Rainmeter::DeleteAllMeterWindows() MeterWindow* mw = (*it).second; m_MeterWindows.erase(it); // Remove before deleting MeterWindow - DialogManage::UpdateSkins(mw, true); delete mw; // Get next valid iterator (Fix for iterator invalidation caused by OnCloseAction) @@ -886,7 +333,6 @@ void Rainmeter::DeleteAllMeterWindows() } m_MeterWindows.clear(); - DialogAbout::UpdateSkins(); } void Rainmeter::DeleteAllUnmanagedMeterWindows() @@ -910,9 +356,7 @@ void Rainmeter::RemoveMeterWindow(MeterWindow* meterWindow) if ((*it).second == meterWindow) { m_MeterWindows.erase(it); - DialogManage::UpdateSkins(meterWindow, true); - DialogAbout::UpdateSkins(); - break; + return; } } } @@ -959,39 +403,13 @@ bool Rainmeter::HasMeterWindow(const MeterWindow* meterWindow) const return false; } -MeterWindow* Rainmeter::GetMeterWindow(const std::wstring& folderPath) +MeterWindow* Rainmeter::GetMeterWindow(const std::wstring& filePath) { - const WCHAR* folderSz = folderPath.c_str(); - std::map::const_iterator iter = m_MeterWindows.begin(); - for (; iter != m_MeterWindows.end(); ++iter) - { - if (_wcsicmp((*iter).first.c_str(), folderSz) == 0) - { - return (*iter).second; - } - } + std::wstring filePathLower; + std::transform(filePath.begin(), filePath.end(), filePathLower.begin(), ::tolower); - return nullptr; -} - -MeterWindow* Rainmeter::GetMeterWindowByINI(const std::wstring& ini_searching) -{ - if (_wcsnicmp(m_SkinPath.c_str(), ini_searching.c_str(), m_SkinPath.length()) == 0) - { - const std::wstring config_searching = ini_searching.substr(m_SkinPath.length()); - - std::map::const_iterator iter = m_MeterWindows.begin(); - for (; iter != m_MeterWindows.end(); ++iter) - { - std::wstring config_current = (*iter).second->GetFolderPath() + L'\\'; - config_current += (*iter).second->GetFileName(); - - if (_wcsicmp(config_current.c_str(), config_searching.c_str()) == 0) - { - return (*iter).second; - } - } - } + if (m_MeterWindows.count(filePathLower) > 0) + return m_MeterWindows.at(filePathLower); return nullptr; } @@ -1023,12 +441,11 @@ void Rainmeter::GetMeterWindowsByLoadOrder(std::multimap& win } } -void Rainmeter::SetLoadOrder(int folderIndex, int order) +void Rainmeter::SetLoadOrder(const std::wstring& file, int order) { - std::multimap::iterator iter = m_SkinOrders.begin(); - for ( ; iter != m_SkinOrders.end(); ++iter) + for (auto iter = m_SkinOrders.begin(); iter != m_SkinOrders.end(); ++iter) { - if ((*iter).second == folderIndex) // already exists + if ((*iter).second == file) // already exists { if ((*iter).first != order) { @@ -1042,77 +459,23 @@ void Rainmeter::SetLoadOrder(int folderIndex, int order) } } - m_SkinOrders.insert(std::pair(order, folderIndex)); + m_SkinOrders.insert(std::make_pair(order, file)); } -int Rainmeter::GetLoadOrder(const std::wstring& folderPath) +int Rainmeter::GetLoadOrder(const std::wstring& filePath) { - const int index = m_SkinRegistry.FindFolderIndex(folderPath); - if (index != -1) + for (auto pair : m_SkinOrders) { - std::multimap::const_iterator iter = m_SkinOrders.begin(); - for ( ; iter != m_SkinOrders.end(); ++iter) + if (pair.second == filePath) { - if ((*iter).second == index) - { - return (*iter).first; - } + return pair.first; } } - + // LoadOrder not specified return 0; } -/* -** Scans all the subfolders and locates the ini-files. -*/ -void Rainmeter::ScanForSkins() -{ - m_SkinRegistry.Populate(m_SkinPath); - m_SkinOrders.clear(); -} - -/* -** Scans the given folder for layouts -*/ -void Rainmeter::ScanForLayouts() -{ - m_Layouts.clear(); - - WIN32_FIND_DATA fileData; // Data structure describes the file found - HANDLE hSearch; // Search handle returned by FindFirstFile - - // Scan for folders - std::wstring folders = GetLayoutPath(); - folders += L'*'; - - hSearch = FindFirstFileEx( - folders.c_str(), - (IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard, - &fileData, - FindExSearchNameMatch, - nullptr, - 0); - - if (hSearch != INVALID_HANDLE_VALUE) - { - do - { - if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && - !PathUtil::IsDotOrDotDot(fileData.cFileName)) - { - m_Layouts.push_back(fileData.cFileName); - } - } - while (FindNextFile(hSearch, &fileData)); - - FindClose(hSearch); - } - - DialogManage::UpdateLayouts(); -} - void Rainmeter::ExecuteBang(const WCHAR* bang, std::vector& args, MeterWindow* meterWindow) { m_CommandHandler.ExecuteBang(bang, args, meterWindow); @@ -1134,68 +497,70 @@ void Rainmeter::ExecuteCommand(const WCHAR* command, MeterWindow* meterWindow, b void Rainmeter::DelayedExecuteCommand(const WCHAR* command) { WCHAR* bang = _wcsdup(command); - PostMessage(m_Window, WM_RAINMETER_DELAYED_EXECUTE, (WPARAM)nullptr, (LPARAM)bang); + PostMessage(m_Window, WM_RAINMETER_DELAYED_EXECUTE, (WPARAM)nullptr, (LPARAM) bang); } /* -** Reads the general settings from the Rainmeter.ini file +** Refreshes all active meter windows. +** Note: This function calls MeterWindow::Refresh() directly for synchronization. Be careful about crash. ** */ -void Rainmeter::ReadGeneralSettings(const std::wstring& iniFile) +void Rainmeter::RefreshAll() { + // Read skins and settings + LoadLayout(); + + // Change the work area if necessary + if (m_DesktopWorkAreaChanged) + { + UpdateDesktopWorkArea(false); + } + + // Make the sending order by using LoadOrder + std::multimap windows; + GetMeterWindowsByLoadOrder(windows); + + // Prepare the helper window + System::PrepareHelperWindow(); + + // Refresh all + std::multimap::const_iterator iter = windows.begin(); + for (; iter != windows.end(); ++iter) + { + MeterWindow* mw = (*iter).second; + if (mw) + { + mw->Refresh(false, true); + } + } +} + +bool Rainmeter::LoadLayout(std::wstring filename) +{ + if (filename.empty()) + { + filename = m_LayoutFile; + } + + if (_waccess(filename.c_str(), 0) == -1) + { + return false; + } + + // Unload current meters + DeleteAllUnmanagedMeterWindows(); + DeleteAllMeterWindows(); + + // Load layout file WCHAR buffer[MAX_PATH]; // Clear old settings m_DesktopWorkAreas.clear(); ConfigParser parser; - parser.Initialize(iniFile, nullptr, nullptr); - - m_UseD2D = parser.ReadBool(L"Rainmeter", L"UseD2D", true); - - m_Debug = parser.ReadBool(L"Rainmeter", L"Debug", false); - - // Read Logging settings - Logger& logger = GetLogger(); - const bool logging = parser.ReadBool(L"Rainmeter", L"Logging", false); - logger.SetLogToFile(logging); - if (logging) - { - logger.StartLogFile(); - } - - if (m_TrayWindow) - { - m_TrayWindow->ReadOptions(parser); - } - - m_GlobalOptions.netInSpeed = parser.ReadFloat(L"Rainmeter", L"NetInSpeed", 0.0); - m_GlobalOptions.netOutSpeed = parser.ReadFloat(L"Rainmeter", L"NetOutSpeed", 0.0); - - m_DisableDragging = parser.ReadBool(L"Rainmeter", L"DisableDragging", false); - m_DisableRDP = parser.ReadBool(L"Rainmeter", L"DisableRDP", false); - - m_SkinEditor = parser.ReadString(L"Rainmeter", L"ConfigEditor", L""); - if (m_SkinEditor.empty()) - { - // Get the program path associated with .ini files - DWORD cchOut = MAX_PATH; - HRESULT hr = AssocQueryString(ASSOCF_NOTRUNCATE, ASSOCSTR_EXECUTABLE, L".ini", L"open", buffer, &cchOut); - m_SkinEditor = (SUCCEEDED(hr) && cchOut > 0) ? buffer : L"Notepad"; - } - - if (m_Debug) - { - LogNoticeF(L"ConfigEditor: %s", m_SkinEditor.c_str()); - } - - m_TrayExecuteR = parser.ReadString(L"Rainmeter", L"TrayExecuteR", L"", false); - m_TrayExecuteM = parser.ReadString(L"Rainmeter", L"TrayExecuteM", L"", false); - m_TrayExecuteDR = parser.ReadString(L"Rainmeter", L"TrayExecuteDR", L"", false); - m_TrayExecuteDM = parser.ReadString(L"Rainmeter", L"TrayExecuteDM", L"", false); - - m_DisableVersionCheck = parser.ReadBool(L"Rainmeter", L"DisableVersionCheck", false); + parser.Initialize(filename, nullptr, nullptr); + // Read desktop work area settings const std::wstring& area = parser.ReadString(L"Rainmeter", L"DesktopWorkArea", L""); if (!area.empty()) { @@ -1217,8 +582,6 @@ void Rainmeter::ReadGeneralSettings(const std::wstring& iniFile) m_DesktopWorkAreaType = parser.ReadBool(L"Rainmeter", L"DesktopWorkAreaType", false); - m_NormalStayDesktop = parser.ReadBool(L"Rainmeter", L"NormalStayDesktop", true); - for (auto iter = parser.GetSections().cbegin(); iter != parser.GetSections().end(); ++iter) { const WCHAR* section = (*iter).c_str(); @@ -1228,183 +591,23 @@ void Rainmeter::ReadGeneralSettings(const std::wstring& iniFile) { continue; } - - const int index = m_SkinRegistry.FindFolderIndex(*iter); - if (index == -1) - { - continue; - } - - SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); - + // Make sure there is a ini file available int active = parser.ReadInt(section, L"Active", 0); - if (active > 0 && active <= (int)skinFolder.files.size()) + if (active > 0) { - skinFolder.active = active; - } + // TODO: fix, get 'active'th file from *iter folder + ActivateSkin(*iter); - int order = parser.ReadInt(section, L"LoadOrder", 0); - SetLoadOrder(index, order); - } -} - -/* -** Refreshes all active meter windows. -** Note: This function calls MeterWindow::Refresh() directly for synchronization. Be careful about crash. -** -*/ -void Rainmeter::RefreshAll() -{ - // Read skins and settings - ReloadSettings(); - - // Change the work area if necessary - if (m_DesktopWorkAreaChanged) - { - UpdateDesktopWorkArea(false); - } - - // Make the sending order by using LoadOrder - std::multimap windows; - GetMeterWindowsByLoadOrder(windows); - - // Prepare the helper window - System::PrepareHelperWindow(); - - // Refresh all - std::multimap::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - MeterWindow* mw = (*iter).second; - if (mw) - { - // Verify whether the cached information is valid - const int index = m_SkinRegistry.FindFolderIndex(mw->GetFolderPath()); - if (index != -1) - { - SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); - const WCHAR* skinIniFile = mw->GetFileName().c_str(); - - bool found = false; - for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) - { - if (_wcsicmp(skinIniFile, skinFolder.files[i].c_str()) == 0) - { - found = true; - if (skinFolder.active != i + 1) - { - // Switch to new ini-file order - skinFolder.active = i + 1; - WriteActive(mw->GetFolderPath(), i); - } - break; - } - } - - if (!found) - { - const WCHAR* skinFolderPath = mw->GetFolderPath().c_str(); - std::wstring error = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, skinFolderPath, skinIniFile); - - DeactivateSkin(mw, index); - - ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONEXCLAMATION); - continue; - } - } - else - { - const WCHAR* skinFolderPath = mw->GetFolderPath().c_str(); - std::wstring error = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, skinFolderPath, L""); - - DeactivateSkin(mw, -2); // -2 = Force deactivate - - ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONEXCLAMATION); - continue; - } - - mw->Refresh(false, true); + // TODO: activate using 'order' + int order = parser.ReadInt(section, L"LoadOrder", 0); + SetLoadOrder(*iter, order); } } - DialogAbout::UpdateSkins(); - DialogManage::UpdateSkins(nullptr); -} - -bool Rainmeter::LoadLayout(const std::wstring& name) -{ - // Replace Rainmeter.ini with layout - std::wstring layout = GetLayoutPath(); - layout += name; - std::wstring wallpaper = layout + L"\\Wallpaper.bmp"; - layout += L"\\Rainmeter.ini"; - - if (_waccess(layout.c_str(), 0) == -1) - { - return false; - } - - DeleteAllUnmanagedMeterWindows(); - DeleteAllMeterWindows(); - - std::wstring backup = GetLayoutPath(); - backup += L"@Backup"; - CreateDirectory(backup.c_str(), nullptr); - backup += L"\\Rainmeter.ini"; - - bool backupLayout = (_wcsicmp(name.c_str(), L"@Backup") == 0); - if (!backupLayout) - { - // Make a copy of current Rainmeter.ini - System::CopyFiles(m_IniFile, backup); - } - - System::CopyFiles(layout, m_IniFile); - - if (!backupLayout) - { - PreserveSetting(backup, L"SkinPath"); - PreserveSetting(backup, L"ConfigEditor"); - PreserveSetting(backup, L"LogViewer"); - PreserveSetting(backup, L"Logging"); - PreserveSetting(backup, L"DisableVersionCheck"); - PreserveSetting(backup, L"Language"); - PreserveSetting(backup, L"NormalStayDesktop"); - PreserveSetting(backup, L"TrayExecuteM", false); - PreserveSetting(backup, L"TrayExecuteR", false); - PreserveSetting(backup, L"TrayExecuteDM", false); - PreserveSetting(backup, L"TrayExecuteDR", false); - PreserveSetting(backup, L"UseD2D"); - - // Set wallpaper if it exists - if (_waccess(wallpaper.c_str(), 0) != -1) - { - SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)wallpaper.c_str(), SPIF_UPDATEINIFILE); - } - } - - ReloadSettings(); - - // Create meter windows for active skins - ActivateActiveSkins(); - return true; } -void Rainmeter::PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace) -{ - WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; - - if ((replace || GetPrivateProfileString(L"Rainmeter", key, L"", buffer, 4, m_IniFile.c_str()) == 0) && - GetPrivateProfileString(L"Rainmeter", key, L"", buffer, MAX_LINE_LENGTH, from.c_str()) > 0) - { - WritePrivateProfileString(L"Rainmeter", key, buffer, m_IniFile.c_str()); - } - - delete [] buffer; -} - /* ** Applies given DesktopWorkArea and DesktopWorkArea@n. ** @@ -1527,23 +730,10 @@ void Rainmeter::ReadStats() { const WCHAR* statsFile = m_StatsFile.c_str(); - // If m_StatsFile doesn't exist, create it and copy the stats section from m_IniFile + // If m_StatsFile doesn't exist, create it if (_waccess(statsFile, 0) == -1) { - const WCHAR* iniFile = m_IniFile.c_str(); - WCHAR* tmpSz = new WCHAR[SHRT_MAX]; // Max size returned by GetPrivateProfileSection() - - if (GetPrivateProfileSection(L"Statistics", tmpSz, SHRT_MAX, iniFile) > 0) - { - WritePrivateProfileString(L"Statistics", nullptr, nullptr, iniFile); - } - else - { - tmpSz[0] = tmpSz[1] = L'\0'; - } - WritePrivateProfileSection(L"Statistics", tmpSz, statsFile); - - delete [] tmpSz; + WritePrivateProfileSection(L"Statistics", L"", statsFile); } // Only Net measure has stats at the moment @@ -1590,77 +780,54 @@ void Rainmeter::ResetStats() MeasureNet::ResetStats(); } -/* -** Wraps MessageBox(). Sets RTL flag if necessary. -** -*/ -int Rainmeter::ShowMessage(HWND parent, const WCHAR* text, UINT type) -{ - type |= MB_TOPMOST; - - if (*GetString(ID_STR_ISRTL) == L'1') - { - type |= MB_RTLREADING; - } - - return MessageBox(parent, text, APPNAME, type); -}; - -void Rainmeter::ShowLogFile() -{ - std::wstring logFile = L'"' + GetLogger().GetLogFilePath(); - logFile += L'"'; - - CommandHandler::RunFile(m_SkinEditor.c_str(), logFile.c_str()); -} - -void Rainmeter::SetDebug(bool debug) -{ - m_Debug = debug; - WritePrivateProfileString(L"Rainmeter", L"Debug", debug ? L"1" : L"0", m_IniFile.c_str()); -} - void Rainmeter::SetDisableDragging(bool dragging) { m_DisableDragging = dragging; - WritePrivateProfileString(L"Rainmeter", L"DisableDragging", dragging ? L"1" : L"0", m_IniFile.c_str()); -} - -void Rainmeter::SetDisableVersionCheck(bool check) -{ - m_DisableVersionCheck = check; - WritePrivateProfileString(L"Rainmeter", L"DisableVersionCheck", check ? L"1" : L"0" , m_IniFile.c_str()); -} - -void Rainmeter::TestSettingsFile(bool bDefaultIniLocation) -{ - const WCHAR* iniFile = m_IniFile.c_str(); - if (!System::IsFileWritable(iniFile)) - { - std::wstring error = GetString(ID_STR_SETTINGSNOTWRITABLE); - - if (!bDefaultIniLocation) - { - std::wstring strTarget = L"%APPDATA%\\Rainmeter\\"; - PathUtil::ExpandEnvironmentVariables(strTarget); - - error += GetFormattedString(ID_STR_SETTINGSMOVEFILE, iniFile, strTarget.c_str()); - } - else - { - error += GetFormattedString(ID_STR_SETTINGSREADONLY, iniFile); - } - - ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONERROR); - } } void Rainmeter::SetUseD2D(bool enabled) { m_UseD2D = enabled; - // Save to Rainmeter.ini - WritePrivateProfileString(L"Rainmeter", L"UseD2D", enabled ? L"1" : L"0", m_IniFile.c_str()); - RefreshAll(); } + +std::wstring Rainmeter::GetAbsolutePath(const std::wstring& path) +{ + if (!PathUtil::IsAbsolute(path)) + { + WCHAR buffer[MAX_PATH]; + std::wstring workdir = GetWorkDirectory(); + + // Work directory not absolute + if (!PathUtil::IsAbsolute(workdir)) + { + // Get current directory + WCHAR currentdir[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, currentdir); + + // Get absolute work directory + PathCombine(buffer, currentdir, workdir.c_str()); + workdir.assign(buffer); + } + + // Combine + PathCombine(buffer, workdir.c_str(), path.c_str()); + + return buffer; + } + + return path; +} + +std::wstring Rainmeter::NormalizePath(const std::wstring& path) +{ + // Convert to absolute + std::wstring res = GetAbsolutePath(path); + + // To lower + std::transform(res.begin(), res.end(), res.begin(), ::towlower); + + // Return + return res; +} \ No newline at end of file diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index c7bc0c9b..42872c08 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ + */ #ifndef __RAINMETER_H__ #define __RAINMETER_H__ @@ -25,10 +25,9 @@ #include #include #include "CommandHandler.h" -#include "ContextMenu.h" #include "Logger.h" #include "MeterWindow.h" -#include "SkinRegistry.h" +#include "../Common/PathUtil.h" #define MAX_LINE_LENGTH 4096 @@ -56,14 +55,21 @@ struct GlobalOptions }; class ConfigParser; -class TrayWindow; class Rainmeter { public: + + #pragma region Singleton + + /// + /// Gets the instance + /// static Rainmeter& GetInstance(); - int Initialize(LPCWSTR iniPath, LPCWSTR layout); + #pragma endregion + + int Initialize(); void Finalize(); int MessagePump(); @@ -73,8 +79,6 @@ public: ConfigParser* GetCurrentParser() { return m_CurrentParser; } void SetCurrentParser(ConfigParser* parser) { m_CurrentParser = parser; } - TrayWindow* GetTrayWindow() { return m_TrayWindow; } - bool HasMeterWindow(const MeterWindow* meterWindow) const; MeterWindow* GetMeterWindow(const std::wstring& folderPath); @@ -83,94 +87,61 @@ public: MeterWindow* GetMeterWindow(HWND hwnd); void GetMeterWindowsByLoadOrder(std::multimap& windows, const std::wstring& group = std::wstring()); std::map& GetAllMeterWindows() { return m_MeterWindows; } - - const std::vector& GetAllLayouts() { return m_Layouts; } - + void RemoveMeterWindow(MeterWindow* meterWindow); void AddUnmanagedMeterWindow(MeterWindow* meterWindow); void RemoveUnmanagedMeterWindow(MeterWindow* meterWindow); - bool ActivateSkin(const std::wstring& folderPath); - bool ActivateSkin(const std::wstring& folderPath, const std::wstring& file); - void ActivateSkin(int folderIndex, int fileIndex); - void DeactivateSkin(MeterWindow* meterWindow, int folderIndex, bool save = true); - void ToggleSkin(int folderIndex, int fileIndex); + void ActivateSkin(std::wstring file); + void DeactivateSkin(MeterWindow* meterWindow); + void ToggleSkin(std::wstring file); void ToggleSkinWithID(UINT id); - const std::wstring& GetPath() { return m_Path; } - const std::wstring& GetIniFile() { return m_IniFile; } - const std::wstring& GetDataFile() { return m_DataFile; } - const std::wstring& GetSettingsPath() { return m_SettingsPath; } - const std::wstring& GetSkinPath() { return m_SkinPath; } - void SetSkinPath(const std::wstring& skinPath); - std::wstring GetLayoutPath() { return m_SettingsPath + L"Layouts\\"; } - std::wstring GetPluginPath() { return m_Path + L"Plugins\\"; } - std::wstring GetUserPluginPath() { return m_SettingsPath + L"Plugins\\"; } - std::wstring GetAddonPath() { return m_SettingsPath + L"Addons\\"; } + std::wstring GetWorkDirectory() + { + if (m_UseCurrentDirectory) + { + WCHAR buffer[MAX_PATH]; + GetCurrentDirectoryW(MAX_PATH, buffer); + return buffer; + } - bool HasUserPluginPath() { return (_wcsicmp(m_Path.c_str(), m_SettingsPath.c_str()) != 0); } + return m_WorkDirectory; + } - std::wstring GetDefaultSkinPath() { return m_Path + L"Defaults\\Skins\\"; } - std::wstring GetDefaultLayoutPath() { return m_Path + L"Defaults\\Layouts\\"; } - std::wstring GetDefaultPluginPath() { return m_Path + L"Defaults\\Plugins\\"; } - std::wstring GetDefaultAddonPath() { return m_Path + L"Defaults\\Addons\\"; } + std::wstring GetSkinPath() { return GetWorkDirectory() + L"Skins\\"; } + std::wstring GetLayoutPath() { return GetWorkDirectory() + L"Layouts\\"; } + std::wstring GetPluginPath() { return GetWorkDirectory() + L"Plugins\\"; } + std::wstring GetUserPluginPath() { return GetWorkDirectory() + L"Plugins\\"; } + std::wstring GetAddonPath() { return GetWorkDirectory() + L"Addons\\"; } - const std::wstring& GetDrive() { return m_Drive; } + std::wstring GetDrive() { return PathUtil::GetVolume(GetWorkDirectory()); } - const std::wstring& GetSkinEditor() { return m_SkinEditor; } - void SetSkinEditor(const std::wstring& path); const std::wstring& GetStatsDate() { return m_StatsDate; } HWND GetWindow() { return m_Window; } HINSTANCE GetModuleInstance() { return m_Instance; } - HINSTANCE GetResourceInstance() { return m_ResourceInstance; } - LCID GetResourceLCID() { return m_ResourceLCID; } bool GetUseD2D() const { return m_UseD2D; } void SetUseD2D(bool enabled); - - bool GetDebug() { return m_Debug; } + bool GetDebug() const { return m_Debug; } GlobalOptions& GetGlobalOptions() { return m_GlobalOptions; } - void ReloadSettings(); - void EditSettings(); - void EditSkinFile(const std::wstring& name, const std::wstring& iniFile); - void OpenSkinFolder(const std::wstring& name = std::wstring()); - void UpdateStats(); void ReadStats(); void WriteStats(bool bForce); void ResetStats(); - bool GetDisableVersionCheck() { return m_DisableVersionCheck; } - void SetDisableVersionCheck(bool check); - bool GetNewVersion() { return m_NewVersion; } - void SetNewVersion() { m_NewVersion = true; } - - void ShowLogFile(); - - bool GetDisableRDP() { return m_DisableRDP; } - bool IsRedrawable() { return (!GetDisableRDP() || !GetSystemMetrics(SM_REMOTESESSION)); } - bool GetDisableDragging() { return m_DisableDragging; } void SetDisableDragging(bool dragging); bool IsNormalStayDesktop() { return m_NormalStayDesktop; } - void SetDebug(bool debug); - - int ShowMessage(HWND parent, const WCHAR* text, UINT type); - - bool IsMenuActive() { return m_ContextMenu.IsMenuActive(); } - void ShowContextMenu(POINT pos, MeterWindow* mw) { return m_ContextMenu.ShowMenu(pos, mw); } - void ShowSkinCustomContextMenu(POINT pos, MeterWindow* mw) { return m_ContextMenu.ShowSkinCustomMenu(pos, mw); } - - const std::wstring& GetTrayExecuteR() { return m_TrayExecuteR; } - const std::wstring& GetTrayExecuteM() { return m_TrayExecuteM; } - const std::wstring& GetTrayExecuteDR() { return m_TrayExecuteDR; } - const std::wstring& GetTrayExecuteDM() { return m_TrayExecuteDM; } + bool IsMenuActive() { /* TODO: implement c# callback */ LogErrorF(L"IsMenuActive callback not implemented."); return false; } + void ShowContextMenu(POINT pos, MeterWindow* mw) { /* TODO: implement c# callback */ LogErrorF(L"ShowContextMenu callback not implemented."); } + void ShowSkinCustomContextMenu(POINT pos, MeterWindow* mw) { /* TODO: implement c# callback */ LogErrorF(L"ShowSkinCustomContextMenu callback not implemented."); } void ExecuteBang(const WCHAR* bang, std::vector& args, MeterWindow* meterWindow); void ExecuteCommand(const WCHAR* command, MeterWindow* meterWindow, bool multi = true); @@ -178,85 +149,60 @@ public: void RefreshAll(); - bool LoadLayout(const std::wstring& name); - void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace = true); + bool LoadLayout(std::wstring filename = std::wstring()); friend class CommandHandler; - friend class ContextMenu; - friend class DialogManage; private: + + #pragma region Constructor, destructor + Rainmeter(); ~Rainmeter(); Rainmeter(const Rainmeter& other) = delete; Rainmeter& operator=(Rainmeter other) = delete; + + #pragma endregion static LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - void ActivateActiveSkins(); - void CreateMeterWindow(const std::wstring& folderPath, const std::wstring& file); + void CreateMeterWindow(std::wstring file); void DeleteAllMeterWindows(); void DeleteAllUnmanagedMeterWindows(); - void WriteActive(const std::wstring& folderPath, int fileIndex); - void ScanForSkins(); - void ScanForLayouts(); void ReadGeneralSettings(const std::wstring& iniFile); - void SetLoadOrder(int folderIndex, int order); + void SetLoadOrder(const std::wstring& file, int order); int GetLoadOrder(const std::wstring& folderPath); void UpdateDesktopWorkArea(bool reset); + std::wstring GetAbsolutePath(const std::wstring& path); + std::wstring NormalizePath(const std::wstring& path); - void CreateOptionsFile(); - void CreateDataFile(); - void CreateComponentFolders(bool defaultIniLocation); - void TestSettingsFile(bool bDefaultIniLocation); + #pragma region Private fields - TrayWindow* m_TrayWindow; - - std::multimap m_SkinOrders; + std::multimap m_SkinOrders; std::map m_MeterWindows; std::list m_UnmanagedMeterWindows; - std::vector m_Layouts; - std::wstring m_Path; - std::wstring m_IniFile; - std::wstring m_DataFile; - std::wstring m_StatsFile; - std::wstring m_SettingsPath; - std::wstring m_SkinPath; - - std::wstring m_Drive; + std::wstring m_WorkDirectory; + bool m_UseCurrentDirectory; // TODO: getter, setter + std::wstring m_StatsFile; // TODO: getter, setter + std::wstring m_LayoutFile; // TODO: getter, setter std::wstring m_StatsDate; - std::wstring m_TrayExecuteR; - std::wstring m_TrayExecuteM; - std::wstring m_TrayExecuteDR; - std::wstring m_TrayExecuteDM; - bool m_UseD2D; - bool m_Debug; - - bool m_DisableVersionCheck; - bool m_NewVersion; - bool m_DesktopWorkAreaChanged; bool m_DesktopWorkAreaType; std::map m_DesktopWorkAreas; std::vector m_OldDesktopWorkAreas; bool m_NormalStayDesktop; - - bool m_DisableRDP; + bool m_Debug; bool m_DisableDragging; - std::wstring m_SkinEditor; - CommandHandler m_CommandHandler; - ContextMenu m_ContextMenu; - SkinRegistry m_SkinRegistry; ConfigParser* m_CurrentParser; @@ -264,23 +210,15 @@ private: HANDLE m_Mutex; HINSTANCE m_Instance; - HMODULE m_ResourceInstance; - LCID m_ResourceLCID; ULONG_PTR m_GDIplusToken; GlobalOptions m_GlobalOptions; + + #pragma endregion }; // Convenience function. inline Rainmeter& GetRainmeter() { return Rainmeter::GetInstance(); } -#ifdef LIBRARY_EXPORTS -#define EXPORT_PLUGIN EXTERN_C -#else -#define EXPORT_PLUGIN EXTERN_C __declspec(dllimport) -#endif - -EXPORT_PLUGIN int RainmeterMain(LPWSTR cmdLine); - #endif diff --git a/Library/RainmeterQuery.h b/Library/RainmeterQuery.h index 0f112bc2..9a5591f8 100644 --- a/Library/RainmeterQuery.h +++ b/Library/RainmeterQuery.h @@ -1,125 +1,125 @@ -/* - Copyright (C) 2010 JamesAC, spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/* -Rainmeter query interface based on Window Message - -The majority of the queries work as detailed below, other queries are explained along with their definitions. -Usage: -1) Post the query to Rainmeter (E.g. QueryRainmeterSkinsPath function) - * target window : Rainmeter(TrayWindow) - * message : WM_QUERY_RAINMETER - * wParam : QUERY ID (RAINMETER_QUERY_ID_XXXXX) - * lParam : window handle which receives WM_COPYDATA - -2) Retrieve the data received from Rainmeter, on WM_COPYDATA - * COPYDATASTRUCT->dwData : QUERY ID (RAINMETER_QUERY_ID_XXXXX) - * COPYDATASTRUCT->lpData : requested information. Form depends on you request. - * COPYDATASTRUCT->cbData : size of lpData - ------ -#include -#include -#include "RainmeterQuery.h" - -void QueryRainmeterSkinsPath(HWND hWndSelf) -{ - HWND hWndRainmeter = FindWindow(RAINMETER_QUERY_CLASS_NAME, RAINMETER_QUERY_WINDOW_NAME); - if (hWndRainmeter) - { - PostMessage(hWndRainmeter, WM_QUERY_RAINMETER, RAINMETER_QUERY_ID_SKINS_PATH, (LPARAM)hWndSelf); - } -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_COPYDATA: - { - COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; - - // Copy ID and string to local - DWORD id = cds->dwData; // contains QUERY ID (RAINMETER_QUERY_ID_XXXXX) - std::wstring string = (WCHAR*)cds->lpData; // contains requested string in wide char - - // - ... - } - break; - - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - return 0; -} ------ -*/ - -#ifndef __RAINMETER_QUERY_H__ -#define __RAINMETER_QUERY_H__ - -#include - -#define RAINMETER_QUERY_CLASS_NAME TEXT("RainmeterTrayClass") -#define RAINMETER_QUERY_WINDOW_NAME nullptr - -#define WM_QUERY_RAINMETER WM_APP + 1000 -#define WM_QUERY_RAINMETER_RETURN WM_APP + 1001 - -/* -QUERY IDs -These Queries return a string in a wide char format -*/ -#define RAINMETER_QUERY_ID_SKINS_PATH 4101 -#define RAINMETER_QUERY_ID_SETTINGS_PATH 4102 -#define RAINMETER_QUERY_ID_PLUGINS_PATH 4103 -#define RAINMETER_QUERY_ID_PROGRAM_PATH 4104 -#define RAINMETER_QUERY_ID_LOG_PATH 4105 -#define RAINMETER_QUERY_ID_CONFIG_EDITOR 4106 - -/* -These Queries return a numerical value in a direct message, the data -is stored in the lParam of the message sent to your window, and the msg section -will contain WM_QUERY_RAINMETER_RETURN -*/ -#define RAINMETER_QUERY_ID_IS_DEBUGGING 4116 - -/*QUERY IDs used with WM_COPYDATA -Usage: Send a WM_COPYDATA message to rainmeter via SendMessage(). -Rainmeter will set the return value depending on the contents -of the COPYDATASTRUCT. -*/ -#define RAINMETER_QUERY_ID_SKIN_WINDOWHANDLE 5101 - -/* -This Retuns the Window Handle of the active skin requested by config name in cds.lpData, -or nullptr if the config is not loaded. Currently, the config name is Case-Sensitive. - -To requst the data, send a message to Rainmeter in a way similar to this example. -COPYDATASTRUCT cds; -LPWSTR SkinName = L"Gnometer\\Clock"; - -cds.dwData = 5101; -cds.lpData = SkinName; -cds.cbData = (wcslen(SkinName) + 1) * 2; - -HWND hWndMeter = (HWND) SendMessage(hWndRainmeter, WM_COPYDATA, (WPARAM) hWndYourWindow, (LPARAM) &cds); -*/ - -#endif +/* + Copyright (C) 2010 JamesAC, spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* +Rainmeter query interface based on Window Message + +The majority of the queries work as detailed below, other queries are explained along with their definitions. +Usage: +1) Post the query to Rainmeter (E.g. QueryRainmeterSkinsPath function) + * target window : Rainmeter(TrayWindow) + * message : WM_QUERY_RAINMETER + * wParam : QUERY ID (RAINMETER_QUERY_ID_XXXXX) + * lParam : window handle which receives WM_COPYDATA + +2) Retrieve the data received from Rainmeter, on WM_COPYDATA + * COPYDATASTRUCT->dwData : QUERY ID (RAINMETER_QUERY_ID_XXXXX) + * COPYDATASTRUCT->lpData : requested information. Form depends on you request. + * COPYDATASTRUCT->cbData : size of lpData + +----- +#include +#include +#include "RainmeterQuery.h" + +void QueryRainmeterSkinsPath(HWND hWndSelf) +{ + HWND hWndRainmeter = FindWindow(RAINMETER_QUERY_CLASS_NAME, RAINMETER_QUERY_WINDOW_NAME); + if (hWndRainmeter) + { + PostMessage(hWndRainmeter, WM_QUERY_RAINMETER, RAINMETER_QUERY_ID_SKINS_PATH, (LPARAM)hWndSelf); + } +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_COPYDATA: + { + COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; + + // Copy ID and string to local + DWORD id = cds->dwData; // contains QUERY ID (RAINMETER_QUERY_ID_XXXXX) + std::wstring string = (WCHAR*)cds->lpData; // contains requested string in wide char + + // + ... + } + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} +----- +*/ + +#ifndef __RAINMETER_QUERY_H__ +#define __RAINMETER_QUERY_H__ + +#include + +#define RAINMETER_QUERY_CLASS_NAME TEXT("RainmeterTrayClass") +#define RAINMETER_QUERY_WINDOW_NAME nullptr + +#define WM_QUERY_RAINMETER WM_APP + 1000 +#define WM_QUERY_RAINMETER_RETURN WM_APP + 1001 + +/* +QUERY IDs +These Queries return a string in a wide char format +*/ +#define RAINMETER_QUERY_ID_SKINS_PATH 4101 +#define RAINMETER_QUERY_ID_SETTINGS_PATH 4102 +#define RAINMETER_QUERY_ID_PLUGINS_PATH 4103 +#define RAINMETER_QUERY_ID_PROGRAm_WorkDirectory 4104 +#define RAINMETER_QUERY_ID_LOG_PATH 4105 +#define RAINMETER_QUERY_ID_CONFIG_EDITOR 4106 + +/* +These Queries return a numerical value in a direct message, the data +is stored in the lParam of the message sent to your window, and the msg section +will contain WM_QUERY_RAINMETER_RETURN +*/ +#define RAINMETER_QUERY_ID_IS_DEBUGGING 4116 + +/*QUERY IDs used with WM_COPYDATA +Usage: Send a WM_COPYDATA message to rainmeter via SendMessage(). +Rainmeter will set the return value depending on the contents +of the COPYDATASTRUCT. +*/ +#define RAINMETER_QUERY_ID_SKIN_WINDOWHANDLE 5101 + +/* +This Retuns the Window Handle of the active skin requested by config name in cds.lpData, +or nullptr if the config is not loaded. Currently, the config name is Case-Sensitive. + +To requst the data, send a message to Rainmeter in a way similar to this example. +COPYDATASTRUCT cds; +LPWSTR SkinName = L"Gnometer\\Clock"; + +cds.dwData = 5101; +cds.lpData = SkinName; +cds.cbData = (wcslen(SkinName) + 1) * 2; + +HWND hWndMeter = (HWND) SendMessage(hWndRainmeter, WM_COPYDATA, (WPARAM) hWndYourWindow, (LPARAM) &cds); +*/ + +#endif diff --git a/Library/SkinRegistry.cpp b/Library/SkinRegistry.cpp deleted file mode 100644 index 764ec33d..00000000 --- a/Library/SkinRegistry.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/PathUtil.h" -#include "SkinRegistry.h" -#include "resource.h" - -/* -** Returns the skin folder path relative to the skin folder (e.g. illustro\Clock). -*/ -std::wstring SkinRegistry::GetFolderPath(int folderIndex) const -{ - // Traverse |m_Folders| backwards until level 1 is reached. - const auto& skinFolder = m_Folders[folderIndex]; - std::wstring path = skinFolder.name; - for (int i = skinFolder.level - 1, index = folderIndex; i >= 1; --i) - { - while (m_Folders[index].level != i) - { - --index; - } - - path.insert(0, L"\\"); - path.insert(0, m_Folders[index].name); - } - return path; -} - -/* -** Finds the skin index for the specified skin folder path. -*/ -int SkinRegistry::FindFolderIndex(const std::wstring& folderPath) const -{ - if (folderPath.empty()) return -1; - - const WCHAR* path = folderPath.c_str(); - int len = 0; - while (path[len] && path[len] != L'\\') ++len; - - int level = 1; - for (int i = 0, isize = (int)m_Folders.size(); i < isize; ++i) - { - const auto& skinFolder = m_Folders[i]; - if (skinFolder.level == level) - { - if (skinFolder.name.length() == len && _wcsnicmp(skinFolder.name.c_str(), path, len) == 0) - { - path += len; - if (*path) - { - ++path; // Skip backslash - len = 0; - while (path[len] && path[len] != L'\\') ++len; - } - else - { - // Match found - return i; - } - - ++level; - } - } - else if (skinFolder.level < level) - { - break; - } - } - - return -1; -} - -SkinRegistry::Folder* SkinRegistry::FindFolder(const std::wstring& folderPath) -{ - const int folderIndex = FindFolderIndex(folderPath); - return (folderIndex != -1) ? &m_Folders[folderIndex] : nullptr; -} - -SkinRegistry::Indexes SkinRegistry::FindIndexes(const std::wstring& folderPath, const std::wstring& file) -{ - const int folderIndex = FindFolderIndex(folderPath); - if (folderIndex != -1) - { - const Folder& skinFolder = m_Folders[folderIndex]; - const WCHAR* fileSz = file.c_str(); - for (size_t i = 0, isize = skinFolder.files.size(); i < isize; ++i) - { - if (_wcsicmp(skinFolder.files[i].c_str(), fileSz) == 0) - { - return Indexes(folderIndex, (int)i); - } - } - } - - return Indexes::Invalid(); // Not found. -} - -SkinRegistry::Indexes SkinRegistry::FindIndexesForID(UINT id) -{ - if (id >= ID_CONFIG_FIRST && id <= ID_CONFIG_LAST) - { - // Check which skin was selected - for (size_t i = 0, isize = m_Folders.size(); i < isize; ++i) - { - const Folder& skinFolder = m_Folders[i]; - if (id >= skinFolder.baseID && - id < (skinFolder.baseID + skinFolder.files.size())) - { - return Indexes((int)i, (int)(id - skinFolder.baseID)); - } - } - } - - return Indexes::Invalid(); // Not found. -} - -/* -** Re-scans all the subfolders of |path| for .ini files and populates |m_Folders|. -*/ -void SkinRegistry::Populate(const std::wstring& path) -{ - m_Folders.clear(); - PopulateRecursive(path, L"", 0, 0); -} - -int SkinRegistry::PopulateRecursive(const std::wstring& path, std::wstring base, int index, UINT level) -{ - WIN32_FIND_DATA fileData; // Data structure describes the file found - HANDLE hSearch; // Search handle returned by FindFirstFile - std::list subfolders; - - // Find all .ini files and subfolders - std::wstring filter = path + base; - filter += L"\\*"; - - hSearch = FindFirstFileEx( - filter.c_str(), - (IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard, - &fileData, - FindExSearchNameMatch, - nullptr, - 0); - - bool foundFiles = false; - if (hSearch != INVALID_HANDLE_VALUE) - { - Folder folder; - folder.baseID = ID_CONFIG_FIRST + index; - folder.active = 0; - folder.level = level; - - do - { - const std::wstring filename = fileData.cFileName; - - if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (!PathUtil::IsDotOrDotDot(fileData.cFileName) && - !(level == 0 && wcscmp(L"@Backup", fileData.cFileName) == 0) && - !(level == 0 && wcscmp(L"Backup", fileData.cFileName) == 0) && - !(level == 1 && wcscmp(L"@Resources", fileData.cFileName) == 0)) - { - subfolders.push_back(filename); - } - } - else if (level != 0) - { - // Check whether the extension is ".ini" - size_t filenameLen = filename.size(); - if (filenameLen >= 4 && _wcsicmp(fileData.cFileName + (filenameLen - 4), L".ini") == 0) - { - foundFiles = true; - folder.files.push_back(filename); - ++index; - } - } - } - while (FindNextFile(hSearch, &fileData)); - - FindClose(hSearch); - - if (level > 0 && (foundFiles || !subfolders.empty())) - { - if (level == 1) - { - folder.name = base; - } - else - { - std::wstring::size_type pos = base.rfind(L'\\') + 1; - folder.name.assign(base, pos, base.length() - pos); - } - - m_Folders.push_back(std::move(folder)); - } - } - - if (level != 0) - { - base += L'\\'; - } - - if (!subfolders.empty()) - { - bool popFolder = !foundFiles; - - std::list::const_iterator iter = subfolders.begin(); - for ( ; iter != subfolders.end(); ++iter) - { - int newIndex = PopulateRecursive(path, base + (*iter), index, level + 1); - if (newIndex != index) - { - popFolder = false; - } - - index = newIndex; - } - - if (popFolder) - { - m_Folders.pop_back(); - } - } - - return index; -} diff --git a/Library/SkinRegistry.h b/Library/SkinRegistry.h deleted file mode 100644 index 1e09bb0d..00000000 --- a/Library/SkinRegistry.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_LIBRARY_SKINDIRECTORY_H_ -#define RM_LIBRARY_SKINDIRECTORY_H_ - -#include -#include -#include -#include - -// Reprsents a hierarchy of skin folders (reprsented by the Folder struct) and the names of their -// respective files. -class SkinRegistry -{ -public: - SkinRegistry() = default; - SkinRegistry(const SkinRegistry& other) = delete; - SkinRegistry& operator=(SkinRegistry other) = delete; - - struct Folder - { - std::wstring name; - std::vector files; - UINT baseID; - - int16_t active; - int16_t level; - - Folder() {} - ~Folder() {} - - Folder(Folder&& r) : - name(std::move(r.name)), - files(std::move(r.files)), - baseID(r.baseID), - active(r.active), - level(r.level) - { - } - - Folder& operator=(Folder&& r) - { - name = std::move(r.name); - files = std::move(r.files); - baseID = r.baseID; - active = r.active; - level = r.level; - return *this; - } - }; - - struct Indexes - { - int folder; - int file; - - Indexes(int folderIndex = 0, int fileIndex = 0) : folder(folderIndex), file(fileIndex) {} - - bool IsValid() const { return folder != -1; } - - static Indexes Invalid() { return Indexes(-1, 0); } - }; - - int FindFolderIndex(const std::wstring& folderPath) const; - Folder* FindFolder(const std::wstring& folderPath); - - Indexes FindIndexes(const std::wstring& folderPath, const std::wstring& file); - Indexes FindIndexesForID(UINT id); - - std::wstring GetFolderPath(int folderIndex) const; - - Folder& GetFolder(int index) { return m_Folders[index]; } - int GetFolderCount() const { return (int)m_Folders.size(); } - bool IsEmpty() const { return m_Folders.empty(); } - - void Populate(const std::wstring& path); - -private: - int PopulateRecursive(const std::wstring& path, std::wstring base, int index, UINT level); - - // Contains a sequential list of Folders. The folders are arranged as follows: - // A (index: 0, level: 1) - // B (index: 1, level: 2) - // C (index: 2, level: 3) - // D (index: 3, level: 2) - std::vector m_Folders; -}; - -#endif diff --git a/Library/SkinRegistry_Test.cpp b/Library/SkinRegistry_Test.cpp deleted file mode 100644 index 83c5627b..00000000 --- a/Library/SkinRegistry_Test.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "SkinRegistry.h" -#include "../Common/UnitTest.h" - -TEST_CLASS(Library_SkinRegistry_Test) -{ -public: - Library_SkinRegistry_Test() - { - m_SkinRegistry.Populate(L"..\\..\\..\\Library\\Test\\SkinRegistry\\"); - } - - TEST_METHOD(TestContents) - { - std::vector files1; - files1.push_back(L"1.ini"); - - std::vector files3; - files3.push_back(L"1.ini"); - files3.push_back(L"2.ini"); - files3.push_back(L"3.ini"); - - Assert::AreEqual(5, m_SkinRegistry.GetFolderCount()); - - const auto& folderA1 = m_SkinRegistry.GetFolder(0); - Assert::AreEqual(L"A1", folderA1.name.c_str()); - Assert::AreEqual((int16_t)1, folderA1.level); - Assert::IsTrue(folderA1.files.empty()); - - const auto& folderA1_B1 = m_SkinRegistry.GetFolder(1); - Assert::AreEqual(L"B1", folderA1_B1.name.c_str()); - Assert::AreEqual((int16_t)2, folderA1_B1.level); - Assert::IsTrue(files1 == folderA1_B1.files); - - const auto& folderA1_B2 = m_SkinRegistry.GetFolder(2); - Assert::AreEqual(L"B2", folderA1_B2.name.c_str()); - Assert::AreEqual((int16_t)2, folderA1_B2.level); - Assert::IsTrue(files1 == folderA1_B2.files); - - const auto& folderA1_B2_C1 = m_SkinRegistry.GetFolder(3); - Assert::AreEqual(L"C1", folderA1_B2_C1.name.c_str()); - Assert::AreEqual((int16_t)3, folderA1_B2_C1.level); - Assert::IsTrue(files1 == folderA1_B2_C1.files); - - const auto& folderA2 = m_SkinRegistry.GetFolder(4); - Assert::AreEqual(L"A2", folderA2.name.c_str()); - Assert::AreEqual((int16_t)1, folderA2.level); - Assert::IsTrue(files3 == folderA2.files); - } - - TEST_METHOD(TestFindFolderIndex) - { - Assert::AreEqual(3, m_SkinRegistry.FindFolderIndex(L"A1\\B2\\C1")); - Assert::AreEqual(-1, m_SkinRegistry.FindFolderIndex(L"A1\\B5\\C1")); - } - - TEST_METHOD(TestFindIndexes) - { - const auto indexes1 = m_SkinRegistry.FindIndexes(L"A1\\B2", L"1.ini"); - Assert::IsTrue(indexes1.folder == 2 && indexes1.file == 0); - - const auto indexes2 = m_SkinRegistry.FindIndexes(L"A2", L"2.ini"); - Assert::IsTrue(indexes2.folder == 4 && indexes2.file == 1); - - const auto indexes3 = m_SkinRegistry.FindIndexes(L"A3", L"1.ini"); - Assert::IsFalse(indexes3.IsValid()); - } - - TEST_METHOD(TestFindIndexesForID) - { - const auto indexes1 = m_SkinRegistry.FindIndexesForID(30002); - Assert::IsTrue(indexes1.folder == 2 && indexes1.file == 0); - - const auto indexes2 = m_SkinRegistry.FindIndexesForID(30005); - Assert::IsTrue(indexes2.folder == 4 && indexes2.file == 1); - } - - TEST_METHOD(TestGetFolderPath) - { - Assert::AreEqual(L"A1\\B2\\C1", m_SkinRegistry.GetFolderPath(3).c_str()); - Assert::AreEqual(L"A2", m_SkinRegistry.GetFolderPath(4).c_str()); - } - -private: - SkinRegistry m_SkinRegistry; -}; diff --git a/Library/System.cpp b/Library/System.cpp index 3b4341c4..ec056bb8 100644 --- a/Library/System.cpp +++ b/Library/System.cpp @@ -942,9 +942,8 @@ LRESULT CALLBACK System::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa break; case TIMER_RESUME: - KillTimer(hWnd, TIMER_RESUME); - if (GetRainmeter().IsRedrawable()) { + KillTimer(hWnd, TIMER_RESUME); std::map::const_iterator iter = GetRainmeter().GetAllMeterWindows().begin(); for ( ; iter != GetRainmeter().GetAllMeterWindows().end(); ++iter) { @@ -1147,7 +1146,7 @@ void System::SetWallpaper(const std::wstring& wallpaper, const std::wstring& sty Bitmap bitmap(wallpaper.c_str()); if (bitmap.GetLastStatus() == Ok) { - std::wstring file = GetRainmeter().GetSettingsPath() + L"Wallpaper.bmp"; + std::wstring file = /*TODO - fix: GetRainmeter().GetSettingsPath() + */ L"Wallpaper.bmp"; const CLSID bmpClsid = { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }; if (bitmap.Save(file.c_str(), &bmpClsid) == Ok) diff --git a/Library/TintedImage.cpp b/Library/TintedImage.cpp index ac68481e..35f24517 100644 --- a/Library/TintedImage.cpp +++ b/Library/TintedImage.cpp @@ -1,819 +1,819 @@ -/* - Copyright (C) 2010 Kimmo Pekkola, Matt King, spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/PathUtil.h" -#include "TintedImage.h" -#include "ConfigParser.h" -#include "System.h" -#include "Error.h" -#include "Logger.h" - -using namespace Gdiplus; - - -class ImageCachePool -{ -public: - static std::wstring CreateKey(const std::wstring& name, ULONGLONG time, DWORD size, WCHAR* exifOrientation) - { - std::wstring key; - - WCHAR buffer[MAX_PATH]; - if (PathCanonicalize(buffer, name.c_str())) - { - key = buffer; - } - else - { - key = name; - } - _wcsupr(&key[0]); - - size_t len = _snwprintf_s(buffer, _TRUNCATE, L":%llx:%x:%s", time, size, exifOrientation); - key.append(buffer, len); - - return key; - } - - static Bitmap* GetCache(const std::wstring& key) - { - std::unordered_map::const_iterator iter = c_CacheMap.find(key); - if (iter != c_CacheMap.end()) - { - return (*iter).second->GetCache(); - } - return nullptr; - } - - static void AddCache(const std::wstring& key, Bitmap* bitmap, HGLOBAL hBuffer) - { - std::unordered_map::const_iterator iter = c_CacheMap.find(key); - if (iter != c_CacheMap.end()) - { - (*iter).second->AddRef(); - //LogDebugF(L"* ADD: key=%s, ref=%i", key.c_str(), (*iter).second->GetRef()); - } - else - { - c_CacheMap[key] = new ImageCache(bitmap, hBuffer); - //LogDebugF(L"* ADD: key=%s, ref=new", key.c_str()); - } - } - - static void RemoveCache(const std::wstring& key) - { - std::unordered_map::const_iterator iter = c_CacheMap.find(key); - if (iter != c_CacheMap.end()) - { - ImageCache* cache = (*iter).second; - cache->Release(); - //LogDebugF(L"* REMOVE: key=%s, ref=%i", key.c_str(), cache->GetRef()); - - if (cache->IsInvalid()) - { - //LogDebugF(L"* EMPTY-ERASE: key=%s", key.c_str()); - c_CacheMap.erase(iter); - delete cache; - } - } - } - -private: - class ImageCache - { - public: - ImageCache(Bitmap* bitmap, HGLOBAL hBuffer) : m_Bitmap(bitmap), m_hBuffer(hBuffer), m_Ref(1) {} - ~ImageCache() { Dispose(); } - - void AddRef() { ++m_Ref; } - void Release() { if (m_Ref > 0) { --m_Ref; } if (m_Ref == 0) { Dispose(); } } - - bool IsInvalid() { return m_Ref == 0; } - //int GetRef() { return m_Ref; } - Bitmap* GetCache() { return m_Bitmap; } - - private: - ImageCache() {} - ImageCache(const ImageCache& cache) {} - - void Dispose() { delete m_Bitmap; m_Bitmap = nullptr; if (m_hBuffer) { ::GlobalFree(m_hBuffer); m_hBuffer = nullptr; } } - - Bitmap* m_Bitmap; - HGLOBAL m_hBuffer; - int m_Ref; - }; - - static std::unordered_map c_CacheMap; -}; -std::unordered_map ImageCachePool::c_CacheMap; - - -#define PI (3.14159265f) -#define CONVERT_TO_RADIANS(X) ((X) * (PI / 180.0f)) - -// GrayScale Matrix -const Gdiplus::ColorMatrix TintedImage::c_GreyScaleMatrix = { - 0.299f, 0.299f, 0.299f, 0.0f, 0.0f, - 0.587f, 0.587f, 0.587f, 0.0f, 0.0f, - 0.114f, 0.114f, 0.114f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 1.0f -}; - -const Gdiplus::ColorMatrix TintedImage::c_IdentityMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 1.0f -}; - -TintedImageHelper_DefineOptionArray(TintedImage::c_DefaultOptionArray, L""); - -/* -** The constructor. -** -** If disableTransform is true, ImageCrop and ImageRotate are ignored. -** -*/ -TintedImage::TintedImage(const WCHAR* name, const WCHAR** optionArray, bool disableTransform, MeterWindow* meterWindow) : m_DisableTransform(disableTransform), - m_Name(name ? name : L"ImageName"), - m_OptionArray(optionArray ? optionArray : c_DefaultOptionArray), - m_Bitmap(), - m_BitmapTint(), - m_NeedsCrop(false), - m_NeedsTinting(false), - m_NeedsTransform(false), - m_Crop(-1, -1, -1, -1), - m_CropMode(CROPMODE_TL), - m_GreyScale(false), - m_ColorMatrix(new ColorMatrix(c_IdentityMatrix)), - m_Flip(RotateNoneFlipNone), - m_Rotate(), - m_UseExifOrientation(false), - m_MeterWindow(meterWindow), - m_HasPathChanged(false) -{ -} - -/* -** The destructor -** -*/ -TintedImage::~TintedImage() -{ - DisposeImage(); - - delete m_ColorMatrix; -} - -/* -** Disposes the image buffers. -** -*/ -void TintedImage::DisposeImage() -{ - delete m_BitmapTint; - m_BitmapTint = nullptr; - - m_Bitmap = nullptr; - - if (!m_CacheKey.empty()) - { - ImageCachePool::RemoveCache(m_CacheKey); - m_CacheKey.clear(); - } -} - -/* -** Loads the image from file handle -** -*/ -Bitmap* TintedImage::LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer) -{ - HGLOBAL hBuffer = ::GlobalAlloc(GMEM_MOVEABLE, fileSize); - if (hBuffer) - { - void* pBuffer = ::GlobalLock(hBuffer); - if (pBuffer) - { - DWORD readBytes; - ReadFile(fileHandle, pBuffer, fileSize, &readBytes, nullptr); - ::GlobalUnlock(hBuffer); - - IStream* pStream = nullptr; - if (::CreateStreamOnHGlobal(hBuffer, FALSE, &pStream) == S_OK) - { - Bitmap* bitmap = Bitmap::FromStream(pStream); - pStream->Release(); - - if (Ok == bitmap->GetLastStatus()) - { - GUID guid; - if (Ok == bitmap->GetRawFormat(&guid) && guid != ImageFormatIcon) - { - // Gather EXIF orientation information - if (m_UseExifOrientation) - { - UINT size = bitmap->GetPropertyItemSize(PropertyTagOrientation); - if (size) - { - RotateFlipType flip = RotateNoneFlipNone; - PropertyItem* orientation = (PropertyItem*)new BYTE[size]; - bitmap->GetPropertyItem(PropertyTagOrientation, size, orientation); - if (orientation) - { - switch(*(short*)orientation->value) - { - case 8: - flip = Rotate270FlipNone; - break; - - case 7: - flip = Rotate270FlipX; - break; - - case 6: - flip = Rotate90FlipNone; - break; - - case 5: - flip = Rotate90FlipX; - break; - - case 4: - flip = Rotate180FlipX; - break; - - case 3: - flip = Rotate180FlipNone; - break; - - case 2: - flip = RotateNoneFlipX; - break; - - default: - flip = RotateNoneFlipNone; - } - - bitmap->RotateFlip(flip); - } - delete [] orientation; - } - } - - //////////////////////////////////////////// - // Convert loaded image to faster blittable bitmap (may increase memory usage slightly) - Rect r(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); - Bitmap* clone = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - { - Graphics graphics(clone); - graphics.DrawImage(bitmap, r, 0, 0, r.Width, r.Height, UnitPixel); - } - delete bitmap; - bitmap = clone; - - ::GlobalFree(hBuffer); - hBuffer = nullptr; - //////////////////////////////////////////// - } - *phBuffer = hBuffer; - return bitmap; - } - - delete bitmap; - } - } - - ::GlobalFree(hBuffer); - } - - *phBuffer = nullptr; - return nullptr; -} - -/* -** Loads the image from disk -** -*/ -void TintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) -{ - // Load the bitmap if defined - if (!imageName.empty()) - { - std::wstring filename = m_Path + imageName; - if (m_MeterWindow) m_MeterWindow->MakePathAbsolute(filename); - m_HasPathChanged = false; - - // Check extension and if it is missing, add .png - size_t pos = filename.rfind(L'\\'); - if (filename.find(L'.', (pos == std::wstring::npos) ? 0 : pos + 1) == std::wstring::npos) - { - filename += L".png"; - } - - // Read the bitmap to memory so that it's not locked by GDI+ - DWORD fileSize; - HANDLE fileHandle = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr); - if (fileHandle != INVALID_HANDLE_VALUE && (fileSize = GetFileSize(fileHandle, nullptr)) != INVALID_FILE_SIZE) - { - // Compare the filename/timestamp/filesize to check if the file has been changed (don't load if it's not) - ULONGLONG fileTime; - GetFileTime(fileHandle, nullptr, nullptr, (LPFILETIME)&fileTime); - std::wstring key = ImageCachePool::CreateKey(filename, fileTime, fileSize, m_UseExifOrientation ? L"EXIF" : L"NONE"); - - if (bLoadAlways || wcscmp(key.c_str(), m_CacheKey.c_str()) != 0) - { - DisposeImage(); - - Bitmap* bitmap = ImageCachePool::GetCache(key); - HGLOBAL hBuffer = nullptr; - - m_Bitmap = (bitmap) ? - bitmap : - LoadImageFromFileHandle(fileHandle, fileSize, &hBuffer); - - if (m_Bitmap) - { - m_CacheKey = key; - ImageCachePool::AddCache(key, m_Bitmap, hBuffer); - - // Check whether the new image needs tinting (or cropping, flipping, rotating) - if (!m_NeedsCrop) - { - if (m_Crop.Width >= 0 || m_Crop.Height >= 0) - { - m_NeedsCrop = true; - } - } - if (!m_NeedsTinting) - { - if (m_GreyScale || !CompareColorMatrix(m_ColorMatrix, &c_IdentityMatrix)) - { - m_NeedsTinting = true; - } - } - if (!m_NeedsTransform) - { - if (m_Flip != RotateNoneFlipNone || m_Rotate != 0.0f) - { - m_NeedsTransform = true; - } - } - } - else - { - LogErrorF(m_MeterWindow, L"%s: Unable to load: %s", m_Name, filename.c_str()); - } - } - CloseHandle(fileHandle); - - if (m_Bitmap) - { - // We need a copy of the image if has tinting (or flipping, rotating) - if (m_NeedsCrop || m_NeedsTinting || m_NeedsTransform) - { - delete m_BitmapTint; - m_BitmapTint = nullptr; - - if (m_Bitmap->GetWidth() > 0 && m_Bitmap->GetHeight() > 0) - { - ApplyCrop(); - - if (!m_BitmapTint || (m_BitmapTint->GetWidth() > 0 && m_BitmapTint->GetHeight() > 0)) - { - ApplyTint(); - ApplyTransform(); - } - } - - m_NeedsCrop = false; - m_NeedsTinting = false; - m_NeedsTransform = false; - } - } - } - else - { - LogErrorF(m_MeterWindow, L"%s: Unable to open: %s", m_Name, filename.c_str()); - - if (fileHandle != INVALID_HANDLE_VALUE) - { - CloseHandle(fileHandle); - } - DisposeImage(); - } - } - else if (IsLoaded()) - { - DisposeImage(); - } -} - -/* -** This will apply the cropping. -** -*/ -void TintedImage::ApplyCrop() -{ - if (m_Crop.Width >= 0 && m_Crop.Height >= 0) - { - if (m_Crop.Width == 0 || m_Crop.Height == 0) - { - m_BitmapTint = new Bitmap(0, 0, PixelFormat32bppPARGB); // create dummy bitmap - } - else - { - int imageW = m_Bitmap->GetWidth(); - int imageH = m_Bitmap->GetHeight(); - - int x, y; - - switch (m_CropMode) - { - case CROPMODE_TL: - default: - x = m_Crop.X; - y = m_Crop.Y; - break; - - case CROPMODE_TR: - x = m_Crop.X + imageW; - y = m_Crop.Y; - break; - - case CROPMODE_BR: - x = m_Crop.X + imageW; - y = m_Crop.Y + imageH; - break; - - case CROPMODE_BL: - x = m_Crop.X; - y = m_Crop.Y + imageH; - break; - - case CROPMODE_C: - x = m_Crop.X + (imageW / 2); - y = m_Crop.Y + (imageH / 2); - break; - } - - Rect r(0, 0, m_Crop.Width, m_Crop.Height); - m_BitmapTint = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - - Graphics graphics(m_BitmapTint); - graphics.DrawImage(m_Bitmap, r, x, y, r.Width, r.Height, UnitPixel); - } - } -} - -/* -** This will apply the Greyscale matrix and the color tinting. -** -*/ -void TintedImage::ApplyTint() -{ - bool useColorMatrix = !CompareColorMatrix(m_ColorMatrix, &c_IdentityMatrix); - - if (m_GreyScale || useColorMatrix) - { - Bitmap* original = GetImage(); - Bitmap* tint; - - if (m_GreyScale && !useColorMatrix) - { - tint = TurnGreyscale(original); - } - else - { - ImageAttributes ImgAttr; - ImgAttr.SetColorMatrix(m_ColorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); - - Rect r(0, 0, original->GetWidth(), original->GetHeight()); - - tint = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - - Graphics graphics(tint); - - if (m_GreyScale) - { - Bitmap* gray = TurnGreyscale(original); - graphics.DrawImage(gray, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); - delete gray; - } - else - { - graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); - } - } - - delete m_BitmapTint; - m_BitmapTint = tint; - } -} - -/* -** Turns the image greyscale by applying a greyscale color matrix. -** Note that the returned bitmap image must be freed by caller. -** -*/ -Bitmap* TintedImage::TurnGreyscale(Bitmap* source) -{ - ImageAttributes ImgAttr; - ImgAttr.SetColorMatrix(&c_GreyScaleMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); - - // We need a blank bitmap to paint our greyscale to in case of alpha - Rect r(0, 0, source->GetWidth(), source->GetHeight()); - Bitmap* bitmap = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - - Graphics graphics(bitmap); - graphics.DrawImage(source, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); - - return bitmap; -} - -/* -** This will apply the flipping and rotating. -** -*/ -void TintedImage::ApplyTransform() -{ - if (m_Rotate != 0.0f) - { - Bitmap* original = GetImage(); - - REAL originalW = (REAL)original->GetWidth(); - REAL originalH = (REAL)original->GetHeight(); - - REAL cos_f = cos(CONVERT_TO_RADIANS(m_Rotate)), sin_f = sin(CONVERT_TO_RADIANS(m_Rotate)); - - REAL transformW = fabs(originalW * cos_f) + fabs(originalH * sin_f); - REAL transformH = fabs(originalW * sin_f) + fabs(originalH * cos_f); - - Bitmap* transform = new Bitmap((int)(transformW + 0.5f), (int)(transformH + 0.5f), PixelFormat32bppPARGB); - - Graphics graphics(transform); - graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality); - - REAL cx = transformW / 2.0f; - REAL cy = transformH / 2.0f; - - Matrix rotateMatrix; - rotateMatrix.RotateAt(m_Rotate, PointF(cx, cy)); - - graphics.SetTransform(&rotateMatrix); - - if (m_Flip != RotateNoneFlipNone) - { - original->RotateFlip(m_Flip); - } - - RectF r(cx - originalW / 2.0f, cy - originalH / 2.0f, originalW, originalH); - graphics.DrawImage(original, r, -0.5f, -0.5f, originalW + 1.0f, originalH + 1.0f, UnitPixel); // Makes the anti-aliased edge - - if (m_Flip != RotateNoneFlipNone) - { - original->RotateFlip(m_Flip); - } - - delete m_BitmapTint; - m_BitmapTint = transform; - } - else if (m_Flip != RotateNoneFlipNone) - { - Bitmap* original = GetImage(); - - Rect r(0, 0, original->GetWidth(), original->GetHeight()); - Bitmap* transform = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - - Graphics graphics(transform); - - original->RotateFlip(m_Flip); - - graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel); - - original->RotateFlip(m_Flip); - - delete m_BitmapTint; - m_BitmapTint = transform; - } -} - -/* -** Read the meter-specific options from the ini-file. -** -*/ -void TintedImage::ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath) -{ - // Store the current values so we know if the image needs to be tinted or transformed - Rect oldCrop = m_Crop; - CROPMODE oldCropMode = m_CropMode; - bool oldGreyScale = m_GreyScale; - ColorMatrix oldColorMatrix = *m_ColorMatrix; - RotateFlipType oldFlip = m_Flip; - REAL oldRotate = m_Rotate; - std::wstring oldPath = m_Path; - - m_Path = parser.ReadString(section, m_OptionArray[OptionIndexImagePath], imagePath); - PathUtil::AppendBacklashIfMissing(m_Path); - - m_HasPathChanged = (oldPath != m_Path); - - if (!m_DisableTransform) - { - m_Crop.X = m_Crop.Y = m_Crop.Width = m_Crop.Height = -1; - m_CropMode = CROPMODE_TL; - - const std::wstring& crop = parser.ReadString(section, m_OptionArray[OptionIndexImageCrop], L""); - if (!crop.empty()) - { - if (wcschr(crop.c_str(), L',')) - { - WCHAR* parseSz = _wcsdup(crop.c_str()); - WCHAR* token; - - token = wcstok(parseSz, L","); - if (token) - { - m_Crop.X = parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - m_Crop.Y = parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - m_Crop.Width = parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - m_Crop.Height = parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - m_CropMode = (CROPMODE)parser.ParseInt(token, 0); - } - } - } - } - } - free(parseSz); - } - - if (m_CropMode < CROPMODE_TL || m_CropMode > CROPMODE_C) - { - m_CropMode = CROPMODE_TL; - LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageCrop], crop, section); - } - } - } - - m_NeedsCrop = (oldCrop.X != m_Crop.X || oldCrop.Y != m_Crop.Y || oldCrop.Width != m_Crop.Width || oldCrop.Height != m_Crop.Height || oldCropMode != m_CropMode); - - m_GreyScale = parser.ReadBool(section, m_OptionArray[OptionIndexGreyscale], false); - - Color tint = parser.ReadColor(section, m_OptionArray[OptionIndexImageTint], Color::White); - int alpha = parser.ReadInt(section, m_OptionArray[OptionIndexImageAlpha], tint.GetAlpha()); // for backwards compatibility - alpha = min(255, alpha); - alpha = max(0, alpha); - - *m_ColorMatrix = c_IdentityMatrix; - - // Read in the Color Matrix - // It has to be read in like this because it crashes when reading over 17 floats - // at one time. The parser does it fine, but after putting the returned values - // into the Color Matrix the next time the parser is used it crashes. - std::vector matrix1 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix1]); - if (matrix1.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 0. - { - m_ColorMatrix->m[0][i] = matrix1[i]; - } - } - else - { - m_ColorMatrix->m[0][0] = (REAL)tint.GetRed() / 255.0f; - } - - std::vector matrix2 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix2]); - if (matrix2.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 0. - { - m_ColorMatrix->m[1][i] = matrix2[i]; - } - } - else - { - m_ColorMatrix->m[1][1] = (REAL)tint.GetGreen() / 255.0f; - } - - std::vector matrix3 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix3]); - if (matrix3.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 0. - { - m_ColorMatrix->m[2][i] = matrix3[i]; - } - } - else - { - m_ColorMatrix->m[2][2] = (REAL)tint.GetBlue() / 255.0f; - } - - std::vector matrix4 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix4]); - if (matrix4.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 0. - { - m_ColorMatrix->m[3][i] = matrix4[i]; - } - } - else - { - m_ColorMatrix->m[3][3] = (REAL)alpha / 255.0f; - } - - std::vector matrix5 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix5]); - if (matrix5.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 1. - { - m_ColorMatrix->m[4][i] = matrix5[i]; - } - } - - m_NeedsTinting = (oldGreyScale != m_GreyScale || !CompareColorMatrix(&oldColorMatrix, m_ColorMatrix)); - - m_UseExifOrientation = parser.ReadBool(section, m_OptionArray[OptionIndexUseExifOrientation], false); - - const WCHAR* flip = parser.ReadString(section, m_OptionArray[OptionIndexImageFlip], L"NONE").c_str(); - if (_wcsicmp(flip, L"NONE") == 0) - { - m_Flip = RotateNoneFlipNone; - } - else if (_wcsicmp(flip, L"HORIZONTAL") == 0) - { - m_Flip = RotateNoneFlipX; - } - else if (_wcsicmp(flip, L"VERTICAL") == 0) - { - m_Flip = RotateNoneFlipY; - } - else if (_wcsicmp(flip, L"BOTH") == 0) - { - m_Flip = RotateNoneFlipXY; - } - else - { - LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageFlip], flip, section); - } - - if (!m_DisableTransform) - { - m_Rotate = (REAL)parser.ReadFloat(section, m_OptionArray[OptionIndexImageRotate], 0.0); - } - - m_NeedsTransform = (oldFlip != m_Flip || oldRotate != m_Rotate); -} - -/* -** Compares the two given color matrices. -** -*/ -bool TintedImage::CompareColorMatrix(const Gdiplus::ColorMatrix* a, const Gdiplus::ColorMatrix* b) -{ - for (int i = 0; i < 5; ++i) - { - for (int j = 0; j < 4; ++j) // The fifth column is reserved. - { - if (a->m[i][j] != b->m[i][j]) - { - return false; - } - } - } - return true; -} +/* + Copyright (C) 2010 Kimmo Pekkola, Matt King, spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/PathUtil.h" +#include "TintedImage.h" +#include "ConfigParser.h" +#include "System.h" +#include "Error.h" +#include "Logger.h" + +using namespace Gdiplus; + + +class ImageCachePool +{ +public: + static std::wstring CreateKey(const std::wstring& name, ULONGLONG time, DWORD size, WCHAR* exifOrientation) + { + std::wstring key; + + WCHAR buffer[MAX_PATH]; + if (PathCanonicalize(buffer, name.c_str())) + { + key = buffer; + } + else + { + key = name; + } + _wcsupr(&key[0]); + + size_t len = _snwprintf_s(buffer, _TRUNCATE, L":%llx:%x:%s", time, size, exifOrientation); + key.append(buffer, len); + + return key; + } + + static Bitmap* GetCache(const std::wstring& key) + { + std::unordered_map::const_iterator iter = c_CacheMap.find(key); + if (iter != c_CacheMap.end()) + { + return (*iter).second->GetCache(); + } + return nullptr; + } + + static void AddCache(const std::wstring& key, Bitmap* bitmap, HGLOBAL hBuffer) + { + std::unordered_map::const_iterator iter = c_CacheMap.find(key); + if (iter != c_CacheMap.end()) + { + (*iter).second->AddRef(); + //LogDebugF(L"* ADD: key=%s, ref=%i", key.c_str(), (*iter).second->GetRef()); + } + else + { + c_CacheMap[key] = new ImageCache(bitmap, hBuffer); + //LogDebugF(L"* ADD: key=%s, ref=new", key.c_str()); + } + } + + static void RemoveCache(const std::wstring& key) + { + std::unordered_map::const_iterator iter = c_CacheMap.find(key); + if (iter != c_CacheMap.end()) + { + ImageCache* cache = (*iter).second; + cache->Release(); + //LogDebugF(L"* REMOVE: key=%s, ref=%i", key.c_str(), cache->GetRef()); + + if (cache->IsInvalid()) + { + //LogDebugF(L"* EMPTY-ERASE: key=%s", key.c_str()); + c_CacheMap.erase(iter); + delete cache; + } + } + } + +private: + class ImageCache + { + public: + ImageCache(Bitmap* bitmap, HGLOBAL hBuffer) : m_Bitmap(bitmap), m_hBuffer(hBuffer), m_Ref(1) {} + ~ImageCache() { Dispose(); } + + void AddRef() { ++m_Ref; } + void Release() { if (m_Ref > 0) { --m_Ref; } if (m_Ref == 0) { Dispose(); } } + + bool IsInvalid() { return m_Ref == 0; } + //int GetRef() { return m_Ref; } + Bitmap* GetCache() { return m_Bitmap; } + + private: + ImageCache() {} + ImageCache(const ImageCache& cache) {} + + void Dispose() { delete m_Bitmap; m_Bitmap = nullptr; if (m_hBuffer) { ::GlobalFree(m_hBuffer); m_hBuffer = nullptr; } } + + Bitmap* m_Bitmap; + HGLOBAL m_hBuffer; + int m_Ref; + }; + + static std::unordered_map c_CacheMap; +}; +std::unordered_map ImageCachePool::c_CacheMap; + + +#define PI (3.14159265f) +#define CONVERT_TO_RADIANS(X) ((X) * (PI / 180.0f)) + +// GrayScale Matrix +const Gdiplus::ColorMatrix TintedImage::c_GreyScaleMatrix = { + 0.299f, 0.299f, 0.299f, 0.0f, 0.0f, + 0.587f, 0.587f, 0.587f, 0.0f, 0.0f, + 0.114f, 0.114f, 0.114f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f +}; + +const Gdiplus::ColorMatrix TintedImage::c_IdentityMatrix = { + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f +}; + +TintedImageHelper_DefineOptionArray(TintedImage::c_DefaultOptionArray, L""); + +/* +** The constructor. +** +** If disableTransform is true, ImageCrop and ImageRotate are ignored. +** +*/ +TintedImage::TintedImage(const WCHAR* name, const WCHAR** optionArray, bool disableTransform, MeterWindow* meterWindow) : m_DisableTransform(disableTransform), + m_Name(name ? name : L"ImageName"), + m_OptionArray(optionArray ? optionArray : c_DefaultOptionArray), + m_Bitmap(), + m_BitmapTint(), + m_NeedsCrop(false), + m_NeedsTinting(false), + m_NeedsTransform(false), + m_Crop(-1, -1, -1, -1), + m_CropMode(CROPMODE_TL), + m_GreyScale(false), + m_ColorMatrix(new ColorMatrix(c_IdentityMatrix)), + m_Flip(RotateNoneFlipNone), + m_Rotate(), + m_UseExifOrientation(false), + m_MeterWindow(meterWindow), + m_HasPathChanged(false) +{ +} + +/* +** The destructor +** +*/ +TintedImage::~TintedImage() +{ + DisposeImage(); + + delete m_ColorMatrix; +} + +/* +** Disposes the image buffers. +** +*/ +void TintedImage::DisposeImage() +{ + delete m_BitmapTint; + m_BitmapTint = nullptr; + + m_Bitmap = nullptr; + + if (!m_CacheKey.empty()) + { + ImageCachePool::RemoveCache(m_CacheKey); + m_CacheKey.clear(); + } +} + +/* +** Loads the image from file handle +** +*/ +Bitmap* TintedImage::LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer) +{ + HGLOBAL hBuffer = ::GlobalAlloc(GMEM_MOVEABLE, fileSize); + if (hBuffer) + { + void* pBuffer = ::GlobalLock(hBuffer); + if (pBuffer) + { + DWORD readBytes; + ReadFile(fileHandle, pBuffer, fileSize, &readBytes, nullptr); + ::GlobalUnlock(hBuffer); + + IStream* pStream = nullptr; + if (::CreateStreamOnHGlobal(hBuffer, FALSE, &pStream) == S_OK) + { + Bitmap* bitmap = Bitmap::FromStream(pStream); + pStream->Release(); + + if (Ok == bitmap->GetLastStatus()) + { + GUID guid; + if (Ok == bitmap->GetRawFormat(&guid) && guid != ImageFormatIcon) + { + // Gather EXIF orientation information + if (m_UseExifOrientation) + { + UINT size = bitmap->GetPropertyItemSize(PropertyTagOrientation); + if (size) + { + RotateFlipType flip = RotateNoneFlipNone; + PropertyItem* orientation = (PropertyItem*)new BYTE[size]; + bitmap->GetPropertyItem(PropertyTagOrientation, size, orientation); + if (orientation) + { + switch(*(short*)orientation->value) + { + case 8: + flip = Rotate270FlipNone; + break; + + case 7: + flip = Rotate270FlipX; + break; + + case 6: + flip = Rotate90FlipNone; + break; + + case 5: + flip = Rotate90FlipX; + break; + + case 4: + flip = Rotate180FlipX; + break; + + case 3: + flip = Rotate180FlipNone; + break; + + case 2: + flip = RotateNoneFlipX; + break; + + default: + flip = RotateNoneFlipNone; + } + + bitmap->RotateFlip(flip); + } + delete [] orientation; + } + } + + //////////////////////////////////////////// + // Convert loaded image to faster blittable bitmap (may increase memory usage slightly) + Rect r(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); + Bitmap* clone = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + { + Graphics graphics(clone); + graphics.DrawImage(bitmap, r, 0, 0, r.Width, r.Height, UnitPixel); + } + delete bitmap; + bitmap = clone; + + ::GlobalFree(hBuffer); + hBuffer = nullptr; + //////////////////////////////////////////// + } + *phBuffer = hBuffer; + return bitmap; + } + + delete bitmap; + } + } + + ::GlobalFree(hBuffer); + } + + *phBuffer = nullptr; + return nullptr; +} + +/* +** Loads the image from disk +** +*/ +void TintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) +{ + // Load the bitmap if defined + if (!imageName.empty()) + { + std::wstring filename = m_WorkDirectory + imageName; + if (m_MeterWindow) m_MeterWindow->MakePathAbsolute(filename); + m_HasPathChanged = false; + + // Check extension and if it is missing, add .png + size_t pos = filename.rfind(L'\\'); + if (filename.find(L'.', (pos == std::wstring::npos) ? 0 : pos + 1) == std::wstring::npos) + { + filename += L".png"; + } + + // Read the bitmap to memory so that it's not locked by GDI+ + DWORD fileSize; + HANDLE fileHandle = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr); + if (fileHandle != INVALID_HANDLE_VALUE && (fileSize = GetFileSize(fileHandle, nullptr)) != INVALID_FILE_SIZE) + { + // Compare the filename/timestamp/filesize to check if the file has been changed (don't load if it's not) + ULONGLONG fileTime; + GetFileTime(fileHandle, nullptr, nullptr, (LPFILETIME)&fileTime); + std::wstring key = ImageCachePool::CreateKey(filename, fileTime, fileSize, m_UseExifOrientation ? L"EXIF" : L"NONE"); + + if (bLoadAlways || wcscmp(key.c_str(), m_CacheKey.c_str()) != 0) + { + DisposeImage(); + + Bitmap* bitmap = ImageCachePool::GetCache(key); + HGLOBAL hBuffer = nullptr; + + m_Bitmap = (bitmap) ? + bitmap : + LoadImageFromFileHandle(fileHandle, fileSize, &hBuffer); + + if (m_Bitmap) + { + m_CacheKey = key; + ImageCachePool::AddCache(key, m_Bitmap, hBuffer); + + // Check whether the new image needs tinting (or cropping, flipping, rotating) + if (!m_NeedsCrop) + { + if (m_Crop.Width >= 0 || m_Crop.Height >= 0) + { + m_NeedsCrop = true; + } + } + if (!m_NeedsTinting) + { + if (m_GreyScale || !CompareColorMatrix(m_ColorMatrix, &c_IdentityMatrix)) + { + m_NeedsTinting = true; + } + } + if (!m_NeedsTransform) + { + if (m_Flip != RotateNoneFlipNone || m_Rotate != 0.0f) + { + m_NeedsTransform = true; + } + } + } + else + { + LogErrorF(m_MeterWindow, L"%s: Unable to load: %s", m_Name, filename.c_str()); + } + } + CloseHandle(fileHandle); + + if (m_Bitmap) + { + // We need a copy of the image if has tinting (or flipping, rotating) + if (m_NeedsCrop || m_NeedsTinting || m_NeedsTransform) + { + delete m_BitmapTint; + m_BitmapTint = nullptr; + + if (m_Bitmap->GetWidth() > 0 && m_Bitmap->GetHeight() > 0) + { + ApplyCrop(); + + if (!m_BitmapTint || (m_BitmapTint->GetWidth() > 0 && m_BitmapTint->GetHeight() > 0)) + { + ApplyTint(); + ApplyTransform(); + } + } + + m_NeedsCrop = false; + m_NeedsTinting = false; + m_NeedsTransform = false; + } + } + } + else + { + LogErrorF(m_MeterWindow, L"%s: Unable to open: %s", m_Name, filename.c_str()); + + if (fileHandle != INVALID_HANDLE_VALUE) + { + CloseHandle(fileHandle); + } + DisposeImage(); + } + } + else if (IsLoaded()) + { + DisposeImage(); + } +} + +/* +** This will apply the cropping. +** +*/ +void TintedImage::ApplyCrop() +{ + if (m_Crop.Width >= 0 && m_Crop.Height >= 0) + { + if (m_Crop.Width == 0 || m_Crop.Height == 0) + { + m_BitmapTint = new Bitmap(0, 0, PixelFormat32bppPARGB); // create dummy bitmap + } + else + { + int imageW = m_Bitmap->GetWidth(); + int imageH = m_Bitmap->GetHeight(); + + int x, y; + + switch (m_CropMode) + { + case CROPMODE_TL: + default: + x = m_Crop.X; + y = m_Crop.Y; + break; + + case CROPMODE_TR: + x = m_Crop.X + imageW; + y = m_Crop.Y; + break; + + case CROPMODE_BR: + x = m_Crop.X + imageW; + y = m_Crop.Y + imageH; + break; + + case CROPMODE_BL: + x = m_Crop.X; + y = m_Crop.Y + imageH; + break; + + case CROPMODE_C: + x = m_Crop.X + (imageW / 2); + y = m_Crop.Y + (imageH / 2); + break; + } + + Rect r(0, 0, m_Crop.Width, m_Crop.Height); + m_BitmapTint = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + + Graphics graphics(m_BitmapTint); + graphics.DrawImage(m_Bitmap, r, x, y, r.Width, r.Height, UnitPixel); + } + } +} + +/* +** This will apply the Greyscale matrix and the color tinting. +** +*/ +void TintedImage::ApplyTint() +{ + bool useColorMatrix = !CompareColorMatrix(m_ColorMatrix, &c_IdentityMatrix); + + if (m_GreyScale || useColorMatrix) + { + Bitmap* original = GetImage(); + Bitmap* tint; + + if (m_GreyScale && !useColorMatrix) + { + tint = TurnGreyscale(original); + } + else + { + ImageAttributes ImgAttr; + ImgAttr.SetColorMatrix(m_ColorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); + + Rect r(0, 0, original->GetWidth(), original->GetHeight()); + + tint = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + + Graphics graphics(tint); + + if (m_GreyScale) + { + Bitmap* gray = TurnGreyscale(original); + graphics.DrawImage(gray, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); + delete gray; + } + else + { + graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); + } + } + + delete m_BitmapTint; + m_BitmapTint = tint; + } +} + +/* +** Turns the image greyscale by applying a greyscale color matrix. +** Note that the returned bitmap image must be freed by caller. +** +*/ +Bitmap* TintedImage::TurnGreyscale(Bitmap* source) +{ + ImageAttributes ImgAttr; + ImgAttr.SetColorMatrix(&c_GreyScaleMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); + + // We need a blank bitmap to paint our greyscale to in case of alpha + Rect r(0, 0, source->GetWidth(), source->GetHeight()); + Bitmap* bitmap = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + + Graphics graphics(bitmap); + graphics.DrawImage(source, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); + + return bitmap; +} + +/* +** This will apply the flipping and rotating. +** +*/ +void TintedImage::ApplyTransform() +{ + if (m_Rotate != 0.0f) + { + Bitmap* original = GetImage(); + + REAL originalW = (REAL)original->GetWidth(); + REAL originalH = (REAL)original->GetHeight(); + + REAL cos_f = cos(CONVERT_TO_RADIANS(m_Rotate)), sin_f = sin(CONVERT_TO_RADIANS(m_Rotate)); + + REAL transformW = fabs(originalW * cos_f) + fabs(originalH * sin_f); + REAL transformH = fabs(originalW * sin_f) + fabs(originalH * cos_f); + + Bitmap* transform = new Bitmap((int)(transformW + 0.5f), (int)(transformH + 0.5f), PixelFormat32bppPARGB); + + Graphics graphics(transform); + graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality); + + REAL cx = transformW / 2.0f; + REAL cy = transformH / 2.0f; + + Matrix rotateMatrix; + rotateMatrix.RotateAt(m_Rotate, PointF(cx, cy)); + + graphics.SetTransform(&rotateMatrix); + + if (m_Flip != RotateNoneFlipNone) + { + original->RotateFlip(m_Flip); + } + + RectF r(cx - originalW / 2.0f, cy - originalH / 2.0f, originalW, originalH); + graphics.DrawImage(original, r, -0.5f, -0.5f, originalW + 1.0f, originalH + 1.0f, UnitPixel); // Makes the anti-aliased edge + + if (m_Flip != RotateNoneFlipNone) + { + original->RotateFlip(m_Flip); + } + + delete m_BitmapTint; + m_BitmapTint = transform; + } + else if (m_Flip != RotateNoneFlipNone) + { + Bitmap* original = GetImage(); + + Rect r(0, 0, original->GetWidth(), original->GetHeight()); + Bitmap* transform = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + + Graphics graphics(transform); + + original->RotateFlip(m_Flip); + + graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel); + + original->RotateFlip(m_Flip); + + delete m_BitmapTint; + m_BitmapTint = transform; + } +} + +/* +** Read the meter-specific options from the ini-file. +** +*/ +void TintedImage::ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath) +{ + // Store the current values so we know if the image needs to be tinted or transformed + Rect oldCrop = m_Crop; + CROPMODE oldCropMode = m_CropMode; + bool oldGreyScale = m_GreyScale; + ColorMatrix oldColorMatrix = *m_ColorMatrix; + RotateFlipType oldFlip = m_Flip; + REAL oldRotate = m_Rotate; + std::wstring oldPath = m_WorkDirectory; + + m_WorkDirectory = parser.ReadString(section, m_OptionArray[OptionIndexImagePath], imagePath); + PathUtil::AppendBacklashIfMissing(m_WorkDirectory); + + m_HasPathChanged = (oldPath != m_WorkDirectory); + + if (!m_DisableTransform) + { + m_Crop.X = m_Crop.Y = m_Crop.Width = m_Crop.Height = -1; + m_CropMode = CROPMODE_TL; + + const std::wstring& crop = parser.ReadString(section, m_OptionArray[OptionIndexImageCrop], L""); + if (!crop.empty()) + { + if (wcschr(crop.c_str(), L',')) + { + WCHAR* parseSz = _wcsdup(crop.c_str()); + WCHAR* token; + + token = wcstok(parseSz, L","); + if (token) + { + m_Crop.X = parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + m_Crop.Y = parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + m_Crop.Width = parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + m_Crop.Height = parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + m_CropMode = (CROPMODE)parser.ParseInt(token, 0); + } + } + } + } + } + free(parseSz); + } + + if (m_CropMode < CROPMODE_TL || m_CropMode > CROPMODE_C) + { + m_CropMode = CROPMODE_TL; + LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageCrop], crop, section); + } + } + } + + m_NeedsCrop = (oldCrop.X != m_Crop.X || oldCrop.Y != m_Crop.Y || oldCrop.Width != m_Crop.Width || oldCrop.Height != m_Crop.Height || oldCropMode != m_CropMode); + + m_GreyScale = parser.ReadBool(section, m_OptionArray[OptionIndexGreyscale], false); + + Color tint = parser.ReadColor(section, m_OptionArray[OptionIndexImageTint], Color::White); + int alpha = parser.ReadInt(section, m_OptionArray[OptionIndexImageAlpha], tint.GetAlpha()); // for backwards compatibility + alpha = min(255, alpha); + alpha = max(0, alpha); + + *m_ColorMatrix = c_IdentityMatrix; + + // Read in the Color Matrix + // It has to be read in like this because it crashes when reading over 17 floats + // at one time. The parser does it fine, but after putting the returned values + // into the Color Matrix the next time the parser is used it crashes. + std::vector matrix1 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix1]); + if (matrix1.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 0. + { + m_ColorMatrix->m[0][i] = matrix1[i]; + } + } + else + { + m_ColorMatrix->m[0][0] = (REAL)tint.GetRed() / 255.0f; + } + + std::vector matrix2 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix2]); + if (matrix2.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 0. + { + m_ColorMatrix->m[1][i] = matrix2[i]; + } + } + else + { + m_ColorMatrix->m[1][1] = (REAL)tint.GetGreen() / 255.0f; + } + + std::vector matrix3 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix3]); + if (matrix3.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 0. + { + m_ColorMatrix->m[2][i] = matrix3[i]; + } + } + else + { + m_ColorMatrix->m[2][2] = (REAL)tint.GetBlue() / 255.0f; + } + + std::vector matrix4 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix4]); + if (matrix4.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 0. + { + m_ColorMatrix->m[3][i] = matrix4[i]; + } + } + else + { + m_ColorMatrix->m[3][3] = (REAL)alpha / 255.0f; + } + + std::vector matrix5 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix5]); + if (matrix5.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 1. + { + m_ColorMatrix->m[4][i] = matrix5[i]; + } + } + + m_NeedsTinting = (oldGreyScale != m_GreyScale || !CompareColorMatrix(&oldColorMatrix, m_ColorMatrix)); + + m_UseExifOrientation = parser.ReadBool(section, m_OptionArray[OptionIndexUseExifOrientation], false); + + const WCHAR* flip = parser.ReadString(section, m_OptionArray[OptionIndexImageFlip], L"NONE").c_str(); + if (_wcsicmp(flip, L"NONE") == 0) + { + m_Flip = RotateNoneFlipNone; + } + else if (_wcsicmp(flip, L"HORIZONTAL") == 0) + { + m_Flip = RotateNoneFlipX; + } + else if (_wcsicmp(flip, L"VERTICAL") == 0) + { + m_Flip = RotateNoneFlipY; + } + else if (_wcsicmp(flip, L"BOTH") == 0) + { + m_Flip = RotateNoneFlipXY; + } + else + { + LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageFlip], flip, section); + } + + if (!m_DisableTransform) + { + m_Rotate = (REAL)parser.ReadFloat(section, m_OptionArray[OptionIndexImageRotate], 0.0); + } + + m_NeedsTransform = (oldFlip != m_Flip || oldRotate != m_Rotate); +} + +/* +** Compares the two given color matrices. +** +*/ +bool TintedImage::CompareColorMatrix(const Gdiplus::ColorMatrix* a, const Gdiplus::ColorMatrix* b) +{ + for (int i = 0; i < 5; ++i) + { + for (int j = 0; j < 4; ++j) // The fifth column is reserved. + { + if (a->m[i][j] != b->m[i][j]) + { + return false; + } + } + } + return true; +} diff --git a/Library/TintedImage.h b/Library/TintedImage.h index 2cb7c741..395c90c3 100644 --- a/Library/TintedImage.h +++ b/Library/TintedImage.h @@ -1,144 +1,144 @@ -/* - Copyright (C) 2010 Kimmo Pekkola, Matt King, spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __TINTEDIMAGE_H__ -#define __TINTEDIMAGE_H__ - -#include -#include // For Gdiplus.h. -#include -#include -#include "MeterWindow.h" - -/* -** Helper macro to define an array of option names. A prefix must be given. -** -*/ -#define TintedImageHelper_DefineOptionArray(name, prefix) \ - const WCHAR* (name)[TintedImage::OptionCount] = { \ - prefix L"ImageCrop", \ - prefix L"Greyscale", \ - prefix L"ImageTint", \ - prefix L"ImageAlpha", \ - prefix L"ColorMatrix1", \ - prefix L"ColorMatrix2", \ - prefix L"ColorMatrix3", \ - prefix L"ColorMatrix4", \ - prefix L"ColorMatrix5", \ - prefix L"ImageFlip", \ - prefix L"ImageRotate", \ - prefix L"UseExifOrientation", \ - prefix L"ImagePath" \ - }; - -class ConfigParser; - -class TintedImage -{ -public: - enum OptionIndex - { - OptionIndexImageCrop = 0, - OptionIndexGreyscale, - OptionIndexImageTint, - OptionIndexImageAlpha, - OptionIndexColorMatrix1, - OptionIndexColorMatrix2, - OptionIndexColorMatrix3, - OptionIndexColorMatrix4, - OptionIndexColorMatrix5, - OptionIndexImageFlip, - OptionIndexImageRotate, - OptionIndexUseExifOrientation, - OptionIndexImagePath, - - OptionCount - }; - - TintedImage(const WCHAR* name = L"ImageName", const WCHAR** optionArray = c_DefaultOptionArray, bool disableTransform = false, MeterWindow* meterWindow = nullptr); - ~TintedImage(); - - TintedImage(const TintedImage& other) = delete; - TintedImage& operator=(TintedImage other) = delete; - - void ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath = L""); - - bool IsLoaded() { return (m_Bitmap != nullptr); } - bool IsTinted() { return (m_BitmapTint != nullptr); } - bool IsOptionsChanged() { return m_NeedsCrop || m_NeedsTinting || m_NeedsTransform || m_HasPathChanged; } - void ClearOptionFlags() { m_NeedsCrop = m_NeedsTinting = m_NeedsTransform = m_HasPathChanged = false; } - - Gdiplus::Bitmap* GetOriginalImage() { return m_Bitmap; } - Gdiplus::Bitmap* GetTintedImage() { return m_BitmapTint; } - Gdiplus::Bitmap* GetImage() { return (m_BitmapTint) ? m_BitmapTint : m_Bitmap; } - - void DisposeImage(); - void LoadImage(const std::wstring& imageName, bool bLoadAlways); - -protected: - enum CROPMODE - { - CROPMODE_TL = 1, - CROPMODE_TR, - CROPMODE_BR, - CROPMODE_BL, - CROPMODE_C - }; - - void ApplyCrop(); - void ApplyTint(); - void ApplyTransform(); - - Gdiplus::Bitmap* LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer); - - static Gdiplus::Bitmap* TurnGreyscale(Gdiplus::Bitmap* source); - static bool CompareColorMatrix(const Gdiplus::ColorMatrix* a, const Gdiplus::ColorMatrix* b); - - Gdiplus::Bitmap* m_Bitmap; - Gdiplus::Bitmap* m_BitmapTint; // Tinted bitmap - - const WCHAR* m_Name; - const WCHAR** m_OptionArray; - const bool m_DisableTransform; - - bool m_NeedsCrop; - bool m_NeedsTinting; - bool m_NeedsTransform; - - Gdiplus::Rect m_Crop; - CROPMODE m_CropMode; - bool m_GreyScale; - Gdiplus::ColorMatrix* m_ColorMatrix; - Gdiplus::RotateFlipType m_Flip; - Gdiplus::REAL m_Rotate; - bool m_UseExifOrientation; - - std::wstring m_Path; - bool m_HasPathChanged; - - std::wstring m_CacheKey; - - MeterWindow* m_MeterWindow; - - static const Gdiplus::ColorMatrix c_GreyScaleMatrix; - static const Gdiplus::ColorMatrix c_IdentityMatrix; - - static const WCHAR* c_DefaultOptionArray[OptionCount]; -}; - -#endif +/* + Copyright (C) 2010 Kimmo Pekkola, Matt King, spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __TINTEDIMAGE_H__ +#define __TINTEDIMAGE_H__ + +#include +#include // For Gdiplus.h. +#include +#include +#include "MeterWindow.h" + +/* +** Helper macro to define an array of option names. A prefix must be given. +** +*/ +#define TintedImageHelper_DefineOptionArray(name, prefix) \ + const WCHAR* (name)[TintedImage::OptionCount] = { \ + prefix L"ImageCrop", \ + prefix L"Greyscale", \ + prefix L"ImageTint", \ + prefix L"ImageAlpha", \ + prefix L"ColorMatrix1", \ + prefix L"ColorMatrix2", \ + prefix L"ColorMatrix3", \ + prefix L"ColorMatrix4", \ + prefix L"ColorMatrix5", \ + prefix L"ImageFlip", \ + prefix L"ImageRotate", \ + prefix L"UseExifOrientation", \ + prefix L"ImagePath" \ + }; + +class ConfigParser; + +class TintedImage +{ +public: + enum OptionIndex + { + OptionIndexImageCrop = 0, + OptionIndexGreyscale, + OptionIndexImageTint, + OptionIndexImageAlpha, + OptionIndexColorMatrix1, + OptionIndexColorMatrix2, + OptionIndexColorMatrix3, + OptionIndexColorMatrix4, + OptionIndexColorMatrix5, + OptionIndexImageFlip, + OptionIndexImageRotate, + OptionIndexUseExifOrientation, + OptionIndexImagePath, + + OptionCount + }; + + TintedImage(const WCHAR* name = L"ImageName", const WCHAR** optionArray = c_DefaultOptionArray, bool disableTransform = false, MeterWindow* meterWindow = nullptr); + ~TintedImage(); + + TintedImage(const TintedImage& other) = delete; + TintedImage& operator=(TintedImage other) = delete; + + void ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath = L""); + + bool IsLoaded() { return (m_Bitmap != nullptr); } + bool IsTinted() { return (m_BitmapTint != nullptr); } + bool IsOptionsChanged() { return m_NeedsCrop || m_NeedsTinting || m_NeedsTransform || m_HasPathChanged; } + void ClearOptionFlags() { m_NeedsCrop = m_NeedsTinting = m_NeedsTransform = m_HasPathChanged = false; } + + Gdiplus::Bitmap* GetOriginalImage() { return m_Bitmap; } + Gdiplus::Bitmap* GetTintedImage() { return m_BitmapTint; } + Gdiplus::Bitmap* GetImage() { return (m_BitmapTint) ? m_BitmapTint : m_Bitmap; } + + void DisposeImage(); + void LoadImage(const std::wstring& imageName, bool bLoadAlways); + +protected: + enum CROPMODE + { + CROPMODE_TL = 1, + CROPMODE_TR, + CROPMODE_BR, + CROPMODE_BL, + CROPMODE_C + }; + + void ApplyCrop(); + void ApplyTint(); + void ApplyTransform(); + + Gdiplus::Bitmap* LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer); + + static Gdiplus::Bitmap* TurnGreyscale(Gdiplus::Bitmap* source); + static bool CompareColorMatrix(const Gdiplus::ColorMatrix* a, const Gdiplus::ColorMatrix* b); + + Gdiplus::Bitmap* m_Bitmap; + Gdiplus::Bitmap* m_BitmapTint; // Tinted bitmap + + const WCHAR* m_Name; + const WCHAR** m_OptionArray; + const bool m_DisableTransform; + + bool m_NeedsCrop; + bool m_NeedsTinting; + bool m_NeedsTransform; + + Gdiplus::Rect m_Crop; + CROPMODE m_CropMode; + bool m_GreyScale; + Gdiplus::ColorMatrix* m_ColorMatrix; + Gdiplus::RotateFlipType m_Flip; + Gdiplus::REAL m_Rotate; + bool m_UseExifOrientation; + + std::wstring m_WorkDirectory; + bool m_HasPathChanged; + + std::wstring m_CacheKey; + + MeterWindow* m_MeterWindow; + + static const Gdiplus::ColorMatrix c_GreyScaleMatrix; + static const Gdiplus::ColorMatrix c_IdentityMatrix; + + static const WCHAR* c_DefaultOptionArray[OptionCount]; +}; + +#endif diff --git a/Library/TrayWindow.cpp b/Library/TrayWindow.cpp deleted file mode 100644 index 9ae6f355..00000000 --- a/Library/TrayWindow.cpp +++ /dev/null @@ -1,736 +0,0 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "TrayWindow.h" -#include "Measure.h" -#include "resource.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "DialogAbout.h" -#include "DialogManage.h" -#include "System.h" -#include "Error.h" -#include "RainmeterQuery.h" -#include "resource.h" -#include "../Version.h" - -#define RAINMETER_OFFICIAL L"http://rainmeter.net/cms/" -#define RAINMETER_HELP L"http://docs.rainmeter.net/" - -#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) - -enum TIMER -{ - TIMER_ADDTRAYICON = 1, - TIMER_TRAYMEASURE = 3 -}; -enum INTERVAL -{ - INTERVAL_ADDTRAYICON = 3000, - INTERVAL_TRAYMEASURE = 1000 -}; - -const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(L"TaskbarCreated"); - -using namespace Gdiplus; - -TrayWindow::TrayWindow() : - m_Icon(), - m_Measure(), - m_MeterType(TRAY_METER_TYPE_HISTOGRAM), - m_Color1(0, 100, 0), - m_Color2(0, 255, 0), - m_Bitmap(), - m_Values(), - m_Pos(), - m_Notification(TRAY_NOTIFICATION_NONE), - m_TrayContextMenuEnabled(true), - m_IconEnabled(true) -{ -} - -TrayWindow::~TrayWindow() -{ - KillTimer(m_Window, TIMER_ADDTRAYICON); - KillTimer(m_Window, TIMER_TRAYMEASURE); - RemoveTrayIcon(); - - delete m_Bitmap; - delete m_Measure; - - for (size_t i = 0, isize = m_Icons.size(); i < isize; ++i) - { - DestroyIcon(m_Icons[i]); - } - m_Icons.clear(); - - if (m_Window) DestroyWindow(m_Window); -} - -void TrayWindow::Initialize() -{ - WNDCLASS wc = {0}; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.hInstance = GetRainmeter().GetModuleInstance(); - wc.lpszClassName = L"RainmeterTrayClass"; - wc.hIcon = GetIcon(IDI_RAINMETER); - - RegisterClass(&wc); - - m_Window = CreateWindowEx( - WS_EX_TOOLWINDOW, - L"RainmeterTrayClass", - nullptr, - WS_POPUP | WS_DISABLED, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - wc.hInstance, - this); - - SetWindowPos(m_Window, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); -} - -bool TrayWindow::AddTrayIcon() -{ - NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; - tnid.hWnd = m_Window; - tnid.uID = IDI_TRAY; - tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; - tnid.uCallbackMessage = WM_TRAY_NOTIFYICON; - tnid.hIcon = m_Icon; - wcsncpy_s(tnid.szTip, APPNAME, _TRUNCATE); - - return (Shell_NotifyIcon(NIM_ADD, &tnid) || GetLastError() != ERROR_TIMEOUT); -} - -bool TrayWindow::IsTrayIconReady() -{ - NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; - tnid.hWnd = m_Window; - tnid.uID = IDI_TRAY; - - return Shell_NotifyIcon(NIM_MODIFY, &tnid) != FALSE; -} - -void TrayWindow::TryAddTrayIcon() -{ - if (IsTrayIconReady()) - { - ModifyTrayIcon(0); - return; - } - - if (m_Icon) - { - DestroyIcon(m_Icon); - m_Icon = nullptr; - } - - m_Icon = CreateTrayIcon(0); - - if (!AddTrayIcon()) - { - SetTimer(m_Window, TIMER_ADDTRAYICON, INTERVAL_ADDTRAYICON, nullptr); - } -} - -void TrayWindow::CheckTrayIcon() -{ - if (IsTrayIconReady() || AddTrayIcon()) - { - KillTimer(m_Window, TIMER_ADDTRAYICON); - } -} - -void TrayWindow::RemoveTrayIcon() -{ - NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; - tnid.hWnd = m_Window; - tnid.uID = IDI_TRAY; - tnid.uFlags = 0; - - Shell_NotifyIcon(NIM_DELETE, &tnid); - - if (m_Icon) - { - DestroyIcon(m_Icon); - m_Icon = nullptr; - } -} - -void TrayWindow::ModifyTrayIcon(double value) -{ - if (m_Icon) - { - DestroyIcon(m_Icon); - m_Icon = nullptr; - } - - m_Icon = CreateTrayIcon(value); - - NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; - tnid.hWnd = m_Window; - tnid.uID = IDI_TRAY; - tnid.uFlags = NIF_ICON; - tnid.hIcon = m_Icon; - - Shell_NotifyIcon(NIM_MODIFY, &tnid); -} - -HICON TrayWindow::CreateTrayIcon(double value) -{ - if (m_Measure != nullptr) - { - if (m_MeterType == TRAY_METER_TYPE_HISTOGRAM) - { - m_Values[m_Pos] = value; - m_Pos = (m_Pos + 1) % TRAYICON_SIZE; - - Bitmap trayBitmap(TRAYICON_SIZE, TRAYICON_SIZE); - Graphics graphics(&trayBitmap); - graphics.SetSmoothingMode(SmoothingModeAntiAlias); - - Point points[TRAYICON_SIZE + 2]; - points[0].X = 0; - points[0].Y = TRAYICON_SIZE; - points[TRAYICON_SIZE + 1].X = TRAYICON_SIZE - 1; - points[TRAYICON_SIZE + 1].Y = TRAYICON_SIZE; - - for (int i = 0; i < TRAYICON_SIZE; ++i) - { - points[i + 1].X = i; - points[i + 1].Y = (int)(TRAYICON_SIZE * (1.0 - m_Values[(m_Pos + i) % TRAYICON_SIZE])); - } - - SolidBrush brush(m_Color1); - graphics.FillRectangle(&brush, 0, 0, TRAYICON_SIZE, TRAYICON_SIZE); - - SolidBrush brush2(m_Color2); - graphics.FillPolygon(&brush2, points, TRAYICON_SIZE + 2); - - HICON icon = nullptr; - trayBitmap.GetHICON(&icon); - return icon; - } - else if (m_MeterType == TRAY_METER_TYPE_BITMAP && (m_Bitmap || !m_Icons.empty())) - { - if (!m_Icons.empty()) - { - size_t frame = 0; - size_t frameCount = m_Icons.size(); - - // Select the correct frame linearly - frame = (size_t)(value * frameCount); - frame = min((frameCount - 1), frame); - - return CopyIcon(m_Icons[frame]); - } - else - { - int frame = 0; - int frameCount = 0; - int newX, newY; - - if (m_Bitmap->GetWidth() > m_Bitmap->GetHeight()) - { - frameCount = m_Bitmap->GetWidth() / TRAYICON_SIZE; - } - else - { - frameCount = m_Bitmap->GetHeight() / TRAYICON_SIZE; - } - - // Select the correct frame linearly - frame = (int)(value * frameCount); - frame = min((frameCount - 1), frame); - - if (m_Bitmap->GetWidth() > m_Bitmap->GetHeight()) - { - newX = frame * TRAYICON_SIZE; - newY = 0; - } - else - { - newX = 0; - newY = frame * TRAYICON_SIZE; - } - - Bitmap trayBitmap(TRAYICON_SIZE, TRAYICON_SIZE); - Graphics graphics(&trayBitmap); - graphics.SetSmoothingMode(SmoothingModeAntiAlias); - - // Blit the image - Rect r(0, 0, TRAYICON_SIZE, TRAYICON_SIZE); - graphics.DrawImage(m_Bitmap, r, newX, newY, TRAYICON_SIZE, TRAYICON_SIZE, UnitPixel); - - HICON icon = nullptr; - trayBitmap.GetHICON(&icon); - return icon; - } - } - } - - // Return the default icon if there is no valid measure - return GetIcon(IDI_TRAY); -} - -void TrayWindow::ShowNotification(TRAY_NOTIFICATION id, const WCHAR* title, const WCHAR* text) -{ - if (m_Notification == TRAY_NOTIFICATION_NONE) - { - NOTIFYICONDATA nid = {sizeof(NOTIFYICONDATA)}; - nid.hWnd = m_Window; - nid.uID = IDI_TRAY; - nid.uFlags = NIF_INFO; - nid.uTimeout = 30000; - nid.dwInfoFlags = NIIF_USER; - wcsncpy_s(nid.szInfoTitle, title, _TRUNCATE); - wcsncpy_s(nid.szInfo, text, _TRUNCATE); - - if (IsWindows7OrGreater()) - { - nid.dwInfoFlags |= NIIF_LARGE_ICON; - nid.hBalloonIcon = GetIcon(IDI_RAINMETER, true); - } - - if (Shell_NotifyIcon(NIM_MODIFY, &nid)) - { - m_Notification = id; - } - } -} - -void TrayWindow::ShowWelcomeNotification() -{ - ShowNotification(TRAY_NOTIFICATION_WELCOME, GetString(ID_STR_WELCOME), GetString(ID_STR_CLICKTOMANAGE)); -} - -void TrayWindow::ShowUpdateNotification(const WCHAR* newVersion) -{ - std::wstring text = GetFormattedString(ID_STR_CLICKTODOWNLOAD, newVersion); - ShowNotification(TRAY_NOTIFICATION_UPDATE, GetString(ID_STR_UPDATEAVAILABLE), text.c_str()); -} - -void TrayWindow::SetTrayIcon(bool enabled) -{ - enabled ? TryAddTrayIcon() : RemoveTrayIcon(); - m_IconEnabled = enabled; - - // Save to Rainmeter.ini. - const std::wstring& iniFile = GetRainmeter().GetIniFile(); - WritePrivateProfileString(L"Rainmeter", L"TrayIcon", enabled ? nullptr : L"0", iniFile.c_str()); -} - -void TrayWindow::ReadOptions(ConfigParser& parser) -{ - // Clear old Settings - KillTimer(m_Window, TIMER_ADDTRAYICON); - KillTimer(m_Window, TIMER_TRAYMEASURE); - - delete m_Measure; - m_Measure = nullptr; - - delete m_Bitmap; - m_Bitmap = nullptr; - - std::vector::const_iterator iter = m_Icons.begin(); - for ( ; iter != m_Icons.end(); ++iter) - { - DestroyIcon((*iter)); - } - m_Icons.clear(); - - m_MeterType = TRAY_METER_TYPE_NONE; - - // Read tray settings - m_IconEnabled = parser.ReadBool(L"Rainmeter", L"TrayIcon", true); - if (m_IconEnabled) - { - const std::wstring& measureName = parser.ReadString(L"TrayMeasure", L"Measure", L""); - - if (!measureName.empty()) - { - ConfigParser* oldParser = GetRainmeter().GetCurrentParser(); - GetRainmeter().SetCurrentParser(&parser); - - m_Measure = Measure::Create(measureName.c_str(), nullptr, L"TrayMeasure"); - if (m_Measure) - { - m_Measure->ReadOptions(parser); - } - - GetRainmeter().SetCurrentParser(oldParser); - } - - const WCHAR* type = parser.ReadString(L"TrayMeasure", L"TrayMeter", m_Measure ? L"HISTOGRAM" : L"NONE").c_str(); - if (_wcsicmp(type, L"NONE") == 0) - { - // Use main icon - } - else if (_wcsicmp(type, L"HISTOGRAM") == 0) - { - m_MeterType = TRAY_METER_TYPE_HISTOGRAM; - m_Color1 = parser.ReadColor(L"TrayMeasure", L"TrayColor1", Color::MakeARGB(255, 0, 100, 0)); - m_Color2 = parser.ReadColor(L"TrayMeasure", L"TrayColor2", Color::MakeARGB(255, 0, 255, 0)); - } - else if (_wcsicmp(type, L"BITMAP") == 0) - { - m_MeterType = TRAY_METER_TYPE_BITMAP; - - std::wstring imageName = parser.ReadString(L"TrayMeasure", L"TrayBitmap", L""); - - // Load the bitmaps if defined - if (!imageName.empty()) - { - imageName.insert(0, GetRainmeter().GetSkinPath()); - const WCHAR* imagePath = imageName.c_str(); - if (_wcsicmp(imagePath + (imageName.size() - 4), L".ico") == 0) - { - int count = 1; - HICON hIcon = nullptr; - - // Load the icons - do - { - WCHAR buffer[MAX_PATH]; - _snwprintf_s(buffer, _TRUNCATE, imagePath, count++); - - hIcon = (HICON)LoadImage(nullptr, buffer, IMAGE_ICON, TRAYICON_SIZE, TRAYICON_SIZE, LR_LOADFROMFILE); - if (hIcon) m_Icons.push_back(hIcon); - if (wcscmp(imagePath, buffer) == 0) break; - } - while(hIcon != nullptr); - } - - if (m_Icons.empty()) - { - // No icons found so load as bitmap - delete m_Bitmap; - m_Bitmap = new Bitmap(imagePath); - Status status = m_Bitmap->GetLastStatus(); - if (Ok != status) - { - delete m_Bitmap; - m_Bitmap = nullptr; - LogWarningF(L"Bitmap image not found: %s", imagePath); - } - } - } - } - else - { - LogErrorF(L"No such TrayMeter: %s", type); - } - - TryAddTrayIcon(); - - if (m_Measure) - { - SetTimer(m_Window, TIMER_TRAYMEASURE, INTERVAL_TRAYMEASURE, nullptr); // Update the tray once per sec - } - } - else - { - RemoveTrayIcon(); - } -} - -LRESULT CALLBACK TrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TrayWindow* tray = GetRainmeter().GetTrayWindow(); - - switch (uMsg) - { - case WM_COMMAND: - switch (wParam) - { - case IDM_MANAGE: - DialogManage::Open(); - break; - - case IDM_ABOUT: - DialogAbout::Open(); - break; - - case IDM_SHOW_HELP: - CommandHandler::RunFile(RAINMETER_HELP); - break; - - case IDM_NEW_VERSION: - CommandHandler::RunFile(RAINMETER_OFFICIAL); - break; - - case IDM_REFRESH: - PostMessage(GetRainmeter().GetWindow(), WM_RAINMETER_DELAYED_REFRESH_ALL, (WPARAM)nullptr, (LPARAM)nullptr); - break; - - case IDM_SHOWLOGFILE: - GetRainmeter().ShowLogFile(); - break; - - case IDM_STARTLOG: - GetLogger().StartLogFile(); - break; - - case IDM_STOPLOG: - GetLogger().StopLogFile(); - break; - - case IDM_DELETELOGFILE: - GetLogger().DeleteLogFile(); - break; - - case IDM_DEBUGLOG: - GetRainmeter().SetDebug(!GetRainmeter().GetDebug()); - break; - - case IDM_DISABLEDRAG: - GetRainmeter().SetDisableDragging(!GetRainmeter().GetDisableDragging()); - break; - - case IDM_EDITCONFIG: - GetRainmeter().EditSettings(); - break; - - case IDM_QUIT: - PostQuitMessage(0); - break; - - case IDM_OPENSKINSFOLDER: - GetRainmeter().OpenSkinFolder(); - break; - - default: - { - UINT mID = wParam & 0x0FFFF; - - if (mID >= ID_THEME_FIRST && mID <= ID_THEME_LAST) - { - int pos = mID - ID_THEME_FIRST; - - const std::vector& layouts = GetRainmeter().GetAllLayouts(); - if (pos >= 0 && pos < (int)layouts.size()) - { - GetRainmeter().LoadLayout(layouts[pos]); - } - } - else if (mID >= ID_CONFIG_FIRST && mID <= ID_CONFIG_LAST) - { - GetRainmeter().ToggleSkinWithID(mID); - } - else - { - // Forward the message to correct window - int index = (int)(wParam >> 16); - const std::map& windows = GetRainmeter().GetAllMeterWindows(); - - if (index < (int)windows.size()) - { - std::map::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - --index; - if (index < 0) - { - MeterWindow* meterWindow = (*iter).second; - SendMessage(meterWindow->GetWindow(), WM_COMMAND, mID, 0); - break; - } - } - } - } - } - break; - } - break; // Don't send WM_COMMANDS any further - - case WM_TRAY_NOTIFYICON: - { - UINT uMouseMsg = (UINT)lParam; - LPCWSTR bang; - - // Check TrayExecute actions - switch (uMouseMsg) - { - case WM_MBUTTONDOWN: - bang = GetRainmeter().GetTrayExecuteM().c_str(); - break; - - case WM_RBUTTONDOWN: - bang = GetRainmeter().GetTrayExecuteR().c_str(); - break; - - case WM_MBUTTONDBLCLK: - bang = GetRainmeter().GetTrayExecuteDM().c_str(); - break; - - case WM_RBUTTONDBLCLK: - bang = GetRainmeter().GetTrayExecuteDR().c_str(); - break; - - default: - bang = L""; - break; - } - - if (*bang && - !IsCtrlKeyDown()) // Ctrl is pressed, so only run default action - { - GetRainmeter().ExecuteCommand(bang, nullptr); - tray->m_TrayContextMenuEnabled = (uMouseMsg != WM_RBUTTONDOWN); - break; - } - - // Run default UI action - switch (uMouseMsg) - { - case WM_RBUTTONDOWN: - tray->m_TrayContextMenuEnabled = true; - break; - - case WM_RBUTTONUP: - if (tray->m_TrayContextMenuEnabled) - { - POINT pos = System::GetCursorPosition(); - GetRainmeter().ShowContextMenu(pos, nullptr); - } - break; - - case WM_LBUTTONUP: - case WM_LBUTTONDBLCLK: - DialogManage::Open(); - break; - - case NIN_BALLOONUSERCLICK: - if (tray->m_Notification == TRAY_NOTIFICATION_WELCOME) - { - DialogManage::Open(); - } - else if (tray->m_Notification == TRAY_NOTIFICATION_UPDATE) - { - CommandHandler::RunFile(RAINMETER_OFFICIAL); - } - tray->m_Notification = TRAY_NOTIFICATION_NONE; - break; - - case NIN_BALLOONHIDE: - case NIN_BALLOONTIMEOUT: - tray->m_Notification = TRAY_NOTIFICATION_NONE; - break; - } - } - break; - - case WM_QUERY_RAINMETER: - if (IsWindow((HWND)lParam)) - { - auto sendCopyData = [&](const std::wstring& data) - { - COPYDATASTRUCT cds; - cds.dwData = wParam; - cds.cbData = (DWORD)((data.length() + 1) * sizeof(WCHAR)); - cds.lpData = (PVOID)data.c_str(); - SendMessage((HWND)lParam, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds); - }; - - switch (wParam) - { - case RAINMETER_QUERY_ID_SKINS_PATH: - sendCopyData(GetRainmeter().GetSkinPath()); - return 0; - - case RAINMETER_QUERY_ID_SETTINGS_PATH: - sendCopyData(GetRainmeter().GetSettingsPath()); - return 0; - - case RAINMETER_QUERY_ID_PLUGINS_PATH: - sendCopyData(GetRainmeter().GetPluginPath()); - return 0; - - case RAINMETER_QUERY_ID_PROGRAM_PATH: - sendCopyData(GetRainmeter().GetPath()); - return 0; - - case RAINMETER_QUERY_ID_LOG_PATH: - sendCopyData(GetLogger().GetLogFilePath()); - return 0; - - case RAINMETER_QUERY_ID_CONFIG_EDITOR: - sendCopyData(GetRainmeter().GetSkinEditor()); - return 0; - - case RAINMETER_QUERY_ID_IS_DEBUGGING: - { - BOOL debug = GetRainmeter().GetDebug(); - SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM)debug); - } - return 0; - } - } - return 1; - - case WM_COPYDATA: - { - COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; - if (cds->dwData == RAINMETER_QUERY_ID_SKIN_WINDOWHANDLE) - { - LPCWSTR folderPath = (LPCWSTR)cds->lpData; - MeterWindow* mw = GetRainmeter().GetMeterWindow(folderPath); - return (mw) ? (LRESULT)mw->GetWindow() : 0; - } - } - return 1; - - case WM_TIMER: - if (wParam == TIMER_TRAYMEASURE) - { - if (tray->m_Measure) - { - tray->m_Measure->Update(); - tray->ModifyTrayIcon(tray->m_Measure->GetRelativeValue()); - } - } - else if (wParam == TIMER_ADDTRAYICON) - { - tray->CheckTrayIcon(); - } - break; - - case WM_DESTROY: - PostQuitMessage(0); - break; - - default: - if (uMsg == WM_TASKBARCREATED) - { - if (tray->IsTrayIconEnabled()) - { - tray->RemoveTrayIcon(); - tray->TryAddTrayIcon(); - } - } - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return 0; -} diff --git a/Library/TrayWindow.h b/Library/TrayWindow.h deleted file mode 100644 index 4407ec76..00000000 --- a/Library/TrayWindow.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __TRAYWINDOW_H__ -#define __TRAYWINDOW_H__ - -#include -#include // For Gdiplus.h. -#include -#include - -#define WM_TRAY_NOTIFYICON WM_USER + 101 -#define TRAYICON_SIZE 16 - -enum TRAY_METER_TYPE -{ - TRAY_METER_TYPE_NONE, - TRAY_METER_TYPE_HISTOGRAM, - TRAY_METER_TYPE_BITMAP -}; - -class ConfigParser; -class Measure; - -class TrayWindow -{ -public: - TrayWindow(); - ~TrayWindow(); - - TrayWindow(const TrayWindow& other) = delete; - TrayWindow& operator=(TrayWindow other) = delete; - - void Initialize(); - - void ReadOptions(ConfigParser& parser); - HWND GetWindow() { return m_Window; } - bool IsTrayIconEnabled() { return m_IconEnabled; } - void SetTrayIcon(bool enabled); - - void ShowWelcomeNotification(); - void ShowUpdateNotification(const WCHAR* newVersion); - -protected: - static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -private: - enum TRAY_NOTIFICATION - { - TRAY_NOTIFICATION_NONE, - TRAY_NOTIFICATION_WELCOME, - TRAY_NOTIFICATION_UPDATE - }; - - bool AddTrayIcon(); - bool IsTrayIconReady(); - void TryAddTrayIcon(); - void CheckTrayIcon(); - void RemoveTrayIcon(); - void ModifyTrayIcon(double value); - HICON CreateTrayIcon(double value); - - void ShowNotification(TRAY_NOTIFICATION id, const WCHAR* title, const WCHAR* text); - - HICON m_Icon; - HWND m_Window; - Measure* m_Measure; - - TRAY_METER_TYPE m_MeterType; - Gdiplus::Color m_Color1; - Gdiplus::Color m_Color2; - Gdiplus::Bitmap* m_Bitmap; - - std::vector m_Icons; - - double m_Values[TRAYICON_SIZE]; - int m_Pos; - - TRAY_NOTIFICATION m_Notification; - - bool m_TrayContextMenuEnabled; - - bool m_IconEnabled; -}; - -#endif diff --git a/Library/UpdateCheck.cpp b/Library/UpdateCheck.cpp deleted file mode 100644 index fdf9fffd..00000000 --- a/Library/UpdateCheck.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "TrayWindow.h" -#include "../Version.h" - -void CheckVersion(void* dummy) -{ - HINTERNET hRootHandle = InternetOpen( - L"Rainmeter", - INTERNET_OPEN_TYPE_PRECONFIG, - nullptr, - nullptr, - 0); - - if (hRootHandle == nullptr) - { - return; - } - - HINTERNET hUrlDump = InternetOpenUrl( - hRootHandle, L"http://rainmeter.github.io/rainmeter/release", nullptr, 0, INTERNET_FLAG_RESYNCHRONIZE, 0); - if (hUrlDump) - { - DWORD dwSize; - char urlData[16] = {0}; - if (InternetReadFile(hUrlDump, (LPVOID)urlData, sizeof(urlData) - 1, &dwSize)) - { - auto parseVersion = [](const WCHAR* str)->int - { - int version = _wtoi(str) * 1000000; - const WCHAR* pos = wcschr(str, L'.'); - if (pos) - { - ++pos; // Skip . - version += _wtoi(pos) * 1000; - - pos = wcschr(pos, '.'); - if (pos) - { - ++pos; // Skip . - version += _wtoi(pos); - } - } - return version; - }; - - std::wstring tmpSz = StringUtil::Widen(urlData); - const WCHAR* version = tmpSz.c_str(); - - int availableVersion = parseVersion(version); - if (availableVersion > RAINMETER_VERSION || - (revision_beta && availableVersion == RAINMETER_VERSION)) - { - GetRainmeter().SetNewVersion(); - - WCHAR buffer[32]; - const WCHAR* dataFile = GetRainmeter().GetDataFile().c_str(); - GetPrivateProfileString(L"Rainmeter", L"LastCheck", L"0", buffer, _countof(buffer), dataFile); - - // Show tray notification only once per new version - int lastVersion = parseVersion(buffer); - if (availableVersion > lastVersion) - { - GetRainmeter().GetTrayWindow()->ShowUpdateNotification(version); - WritePrivateProfileString(L"Rainmeter", L"LastCheck", version, dataFile); - } - } - } - InternetCloseHandle(hUrlDump); - } - - InternetCloseHandle(hRootHandle); -} - -void CheckUpdate() -{ - _beginthread(CheckVersion, 0, nullptr); -} diff --git a/Library/UpdateCheck.h b/Library/UpdateCheck.h deleted file mode 100644 index 9a63c2f6..00000000 --- a/Library/UpdateCheck.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __UPDATE_CHECK_H__ -#define __UPDATE_CHECK_H__ - -void CheckUpdate(); - -#endif