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"
/>