Added !LoadLayout

This commit is contained in:
Birunthan Mohanathas 2012-10-06 20:12:40 +03:00
parent 0cd82ae789
commit c7286881ee
5 changed files with 101 additions and 104 deletions

View File

@ -50,6 +50,11 @@ CRainmeter* Rainmeter; // The module
*/
int RainmeterMain(LPWSTR cmdLine)
{
// Avoid loading a dll from current directory
SetDllDirectory(L"");
const WCHAR* layout = NULL;
if (cmdLine[0] == L'!' || cmdLine[0] == L'[')
{
HWND wnd = FindWindow(RAINMETER_CLASS_NAME, RAINMETER_WINDOW_NAME);
@ -64,8 +69,16 @@ int RainmeterMain(LPWSTR cmdLine)
return 0;
}
// Disallow everything except !LoadLayout.
if (_wcsnicmp(cmdLine, L"!LoadLayout ", 11) == 0)
{
layout = cmdLine + 11; // Skip "!LoadLayout ".
}
else
{
return 1;
}
}
else if (cmdLine[0] == L'"')
{
// Strip quotes
@ -77,13 +90,10 @@ int RainmeterMain(LPWSTR cmdLine)
}
}
// Avoid loading a dll from current directory
SetDllDirectory(L"");
int ret = 1;
const WCHAR* iniFile = (*cmdLine && !layout) ? cmdLine : NULL;
Rainmeter = new CRainmeter;
ret = Rainmeter->Initialize(cmdLine);
int ret = Rainmeter->Initialize(iniFile, layout);
if (ret == 0)
{
ret = Rainmeter->MessagePump();
@ -394,6 +404,30 @@ void CRainmeter::Bang_DeactivateSkinGroup(std::vector<std::wstring>& args)
}
}
/*
** !LoadLayout bang
**
*/
void CRainmeter::Bang_LoadLayout(std::vector<std::wstring>& args, CMeterWindow* meterWindow)
{
if (args.size() == 1)
{
if (meterWindow)
{
// Delay to avoid loading theme in the middle of an update.
std::wstring command = L"!LoadLayout \"";
command += args[0];
command += L'"';
Rainmeter->DelayedExecuteCommand(command.c_str());
}
else
{
// Not called from a skin (or called with delay).
LoadLayout(args[0]);
}
}
}
/*
** !SetClip bang
**
@ -728,7 +762,7 @@ CRainmeter::~CRainmeter()
** The main initialization function for the module.
**
*/
int CRainmeter::Initialize(LPCWSTR iniPath)
int CRainmeter::Initialize(LPCWSTR iniPath, LPCWSTR layout)
{
InitalizeLitestep();
@ -742,7 +776,7 @@ int CRainmeter::Initialize(LPCWSTR iniPath)
m_Path.assign(buffer, pos ? pos - buffer + 1 : 0);
bool bDefaultIniLocation = false;
if (*iniPath)
if (iniPath)
{
// The command line defines the location of Rainmeter.ini (or whatever it calls it).
std::wstring iniFile = iniPath;
@ -988,8 +1022,17 @@ int CRainmeter::Initialize(LPCWSTR iniPath)
UpdateDesktopWorkArea(false);
}
// Create meter windows for active skins
bool layoutLoaded = false;
if (layout)
{
std::vector<std::wstring> args = ParseString(layout);
layoutLoaded = (args.size() == 1 && LoadLayout(args[0]));
}
if (!layoutLoaded)
{
ActivateActiveSkins();
}
if (dataFileCreated)
{
@ -2138,6 +2181,10 @@ void CRainmeter::ExecuteBang(const WCHAR* bang, std::vector<std::wstring>& args,
{
BangWithArgs(BANG_PLUGIN, args, 1, meterWindow);
}
else if (_wcsicmp(bang, L"LoadLayout") == 0)
{
Bang_LoadLayout(args, meterWindow);
}
else if (_wcsicmp(bang, L"SetClip") == 0)
{
Bang_SetClip(args);
@ -2530,8 +2577,19 @@ void CRainmeter::RefreshAll()
CDialogManage::UpdateSkins(NULL);
}
void CRainmeter::LoadLayout(const std::wstring& name)
bool CRainmeter::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;
}
// Delete all meter windows
DeleteMeterWindow(NULL);
@ -2540,23 +2598,17 @@ void CRainmeter::LoadLayout(const std::wstring& name)
CreateDirectory(backup.c_str(), NULL);
backup += L"\\Rainmeter.ini";
if (_wcsicmp(name.c_str(), L"@Backup") == 0)
{
// Just load the backup
CSystem::CopyFiles(backup, m_IniFile);
}
else
bool backupLayout = (_wcsicmp(name.c_str(), L"@Backup") == 0);
if (!backupLayout)
{
// Make a copy of current Rainmeter.ini
CSystem::CopyFiles(m_IniFile, backup);
}
// Replace Rainmeter.ini with layout
std::wstring layout = GetLayoutPath();
layout += name;
std::wstring wallpaper = layout + L"\\Wallpaper.bmp";
layout += L"\\Rainmeter.ini";
CSystem::CopyFiles(layout, GetIniFile());
CSystem::CopyFiles(layout, m_IniFile);
if (!backupLayout)
{
PreserveSetting(backup, L"SkinPath");
PreserveSetting(backup, L"ConfigEditor");
PreserveSetting(backup, L"LogViewer");
@ -2580,6 +2632,8 @@ void CRainmeter::LoadLayout(const std::wstring& name)
// Create meter windows for active skins
ActivateActiveSkins();
return true;
}
void CRainmeter::PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace)

View File

@ -99,7 +99,7 @@ public:
CRainmeter();
~CRainmeter();
int Initialize(LPCWSTR iniPath);
int Initialize(LPCWSTR iniPath, LPCWSTR layout);
bool IsAlreadyRunning();
int MessagePump();
@ -215,7 +215,7 @@ public:
void RefreshAll();
void LoadLayout(const std::wstring& name);
bool LoadLayout(const std::wstring& name);
void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace = true);
static std::vector<std::wstring> ParseString(LPCTSTR str, CConfigParser* parser = NULL);
@ -233,6 +233,7 @@ private:
void Bang_DeactivateSkin(std::vector<std::wstring>& args, CMeterWindow* meterWindow);
void Bang_ToggleSkin(std::vector<std::wstring>& args);
void Bang_DeactivateSkinGroup(std::vector<std::wstring>& args);
void Bang_LoadLayout(std::vector<std::wstring>& args, CMeterWindow* meterWindow);
void Bang_SetClip(std::vector<std::wstring>& args);
void Bang_SetWallpaper(std::vector<std::wstring>& args, CMeterWindow* meterWindow);
void Bang_SkinMenu(std::vector<std::wstring>& args, CMeterWindow* meterWindow);

