diff --git a/Application/Application.vcproj b/Application/Application.vcproj index 0c3500a7..4ea2c874 100644 --- a/Application/Application.vcproj +++ b/Application/Application.vcproj @@ -154,6 +154,7 @@ ProgramDataBaseFileName=".\x64/Release/" WarningLevel="3" SuppressStartupBanner="true" + DebugInformationFormat="3" /> extern CRainmeter* Rainmeter; @@ -201,7 +202,7 @@ void ScanPlugins() WIN32_FIND_DATA fileData; // Data structure describes the file found HANDLE hSearch; // Search handle returned by FindFirstFile - std::wstring files = CRainmeter::FixPath(L"*.dll", PATH_FOLDER_PLUGIN, L""); + std::wstring files = Rainmeter->GetPluginPath() + L"*.dll"; g_Plugins.clear(); @@ -216,7 +217,7 @@ void ScanPlugins() info.version = 0; // Try to get the version and author - std::wstring tmpSz = CRainmeter::FixPath(fileData.cFileName, PATH_FOLDER_PLUGIN, L""); + std::wstring tmpSz = Rainmeter->GetPluginPath() + fileData.cFileName; HMODULE dll = LoadLibrary(tmpSz.c_str()); if (dll) { @@ -284,7 +285,7 @@ BOOL OnInitAboutDialog(HWND window) HWND widget; widget = GetDlgItem(window, IDC_VERSION_STRING); - swprintf(tmpSz, L"%s version %s", APPNAME, APPVERSION); + swprintf(tmpSz, L"%s version %s rev %i %s", APPNAME, APPVERSION, revision_number, APPBITS); SetWindowText(widget, tmpSz); widget = GetDlgItem(window, IDC_BUILD_STRING); diff --git a/Library/Library.rc b/Library/Library.rc index 118e26e8..93956e9d 100644 --- a/Library/Library.rc +++ b/Library/Library.rc @@ -107,13 +107,14 @@ BEGIN MENUITEM "Click Through", ID_CONTEXT_SKINMENU_CLICKTHROUGH - MENUITEM "Keep on screen", ID_CONTEXT_SKINMENU_KEEPONSCREEN + MENUITEM "Keep on Screen", ID_CONTEXT_SKINMENU_KEEPONSCREEN MENUITEM SEPARATOR MENUITEM "Edit Skin...", ID_CONTEXT_SKINMENU_EDITSKIN + MENUITEM "Open Skin's folder", ID_CONTEXT_SKINMENU_OPENSKINSFOLDER MENUITEM "Refresh Skin", ID_CONTEXT_SKINMENU_REFRESH MENUITEM SEPARATOR - MENUITEM "Close skin", ID_CONTEXT_CLOSESKIN + MENUITEM "Close Skin", ID_CONTEXT_CLOSESKIN END END diff --git a/Library/Library.vcproj b/Library/Library.vcproj index 0c7093f4..49f41db1 100644 --- a/Library/Library.vcproj +++ b/Library/Library.vcproj @@ -246,6 +246,7 @@ ProgramDataBaseFileName=".\x32/Release/" WarningLevel="3" SuppressStartupBanner="true" + DebugInformationFormat="3" /> FixPath(L"", PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()).c_str()); + SetCurrentDirectory(m_MeterWindow->MakePathAbsolute(L"").c_str()); if(UpdateFunc) { @@ -115,7 +115,7 @@ void CMeasurePlugin::ReadConfig(CConfigParser& parser, const WCHAR* section) { m_PluginName = L"..\\" + m_PluginName; } - m_PluginName = Rainmeter->FixPath(m_PluginName, PATH_FOLDER_PLUGIN, L""); + m_PluginName = Rainmeter->GetPluginPath() + m_PluginName; m_Plugin = LoadLibrary(m_PluginName.c_str()); @@ -155,7 +155,7 @@ void CMeasurePlugin::ReadConfig(CConfigParser& parser, const WCHAR* section) WCHAR buffer[MAX_PATH]; GetCurrentDirectory(MAX_PATH, buffer); - SetCurrentDirectory(Rainmeter->FixPath(L"", PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()).c_str()); + SetCurrentDirectory(m_MeterWindow->MakePathAbsolute(L"").c_str()); double maxValue; maxValue = InitializeFunc(m_Plugin, parser.GetFilename().c_str(), section, m_ID); diff --git a/Library/MeterBar.cpp b/Library/MeterBar.cpp index deed9416..4571de77 100644 --- a/Library/MeterBar.cpp +++ b/Library/MeterBar.cpp @@ -97,7 +97,7 @@ void CMeterBar::ReadConfig(const WCHAR* section) m_Color = parser.ReadColor(section, L"BarColor", Color::Green); m_ImageName = parser.ReadString(section, L"BarImage", L""); - m_ImageName = Rainmeter->FixPath(m_ImageName, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + m_ImageName = m_MeterWindow->MakePathAbsolute(m_ImageName); m_Border = parser.ReadInt(section, L"BarBorder", 0); diff --git a/Library/MeterBitmap.cpp b/Library/MeterBitmap.cpp index 9fc7fff3..42aeea58 100644 --- a/Library/MeterBitmap.cpp +++ b/Library/MeterBitmap.cpp @@ -169,7 +169,7 @@ void CMeterBitmap::ReadConfig(const WCHAR* section) CConfigParser& parser = m_MeterWindow->GetParser(); m_ImageName = parser.ReadString(section, L"BitmapImage", L""); - m_ImageName = Rainmeter->FixPath(m_ImageName, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + m_ImageName = m_MeterWindow->MakePathAbsolute(m_ImageName); m_FrameCount = parser.ReadInt(section, L"BitmapFrames", 1); m_ZeroFrame = 0!=parser.ReadInt(section, L"BitmapZeroFrame", 0); diff --git a/Library/MeterButton.cpp b/Library/MeterButton.cpp index 5a4bd253..ffdc6575 100644 --- a/Library/MeterButton.cpp +++ b/Library/MeterButton.cpp @@ -136,7 +136,7 @@ void CMeterButton::ReadConfig(const WCHAR* section) CConfigParser& parser = m_MeterWindow->GetParser(); m_ImageName = parser.ReadString(section, L"ButtonImage", L""); - m_ImageName = Rainmeter->FixPath(m_ImageName, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + m_ImageName = m_MeterWindow->MakePathAbsolute(m_ImageName); m_Command = parser.ReadString(section, L"ButtonCommand", L""); } diff --git a/Library/MeterHistogram.cpp b/Library/MeterHistogram.cpp index ee3e8e95..07db0252 100644 --- a/Library/MeterHistogram.cpp +++ b/Library/MeterHistogram.cpp @@ -150,13 +150,13 @@ void CMeterHistogram::ReadConfig(const WCHAR* section) m_SecondaryMeasureName = parser.ReadString(section, L"SecondaryMeasureName", L""); m_PrimaryImageName = parser.ReadString(section, L"PrimaryImage", L""); - m_PrimaryImageName = Rainmeter->FixPath(m_PrimaryImageName, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + m_PrimaryImageName = m_MeterWindow->MakePathAbsolute(m_PrimaryImageName); m_SecondaryImageName = parser.ReadString(section, L"SecondaryImage", L""); - m_SecondaryImageName = Rainmeter->FixPath(m_SecondaryImageName, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + m_SecondaryImageName = m_MeterWindow->MakePathAbsolute(m_SecondaryImageName); m_BothImageName = parser.ReadString(section, L"BothImage", L""); - m_BothImageName = Rainmeter->FixPath(m_BothImageName, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + m_BothImageName = m_MeterWindow->MakePathAbsolute(m_BothImageName); m_Autoscale = 0!=parser.ReadInt(section, L"AutoScale", 0); m_Flip = 0!=parser.ReadInt(section, L"Flip", 0); diff --git a/Library/MeterImage.cpp b/Library/MeterImage.cpp index a7d11f12..f1aeeb5c 100644 --- a/Library/MeterImage.cpp +++ b/Library/MeterImage.cpp @@ -178,7 +178,7 @@ void CMeterImage::ReadConfig(const WCHAR* section) CConfigParser& parser = m_MeterWindow->GetParser(); m_ImageName = parser.ReadString(section, L"ImageName", L""); - m_ImageName = Rainmeter->FixPath(m_ImageName, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + m_ImageName = m_MeterWindow->MakePathAbsolute(m_ImageName); if (-1 != parser.ReadInt(section, L"W", -1) && -1 != parser.ReadInt(section, L"H", -1)) { @@ -200,7 +200,7 @@ bool CMeterImage::Update() if (!val.empty()) { // Load the new image - val = Rainmeter->FixPath(val, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + val = m_MeterWindow->MakePathAbsolute(val); if (val != m_ImageName) { m_ImageName = val; diff --git a/Library/MeterRotator.cpp b/Library/MeterRotator.cpp index 61c75ebc..34d6e315 100644 --- a/Library/MeterRotator.cpp +++ b/Library/MeterRotator.cpp @@ -88,7 +88,7 @@ void CMeterRotator::ReadConfig(const WCHAR* section) CConfigParser& parser = m_MeterWindow->GetParser(); m_ImageName = parser.ReadString(section, L"ImageName", L""); - m_ImageName = Rainmeter->FixPath(m_ImageName, PATH_FOLDER_CURRENT_SKIN, m_MeterWindow->GetSkinName()); + m_ImageName = m_MeterWindow->MakePathAbsolute(m_ImageName); m_OffsetX = parser.ReadFloat(section, L"OffsetX", 0.0); m_OffsetY = parser.ReadFloat(section, L"OffsetY", 0.0); diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index c6797ada..a6582b22 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -61,7 +61,7 @@ MULTIMONITOR_INFO CMeterWindow::m_Monitors = { 0 }; ** Constructor ** */ -CMeterWindow::CMeterWindow(std::wstring& config, std::wstring& iniFile) +CMeterWindow::CMeterWindow(std::wstring& path, std::wstring& config, std::wstring& iniFile) { m_Background = NULL; m_Window = NULL; @@ -124,6 +124,7 @@ CMeterWindow::CMeterWindow(std::wstring& config, std::wstring& iniFile) m_BackgroundMode = BGMODE_IMAGE; m_SolidBevel = BEVELTYPE_NONE; + m_SkinPath = path; m_SkinName = config; m_SkinIniFile = iniFile; @@ -1279,7 +1280,7 @@ void CMeterWindow::WriteConfig() */ void CMeterWindow::ReadSkin() { - std::wstring iniFile = m_Rainmeter->GetSkinPath(); + std::wstring iniFile = m_SkinPath; iniFile += m_SkinName; iniFile += L"\\"; iniFile += m_SkinIniFile; @@ -1303,7 +1304,7 @@ void CMeterWindow::ReadSkin() m_Author = m_Parser.ReadString(L"Rainmeter", L"Author", L""); m_BackgroundName = m_Parser.ReadString(L"Rainmeter", L"Background", L""); - m_BackgroundName = Rainmeter->FixPath(m_BackgroundName, PATH_FOLDER_CURRENT_SKIN, m_SkinName); + m_BackgroundName = MakePathAbsolute(m_BackgroundName); std::wstring margins = m_Parser.ReadString(L"Rainmeter", L"BackgroundMargins", L"0, 0, 0, 0"); int left = 0, top = 0, right = 0, bottom = 0; @@ -2295,9 +2296,25 @@ LRESULT CMeterWindow::OnCommand(WPARAM wParam, LPARAM lParam) { std::wstring command = Rainmeter->GetConfigEditor(); command += L" \""; - command += m_Rainmeter->GetSkinPath() + L"\\" + m_SkinName + L"\\" + m_SkinIniFile + L"\""; - LSExecuteAsAdmin(NULL, command.c_str(), SW_SHOWNORMAL); + command += m_SkinPath + L"\\" + m_SkinName + L"\\" + m_SkinIniFile + L"\""; + + if (m_SkinPath == Rainmeter->GetSkinPath()) + { + LSExecuteAsAdmin(NULL, command.c_str(), SW_SHOWNORMAL); + } + else + { + LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); + } } + else if(wParam == ID_CONTEXT_SKINMENU_OPENSKINSFOLDER) + { + std::wstring command; + command += L"\""; + command += m_SkinPath + L"\\" + m_SkinName; + command += L"\""; + LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); + } else if(wParam == ID_CONTEXT_SKINMENU_REFRESH) { Refresh(false); @@ -3115,3 +3132,25 @@ LRESULT CMeterWindow::OnCopyData(WPARAM wParam, LPARAM lParam) } } +/* +** MakePathAbsolute +** +** Converts the path to absolute bu adding the skin's path to it (unless it already is absolute). +** +*/ +std::wstring CMeterWindow::MakePathAbsolute(std::wstring path) +{ + if (path.empty() || path.find(L':') != std::wstring::npos) + { + return path; // It's already absolute path (or it's empty) + } + + std::wstring root = m_SkinPath + m_SkinName; + + if (root[root.length() - 1] != L'\\') + { + root += L"\\"; + } + + return root + path; +} diff --git a/Library/MeterWindow.h b/Library/MeterWindow.h index c8bf3ce3..9dfbbe97 100644 --- a/Library/MeterWindow.h +++ b/Library/MeterWindow.h @@ -99,14 +99,6 @@ enum BANGCOMMAND BANG_PLUGIN }; -enum PATH_FOLDER -{ - PATH_FOLDER_INI, - PATH_FOLDER_SKINS, - PATH_FOLDER_CURRENT_SKIN, - PATH_FOLDER_PLUGIN -}; - typedef struct { int count; //Number of monitors @@ -124,7 +116,7 @@ class CMeter; class CMeterWindow { public: - CMeterWindow(std::wstring& config, std::wstring& iniFile); + CMeterWindow(std::wstring& path, std::wstring& config, std::wstring& iniFile); ~CMeterWindow(); int Initialize(CRainmeter& Rainmeter); @@ -177,6 +169,8 @@ public: LRESULT OnCopyData(WPARAM wParam, LPARAM lParam); + std::wstring MakePathAbsolute(std::wstring path); + protected: static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -303,7 +297,8 @@ private: std::list m_Measures; // All the measures std::list m_Meters; // All the meters - std::wstring m_SkinName; // Name of the current skin folder + std::wstring m_SkinPath; // Path of the skin folder + std::wstring m_SkinName; // Name of the current skin folder std::wstring m_SkinIniFile; // Name of the current skin iniFile std::wstring m_ConfigEditor; diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index 4bebc63f..e1d9e7b2 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -30,6 +30,7 @@ #include #include #include +#include using namespace Gdiplus; @@ -674,16 +675,20 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) m_IniFile = m_Path + L"Rainmeter.ini"; m_SkinPath = m_Path + L"Skins\\"; + bool bDefaultIniLocation = false; + // 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) { WCHAR buffer[4096]; // lets hope the buffer is large enough... // Expand the environment variables - DWORD ret = ExpandEnvironmentStrings(L"%APPDATA%\\Rainmeter\\rainmeter.ini", buffer, 4096); + DWORD ret = ExpandEnvironmentStrings(L"%APPDATA%\\Rainmeter\\", buffer, 4096); if (ret != 0 && ret < 4096) { m_IniFile = buffer; + m_IniFile += L"rainmeter.ini"; + bDefaultIniLocation = true; // If the ini file doesn't exist in the %APPDATA% either, create a default rainmeter.ini file. if (_waccess(m_IniFile.c_str(), 0) == -1) @@ -693,6 +698,59 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) } } + // Read the skin folder from the ini file + WCHAR tmpSz[MAX_LINE_LENGTH]; + if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", tmpSz, MAX_LINE_LENGTH, m_IniFile.c_str()) > 0) + { + m_SkinPath = tmpSz; + } + else if (bDefaultIniLocation) + { + // If the skin path is not defined in the rainmeter.ini file use My Documents/Rainmeter/Skins + TCHAR szPath[MAX_PATH] = {0}; + HRESULT hr = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, szPath); + if (SUCCEEDED(hr)) + { + // Make the folders if they don't exist yet + m_SkinPath = szPath; + m_SkinPath += L"\\Rainmeter"; + CreateDirectory(m_SkinPath.c_str(), NULL); + m_SkinPath += L"\\Skins"; + DWORD result = CreateDirectory(m_SkinPath.c_str(), NULL); + m_SkinPath += L"\\"; + if (result != 0) + { + // The folder was created successfully which means that it wasn't available yet. + // Copy the default skin to the Skins folder + std::wstring strFrom(m_Path + L"Skins\\" + L"*.*"); + std::wstring strTo(m_SkinPath); + + // The strings must end with double nul + strFrom.append(L"0"); + strFrom[strFrom.size() - 1] = L'\0'; + strTo.append(L"0"); + strTo[strTo.size() - 1] = L'\0'; + + SHFILEOPSTRUCT fo = {0}; + fo.wFunc = FO_COPY; + fo.pFrom = strFrom.c_str(); + fo.pTo = strTo.c_str(); + fo.fFlags = FOF_NO_UI; + + int result = SHFileOperation(&fo); + if (result != 0) + { + DebugLog(L"Unable to copy the default skin %i", result); + } + } + } + else + { + DebugLog(L"Unable to get the My Documents location."); + } + } + WritePrivateProfileString(L"Rainmeter", L"SkinPath", m_SkinPath.c_str(), m_IniFile.c_str()); + // Set the log file location m_LogFile = m_IniFile; size_t posExt = m_LogFile.find(L".ini"); @@ -736,10 +794,20 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) DebugLog(L"SkinPath: %s", m_SkinPath.c_str()); DebugLog(L"PluginPath: %s", m_PluginPath.c_str()); + // Test that the Rainmeter.ini file is writable + TestSettingsFile(bDefaultIniLocation); + // Tray must exist before configs are read m_TrayWindow = new CTrayWindow(m_Instance); ScanForConfigs(m_SkinPath); + + if(m_ConfigStrings.empty()) + { + std::wstring error = L"There are no available skins at:\n" + m_SkinPath; + MessageBox(NULL, error.c_str(), L"Rainmeter", MB_OK | MB_ICONERROR); + } + ReadGeneralSettings(m_IniFile); if (m_CheckUpdate) @@ -797,7 +865,7 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) // Create meter windows for active configs for (size_t i = 0; i < m_ConfigStrings.size(); i++) { - if (m_ConfigStrings[i].active > 0 && m_ConfigStrings[i].active <= m_ConfigStrings[i].iniFiles.size()) + if (m_ConfigStrings[i].active > 0 && m_ConfigStrings[i].active <= (int)m_ConfigStrings[i].iniFiles.size()) { ActivateConfig(i, m_ConfigStrings[i].active - 1); } @@ -843,6 +911,7 @@ void CRainmeter::ActivateConfig(int configIndex, int iniIndex) WCHAR buffer[256]; std::wstring skinIniFile = m_ConfigStrings[configIndex].iniFiles[iniIndex]; std::wstring skinConfig = m_ConfigStrings[configIndex].config; + std::wstring skinPath = m_ConfigStrings[configIndex].path; // Verify that the config is not already active std::map::iterator iter = m_Meters.find(skinConfig); @@ -864,7 +933,7 @@ void CRainmeter::ActivateConfig(int configIndex, int iniIndex) { m_ConfigStrings[configIndex].active = iniIndex + 1; - CreateMeterWindow(skinConfig, skinIniFile); + CreateMeterWindow(skinPath, skinConfig, skinIniFile); wsprintf(buffer, L"%i", iniIndex + 1); WritePrivateProfileString(skinConfig.c_str(), L"Active", buffer, m_IniFile.c_str()); @@ -901,9 +970,9 @@ bool CRainmeter::DeactivateConfig(CMeterWindow* meterWindow, int configIndex) return false; } -void CRainmeter::CreateMeterWindow(std::wstring config, std::wstring iniFile) +void CRainmeter::CreateMeterWindow(std::wstring path, std::wstring config, std::wstring iniFile) { - CMeterWindow* mw = new CMeterWindow(config, iniFile); + CMeterWindow* mw = new CMeterWindow(path, config, iniFile); if (mw) { @@ -1001,14 +1070,8 @@ void CRainmeter::ScanForConfigs(std::wstring& path) { m_ConfigStrings.clear(); m_ConfigMenu.clear(); - - ScanForConfigsRecursive(path, L"", 0, m_ConfigMenu); - if(m_ConfigStrings.empty()) - { - std::wstring error = L"There are no skins available in folder\n" + path; - MessageBox(NULL, error.c_str(), L"Rainmeter", MB_OK); - } + ScanForConfigsRecursive(path, L"", 0, m_ConfigMenu); } int CRainmeter::ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector& menu) @@ -1022,6 +1085,7 @@ int CRainmeter::ScanForConfigsRecursive(std::wstring& path, std::wstring base, i { // Scan for ini-files CONFIG config; + config.path = path; config.config = base; config.active = false; @@ -1425,7 +1489,7 @@ void CRainmeter::ReadGeneralSettings(std::wstring& iniFile) int active = parser.ReadInt(m_ConfigStrings[i].config.c_str(), L"Active", 0); // Make sure there is a ini file available - if (active > 0 && active <= m_ConfigStrings[i].iniFiles.size()) + if (active > 0 && active <= (int)m_ConfigStrings[i].iniFiles.size()) { m_ConfigStrings[i].active = active; } @@ -1610,6 +1674,9 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow) HMENU configMenu = CreateConfigMenu(m_ConfigMenu); if (configMenu) { + AppendMenu(configMenu, MF_SEPARATOR, 0, NULL); + AppendMenu(configMenu, 0, ID_CONTEXT_OPENSKINSFOLDER, L"Open Skins\' Folder"); + InsertMenu(subMenu, 3, MF_BYPOSITION | MF_POPUP, (UINT_PTR)configMenu, L"Configs"); } @@ -1837,44 +1904,53 @@ void CRainmeter::ChangeSkinIndex(HMENU menu, int index) } } -/* -** FixPath -** -** Converts relative path to absolute. -** -*/ -std::wstring CRainmeter::FixPath(const std::wstring& path, PATH_FOLDER folder, const std::wstring& currentSkin) +void CRainmeter::TestSettingsFile(bool bDefaultIniLocation) { - if (path.empty() || path.find(L':') != std::wstring::npos) + WritePrivateProfileString(L"Rainmeter", L"WriteTest", L"TRUE", m_IniFile.c_str()); + WritePrivateProfileString(NULL, NULL, NULL, m_IniFile.c_str()); // FLUSH + + WCHAR tmpSz[5]; + bool bSuccess = (GetPrivateProfileString(L"Rainmeter", L"WriteTest", L"", tmpSz, 5, m_IniFile.c_str()) > 0); + if (bSuccess) { - return path; // It's already absolute path (or it's empty) + bSuccess = (wcscmp(L"TRUE", tmpSz) == 0); + WritePrivateProfileString(L"Rainmeter", L"WriteTest", NULL, m_IniFile.c_str()); } - - std::wstring root; - - switch(folder) + if (!bSuccess) { - case PATH_FOLDER_INI: - root = Rainmeter->GetPath(); - break; + DebugLog(L"The rainmeter.ini file is NOT writable."); - case PATH_FOLDER_SKINS: - root = Rainmeter->GetSkinPath(); - break; + std::wstring error; + error += L"The Rainmeter.ini file is not writable. This means that the\n"; + error += L"application will not be able to save any settings permanently.\n\n"; - case PATH_FOLDER_CURRENT_SKIN: - root = Rainmeter->GetSkinPath() + currentSkin; - break; + if (!bDefaultIniLocation) + { + WCHAR buffer[4096] = {0}; // lets hope the buffer is large enough... + // Expand the environment variables + ExpandEnvironmentStrings(L"%APPDATA%\\Rainmeter\\", buffer, 4096); - case PATH_FOLDER_PLUGIN: - root = Rainmeter->GetPluginPath(); - break; + error += L"You should quit Rainmeter and move the settings file from\n\n"; + error += m_IniFile; + error += L"\n\nto\n\n"; + error += buffer; + error += L"\n\nAlternatively you can also just remove the file and\n"; + error += L"it will be automatically recreated to the correct location\n"; + error += L"when Rainmeter is restarted the next time (you\'ll lose your\n"; + error += L"current settings though).\n"; + } + else + { + error += L"Make sure that the settings file is not set as read-only and\n"; + error += L"it is located in a folder where you have write permissions.\n\n"; + error += L"The settings file is located at:\n"; + error += m_IniFile; + } + + MessageBox(NULL, error.c_str(), L"Rainmeter", MB_OK | MB_ICONERROR); } - - if (root[root.length() - 1] != L'\\') + else { - root += L"\\"; + DebugLog(L"The rainmeter.ini file is writable."); } - - return root + path; -} +} \ No newline at end of file diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index 4d2bf7f2..51784391 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -32,10 +32,11 @@ #define MAKE_VER(major, minor) major * 1000 + minor #define APPNAME L"Rainmeter" +#define APPVERSION L"0.14.1" #ifdef _WIN64 -#define APPVERSION L"0.14.1 (64-bit)" +#define APPBITS L"(64-bit)" #else -#define APPVERSION L"0.14.1 (32-bit)" +#define APPBITS L"(32-bit)" #endif #define RAINMETER_VERSION MAKE_VER(14, 1) @@ -82,6 +83,7 @@ class CRainmeter public: struct CONFIG { + std::wstring path; std::wstring config; std::vector iniFiles; std::vector commands; @@ -154,12 +156,11 @@ public: BOOL ExecuteBang(const std::wstring& bang, const std::wstring& arg, CMeterWindow* meterWindow); std::wstring ParseCommand(const WCHAR* command, CMeterWindow* meterWindow); void ExecuteCommand(const WCHAR* command, CMeterWindow* meterWindow); - static std::wstring FixPath(const std::wstring& path, PATH_FOLDER folder, const std::wstring& currentSkin); static PLATFORM IsNT(); private: - void CreateMeterWindow(std::wstring config, std::wstring iniFile); + void CreateMeterWindow(std::wstring path, std::wstring config, std::wstring iniFile); bool DeleteMeterWindow(CMeterWindow* meterWindow); void ScanForConfigs(std::wstring& path); void ReadGeneralSettings(std::wstring& path); @@ -170,6 +171,7 @@ private: int ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector& menu); HMENU CreateConfigMenu(std::vector& configMenuData); void CreateDefaultConfigFile(std::wstring strFile); + void TestSettingsFile(bool bDefaultIniLocation); CTrayWindow* m_TrayWindow; diff --git a/Library/TrayWindow.cpp b/Library/TrayWindow.cpp index ea693756..f7987650 100644 --- a/Library/TrayWindow.cpp +++ b/Library/TrayWindow.cpp @@ -334,8 +334,7 @@ void CTrayWindow::ReadConfig(CConfigParser& parser) // Load the bitmaps if defined if (!imageName.empty()) { - imageName = Rainmeter->FixPath(imageName, PATH_FOLDER_SKINS, L""); - + imageName = Rainmeter->GetSkinPath() + imageName; if (imageName.size() > 3) { std::wstring extension = imageName.substr(imageName.size() - 3); @@ -474,6 +473,14 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA if (Rainmeter->GetDummyLitestep()) PostQuitMessage(0); quitModule(Rainmeter->GetInstance()); } + else if(wParam == ID_CONTEXT_OPENSKINSFOLDER) + { + std::wstring command; + command += L"\""; + command += Rainmeter->GetSkinPath(); + command += L"\""; + LSExecute(tray->GetWindow(), command.c_str(), SW_SHOWNORMAL); + } else if((wParam & 0x0ffff) >= ID_CONFIG_FIRST) { wParam = wParam & 0x0ffff; diff --git a/Library/resource.h b/Library/resource.h index f5a9d966..fafbb349 100644 --- a/Library/resource.h +++ b/Library/resource.h @@ -52,6 +52,8 @@ #define ID_CONTEXT_SKINMENU_FROMBOTTOM 4041 #define ID_CONTEXT_SKINMENU_XPERCENTAGE 4042 #define ID_CONTEXT_SKINMENU_YPERCENTAGE 4043 +#define ID_CONTEXT_OPENSKINSFOLDER 4044 +#define ID_CONTEXT_SKINMENU_OPENSKINSFOLDER 4045 #define ID_CONFIG_EDIT 30000 #define ID_CONFIG_FIRST 30001 diff --git a/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.vcproj b/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.vcproj index 83646fdd..c5d07135 100644 --- a/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.vcproj +++ b/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.vcproj @@ -153,6 +153,7 @@ ProgramDataBaseFileName=".\x64/Release/" WarningLevel="3" SuppressStartupBanner="true" + DebugInformationFormat="3" />