View File

@ -120,22 +120,20 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
if (_wcsnicmp(lpCmdLine, L"/LoadTheme ", 11) == 0)
{
// Skip "/LoadTheme "
lpCmdLine += 11;
if (*lpCmdLine && CloseRainmeterIfActive())
{
CDialogInstall::LoadLayout(lpCmdLine, true);
// For backwards compatibility.
std::wstring args = L"!LoadLayout \"";
args += &lpCmdLine[11]; // Skip "/LoadTheme ".
args += L'"';
std::wstring file = g_Data.programPath + L"Rainmeter.exe";
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_UNICODE;
sei.lpFile = file.c_str();
sei.lpParameters = args.c_str();
sei.lpDirectory = g_Data.programPath.c_str();
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
}
return 0;
}

View File

@ -1054,78 +1054,24 @@ void CDialogInstall::KeepVariables()
}
}
void CDialogInstall::LoadLayout(const std::wstring& name, bool setWallpaper)
{
// Take a copy of current Rainmeter.ini before doing anything
std::wstring backupFile = g_Data.settingsPath;
backupFile += L"Layouts\\@Backup\\";
CreateDirectory(backupFile.c_str(), NULL);
backupFile += L"Rainmeter.ini";
CopyFiles(g_Data.iniFile, backupFile, false);
if (name.empty())
{
return;
}
std::wstring layoutFile = g_Data.settingsPath;
layoutFile += L"Layouts\\";
layoutFile += name;
std::wstring wallpaperFile = layoutFile + L"\\Wallpaper.bmp";
layoutFile += L"\\Rainmeter.ini";
if (_waccess(layoutFile.c_str(), 0) != -1)
{
CopyFiles(layoutFile, g_Data.iniFile, false);
const WCHAR* iniFileSz = g_Data.iniFile.c_str();
const WCHAR* backupFileSz = backupFile.c_str();
auto preserveOption = [&](LPCTSTR section, LPCTSTR key)
{
WCHAR buffer[MAX_LINE_LENGTH];
if (GetPrivateProfileString(section, key, L"", buffer, MAX_LINE_LENGTH, iniFileSz) == 0 &&
GetPrivateProfileString(section, key, L"", buffer, MAX_LINE_LENGTH, backupFileSz) > 0)
{
WritePrivateProfileString(section, key, buffer, iniFileSz);
}
};
preserveOption(L"Rainmeter", L"SkinPath");
preserveOption(L"Rainmeter", L"ConfigEditor");
preserveOption(L"Rainmeter", L"LogViewer");
preserveOption(L"Rainmeter", L"Logging");
preserveOption(L"Rainmeter", L"DisableVersionCheck");
preserveOption(L"Rainmeter", L"Language");
preserveOption(L"Rainmeter", L"TrayExecuteM");
preserveOption(L"Rainmeter", L"TrayExecuteR");
preserveOption(L"Rainmeter", L"TrayExecuteDM");
preserveOption(L"Rainmeter", L"TrayExecuteDR");
// Set wallpaper if it exists
const WCHAR* wallpaperFileSz = wallpaperFile.c_str();
if (_waccess(wallpaperFileSz, 0) != -1)
{
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)wallpaperFileSz, SPIF_UPDATEINIFILE);
}
}
}
void CDialogInstall::LaunchRainmeter()
{
// Backup Rainmeter.ini and load layout (if specified)
LoadLayout(m_LoadLayout, false);
// Execute Rainmeter and wait up to a minute for it process all messages
std::wstring rainmeterExe = g_Data.programPath + L"Rainmeter.exe";
std::wstring args;
if (!m_LoadLayout.empty())
{
args += L"!LoadLayout \"";
args += m_LoadLayout;
args += L'"';
}
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_WAITFORINPUTIDLE | SEE_MASK_UNICODE;
sei.hwnd = NULL;
sei.lpVerb = NULL;
sei.lpFile = rainmeterExe.c_str();
sei.lpParameters = args.c_str();
sei.lpDirectory = g_Data.programPath.c_str();
sei.lpParameters = NULL;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);

View File

@ -33,8 +33,6 @@ public:
INT_PTR OnCommand(WPARAM wParam, LPARAM lParam);
INT_PTR OnNotify(WPARAM wParam, LPARAM lParam);
static void LoadLayout(const std::wstring& name, bool setWallpaper);
static CDialogInstall* c_Dialog;
protected: